aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-02-27 13:43:29 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-02-27 13:43:29 +0000
commit244fd6a8054352cb6b31f7b9eb620769c3c7d7a6 (patch)
treebc1ef71e542be614e0c50e4cab8783a56b2ed6a1
parent43a56296dfb61c42bf8789ffae3d5b7a94d12304 (diff)
downloadgnunet-244fd6a8054352cb6b31f7b9eb620769c3c7d7a6.tar.gz
gnunet-244fd6a8054352cb6b31f7b9eb620769c3c7d7a6.zip
checkpoint save
-rw-r--r--src/testbed/Makefile.am8
-rw-r--r--src/testbed/gnunet_testbed_mpi_spawn.c343
2 files changed, 350 insertions, 1 deletions
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 1253f6d0e..c148477c7 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -14,7 +14,8 @@ if WITH_LL
14 ll_binaries = \ 14 ll_binaries = \
15 gnunet-mpi-test \ 15 gnunet-mpi-test \
16 gnunet-testbed-ll-master \ 16 gnunet-testbed-ll-master \
17 gnunet-testbed-ll-monitor 17 gnunet-testbed-ll-monitor \
18 gnunet-testbed-mpi-spawn
18endif 19endif
19 20
20libexecdir= $(pkglibdir)/libexec/ 21libexecdir= $(pkglibdir)/libexec/
@@ -82,6 +83,11 @@ gnunet_mpi_test_SOURCES = gnunet_mpi_test.c
82gnunet_mpi_test_LDADD = \ 83gnunet_mpi_test_LDADD = \
83 $(top_builddir)/src/util/libgnunetutil.la 84 $(top_builddir)/src/util/libgnunetutil.la
84 85
86gnunet_testbed_mpi_spawn_SOURCES = gnunet_testbed_mpi_spawn.c
87gnunet_testbed_mpi_spawn_LDADD = \
88 $(top_builddir)/src/util/libgnunetutil.la \
89 $(top_builddir)/src/testbed/libgnunettestbed.la
90
85lib_LTLIBRARIES = \ 91lib_LTLIBRARIES = \
86 libgnunettestbed.la 92 libgnunettestbed.la
87 93
diff --git a/src/testbed/gnunet_testbed_mpi_spawn.c b/src/testbed/gnunet_testbed_mpi_spawn.c
new file mode 100644
index 000000000..c147d460b
--- /dev/null
+++ b/src/testbed/gnunet_testbed_mpi_spawn.c
@@ -0,0 +1,343 @@
1#include "platform.h"
2#include "gnunet_util_lib.h"
3#include "gnunet_resolver_service.h"
4#include <mpi.h>
5
6/**
7 * Generic logging shorthand
8 */
9#define LOG(kind,...) \
10 GNUNET_log_from (kind, "gnunet-mpi-test", __VA_ARGS__)
11
12/**
13 * Debug logging shorthand
14 */
15#define LOG_DEBUG(...) \
16 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
17
18/**
19 * Timeout for resolving IPs
20 */
21#define RESOLVE_TIMEOUT \
22 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
23
24/**
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).
28 */
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)
30
31/**
32 * Global result
33 */
34static int ret;
35
36/**
37 * The array of hostnames
38 */
39static char **hostnames;
40
41/**
42 * The array of host's addresses
43 */
44static char **hostaddrs;
45
46/**
47 * The resolution request handles; one per each hostname resolution
48 */
49struct GNUNET_RESOLVER_RequestHandle **rhs;
50
51/**
52 * Number of hosts in the hostname array
53 */
54static unsigned int nhosts;
55
56/**
57 * Number of addresses in the hostaddr array
58 */
59static unsigned int nhostaddrs;
60
61/**
62 * Did we connect to the resolver service
63 */
64static unsigned int resolver_connected;
65
66/**
67 * Task for resolving ips
68 */
69static GNUNET_SCHEDULER_TaskIdentifier resolve_task_id;
70
71
72/**
73 * Resolves the hostnames array
74 *
75 * @param cls NULL
76 * @param tc the scheduler task context
77 */
78static void
79resolve_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
80{
81 struct addrinfo hint;
82 const struct sockaddr_in *in_addr;
83 struct addrinfo *res;
84 char *hostip;
85 unsigned int host;
86 unsigned int rc;
87
88 resolve_task_id = GNUNET_SCHEDULER_NO_TASK;
89 hint.ai_family = AF_INET; /* IPv4 */
90 hint.ai_socktype = 0;
91 hint.ai_protocol = 0;
92 hint.ai_addrlen = 0;
93 hint.ai_addr = NULL;
94 hint.ai_canonname = NULL;
95 hint.ai_next = NULL;
96 hint.ai_flags = AI_NUMERICSERV;
97 for (host = 0; host < nhosts; host++)
98 {
99 res = NULL;
100 LOG_DEBUG ("Resolving: %s host\n", hostnames[host]);
101 if (0 != (rc = getaddrinfo (hostnames[host], "22", &hint, &res)))
102 {
103 LOG_GAI (GNUNET_ERROR_TYPE_ERROR, "getaddrinfo", rc);
104 ret = GNUNET_SYSERR;
105 return;
106 }
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]);
115 freeaddrinfo (res);
116 }
117 ret = GNUNET_OK;
118}
119
120
121/**
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
125 *
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
129 */
130unsigned int
131get_loadleveler_hosts ()
132{
133 const char *hostfile;
134 char *buf;
135 char *hostname;
136 struct addrinfo *ret;
137 struct addrinfo hint;
138 ssize_t rsize;
139 uint64_t size;
140 uint64_t offset;
141 enum {
142 SCAN,
143 SKIP,
144 TRIM,
145 READHOST
146 } pstep;
147 unsigned int host;
148
149 if (NULL == (hostfile = getenv ("MP_SAVEHOSTFILE")))
150 {
151 GNUNET_break (0);
152 return 0;
153 }
154 if (GNUNET_SYSERR == GNUNET_DISK_file_size (hostfile, &size, GNUNET_YES,
155 GNUNET_YES))
156 {
157 GNUNET_break (0);
158 return 0;
159 }
160 if (0 == size)
161 {
162 GNUNET_break (0);
163 return 0;
164 }
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) )
168 {
169 GNUNET_free (buf);
170 GNUNET_break (0);
171 return 0;
172 }
173 size++;
174 offset = 0;
175 pstep = SCAN;
176 hostname = NULL;
177 while (offset < size)
178 {
179 switch (pstep)
180 {
181 case SCAN:
182 if ('!' == buf[offset])
183 pstep = SKIP;
184 else
185 pstep = TRIM;
186 break;
187 case SKIP:
188 if ('\n' == buf[offset])
189 pstep = SCAN;
190 break;
191 case TRIM:
192 if ('!' == buf[offset])
193 {
194 pstep = SKIP;
195 break;
196 }
197 if ( (' ' == buf[offset])
198 || ('\t' == buf[offset])
199 || ('\r' == buf[offset]) )
200 pstep = TRIM;
201 else
202 {
203 pstep = READHOST;
204 hostname = &buf[offset];
205 }
206 break;
207 case READHOST:
208 if (isspace (buf[offset]))
209 {
210 buf[offset] = '\0';
211 for (host = 0; host < nhosts; host++)
212 if (0 == strcmp (hostnames[host], hostname))
213 break;
214 if (host == nhosts)
215 {
216 LOG_DEBUG ("Adding host: %s\n", hostname);
217 hostname = GNUNET_strdup (hostname);
218 GNUNET_array_append (hostnames, nhosts, hostname);
219 }
220 else
221 LOG_DEBUG ("Not adding host %s as it is already included\n", hostname);
222 hostname = NULL;
223 pstep = SCAN;
224 }
225 break;
226 }
227 offset++;
228 }
229 GNUNET_free_non_null (buf);
230 return nhosts;
231}
232
233
234/**
235 * Main function that will be run by the scheduler.
236 *
237 * @param cls closure
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
241 */
242static void
243run (void *cls, char *const *args, const char *cfgfile,
244 const struct GNUNET_CONFIGURATION_Handle *config)
245{
246 struct GNUNET_OS_Process *proc;
247 unsigned long code;
248 enum GNUNET_OS_ProcessStatusType proc_status;
249 int rank;
250 int msg_size;
251
252 if (MPI_SUCCESS != MPI_Comm_rank (MPI_COMM_WORLD, &rank))
253 {
254 GNUNET_break (0);
255 return;
256 }
257 if (0 != rank)
258 {
259 ret = GNUNET_OK;
260 return;
261 }
262 PRINTF ("Spawning process\n");
263 proc =
264 GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
265 NULL, args[0], args);
266 if (NULL == proc)
267 {
268 printf ("Cannot exec\n");
269 return;
270 }
271 do
272 {
273 (void) sleep (1);
274 ret = GNUNET_OS_process_status (proc, &proc_status, &code);
275 }
276 while (GNUNET_NO == ret);
277 GNUNET_assert (GNUNET_NO != ret);
278 if (GNUNET_OK == ret)
279 {
280 if (0 != code)
281 {
282 LOG (GNUNET_ERROR_TYPE_WARNING, "Child terminated abnormally\n");
283 ret = GNUNET_SYSERR;
284 GNUNET_break (0);
285 return;
286 }
287 }
288 else
289 {
290 ret = GNUNET_SYSERR;
291 GNUNET_break (0);
292 return;
293 }
294 if (0 == get_loadleveler_hosts())
295 {
296 GNUNET_break (0);
297 ret = GNUNET_SYSERR;
298 return;
299 }
300 resolve_task_id = GNUNET_SCHEDULER_add_now (&resolve_task, NULL);
301}
302
303
304/**
305 * Execution start point
306 */
307int
308main (int argc, char *argv[])
309{
310 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
311 GNUNET_GETOPT_OPTION_END
312 };
313 unsigned int host;
314 int rres;
315
316 ret = GNUNET_SYSERR;
317 if (argc < 2)
318 {
319 printf ("Need arguments: gnunet-testbed-mpi-spawn <cmd> <cmd_args>");
320 return 1;
321 }
322 if (MPI_SUCCESS != MPI_Init (&argc, &argv))
323 {
324 GNUNET_break (0);
325 return 1;
326 }
327 rres =
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))
340 return 0;
341 printf ("Something went wrong\n");
342 return 1;
343}