root/mpich2/trunk/src/pm/hydra/utils/launch/allocate.c @ 4887

Revision 4887, 12.9 KB (checked in by balaji, 5 months ago)

Warning stomp.

Line 
1/* -*- Mode: C; c-basic-offset:4 ; -*- */
2/*
3 *  (C) 2008 by Argonne National Laboratory.
4 *      See COPYRIGHT in top-level directory.
5 */
6
7#include "hydra_utils.h"
8
9static HYD_Status alloc_partition_base(struct HYD_Partition_base **base)
10{
11    static int partition_id = 0;
12    HYD_Status status = HYD_SUCCESS;
13
14    HYDU_MALLOC(*base, struct HYD_Partition_base *, sizeof(struct HYD_Partition_base), status);
15
16    (*base)->name = NULL;
17    (*base)->pid = -1;
18    (*base)->in = -1;
19    (*base)->out = -1;
20    (*base)->err = -1;
21
22    (*base)->partition_id = partition_id++;
23    (*base)->active = 0;
24    (*base)->exec_args = NULL;
25
26    (*base)->next = NULL;
27
28  fn_exit:
29    return status;
30
31  fn_fail:
32    goto fn_exit;
33}
34
35static void free_partition_base(struct HYD_Partition_base *base)
36{
37    if (base->name)
38        HYDU_FREE(base->name);
39    if (base->exec_args) {
40        HYDU_free_strlist(base->exec_args);
41        HYDU_FREE(base->exec_args);
42    }
43
44    HYDU_FREE(base);
45}
46
47HYD_Status HYDU_alloc_partition(struct HYD_Partition **partition)
48{
49    HYD_Status status = HYD_SUCCESS;
50
51    HYDU_FUNC_ENTER();
52
53    HYDU_MALLOC(*partition, struct HYD_Partition *, sizeof(struct HYD_Partition), status);
54
55    alloc_partition_base(&((*partition)->base));
56
57    (*partition)->user_bind_map = NULL;
58    (*partition)->segment_list = NULL;
59    (*partition)->partition_core_count = 0;
60
61    (*partition)->exit_status = NULL;
62    (*partition)->control_fd = -1;
63
64    (*partition)->exec_list = NULL;
65    (*partition)->next = NULL;
66
67  fn_exit:
68    HYDU_FUNC_EXIT();
69    return status;
70
71  fn_fail:
72    goto fn_exit;
73}
74
75
76HYD_Status HYDU_alloc_exec_info(struct HYD_Exec_info **exec_info)
77{
78    HYD_Status status = HYD_SUCCESS;
79
80    HYDU_FUNC_ENTER();
81
82    HYDU_MALLOC(*exec_info, struct HYD_Exec_info *, sizeof(struct HYD_Exec_info), status);
83    (*exec_info)->exec_proc_count = 0;
84    (*exec_info)->exec[0] = NULL;
85    (*exec_info)->user_env = NULL;
86    (*exec_info)->prop = HYD_ENV_PROP_UNSET;
87    (*exec_info)->next = NULL;
88
89  fn_exit:
90    HYDU_FUNC_EXIT();
91    return status;
92
93  fn_fail:
94    goto fn_exit;
95}
96
97
98void HYDU_free_exec_info_list(struct HYD_Exec_info *exec_info_list)
99{
100    struct HYD_Exec_info *exec_info, *run;
101
102    HYDU_FUNC_ENTER();
103
104    exec_info = exec_info_list;
105    while (exec_info) {
106        run = exec_info->next;
107        HYDU_free_strlist(exec_info->exec);
108
109        HYDU_env_free_list(exec_info->user_env);
110        exec_info->user_env = NULL;
111
112        HYDU_FREE(exec_info);
113        exec_info = run;
114    }
115
116    HYDU_FUNC_EXIT();
117}
118
119
120void HYDU_free_partition_list(struct HYD_Partition *partition_list)
121{
122    struct HYD_Partition *partition, *tpartition;
123    struct HYD_Partition_segment *segment, *tsegment;
124    struct HYD_Partition_exec *exec, *texec;
125
126    HYDU_FUNC_ENTER();
127
128    partition = partition_list;
129    while (partition) {
130        tpartition = partition->next;
131
132        free_partition_base(partition->base);
133
134        if (partition->user_bind_map)
135            HYDU_FREE(partition->user_bind_map);
136
137        segment = partition->segment_list;
138        while (segment) {
139            tsegment = segment->next;
140            if (segment->mapping) {
141                HYDU_free_strlist(segment->mapping);
142                HYDU_FREE(segment->mapping);
143            }
144            HYDU_FREE(segment);
145            segment = tsegment;
146        }
147
148        if (partition->exit_status)
149            HYDU_FREE(partition->exit_status);
150
151        exec = partition->exec_list;
152        while (exec) {
153            texec = exec->next;
154            HYDU_free_strlist(exec->exec);
155            if (exec->user_env)
156                HYDU_env_free(exec->user_env);
157            HYDU_FREE(exec);
158            exec = texec;
159        }
160
161        HYDU_FREE(partition);
162        partition = tpartition;
163    }
164
165    HYDU_FUNC_EXIT();
166}
167
168
169HYD_Status HYDU_alloc_partition_segment(struct HYD_Partition_segment **segment)
170{
171    HYD_Status status = HYD_SUCCESS;
172
173    HYDU_FUNC_ENTER();
174
175    HYDU_MALLOC(*segment, struct HYD_Partition_segment *,
176                sizeof(struct HYD_Partition_segment), status);
177    (*segment)->start_pid = -1;
178    (*segment)->proc_count = 0;
179    (*segment)->mapping = NULL;
180    (*segment)->next = NULL;
181
182  fn_exit:
183    HYDU_FUNC_EXIT();
184    return status;
185
186  fn_fail:
187    goto fn_exit;
188}
189
190
191HYD_Status HYDU_merge_partition_segment(char *name, struct HYD_Partition_segment *segment,
192                                        struct HYD_Partition **partition_list)
193{
194    struct HYD_Partition *partition;
195    struct HYD_Partition_segment *s;
196    HYD_Status status = HYD_SUCCESS;
197
198    HYDU_FUNC_ENTER();
199
200    if (*partition_list == NULL) {
201        status = HYDU_alloc_partition(partition_list);
202        HYDU_ERR_POP(status, "Unable to alloc partition\n");
203        (*partition_list)->segment_list = segment;
204        (*partition_list)->base->name = HYDU_strdup(name);
205        (*partition_list)->partition_core_count += segment->proc_count;
206    }
207    else {
208        partition = *partition_list;
209        while (partition) {
210            if (strcmp(partition->base->name, name) == 0) {
211                if (partition->segment_list == NULL)
212                    partition->segment_list = segment;
213                else {
214                    s = partition->segment_list;
215                    while (s->next)
216                        s = s->next;
217                    s->next = segment;
218                }
219                partition->partition_core_count += segment->proc_count;
220                break;
221            }
222            else if (partition->next == NULL) {
223                status = HYDU_alloc_partition(&partition->next);
224                HYDU_ERR_POP(status, "Unable to alloc partition\n");
225                partition->next->segment_list = segment;
226                partition->next->base->name = HYDU_strdup(name);
227                partition->next->partition_core_count += segment->proc_count;
228                partition->base->next = partition->next->base;
229                break;
230            }
231            else {
232                partition = partition->next;
233            }
234        }
235    }
236
237  fn_exit:
238    HYDU_FUNC_EXIT();
239    return status;
240  fn_fail:
241    goto fn_exit;
242}
243
244
245static int count_elements(char *str, const char *delim)
246{
247    int count;
248
249    HYDU_FUNC_ENTER();
250
251    strtok(str, delim);
252    count = 1;
253    while (strtok(NULL, delim))
254        count++;
255
256    HYDU_FUNC_EXIT();
257
258    return count;
259}
260
261
262static char *pad_string(char *str, const char *pad, int count)
263{
264    char *tmp[HYD_NUM_TMP_STRINGS], *out;
265    int i, j;
266    HYD_Status status = HYD_SUCCESS;
267
268    HYDU_FUNC_ENTER();
269
270    i = 0;
271    tmp[i++] = HYDU_strdup(str);
272    for (j = 0; j < count; j++)
273        tmp[i++] = HYDU_strdup(pad);
274    tmp[i] = NULL;
275
276    status = HYDU_str_alloc_and_join(tmp, &out);
277    HYDU_ERR_POP(status, "unable to join strings\n");
278
279    HYDU_free_strlist(tmp);
280
281  fn_exit:
282    HYDU_FUNC_EXIT();
283    return out;
284
285  fn_fail:
286    goto fn_exit;
287}
288
289
290HYD_Status HYDU_merge_partition_mapping(char *name, char *map, int num_procs,
291                                        struct HYD_Partition **partition_list)
292{
293    struct HYD_Partition *partition;
294    char *tmp[HYD_NUM_TMP_STRINGS], *x;
295    int i, count;
296    HYD_Status status = HYD_SUCCESS;
297
298    HYDU_FUNC_ENTER();
299
300    if (*partition_list == NULL) {
301        HYDU_alloc_partition(partition_list);
302        (*partition_list)->base->name = HYDU_strdup(name);
303
304        x = HYDU_strdup(map);
305        count = num_procs - count_elements(x, ",");
306        HYDU_FREE(x);
307
308        (*partition_list)->user_bind_map = pad_string(map, ",-1", count);
309    }
310    else {
311        partition = *partition_list;
312        while (partition) {
313            if (strcmp(partition->base->name, name) == 0) {
314                /* Found a partition with the same name; append */
315                if (partition->user_bind_map == NULL) {
316                    x = HYDU_strdup(map);
317                    count = num_procs - count_elements(x, ",");
318                    HYDU_FREE(x);
319
320                    partition->user_bind_map = pad_string(map, ",-1", count);
321                }
322                else {
323                    x = HYDU_strdup(map);
324                    count = num_procs - count_elements(x, ",");
325                    HYDU_FREE(x);
326
327                    i = 0;
328                    tmp[i++] = HYDU_strdup(partition->user_bind_map);
329                    tmp[i++] = HYDU_strdup(",");
330                    tmp[i++] = pad_string(map, ",-1", count);
331                    tmp[i++] = NULL;
332
333                    HYDU_FREE(partition->user_bind_map);
334                    status = HYDU_str_alloc_and_join(tmp, &partition->user_bind_map);
335                    HYDU_ERR_POP(status, "unable to join strings\n");
336
337                    HYDU_free_strlist(tmp);
338                }
339                break;
340            }
341            else if (partition->next == NULL) {
342                HYDU_alloc_partition(&partition->next);
343                partition->base->next = partition->next->base;
344                partition->next->base->name = HYDU_strdup(name);
345                partition->next->user_bind_map = HYDU_strdup(map);
346                break;
347            }
348            else {
349                partition = partition->next;
350            }
351        }
352    }
353
354  fn_exit:
355    HYDU_FUNC_EXIT();
356    return status;
357
358  fn_fail:
359    goto fn_exit;
360}
361
362
363HYD_Status HYDU_alloc_partition_exec(struct HYD_Partition_exec **exec)
364{
365    HYD_Status status = HYD_SUCCESS;
366
367    HYDU_FUNC_ENTER();
368
369    HYDU_MALLOC(*exec, struct HYD_Partition_exec *, sizeof(struct HYD_Partition_exec), status);
370    (*exec)->exec[0] = NULL;
371    (*exec)->proc_count = 0;
372    (*exec)->prop = HYD_ENV_PROP_UNSET;
373    (*exec)->user_env = NULL;
374    (*exec)->next = NULL;
375
376  fn_exit:
377    HYDU_FUNC_EXIT();
378    return status;
379
380  fn_fail:
381    goto fn_exit;
382}
383
384
385HYD_Status HYDU_create_node_list_from_file(char *host_file,
386                                           struct HYD_Partition **partition_list)
387{
388    FILE *fp = NULL;
389    char line[HYD_TMP_STRLEN], *hostname, *procs, **arg_list;
390    char *str[2] = { NULL };
391    int num_procs, total_count, arg, i;
392    struct HYD_Partition_segment *segment;
393    HYD_Status status = HYD_SUCCESS;
394
395    HYDU_FUNC_ENTER();
396
397    if (!strcmp(host_file, "HYDRA_USE_LOCALHOST")) {
398        HYDU_alloc_partition(&(*partition_list));
399        (*partition_list)->base->name = HYDU_strdup("localhost");
400        (*partition_list)->partition_core_count = 1;
401
402        HYDU_alloc_partition_segment(&((*partition_list)->segment_list));
403        (*partition_list)->segment_list->start_pid = 0;
404        (*partition_list)->segment_list->proc_count = 1;
405    }
406    else {
407        fp = fopen(host_file, "r");
408        if (!fp)
409            HYDU_ERR_SETANDJUMP1(status, HYD_INTERNAL_ERROR,
410                                 "unable to open host file: %s\n", host_file);
411
412        total_count = 0;
413        while (fgets(line, HYD_TMP_STRLEN, fp)) {
414            char *linep = NULL;
415
416            linep = line;
417
418            strtok(linep, "#");
419
420            while (isspace(*linep))
421                linep++;
422
423            /* Ignore blank lines & comments */
424            if ((*linep == '#') || (*linep == '\0'))
425                continue;
426
427            arg_list = HYDU_str_to_strlist(linep);
428            if (!arg_list)
429                HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR,
430                                    "Unable to convert host file entry to strlist\n");
431
432            hostname = strtok(arg_list[0], ":");
433            procs = strtok(NULL, ":");
434            num_procs = procs ? atoi(procs) : 1;
435
436            /* Try to find an existing partition with this name and
437             * add this segment in. If there is no existing partition
438             * with this name, we create a new one. */
439            status = HYDU_alloc_partition_segment(&segment);
440            HYDU_ERR_POP(status, "Unable to allocate partition segment\n");
441            segment->start_pid = total_count;
442            segment->proc_count = num_procs;
443            status = HYDU_merge_partition_segment(hostname, segment, partition_list);
444            HYDU_ERR_POP(status, "merge partition segment failed\n");
445
446            total_count += num_procs;
447
448            /* Check for the remaining parameters */
449            arg = 1;
450            str[0] = str[1] = NULL;
451            while (arg_list[arg]) {
452                status = HYDU_strsplit(arg_list[arg], &str[0], &str[1], '=');
453                HYDU_ERR_POP(status, "unable to split string\n");
454
455                if (!strcmp(str[0], "map")) {
456                    status = HYDU_merge_partition_mapping(hostname, str[1], num_procs,
457                                                          partition_list);
458                    HYDU_ERR_POP(status, "merge partition mapping failed\n");
459                }
460                if (str[0])
461                    HYDU_FREE(str[0]);
462                if (str[1])
463                    HYDU_FREE(str[1]);
464                str[0] = str[1] = NULL;
465                arg++;
466            }
467            HYDU_free_strlist(arg_list);
468            HYDU_FREE(arg_list);
469        }
470
471        fclose(fp);
472    }
473
474  fn_exit:
475    HYDU_FUNC_EXIT();
476    return status;
477
478  fn_fail:
479    for (i = 0; i < 2; i++)
480        if (str[i])
481            HYDU_FREE(str[i]);
482    goto fn_exit;
483}
Note: See TracBrowser for help on using the browser.