diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-02-27 13:43:29 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-02-27 13:43:29 +0000 |
commit | 244fd6a8054352cb6b31f7b9eb620769c3c7d7a6 (patch) | |
tree | bc1ef71e542be614e0c50e4cab8783a56b2ed6a1 | |
parent | 43a56296dfb61c42bf8789ffae3d5b7a94d12304 (diff) | |
download | gnunet-244fd6a8054352cb6b31f7b9eb620769c3c7d7a6.tar.gz gnunet-244fd6a8054352cb6b31f7b9eb620769c3c7d7a6.zip |
checkpoint save
-rw-r--r-- | src/testbed/Makefile.am | 8 | ||||
-rw-r--r-- | src/testbed/gnunet_testbed_mpi_spawn.c | 343 |
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 | ||
18 | endif | 19 | endif |
19 | 20 | ||
20 | libexecdir= $(pkglibdir)/libexec/ | 21 | libexecdir= $(pkglibdir)/libexec/ |
@@ -82,6 +83,11 @@ gnunet_mpi_test_SOURCES = gnunet_mpi_test.c | |||
82 | gnunet_mpi_test_LDADD = \ | 83 | gnunet_mpi_test_LDADD = \ |
83 | $(top_builddir)/src/util/libgnunetutil.la | 84 | $(top_builddir)/src/util/libgnunetutil.la |
84 | 85 | ||
86 | gnunet_testbed_mpi_spawn_SOURCES = gnunet_testbed_mpi_spawn.c | ||
87 | gnunet_testbed_mpi_spawn_LDADD = \ | ||
88 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
89 | $(top_builddir)/src/testbed/libgnunettestbed.la | ||
90 | |||
85 | lib_LTLIBRARIES = \ | 91 | lib_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 | */ | ||
34 | static int ret; | ||
35 | |||
36 | /** | ||
37 | * The array of hostnames | ||
38 | */ | ||
39 | static char **hostnames; | ||
40 | |||
41 | /** | ||
42 | * The array of host's addresses | ||
43 | */ | ||
44 | static char **hostaddrs; | ||
45 | |||
46 | /** | ||
47 | * The resolution request handles; one per each hostname resolution | ||
48 | */ | ||
49 | struct GNUNET_RESOLVER_RequestHandle **rhs; | ||
50 | |||
51 | /** | ||
52 | * Number of hosts in the hostname array | ||
53 | */ | ||
54 | static unsigned int nhosts; | ||
55 | |||
56 | /** | ||
57 | * Number of addresses in the hostaddr array | ||
58 | */ | ||
59 | static unsigned int nhostaddrs; | ||
60 | |||
61 | /** | ||
62 | * Did we connect to the resolver service | ||
63 | */ | ||
64 | static unsigned int resolver_connected; | ||
65 | |||
66 | /** | ||
67 | * Task for resolving ips | ||
68 | */ | ||
69 | static 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 | */ | ||
78 | static void | ||
79 | resolve_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 | */ | ||
130 | unsigned int | ||
131 | get_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 | */ | ||
242 | static void | ||
243 | run (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 | */ | ||
307 | int | ||
308 | main (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 | } | ||