1 /*
2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3  *                         University Research and Technology
4  *                         Corporation.  All rights reserved.
5  * Copyright (c) 2004-2011 The University of Tennessee and The University
6  *                         of Tennessee Research Foundation.  All rights
7  *                         reserved.
8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9  *                         University of Stuttgart.  All rights reserved.
10  * Copyright (c) 2004-2005 The Regents of the University of California.
11  *                         All rights reserved.
12  * Copyright (c) 2010      Oracle and/or its affiliates.  All rights reserved.
13  * Copyright (c) 2014-2016 Research Organization for Information Science
14  *                         and Technology (RIST). All rights reserved.
15  * Copyright (c) 2016      Intel, Inc. All rights reserved.
16  * $COPYRIGHT$
17  *
18  * Additional copyrights may follow
19  *
20  * $HEADER$
21  */
22 #include "orte_config.h"
23 #include "orte/types.h"
24 #include "orte/constants.h"
25 
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "opal/util/printf.h"
30 #include "opal/threads/tsd.h"
31 
32 #include "orte/mca/errmgr/errmgr.h"
33 
34 #include "orte/util/name_fns.h"
35 
36 #define ORTE_PRINT_NAME_ARGS_MAX_SIZE   50
37 #define ORTE_PRINT_NAME_ARG_NUM_BUFS    16
38 
39 #define ORTE_SCHEMA_DELIMITER_CHAR      '.'
40 #define ORTE_SCHEMA_WILDCARD_CHAR       '*'
41 #define ORTE_SCHEMA_WILDCARD_STRING     "*"
42 #define ORTE_SCHEMA_INVALID_CHAR        '$'
43 #define ORTE_SCHEMA_INVALID_STRING      "$"
44 
45 /* constructor - used to initialize namelist instance */
orte_namelist_construct(orte_namelist_t * list)46 static void orte_namelist_construct(orte_namelist_t* list)
47 {
48     list->name.jobid = ORTE_JOBID_INVALID;
49     list->name.vpid = ORTE_VPID_INVALID;
50 }
51 
52 /* destructor - used to free any resources held by instance */
orte_namelist_destructor(orte_namelist_t * list)53 static void orte_namelist_destructor(orte_namelist_t* list)
54 {
55 }
56 
57 /* define instance of opal_class_t */
58 OBJ_CLASS_INSTANCE(orte_namelist_t,              /* type name */
59                    opal_list_item_t,             /* parent "class" name */
60                    orte_namelist_construct,      /* constructor */
61                    orte_namelist_destructor);    /* destructor */
62 
63 static bool fns_init=false;
64 
65 static opal_tsd_key_t print_args_tsd_key;
66 char* orte_print_args_null = "NULL";
67 typedef struct {
68     char *buffers[ORTE_PRINT_NAME_ARG_NUM_BUFS];
69     int cntr;
70 } orte_print_args_buffers_t;
71 
72 static void
buffer_cleanup(void * value)73 buffer_cleanup(void *value)
74 {
75     int i;
76     orte_print_args_buffers_t *ptr;
77 
78     if (NULL != value) {
79         ptr = (orte_print_args_buffers_t*)value;
80         for (i=0; i < ORTE_PRINT_NAME_ARG_NUM_BUFS; i++) {
81             free(ptr->buffers[i]);
82         }
83         free (ptr);
84     }
85 }
86 
87 static orte_print_args_buffers_t*
get_print_name_buffer(void)88 get_print_name_buffer(void)
89 {
90     orte_print_args_buffers_t *ptr;
91     int ret, i;
92 
93     if (!fns_init) {
94         /* setup the print_args function */
95         if (ORTE_SUCCESS != (ret = opal_tsd_key_create(&print_args_tsd_key, buffer_cleanup))) {
96             ORTE_ERROR_LOG(ret);
97             return NULL;
98         }
99         fns_init = true;
100     }
101 
102     ret = opal_tsd_getspecific(print_args_tsd_key, (void**)&ptr);
103     if (OPAL_SUCCESS != ret) return NULL;
104 
105     if (NULL == ptr) {
106         ptr = (orte_print_args_buffers_t*)malloc(sizeof(orte_print_args_buffers_t));
107         for (i=0; i < ORTE_PRINT_NAME_ARG_NUM_BUFS; i++) {
108             ptr->buffers[i] = (char *) malloc((ORTE_PRINT_NAME_ARGS_MAX_SIZE+1) * sizeof(char));
109         }
110         ptr->cntr = 0;
111         ret = opal_tsd_setspecific(print_args_tsd_key, (void*)ptr);
112     }
113 
114     return (orte_print_args_buffers_t*) ptr;
115 }
116 
orte_util_print_name_args(const orte_process_name_t * name)117 char* orte_util_print_name_args(const orte_process_name_t *name)
118 {
119     orte_print_args_buffers_t *ptr;
120     char *job, *vpid;
121 
122     /* protect against NULL names */
123     if (NULL == name) {
124         /* get the next buffer */
125         ptr = get_print_name_buffer();
126         if (NULL == ptr) {
127             ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
128             return orte_print_args_null;
129         }
130         /* cycle around the ring */
131         if (ORTE_PRINT_NAME_ARG_NUM_BUFS == ptr->cntr) {
132             ptr->cntr = 0;
133         }
134         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "[NO-NAME]");
135         return ptr->buffers[ptr->cntr-1];
136     }
137 
138     /* get the jobid, vpid strings first - this will protect us from
139      * stepping on each other's buffer. This also guarantees
140      * that the print_args function has been initialized, so
141      * we don't need to duplicate that here
142      */
143     job = orte_util_print_jobids(name->jobid);
144     vpid = orte_util_print_vpids(name->vpid);
145 
146     /* get the next buffer */
147     ptr = get_print_name_buffer();
148 
149     if (NULL == ptr) {
150         ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
151         return orte_print_args_null;
152     }
153 
154     /* cycle around the ring */
155     if (ORTE_PRINT_NAME_ARG_NUM_BUFS == ptr->cntr) {
156         ptr->cntr = 0;
157     }
158 
159     snprintf(ptr->buffers[ptr->cntr++],
160              ORTE_PRINT_NAME_ARGS_MAX_SIZE,
161              "[%s,%s]", job, vpid);
162 
163     return ptr->buffers[ptr->cntr-1];
164 }
165 
orte_util_print_jobids(const orte_jobid_t job)166 char* orte_util_print_jobids(const orte_jobid_t job)
167 {
168     orte_print_args_buffers_t *ptr;
169     unsigned long tmp1, tmp2;
170 
171     ptr = get_print_name_buffer();
172 
173     if (NULL == ptr) {
174         ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
175         return orte_print_args_null;
176     }
177 
178     /* cycle around the ring */
179     if (ORTE_PRINT_NAME_ARG_NUM_BUFS == ptr->cntr) {
180         ptr->cntr = 0;
181     }
182 
183     if (ORTE_JOBID_INVALID == job) {
184         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "[INVALID]");
185     } else if (ORTE_JOBID_WILDCARD == job) {
186         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "[WILDCARD]");
187     } else {
188         tmp1 = ORTE_JOB_FAMILY((unsigned long)job);
189         tmp2 = ORTE_LOCAL_JOBID((unsigned long)job);
190         snprintf(ptr->buffers[ptr->cntr++],
191                  ORTE_PRINT_NAME_ARGS_MAX_SIZE,
192                  "[%lu,%lu]", tmp1, tmp2);
193     }
194     return ptr->buffers[ptr->cntr-1];
195 }
196 
orte_util_print_job_family(const orte_jobid_t job)197 char* orte_util_print_job_family(const orte_jobid_t job)
198 {
199     orte_print_args_buffers_t *ptr;
200     unsigned long tmp1;
201 
202     ptr = get_print_name_buffer();
203 
204     if (NULL == ptr) {
205         ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
206         return orte_print_args_null;
207     }
208 
209     /* cycle around the ring */
210     if (ORTE_PRINT_NAME_ARG_NUM_BUFS == ptr->cntr) {
211         ptr->cntr = 0;
212     }
213 
214     if (ORTE_JOBID_INVALID == job) {
215         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "INVALID");
216     } else if (ORTE_JOBID_WILDCARD == job) {
217         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "WILDCARD");
218     } else {
219         tmp1 = ORTE_JOB_FAMILY((unsigned long)job);
220         snprintf(ptr->buffers[ptr->cntr++],
221                  ORTE_PRINT_NAME_ARGS_MAX_SIZE,
222                  "%lu", tmp1);
223     }
224     return ptr->buffers[ptr->cntr-1];
225 }
226 
orte_util_print_local_jobid(const orte_jobid_t job)227 char* orte_util_print_local_jobid(const orte_jobid_t job)
228 {
229     orte_print_args_buffers_t *ptr;
230     unsigned long tmp1;
231 
232     ptr = get_print_name_buffer();
233 
234     if (NULL == ptr) {
235         ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
236         return orte_print_args_null;
237     }
238 
239     /* cycle around the ring */
240     if (ORTE_PRINT_NAME_ARG_NUM_BUFS == ptr->cntr) {
241         ptr->cntr = 0;
242     }
243 
244     if (ORTE_JOBID_INVALID == job) {
245         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "INVALID");
246     } else if (ORTE_JOBID_WILDCARD == job) {
247         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "WILDCARD");
248     } else {
249         tmp1 = (unsigned long)job & 0x0000ffff;
250         snprintf(ptr->buffers[ptr->cntr++],
251                  ORTE_PRINT_NAME_ARGS_MAX_SIZE,
252                  "%lu", tmp1);
253     }
254     return ptr->buffers[ptr->cntr-1];
255 }
256 
orte_util_print_vpids(const orte_vpid_t vpid)257 char* orte_util_print_vpids(const orte_vpid_t vpid)
258 {
259     orte_print_args_buffers_t *ptr;
260 
261     ptr = get_print_name_buffer();
262 
263     if (NULL == ptr) {
264         ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
265         return orte_print_args_null;
266     }
267 
268     /* cycle around the ring */
269     if (ORTE_PRINT_NAME_ARG_NUM_BUFS == ptr->cntr) {
270         ptr->cntr = 0;
271     }
272 
273     if (ORTE_VPID_INVALID == vpid) {
274         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "INVALID");
275     } else if (ORTE_VPID_WILDCARD == vpid) {
276         snprintf(ptr->buffers[ptr->cntr++], ORTE_PRINT_NAME_ARGS_MAX_SIZE, "WILDCARD");
277     } else {
278         snprintf(ptr->buffers[ptr->cntr++],
279                  ORTE_PRINT_NAME_ARGS_MAX_SIZE,
280                  "%ld", (long)vpid);
281     }
282     return ptr->buffers[ptr->cntr-1];
283 }
284 
285 
286 
287 /***   STRING FUNCTIONS   ***/
288 
orte_util_snprintf_jobid(char * jobid_string,size_t size,const orte_jobid_t jobid)289 int orte_util_snprintf_jobid(char *jobid_string, size_t size, const orte_jobid_t jobid)
290 {
291     int rc;
292 
293     /* check for wildcard value - handle appropriately */
294     if (ORTE_JOBID_WILDCARD == jobid) {
295         (void)strncpy(jobid_string, ORTE_SCHEMA_WILDCARD_STRING, size);
296     } else {
297         rc = snprintf(jobid_string, size, "%ld", (long) jobid);
298         if (0 > rc) {
299             return ORTE_ERROR;
300         }
301     }
302 
303     return ORTE_SUCCESS;
304 }
305 
orte_util_convert_jobid_to_string(char ** jobid_string,const orte_jobid_t jobid)306 int orte_util_convert_jobid_to_string(char **jobid_string, const orte_jobid_t jobid)
307 {
308     int rc;
309     char str[256];
310     rc = orte_util_snprintf_jobid(str, 255, jobid);
311     if (0 > rc) {
312         *jobid_string = NULL;
313         return rc;
314     }
315     *jobid_string = strdup(str);
316     if (NULL == *jobid_string) {
317         ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
318         return ORTE_ERR_OUT_OF_RESOURCE;
319     }
320     return ORTE_SUCCESS;
321 }
322 
323 
orte_util_convert_string_to_jobid(orte_jobid_t * jobid,const char * jobidstring)324 int orte_util_convert_string_to_jobid(orte_jobid_t *jobid, const char* jobidstring)
325 {
326     if (NULL == jobidstring) {  /* got an error */
327         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
328         *jobid = ORTE_JOBID_INVALID;
329         return ORTE_ERR_BAD_PARAM;
330     }
331 
332     /** check for wildcard character - handle appropriately */
333     if (0 == strcmp(ORTE_SCHEMA_WILDCARD_STRING, jobidstring)) {
334         *jobid = ORTE_JOBID_WILDCARD;
335         return ORTE_SUCCESS;
336     }
337 
338     /* check for invalid value */
339     if (0 == strcmp(ORTE_SCHEMA_INVALID_STRING, jobidstring)) {
340         *jobid = ORTE_JOBID_INVALID;
341         return ORTE_SUCCESS;
342     }
343 
344     *jobid = strtoul(jobidstring, NULL, 10);
345 
346     return ORTE_SUCCESS;
347 }
348 
orte_util_convert_vpid_to_string(char ** vpid_string,const orte_vpid_t vpid)349 int orte_util_convert_vpid_to_string(char **vpid_string, const orte_vpid_t vpid)
350 {
351     /* check for wildcard value - handle appropriately */
352     if (ORTE_VPID_WILDCARD == vpid) {
353         *vpid_string = strdup(ORTE_SCHEMA_WILDCARD_STRING);
354         return ORTE_SUCCESS;
355     }
356 
357     /* check for invalid value - handle appropriately */
358     if (ORTE_VPID_INVALID == vpid) {
359         *vpid_string = strdup(ORTE_SCHEMA_INVALID_STRING);
360         return ORTE_SUCCESS;
361     }
362 
363     if (0 > asprintf(vpid_string, "%ld", (long) vpid)) {
364         ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
365         return ORTE_ERR_OUT_OF_RESOURCE;
366     }
367 
368     return ORTE_SUCCESS;
369 }
370 
371 
orte_util_convert_string_to_vpid(orte_vpid_t * vpid,const char * vpidstring)372 int orte_util_convert_string_to_vpid(orte_vpid_t *vpid, const char* vpidstring)
373 {
374     if (NULL == vpidstring) {  /* got an error */
375         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
376         *vpid = ORTE_VPID_INVALID;
377         return ORTE_ERR_BAD_PARAM;
378     }
379 
380     /** check for wildcard character - handle appropriately */
381     if (0 == strcmp(ORTE_SCHEMA_WILDCARD_STRING, vpidstring)) {
382         *vpid = ORTE_VPID_WILDCARD;
383         return ORTE_SUCCESS;
384     }
385 
386     /* check for invalid value */
387     if (0 == strcmp(ORTE_SCHEMA_INVALID_STRING, vpidstring)) {
388         *vpid = ORTE_VPID_INVALID;
389         return ORTE_SUCCESS;
390     }
391 
392     *vpid = strtol(vpidstring, NULL, 10);
393 
394     return ORTE_SUCCESS;
395 }
396 
orte_util_convert_string_to_process_name(orte_process_name_t * name,const char * name_string)397 int orte_util_convert_string_to_process_name(orte_process_name_t *name,
398                                              const char* name_string)
399 {
400     char *temp, *token;
401     orte_jobid_t job;
402     orte_vpid_t vpid;
403     int return_code=ORTE_SUCCESS;
404 
405     /* set default */
406     name->jobid = ORTE_JOBID_INVALID;
407     name->vpid = ORTE_VPID_INVALID;
408 
409     /* check for NULL string - error */
410     if (NULL == name_string) {
411         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
412         return ORTE_ERR_BAD_PARAM;
413     }
414 
415     temp = strdup(name_string);  /** copy input string as the strtok process is destructive */
416     token = strchr(temp, ORTE_SCHEMA_DELIMITER_CHAR); /** get first field -> jobid */
417 
418     /* check for error */
419     if (NULL == token) {
420         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
421         free(temp);
422         return ORTE_ERR_BAD_PARAM;
423     }
424     *token = '\0';
425     token++;
426 
427     /* check for WILDCARD character - assign
428      * value accordingly, if found
429      */
430     if (0 == strcmp(temp, ORTE_SCHEMA_WILDCARD_STRING)) {
431         job = ORTE_JOBID_WILDCARD;
432     } else if (0 == strcmp(temp, ORTE_SCHEMA_INVALID_STRING)) {
433         job = ORTE_JOBID_INVALID;
434     } else {
435         job = strtoul(temp, NULL, 10);
436     }
437 
438     /* check for WILDCARD character - assign
439      * value accordingly, if found
440      */
441     if (0 == strcmp(token, ORTE_SCHEMA_WILDCARD_STRING)) {
442         vpid = ORTE_VPID_WILDCARD;
443     } else if (0 == strcmp(token, ORTE_SCHEMA_INVALID_STRING)) {
444         vpid = ORTE_VPID_INVALID;
445     } else {
446         vpid = strtoul(token, NULL, 10);
447     }
448 
449     name->jobid = job;
450     name->vpid = vpid;
451 
452     free(temp);
453 
454     return return_code;
455 }
456 
orte_util_convert_process_name_to_string(char ** name_string,const orte_process_name_t * name)457 int orte_util_convert_process_name_to_string(char **name_string,
458                                              const orte_process_name_t* name)
459 {
460     char *tmp, *tmp2;
461 
462     if (NULL == name) { /* got an error */
463         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
464         return ORTE_ERR_BAD_PARAM;
465     }
466 
467     /* check for wildcard and invalid values - where encountered, insert the
468      * corresponding string so we can correctly parse the name string when
469      * it is passed back to us later
470      */
471     if (ORTE_JOBID_WILDCARD == name->jobid) {
472         asprintf(&tmp, "%s", ORTE_SCHEMA_WILDCARD_STRING);
473     } else if (ORTE_JOBID_INVALID == name->jobid) {
474         asprintf(&tmp, "%s", ORTE_SCHEMA_INVALID_STRING);
475     } else {
476         asprintf(&tmp, "%lu", (unsigned long)name->jobid);
477     }
478 
479     if (ORTE_VPID_WILDCARD == name->vpid) {
480         asprintf(&tmp2, "%s%c%s", tmp, ORTE_SCHEMA_DELIMITER_CHAR, ORTE_SCHEMA_WILDCARD_STRING);
481     } else if (ORTE_VPID_INVALID == name->vpid) {
482         asprintf(&tmp2, "%s%c%s", tmp, ORTE_SCHEMA_DELIMITER_CHAR, ORTE_SCHEMA_INVALID_STRING);
483     } else {
484         asprintf(&tmp2, "%s%c%lu", tmp, ORTE_SCHEMA_DELIMITER_CHAR, (unsigned long)name->vpid);
485     }
486 
487     asprintf(name_string, "%s", tmp2);
488 
489     free(tmp);
490     free(tmp2);
491 
492     return ORTE_SUCCESS;
493 }
494 
495 
496 /****    CREATE PROCESS NAME    ****/
orte_util_create_process_name(orte_process_name_t ** name,orte_jobid_t job,orte_vpid_t vpid)497 int orte_util_create_process_name(orte_process_name_t **name,
498                                   orte_jobid_t job,
499                                   orte_vpid_t vpid
500                                   )
501 {
502     *name = NULL;
503 
504     *name = (orte_process_name_t*)malloc(sizeof(orte_process_name_t));
505     if (NULL == *name) { /* got an error */
506         ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
507         return ORTE_ERR_OUT_OF_RESOURCE;
508     }
509 
510     (*name)->jobid = job;
511     (*name)->vpid = vpid;
512 
513     return ORTE_SUCCESS;
514 }
515 
516 /****    COMPARE NAME FIELDS     ****/
orte_util_compare_name_fields(orte_ns_cmp_bitmask_t fields,const orte_process_name_t * name1,const orte_process_name_t * name2)517 int orte_util_compare_name_fields(orte_ns_cmp_bitmask_t fields,
518                                   const orte_process_name_t* name1,
519                                   const orte_process_name_t* name2)
520 {
521     /* handle the NULL pointer case */
522     if (NULL == name1 && NULL == name2) {
523         return OPAL_EQUAL;
524     } else if (NULL == name1) {
525         return OPAL_VALUE2_GREATER;
526     } else if (NULL == name2) {
527         return OPAL_VALUE1_GREATER;
528     }
529 
530     /* in this comparison function, we check for exact equalities.
531      * In the case of wildcards, we check to ensure that the fields
532      * actually match those values - thus, a "wildcard" in this
533      * function does not actually stand for a wildcard value, but
534      * rather a specific value - UNLESS the CMP_WILD bitmask value
535      * is set
536      */
537 
538     /* check job id */
539     if (ORTE_NS_CMP_JOBID & fields) {
540         if (ORTE_NS_CMP_WILD & fields &&
541             (ORTE_JOBID_WILDCARD == name1->jobid ||
542              ORTE_JOBID_WILDCARD == name2->jobid)) {
543             goto check_vpid;
544         }
545         if (name1->jobid < name2->jobid) {
546             return OPAL_VALUE2_GREATER;
547         } else if (name1->jobid > name2->jobid) {
548             return OPAL_VALUE1_GREATER;
549         }
550     }
551 
552     /* get here if jobid's are equal, or not being checked
553      * now check vpid
554      */
555  check_vpid:
556     if (ORTE_NS_CMP_VPID & fields) {
557         if (ORTE_NS_CMP_WILD & fields &&
558             (ORTE_VPID_WILDCARD == name1->vpid ||
559              ORTE_VPID_WILDCARD == name2->vpid)) {
560             return OPAL_EQUAL;
561         }
562         if (name1->vpid < name2->vpid) {
563             return OPAL_VALUE2_GREATER;
564         } else if (name1->vpid > name2->vpid) {
565             return OPAL_VALUE1_GREATER;
566         }
567     }
568 
569     /* only way to get here is if all fields are being checked and are equal,
570     * or jobid not checked, but vpid equal,
571     * only vpid being checked, and equal
572     * return that fact
573     */
574     return OPAL_EQUAL;
575 }
576 
577 /* hash a vpid based on Robert Jenkin's algorithm - note
578  * that the precise values of the constants in the algo are
579  * irrelevant.
580  */
orte_util_hash_vpid(orte_vpid_t vpid)581 uint32_t  orte_util_hash_vpid(orte_vpid_t vpid) {
582     uint32_t hash;
583 
584     hash = vpid;
585     hash = (hash + 0x7ed55d16) + (hash<<12);
586     hash = (hash ^ 0xc761c23c) ^ (hash>>19);
587     hash = (hash + 0x165667b1) + (hash<<5);
588     hash = (hash + 0xd3a2646c) ^ (hash<<9);
589     hash = (hash + 0xfd7046c5) + (hash<<3);
590     hash = (hash ^ 0xb55a4f09) ^ (hash>>16);
591     return hash;
592 }
593 
594 /* sysinfo conversion to and from string */
orte_util_convert_string_to_sysinfo(char ** cpu_type,char ** cpu_model,const char * sysinfo_string)595 int orte_util_convert_string_to_sysinfo(char **cpu_type, char **cpu_model,
596 					const char* sysinfo_string)
597 {
598     char *temp, *token;
599     int return_code=ORTE_SUCCESS;
600 
601     /* check for NULL string - error */
602     if (NULL == sysinfo_string) {
603         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
604         return ORTE_ERR_BAD_PARAM;
605     }
606 
607     temp = strdup(sysinfo_string);  /** copy input string as the strtok process is destructive */
608     token = strchr(temp, ORTE_SCHEMA_DELIMITER_CHAR); /** get first field -> cpu_type */
609 
610     /* check for error */
611     if (NULL == token) {
612         free(temp);
613         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
614         return ORTE_ERR_BAD_PARAM;
615     }
616     *token = '\0';
617     token++;
618 
619     /* If type is a valid string get the value otherwise leave cpu_type untouched.
620      */
621     if (0 != strcmp(temp, ORTE_SCHEMA_INVALID_STRING)) {
622         *cpu_type = strdup(temp);
623     }
624 
625     /* If type is a valid string get the value otherwise leave cpu_type untouched.
626      */
627     if (0 != strcmp(token, ORTE_SCHEMA_INVALID_STRING)) {
628         *cpu_model = strdup(token);
629     }
630 
631     free(temp);
632 
633     return return_code;
634 }
635 
orte_util_convert_sysinfo_to_string(char ** sysinfo_string,const char * cpu_type,const char * cpu_model)636 int orte_util_convert_sysinfo_to_string(char **sysinfo_string,
637 					const char *cpu_type, const char *cpu_model)
638 {
639     char *tmp;
640 
641     /* check for no sysinfo values (like empty cpu_type) - where encountered, insert the
642      * invalid string so we can correctly parse the name string when
643      * it is passed back to us later
644      */
645     if (NULL == cpu_type) {
646         asprintf(&tmp, "%s", ORTE_SCHEMA_INVALID_STRING);
647     } else {
648         asprintf(&tmp, "%s", cpu_type);
649     }
650 
651     if (NULL == cpu_model) {
652         asprintf(sysinfo_string, "%s%c%s", tmp, ORTE_SCHEMA_DELIMITER_CHAR, ORTE_SCHEMA_INVALID_STRING);
653     } else {
654         asprintf(sysinfo_string, "%s%c%s", tmp, ORTE_SCHEMA_DELIMITER_CHAR, cpu_model);
655     }
656     free(tmp);
657     return ORTE_SUCCESS;
658 }
659 
orte_pretty_print_timing(int64_t secs,int64_t usecs)660 char *orte_pretty_print_timing(int64_t secs, int64_t usecs)
661 {
662     unsigned long minutes, seconds;
663     float fsecs;
664     char *timestring;
665 
666     seconds = secs + (usecs / 1000000l);
667     minutes = seconds / 60l;
668     seconds = seconds % 60l;
669     if (0 == minutes && 0 == seconds) {
670         fsecs = ((float)(secs)*1000000.0 + (float)usecs) / 1000.0;
671         asprintf(&timestring, "%8.2f millisecs", fsecs);
672     } else {
673         asprintf(&timestring, "%3lu:%02lu min:sec", minutes, seconds);
674     }
675 
676     return timestring;
677 }
678 
679 
680