This source file includes following definitions.
- clf_constructor
- clf_destructor
- process_repository_item
- file_exists
- pmix_mca_base_component_repository_add
- pmix_mca_base_component_repository_init
- pmix_mca_base_component_repository_get_components
- pmix_mca_base_component_repository_release_internal
- find_component
- pmix_mca_base_component_repository_release
- pmix_mca_base_component_repository_retain_component
- pmix_mca_base_component_repository_open
- pmix_mca_base_component_repository_finalize
- ri_constructor
- ri_destructor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <src/include/pmix_config.h>
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
30 #endif
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include "src/class/pmix_list.h"
39 #include "src/mca/mca.h"
40 #include "src/mca/base/base.h"
41 #include "src/mca/base/pmix_mca_base_component_repository.h"
42 #include "src/mca/pdl/base/base.h"
43 #include "pmix_common.h"
44 #include "src/class/pmix_hash_table.h"
45 #include "src/util/basename.h"
46 #include "src/util/show_help.h"
47
48 #if PMIX_HAVE_PDL_SUPPORT
49
50
51
52
53 static void ri_constructor(pmix_mca_base_component_repository_item_t *ri);
54 static void ri_destructor(pmix_mca_base_component_repository_item_t *ri);
55 PMIX_CLASS_INSTANCE(pmix_mca_base_component_repository_item_t, pmix_list_item_t,
56 ri_constructor, ri_destructor);
57
58 #endif
59
60 static void clf_constructor(pmix_object_t *obj)
61 {
62 pmix_mca_base_failed_component_t *cli = (pmix_mca_base_failed_component_t *) obj;
63 cli->comp = NULL;
64 cli->error_msg = NULL;
65 }
66
67 static void clf_destructor(pmix_object_t *obj)
68 {
69 pmix_mca_base_failed_component_t *cli = (pmix_mca_base_failed_component_t *) obj;
70 cli->comp = NULL;
71 if( NULL != cli->error_msg ) {
72 free(cli->error_msg);
73 cli->error_msg = NULL;
74 }
75 }
76
77 PMIX_CLASS_INSTANCE(pmix_mca_base_failed_component_t, pmix_list_item_t,
78 clf_constructor, clf_destructor);
79
80
81
82
83
84 static bool initialized = false;
85
86
87 #if PMIX_HAVE_PDL_SUPPORT
88
89 static pmix_hash_table_t pmix_mca_base_component_repository;
90
91
92 #define STRINGIFYX(x) #x
93 #define STRINGIFY(x) STRINGIFYX(x)
94
95 static int process_repository_item (const char *filename, void *data)
96 {
97 char name[PMIX_MCA_BASE_MAX_COMPONENT_NAME_LEN + 1];
98 char type[PMIX_MCA_BASE_MAX_TYPE_NAME_LEN + 1];
99 pmix_mca_base_component_repository_item_t *ri;
100 pmix_list_t *component_list;
101 char *base;
102 int ret;
103
104 base = pmix_basename (filename);
105 if (NULL == base) {
106 return PMIX_ERROR;
107 }
108
109
110 if (0 != strncmp (base, "mca_", 4)) {
111 free (base);
112 return PMIX_SUCCESS;
113 }
114
115
116
117 ret = sscanf(base, "mca_%" STRINGIFY(PMIX_MCA_BASE_MAX_TYPE_NAME_LEN) "[^_]_%"
118 STRINGIFY(PMIX_MCA_BASE_MAX_COMPONENT_NAME_LEN) "s", type, name);
119 if (0 > ret) {
120
121 free(base);
122 return PMIX_SUCCESS;
123 }
124
125
126 ret = pmix_hash_table_get_value_ptr(&pmix_mca_base_component_repository, type,
127 strlen (type), (void **) &component_list);
128 if (PMIX_SUCCESS != ret) {
129 component_list = PMIX_NEW(pmix_list_t);
130 if (NULL == component_list) {
131 free (base);
132
133 return PMIX_ERR_OUT_OF_RESOURCE;
134 }
135
136 ret = pmix_hash_table_set_value_ptr(&pmix_mca_base_component_repository, type,
137 strlen (type), (void *) component_list);
138 if (PMIX_SUCCESS != ret) {
139 free (base);
140 PMIX_RELEASE(component_list);
141 return ret;
142 }
143 }
144
145
146 PMIX_LIST_FOREACH(ri, component_list, pmix_mca_base_component_repository_item_t) {
147 if (0 == strcmp (ri->ri_name, name)) {
148
149 free (base);
150 return PMIX_SUCCESS;
151 }
152 }
153
154 ri = PMIX_NEW(pmix_mca_base_component_repository_item_t);
155 if (NULL == ri) {
156 free (base);
157 return PMIX_ERR_OUT_OF_RESOURCE;
158 }
159
160 ri->ri_base = base;
161
162 ri->ri_path = strdup (filename);
163 if (NULL == ri->ri_path) {
164 PMIX_RELEASE(ri);
165 return PMIX_ERR_OUT_OF_RESOURCE;
166 }
167
168
169 ri->ri_type[PMIX_MCA_BASE_MAX_TYPE_NAME_LEN] = '\0';
170 pmix_strncpy (ri->ri_type, type, PMIX_MCA_BASE_MAX_TYPE_NAME_LEN);
171
172 ri->ri_name[PMIX_MCA_BASE_MAX_TYPE_NAME_LEN] = '\0';
173 pmix_strncpy (ri->ri_name, name, PMIX_MCA_BASE_MAX_COMPONENT_NAME_LEN);
174
175 pmix_list_append (component_list, &ri->super);
176
177 return PMIX_SUCCESS;
178 }
179
180 static int file_exists(const char *filename, const char *ext)
181 {
182 char *final;
183 int ret;
184
185 if (NULL == ext) {
186 return access (filename, F_OK) == 0;
187 }
188
189 ret = asprintf(&final, "%s.%s", filename, ext);
190 if (0 > ret || NULL == final) {
191 return 0;
192 }
193
194 ret = access (final, F_OK);
195 free(final);
196 return (0 == ret);
197 }
198
199 #endif
200
201 int pmix_mca_base_component_repository_add (const char *path)
202 {
203 #if PMIX_HAVE_PDL_SUPPORT
204 char *path_to_use = NULL, *dir, *ctx;
205 const char sep[] = {PMIX_ENV_SEP, '\0'};
206
207 if (NULL == path) {
208
209 return PMIX_SUCCESS;
210 }
211
212 path_to_use = strdup (path);
213
214 dir = strtok_r (path_to_use, sep, &ctx);
215 do {
216 if ((0 == strcmp(dir, "USER_DEFAULT") || 0 == strcmp(dir, "USR_DEFAULT"))
217 && NULL != pmix_mca_base_user_default_path) {
218 dir = pmix_mca_base_user_default_path;
219 } else if (0 == strcmp(dir, "SYS_DEFAULT") ||
220 0 == strcmp(dir, "SYSTEM_DEFAULT")) {
221 dir = pmix_mca_base_system_default_path;
222 }
223
224 if (0 != pmix_pdl_foreachfile(dir, process_repository_item, NULL) &&
225 !(0 == strcmp(dir, pmix_mca_base_system_default_path) || 0 == strcmp(dir, pmix_mca_base_user_default_path))) {
226
227
228
229 pmix_show_help("help-pmix-mca-base.txt",
230 "failed to add component dir", true, dir);
231 }
232 } while (NULL != (dir = strtok_r (NULL, sep, &ctx)));
233
234 free (path_to_use);
235
236 #endif
237
238 return PMIX_SUCCESS;
239 }
240
241
242
243
244
245 int pmix_mca_base_component_repository_init(void)
246 {
247
248
249 if (!initialized) {
250 #if PMIX_HAVE_PDL_SUPPORT
251
252
253 int ret = pmix_mca_base_framework_open(&pmix_pdl_base_framework, 0);
254 if (PMIX_SUCCESS != ret) {
255 pmix_output(0, "%s %d:%s failed -- process will likely abort (open the dl framework returned %d instead of PMIX_SUCCESS)\n",
256 __FILE__, __LINE__, __func__, ret);
257 return ret;
258 }
259 pmix_pdl_base_select();
260
261 PMIX_CONSTRUCT(&pmix_mca_base_component_repository, pmix_hash_table_t);
262 ret = pmix_hash_table_init (&pmix_mca_base_component_repository, 128);
263 if (PMIX_SUCCESS != ret) {
264 (void) pmix_mca_base_framework_close(&pmix_pdl_base_framework);
265 return ret;
266 }
267
268 ret = pmix_mca_base_component_repository_add(pmix_mca_base_component_path);
269 if (PMIX_SUCCESS != ret) {
270 PMIX_DESTRUCT(&pmix_mca_base_component_repository);
271 (void) pmix_mca_base_framework_close(&pmix_pdl_base_framework);
272 return ret;
273 }
274 #endif
275
276 initialized = true;
277 }
278
279
280
281 return PMIX_SUCCESS;
282 }
283
284 int pmix_mca_base_component_repository_get_components (pmix_mca_base_framework_t *framework,
285 pmix_list_t **framework_components)
286 {
287 *framework_components = NULL;
288 #if PMIX_HAVE_PDL_SUPPORT
289 return pmix_hash_table_get_value_ptr (&pmix_mca_base_component_repository, framework->framework_name,
290 strlen (framework->framework_name), (void **) framework_components);
291 #endif
292 return PMIX_ERR_NOT_FOUND;
293 }
294
295 #if PMIX_HAVE_PDL_SUPPORT
296 static void pmix_mca_base_component_repository_release_internal(pmix_mca_base_component_repository_item_t *ri) {
297 int group_id;
298
299 group_id = pmix_mca_base_var_group_find (NULL, ri->ri_type, ri->ri_name);
300 if (0 <= group_id) {
301
302 pmix_mca_base_var_group_deregister (group_id);
303 }
304
305
306 if (ri->ri_dlhandle) {
307 pmix_pdl_close(ri->ri_dlhandle);
308 ri->ri_dlhandle = NULL;
309 }
310 }
311 #endif
312
313 #if PMIX_HAVE_PDL_SUPPORT
314 static pmix_mca_base_component_repository_item_t *find_component(const char *type, const char *name)
315 {
316 pmix_mca_base_component_repository_item_t *ri;
317 pmix_list_t *component_list;
318 int ret;
319
320 ret = pmix_hash_table_get_value_ptr (&pmix_mca_base_component_repository, type,
321 strlen (type), (void **) &component_list);
322 if (PMIX_SUCCESS != ret) {
323
324 return NULL;
325 }
326
327 PMIX_LIST_FOREACH(ri, component_list, pmix_mca_base_component_repository_item_t) {
328 if (0 == strcmp (ri->ri_name, name)) {
329 return ri;
330 }
331 }
332
333 return NULL;
334 }
335 #endif
336
337 void pmix_mca_base_component_repository_release(const pmix_mca_base_component_t *component)
338 {
339 #if PMIX_HAVE_PDL_SUPPORT
340 pmix_mca_base_component_repository_item_t *ri;
341
342 ri = find_component (component->pmix_mca_type_name, component->pmix_mca_component_name);
343 if (NULL != ri && !(--ri->ri_refcnt)) {
344 pmix_mca_base_component_repository_release_internal (ri);
345 }
346 #endif
347 }
348
349 int pmix_mca_base_component_repository_retain_component(const char *type, const char *name)
350 {
351 #if PMIX_HAVE_PDL_SUPPORT
352 pmix_mca_base_component_repository_item_t *ri = find_component(type, name);
353
354 if (NULL != ri) {
355 ++ri->ri_refcnt;
356 return PMIX_SUCCESS;
357 }
358
359 return PMIX_ERR_NOT_FOUND;
360 #else
361 return PMIX_ERR_NOT_SUPPORTED;
362 #endif
363 }
364
365 int pmix_mca_base_component_repository_open(pmix_mca_base_framework_t *framework,
366 pmix_mca_base_component_repository_item_t *ri)
367 {
368 #if PMIX_HAVE_PDL_SUPPORT
369 pmix_mca_base_component_t *component_struct;
370 pmix_mca_base_component_list_item_t *mitem = NULL;
371 char *struct_name = NULL;
372 int vl, ret;
373
374 pmix_output_verbose(PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix_mca_base_component_repository_open: examining dynamic "
375 "%s MCA component \"%s\" at path %s", ri->ri_type, ri->ri_name, ri->ri_path);
376
377 vl = pmix_mca_base_component_show_load_errors ? PMIX_MCA_BASE_VERBOSE_ERROR : PMIX_MCA_BASE_VERBOSE_INFO;
378
379
380
381
382
383
384
385 PMIX_LIST_FOREACH(mitem, &framework->framework_components, pmix_mca_base_component_list_item_t) {
386 if (0 == strcmp(mitem->cli_component->pmix_mca_component_name, ri->ri_name)) {
387 pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix_mca_base_component_repository_open: already loaded (ignored)");
388 return PMIX_ERR_BAD_PARAM;
389 }
390 }
391
392
393 mitem = NULL;
394
395 if (NULL != ri->ri_dlhandle) {
396 pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix_mca_base_component_repository_open: already loaded. returning cached component");
397 mitem = PMIX_NEW(pmix_mca_base_component_list_item_t);
398 if (NULL == mitem) {
399 return PMIX_ERR_OUT_OF_RESOURCE;
400 }
401
402 mitem->cli_component = ri->ri_component_struct;
403 pmix_list_append (&framework->framework_components, &mitem->super);
404
405 return PMIX_SUCCESS;
406 }
407
408 if (0 != strcmp (ri->ri_type, framework->framework_name)) {
409
410
411
412 assert (0);
413 return PMIX_ERR_NOT_SUPPORTED;
414 }
415
416
417
418 char *err_msg = NULL;
419 if (PMIX_SUCCESS != pmix_pdl_open(ri->ri_path, true, false, &ri->ri_dlhandle, &err_msg)) {
420 if (NULL == err_msg) {
421 err_msg = "pmix_dl_open() error message was NULL!";
422 }
423
424
425
426
427
428
429 if (0 == strcasecmp("file not found", err_msg) &&
430 (file_exists(ri->ri_path, "lo") ||
431 file_exists(ri->ri_path, "so") ||
432 file_exists(ri->ri_path, "dylib") ||
433 file_exists(ri->ri_path, "dll"))) {
434 err_msg = "perhaps a missing symbol, or compiled for a different version of Open MPI?";
435 }
436 pmix_output_verbose(vl, 0, "pmix_mca_base_component_repository_open: unable to open %s: %s (ignored)",
437 ri->ri_base, err_msg);
438
439 if( pmix_mca_base_component_track_load_errors ) {
440 pmix_mca_base_failed_component_t *f_comp = PMIX_NEW(pmix_mca_base_failed_component_t);
441 f_comp->comp = ri;
442 if (0 > asprintf(&(f_comp->error_msg), "%s", err_msg)) {
443 PMIX_RELEASE(f_comp);
444 return PMIX_ERR_BAD_PARAM;
445 }
446 pmix_list_append(&framework->framework_failed_components, &f_comp->super);
447 }
448
449 return PMIX_ERR_BAD_PARAM;
450 }
451
452
453
454
455 do {
456 ret = asprintf (&struct_name, "mca_%s_%s_component", ri->ri_type, ri->ri_name);
457 if (0 > ret) {
458 ret = PMIX_ERR_OUT_OF_RESOURCE;
459 break;
460 }
461
462 mitem = PMIX_NEW(pmix_mca_base_component_list_item_t);
463 if (NULL == mitem) {
464 ret = PMIX_ERR_OUT_OF_RESOURCE;
465 break;
466 }
467
468 err_msg = NULL;
469 ret = pmix_pdl_lookup(ri->ri_dlhandle, struct_name, (void**) &component_struct, &err_msg);
470 if (PMIX_SUCCESS != ret || NULL == component_struct) {
471 if (NULL == err_msg) {
472 err_msg = "pmix_dl_loookup() error message was NULL!";
473 }
474 pmix_output_verbose(vl, 0, "pmix_mca_base_component_repository_open: \"%s\" does not appear to be a valid "
475 "%s MCA dynamic component (ignored): %s. ret %d", ri->ri_base, ri->ri_type, err_msg, ret);
476
477 ret = PMIX_ERR_BAD_PARAM;
478 break;
479 }
480
481
482 free (struct_name);
483 struct_name = NULL;
484
485
486
487 if (!(PMIX_MCA_BASE_VERSION_MAJOR == component_struct->pmix_mca_major_version &&
488 PMIX_MCA_BASE_VERSION_MINOR == component_struct->pmix_mca_minor_version)) {
489 pmix_output_verbose(vl, 0, "pmix_mca_base_component_repository_open: %s \"%s\" uses an MCA interface that is "
490 "not recognized (component MCA v%d.%d.%d != supported MCA v%d.%d.%d) -- ignored",
491 ri->ri_type, ri->ri_path, component_struct->pmix_mca_major_version,
492 component_struct->pmix_mca_minor_version, component_struct->pmix_mca_release_version,
493 PMIX_MCA_BASE_VERSION_MAJOR, PMIX_MCA_BASE_VERSION_MINOR, PMIX_MCA_BASE_VERSION_RELEASE);
494 ret = PMIX_ERR_BAD_PARAM;
495 break;
496 }
497
498
499
500 if (0 != strcmp(component_struct->pmix_mca_type_name, ri->ri_type) ||
501 0 != strcmp(component_struct->pmix_mca_component_name, ri->ri_name)) {
502 pmix_output_verbose(vl, 0, "Component file data does not match filename: %s (%s / %s) != %s %s -- ignored",
503 ri->ri_path, ri->ri_type, ri->ri_name,
504 component_struct->pmix_mca_type_name,
505 component_struct->pmix_mca_component_name);
506 ret = PMIX_ERR_BAD_PARAM;
507 break;
508 }
509
510
511
512
513 ri->ri_component_struct = mitem->cli_component = component_struct;
514 ri->ri_refcnt = 1;
515 pmix_list_append(&framework->framework_components, &mitem->super);
516
517 pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix_mca_base_component_repository_open: opened dynamic %s MCA "
518 "component \"%s\"", ri->ri_type, ri->ri_name);
519
520 return PMIX_SUCCESS;
521 } while (0);
522
523 if (mitem) {
524 PMIX_RELEASE(mitem);
525 }
526
527 if (struct_name) {
528 free (struct_name);
529 }
530
531 pmix_pdl_close (ri->ri_dlhandle);
532 ri->ri_dlhandle = NULL;
533
534 return ret;
535 #else
536
537
538 return PMIX_ERR_NOT_SUPPORTED;
539 #endif
540 }
541
542
543
544
545 void pmix_mca_base_component_repository_finalize(void)
546 {
547 if (!initialized) {
548 return;
549 }
550
551 initialized = false;
552
553 #if PMIX_HAVE_PDL_SUPPORT
554 pmix_list_t *component_list;
555 void *node, *key;
556 size_t key_size;
557 int ret;
558
559 ret = pmix_hash_table_get_first_key_ptr (&pmix_mca_base_component_repository, &key, &key_size,
560 (void **) &component_list, &node);
561 while (PMIX_SUCCESS == ret) {
562 PMIX_LIST_RELEASE(component_list);
563 ret = pmix_hash_table_get_next_key_ptr (&pmix_mca_base_component_repository, &key,
564 &key_size, (void **) &component_list,
565 node, &node);
566 }
567
568 (void) pmix_mca_base_framework_close(&pmix_pdl_base_framework);
569 PMIX_DESTRUCT(&pmix_mca_base_component_repository);
570 #endif
571 }
572
573 #if PMIX_HAVE_PDL_SUPPORT
574
575
576
577
578 static void ri_constructor (pmix_mca_base_component_repository_item_t *ri)
579 {
580 memset(ri->ri_type, 0, sizeof(ri->ri_type));
581 ri->ri_dlhandle = NULL;
582 ri->ri_component_struct = NULL;
583 ri->ri_path = NULL;
584 }
585
586
587
588
589
590 static void ri_destructor (pmix_mca_base_component_repository_item_t *ri)
591 {
592
593 pmix_mca_base_component_repository_release_internal (ri);
594
595
596
597
598
599
600 if (ri->ri_path) {
601 free (ri->ri_path);
602 }
603
604 if (ri->ri_base) {
605 free (ri->ri_base);
606 }
607 }
608
609 #endif