2 #include "gnunet_util_lib.h"
3 #include "gnunet_resolver_service.h"
7 * Generic logging shorthand
9 #define LOG(kind,...) \
10 GNUNET_log_from (kind, "gnunet-mpi-test", __VA_ARGS__)
13 * Debug logging shorthand
15 #define LOG_DEBUG(...) \
16 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
19 * Timeout for resolving IPs
21 #define RESOLVE_TIMEOUT \
22 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
25 * Log an error message at log-level 'level' that indicates
26 * a failure of the command 'cmd' with the message given
27 * by gcry_strerror(rc).
29 #define LOG_GAI(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gai_strerror(rc)); } while(0)
37 * The array of hostnames
39 static char **hostnames;
42 * The array of host's addresses
44 static char **hostaddrs;
47 * The resolution request handles; one per each hostname resolution
49 struct GNUNET_RESOLVER_RequestHandle **rhs;
52 * Number of hosts in the hostname array
54 static unsigned int nhosts;
57 * Number of addresses in the hostaddr array
59 static unsigned int nhostaddrs;
62 * Did we connect to the resolver service
64 static unsigned int resolver_connected;
67 * Task for resolving ips
69 static GNUNET_SCHEDULER_TaskIdentifier resolve_task_id;
73 * Resolves the hostnames array
76 * @param tc the scheduler task context
79 resolve_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
82 const struct sockaddr_in *in_addr;
88 resolve_task_id = GNUNET_SCHEDULER_NO_TASK;
89 hint.ai_family = AF_INET; /* IPv4 */
94 hint.ai_canonname = NULL;
96 hint.ai_flags = AI_NUMERICSERV;
97 for (host = 0; host < nhosts; host++)
100 LOG_DEBUG ("Resolving: %s host\n", hostnames[host]);
101 if (0 != (rc = getaddrinfo (hostnames[host], "22", &hint, &res)))
103 LOG_GAI (GNUNET_ERROR_TYPE_ERROR, "getaddrinfo", rc);
107 GNUNET_assert (NULL != res);
108 GNUNET_assert (NULL != res->ai_addr);
109 GNUNET_assert (sizeof (struct sockaddr_in) == res->ai_addrlen);
110 in_addr = (const struct sockaddr_in *) res->ai_addr;
111 hostip = inet_ntoa (in_addr->sin_addr);
112 GNUNET_assert (NULL != hostip);
113 GNUNET_array_append (hostaddrs, nhostaddrs, GNUNET_strdup (hostip));
114 LOG_DEBUG ("%s --> %s\n", hostnames[host], hostaddrs[host]);
122 * Loads the set of host allocated by the LoadLeveler Job Scheduler. This
123 * function is only available when compiled with support for LoadLeveler and is
124 * used for running on the SuperMUC
126 * @param hostlist set to the hosts found in the file; caller must free this if
127 * number of hosts returned is greater than 0
128 * @return number of hosts returned in 'hosts', 0 on error
131 get_loadleveler_hosts ()
133 const char *hostfile;
136 struct addrinfo *ret;
137 struct addrinfo hint;
149 if (NULL == (hostfile = getenv ("MP_SAVEHOSTFILE")))
154 if (GNUNET_SYSERR == GNUNET_DISK_file_size (hostfile, &size, GNUNET_YES,
165 buf = GNUNET_malloc (size + 1);
166 rsize = GNUNET_DISK_fn_read (hostfile, buf, (size_t) size);
167 if ( (GNUNET_SYSERR == rsize) || ((ssize_t) size != rsize) )
177 while (offset < size)
182 if ('!' == buf[offset])
188 if ('\n' == buf[offset])
192 if ('!' == buf[offset])
197 if ( (' ' == buf[offset])
198 || ('\t' == buf[offset])
199 || ('\r' == buf[offset]) )
204 hostname = &buf[offset];
208 if (isspace (buf[offset]))
211 for (host = 0; host < nhosts; host++)
212 if (0 == strcmp (hostnames[host], hostname))
216 LOG_DEBUG ("Adding host: %s\n", hostname);
217 hostname = GNUNET_strdup (hostname);
218 GNUNET_array_append (hostnames, nhosts, hostname);
221 LOG_DEBUG ("Not adding host %s as it is already included\n", hostname);
229 GNUNET_free_non_null (buf);
235 * Main function that will be run by the scheduler.
238 * @param args remaining command-line arguments
239 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
240 * @param config configuration
243 run (void *cls, char *const *args, const char *cfgfile,
244 const struct GNUNET_CONFIGURATION_Handle *config)
246 struct GNUNET_OS_Process *proc;
248 enum GNUNET_OS_ProcessStatusType proc_status;
252 if (MPI_SUCCESS != MPI_Comm_rank (MPI_COMM_WORLD, &rank))
262 PRINTF ("Spawning process\n");
264 GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
265 NULL, args[0], args);
268 printf ("Cannot exec\n");
274 ret = GNUNET_OS_process_status (proc, &proc_status, &code);
276 while (GNUNET_NO == ret);
277 GNUNET_assert (GNUNET_NO != ret);
278 if (GNUNET_OK == ret)
282 LOG (GNUNET_ERROR_TYPE_WARNING, "Child terminated abnormally\n");
294 if (0 == get_loadleveler_hosts())
300 resolve_task_id = GNUNET_SCHEDULER_add_now (&resolve_task, NULL);
305 * Execution start point
308 main (int argc, char *argv[])
310 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
311 GNUNET_GETOPT_OPTION_END
319 printf ("Need arguments: gnunet-testbed-mpi-spawn <cmd> <cmd_args>");
322 if (MPI_SUCCESS != MPI_Init (&argc, &argv))
328 GNUNET_PROGRAM_run (argc, argv,
329 "gnunet-testbed-mpi-spawn <cmd> <cmd_args>",
330 _("Spawns cmd after starting my the MPI run-time"),
331 options, &run, NULL);
332 (void) MPI_Finalize ();
333 for (host = 0; host < nhosts; host++)
334 GNUNET_free (hostnames[host]);
335 for (host = 0; host < nhostaddrs; host++)
336 GNUNET_free (hostaddrs[host]);
337 GNUNET_free_non_null (hostnames);
338 GNUNET_free_non_null (hostaddrs);
339 if ((GNUNET_OK == rres) && (GNUNET_OK == ret))
341 printf ("Something went wrong\n");