This source file includes following definitions.
- clf_constructor
- clf_destructor
- process_repository_item
- file_exists
- mca_base_component_repository_add
- mca_base_component_repository_init
- mca_base_component_repository_get_components
- mca_base_component_repository_release_internal
- find_component
- mca_base_component_repository_release
- mca_base_component_repository_retain_component
- mca_base_component_repository_open
- 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
28 #include "opal_config.h"
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
31 #endif
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38
39 #include "opal/class/opal_list.h"
40 #include "opal/mca/mca.h"
41 #include "opal/mca/base/base.h"
42 #include "opal/mca/base/mca_base_component_repository.h"
43 #include "opal/mca/dl/base/base.h"
44 #include "opal/constants.h"
45 #include "opal/class/opal_hash_table.h"
46 #include "opal/util/basename.h"
47 #include "opal/util/string_copy.h"
48 #include "opal/util/printf.h"
49
50 #if OPAL_HAVE_DL_SUPPORT
51
52
53
54
55 static void ri_constructor(mca_base_component_repository_item_t *ri);
56 static void ri_destructor(mca_base_component_repository_item_t *ri);
57 OBJ_CLASS_INSTANCE(mca_base_component_repository_item_t, opal_list_item_t,
58 ri_constructor, ri_destructor);
59
60 #endif
61
62 static void clf_constructor(opal_object_t *obj);
63 static void clf_destructor(opal_object_t *obj);
64
65 OBJ_CLASS_INSTANCE(mca_base_failed_component_t, opal_list_item_t,
66 clf_constructor, clf_destructor);
67
68
69 static void clf_constructor(opal_object_t *obj)
70 {
71 mca_base_failed_component_t *cli = (mca_base_failed_component_t *) obj;
72 cli->comp = NULL;
73 cli->error_msg = NULL;
74 }
75
76 static void clf_destructor(opal_object_t *obj)
77 {
78 mca_base_failed_component_t *cli = (mca_base_failed_component_t *) obj;
79 cli->comp = NULL;
80 if( NULL != cli->error_msg ) {
81 free(cli->error_msg);
82 cli->error_msg = NULL;
83 }
84 }
85
86
87
88
89 static bool initialized = false;
90
91
92 #if OPAL_HAVE_DL_SUPPORT
93
94 static opal_hash_table_t mca_base_component_repository;
95
96
97 #define STRINGIFYX(x) #x
98 #define STRINGIFY(x) STRINGIFYX(x)
99
100 static int process_repository_item (const char *filename, void *data)
101 {
102 char name[MCA_BASE_MAX_COMPONENT_NAME_LEN + 1];
103 char type[MCA_BASE_MAX_TYPE_NAME_LEN + 1];
104 mca_base_component_repository_item_t *ri;
105 opal_list_t *component_list;
106 char *base;
107 int ret;
108
109 base = opal_basename (filename);
110 if (NULL == base) {
111 return OPAL_ERROR;
112 }
113
114
115 if (0 != strncmp (base, "mca_", 4)) {
116 free (base);
117 return OPAL_SUCCESS;
118 }
119
120
121
122 ret = sscanf (base, "mca_%" STRINGIFY(MCA_BASE_MAX_TYPE_NAME_LEN) "[^_]_%"
123 STRINGIFY(MCA_BASE_MAX_COMPONENT_NAME_LEN) "s", type, name);
124 if (0 > ret) {
125
126 free(base);
127 return OPAL_SUCCESS;
128 }
129
130
131 ret = opal_hash_table_get_value_ptr (&mca_base_component_repository, type,
132 strlen (type), (void **) &component_list);
133 if (OPAL_SUCCESS != ret) {
134 component_list = OBJ_NEW(opal_list_t);
135 if (NULL == component_list) {
136 free (base);
137
138 return OPAL_ERR_OUT_OF_RESOURCE;
139 }
140
141 ret = opal_hash_table_set_value_ptr (&mca_base_component_repository, type,
142 strlen (type), (void *) component_list);
143 if (OPAL_SUCCESS != ret) {
144 free (base);
145 OBJ_RELEASE(component_list);
146 return ret;
147 }
148 }
149
150
151 OPAL_LIST_FOREACH(ri, component_list, mca_base_component_repository_item_t) {
152 if (0 == strcmp (ri->ri_name, name)) {
153
154 free (base);
155 return OPAL_SUCCESS;
156 }
157 }
158
159 ri = OBJ_NEW(mca_base_component_repository_item_t);
160 if (NULL == ri) {
161 free (base);
162 return OPAL_ERR_OUT_OF_RESOURCE;
163 }
164
165 ri->ri_base = base;
166
167 ri->ri_path = strdup (filename);
168 if (NULL == ri->ri_path) {
169 OBJ_RELEASE(ri);
170 return OPAL_ERR_OUT_OF_RESOURCE;
171 }
172
173 opal_string_copy (ri->ri_type, type, MCA_BASE_MAX_TYPE_NAME_LEN);
174 opal_string_copy (ri->ri_name, name, MCA_BASE_MAX_COMPONENT_NAME_LEN);
175
176 opal_list_append (component_list, &ri->super);
177
178 return OPAL_SUCCESS;
179 }
180
181 static int file_exists(const char *filename, const char *ext)
182 {
183 char *final;
184 int ret;
185
186 if (NULL == ext) {
187 return access (filename, F_OK) == 0;
188 }
189
190 ret = opal_asprintf(&final, "%s.%s", filename, ext);
191 if (0 > ret || NULL == final) {
192 return 0;
193 }
194
195 ret = access (final, F_OK);
196 free(final);
197 return (0 == ret);
198 }
199
200 #endif
201
202 int mca_base_component_repository_add (const char *path)
203 {
204 #if OPAL_HAVE_DL_SUPPORT
205 char *path_to_use = NULL, *dir, *ctx;
206 const char sep[] = {OPAL_ENV_SEP, '\0'};
207
208 if (NULL == path) {
209
210 return OPAL_SUCCESS;
211 }
212
213 path_to_use = strdup (path);
214
215 dir = strtok_r (path_to_use, sep, &ctx);
216 do {
217 if ((0 == strcmp(dir, "USER_DEFAULT") || 0 == strcmp(dir, "USR_DEFAULT"))
218 && NULL != mca_base_user_default_path) {
219 dir = mca_base_user_default_path;
220 } else if (0 == strcmp(dir, "SYS_DEFAULT") ||
221 0 == strcmp(dir, "SYSTEM_DEFAULT")) {
222 dir = mca_base_system_default_path;
223 }
224
225 if (0 != opal_dl_foreachfile(dir, process_repository_item, NULL)) {
226 break;
227 }
228 } while (NULL != (dir = strtok_r (NULL, sep, &ctx)));
229
230 free (path_to_use);
231
232 #endif
233
234 return OPAL_SUCCESS;
235 }
236
237
238
239
240
241 int mca_base_component_repository_init(void)
242 {
243
244
245 if (!initialized) {
246 #if OPAL_HAVE_DL_SUPPORT
247
248
249 int ret = mca_base_framework_open(&opal_dl_base_framework, 0);
250 if (OPAL_SUCCESS != ret) {
251 opal_output(0, "%s %d:%s failed -- process will likely abort (open the dl framework returned %d instead of OPAL_SUCCESS)\n",
252 __FILE__, __LINE__, __func__, ret);
253 return ret;
254 }
255 opal_dl_base_select();
256
257 OBJ_CONSTRUCT(&mca_base_component_repository, opal_hash_table_t);
258 ret = opal_hash_table_init (&mca_base_component_repository, 128);
259 if (OPAL_SUCCESS != ret) {
260 (void) mca_base_framework_close (&opal_dl_base_framework);
261 return ret;
262 }
263
264 ret = mca_base_component_repository_add (mca_base_component_path);
265 if (OPAL_SUCCESS != ret) {
266 OBJ_DESTRUCT(&mca_base_component_repository);
267 (void) mca_base_framework_close (&opal_dl_base_framework);
268 return ret;
269 }
270 #endif
271
272 initialized = true;
273 }
274
275
276
277 return OPAL_SUCCESS;
278 }
279
280 int mca_base_component_repository_get_components (mca_base_framework_t *framework,
281 opal_list_t **framework_components)
282 {
283 *framework_components = NULL;
284 #if OPAL_HAVE_DL_SUPPORT
285 return opal_hash_table_get_value_ptr (&mca_base_component_repository, framework->framework_name,
286 strlen (framework->framework_name), (void **) framework_components);
287 #endif
288 return OPAL_ERR_NOT_FOUND;
289 }
290
291 #if OPAL_HAVE_DL_SUPPORT
292 static void mca_base_component_repository_release_internal (mca_base_component_repository_item_t *ri) {
293 int group_id;
294
295 group_id = mca_base_var_group_find (NULL, ri->ri_type, ri->ri_name);
296 if (0 <= group_id) {
297
298 mca_base_var_group_deregister (group_id);
299 }
300
301
302 if (ri->ri_dlhandle) {
303 opal_dl_close(ri->ri_dlhandle);
304 ri->ri_dlhandle = NULL;
305 }
306 }
307 #endif
308
309 #if OPAL_HAVE_DL_SUPPORT
310 static mca_base_component_repository_item_t *find_component (const char *type, const char *name)
311 {
312 mca_base_component_repository_item_t *ri;
313 opal_list_t *component_list;
314 int ret;
315
316 ret = opal_hash_table_get_value_ptr (&mca_base_component_repository, type,
317 strlen (type), (void **) &component_list);
318 if (OPAL_SUCCESS != ret) {
319
320 return NULL;
321 }
322
323 OPAL_LIST_FOREACH(ri, component_list, mca_base_component_repository_item_t) {
324 if (0 == strcmp (ri->ri_name, name)) {
325 return ri;
326 }
327 }
328
329 return NULL;
330 }
331 #endif
332
333 void mca_base_component_repository_release(const mca_base_component_t *component)
334 {
335 #if OPAL_HAVE_DL_SUPPORT
336 mca_base_component_repository_item_t *ri;
337
338 ri = find_component (component->mca_type_name, component->mca_component_name);
339 if (NULL != ri && !(--ri->ri_refcnt)) {
340 mca_base_component_repository_release_internal (ri);
341 }
342 #endif
343 }
344
345 int mca_base_component_repository_retain_component (const char *type, const char *name)
346 {
347 #if OPAL_HAVE_DL_SUPPORT
348 mca_base_component_repository_item_t *ri = find_component(type, name);
349
350 if (NULL != ri) {
351 ++ri->ri_refcnt;
352 return OPAL_SUCCESS;
353 }
354
355 return OPAL_ERR_NOT_FOUND;
356 #else
357 return OPAL_ERR_NOT_SUPPORTED;
358 #endif
359 }
360
361 int mca_base_component_repository_open (mca_base_framework_t *framework,
362 mca_base_component_repository_item_t *ri)
363 {
364 #if OPAL_HAVE_DL_SUPPORT
365 mca_base_component_t *component_struct;
366 mca_base_component_list_item_t *mitem = NULL;
367 char *struct_name = NULL;
368 int vl, ret;
369
370 opal_output_verbose(MCA_BASE_VERBOSE_INFO, 0, "mca_base_component_repository_open: examining dynamic "
371 "%s MCA component \"%s\" at path %s", ri->ri_type, ri->ri_name, ri->ri_path);
372
373 vl = mca_base_component_show_load_errors ? MCA_BASE_VERBOSE_ERROR : MCA_BASE_VERBOSE_INFO;
374
375
376
377
378
379
380
381 OPAL_LIST_FOREACH(mitem, &framework->framework_components, mca_base_component_list_item_t) {
382 if (0 == strcmp(mitem->cli_component->mca_component_name, ri->ri_name)) {
383 opal_output_verbose (MCA_BASE_VERBOSE_INFO, 0, "mca_base_component_repository_open: already loaded (ignored)");
384 return OPAL_ERR_BAD_PARAM;
385 }
386 }
387
388
389 mitem = NULL;
390
391 if (NULL != ri->ri_dlhandle) {
392 opal_output_verbose (MCA_BASE_VERBOSE_INFO, 0, "mca_base_component_repository_open: already loaded. returning cached component");
393 mitem = OBJ_NEW(mca_base_component_list_item_t);
394 if (NULL == mitem) {
395 return OPAL_ERR_OUT_OF_RESOURCE;
396 }
397
398 mitem->cli_component = ri->ri_component_struct;
399 opal_list_append (&framework->framework_components, &mitem->super);
400
401 return OPAL_SUCCESS;
402 }
403
404 if (0 != strcmp (ri->ri_type, framework->framework_name)) {
405
406
407
408 assert (0);
409 return OPAL_ERR_NOT_SUPPORTED;
410 }
411
412
413
414 char *err_msg = NULL;
415 if (OPAL_SUCCESS != opal_dl_open(ri->ri_path, true, false, &ri->ri_dlhandle, &err_msg)) {
416 if (NULL == err_msg) {
417 err_msg = "opal_dl_open() error message was NULL!";
418 }
419
420
421
422
423
424
425 if (0 == strcasecmp("file not found", err_msg) &&
426 (file_exists(ri->ri_path, "lo") ||
427 file_exists(ri->ri_path, "so") ||
428 file_exists(ri->ri_path, "dylib") ||
429 file_exists(ri->ri_path, "dll"))) {
430 err_msg = "perhaps a missing symbol, or compiled for a different version of Open MPI?";
431 }
432 opal_output_verbose(vl, 0, "mca_base_component_repository_open: unable to open %s: %s (ignored)",
433 ri->ri_base, err_msg);
434
435 if( mca_base_component_track_load_errors ) {
436 mca_base_failed_component_t *f_comp = OBJ_NEW(mca_base_failed_component_t);
437 f_comp->comp = ri;
438 opal_asprintf(&(f_comp->error_msg), "%s", err_msg);
439 opal_list_append(&framework->framework_failed_components, &f_comp->super);
440 }
441
442 return OPAL_ERR_BAD_PARAM;
443 }
444
445
446
447
448 do {
449 ret = opal_asprintf (&struct_name, "mca_%s_%s_component", ri->ri_type, ri->ri_name);
450 if (0 > ret) {
451 ret = OPAL_ERR_OUT_OF_RESOURCE;
452 break;
453 }
454
455 mitem = OBJ_NEW(mca_base_component_list_item_t);
456 if (NULL == mitem) {
457 ret = OPAL_ERR_OUT_OF_RESOURCE;
458 break;
459 }
460
461 err_msg = NULL;
462 ret = opal_dl_lookup(ri->ri_dlhandle, struct_name, (void**) &component_struct, &err_msg);
463 if (OPAL_SUCCESS != ret || NULL == component_struct) {
464 if (NULL == err_msg) {
465 err_msg = "opal_dl_loookup() error message was NULL!";
466 }
467 opal_output_verbose(vl, 0, "mca_base_component_repository_open: \"%s\" does not appear to be a valid "
468 "%s MCA dynamic component (ignored): %s. ret %d", ri->ri_base, ri->ri_type, err_msg, ret);
469
470 ret = OPAL_ERR_BAD_PARAM;
471 break;
472 }
473
474
475 free (struct_name);
476 struct_name = NULL;
477
478
479
480 if (!(MCA_BASE_VERSION_MAJOR == component_struct->mca_major_version &&
481 MCA_BASE_VERSION_MINOR == component_struct->mca_minor_version)) {
482 opal_output_verbose(vl, 0, "mca_base_component_repository_open: %s \"%s\" uses an MCA interface that is "
483 "not recognized (component MCA v%d.%d.%d != supported MCA v%d.%d.%d) -- ignored",
484 ri->ri_type, ri->ri_path, component_struct->mca_major_version,
485 component_struct->mca_minor_version, component_struct->mca_release_version,
486 MCA_BASE_VERSION_MAJOR, MCA_BASE_VERSION_MINOR, MCA_BASE_VERSION_RELEASE);
487 ret = OPAL_ERR_BAD_PARAM;
488 break;
489 }
490
491
492
493 if (0 != strcmp(component_struct->mca_type_name, ri->ri_type) ||
494 0 != strcmp(component_struct->mca_component_name, ri->ri_name)) {
495 opal_output_verbose(vl, 0, "Component file data does not match filename: %s (%s / %s) != %s %s -- ignored",
496 ri->ri_path, ri->ri_type, ri->ri_name,
497 component_struct->mca_type_name,
498 component_struct->mca_component_name);
499 ret = OPAL_ERR_BAD_PARAM;
500 break;
501 }
502
503
504
505
506 ri->ri_component_struct = mitem->cli_component = component_struct;
507 ri->ri_refcnt = 1;
508 opal_list_append(&framework->framework_components, &mitem->super);
509
510 opal_output_verbose (MCA_BASE_VERBOSE_INFO, 0, "mca_base_component_repository_open: opened dynamic %s MCA "
511 "component \"%s\"", ri->ri_type, ri->ri_name);
512
513 return OPAL_SUCCESS;
514 } while (0);
515
516 if (mitem) {
517 OBJ_RELEASE(mitem);
518 }
519
520 if (struct_name) {
521 free (struct_name);
522 }
523
524 opal_dl_close (ri->ri_dlhandle);
525 ri->ri_dlhandle = NULL;
526
527 return ret;
528 #else
529
530
531 return OPAL_ERR_NOT_SUPPORTED;
532 #endif
533 }
534
535
536
537
538 void mca_base_component_repository_finalize(void)
539 {
540 if (!initialized) {
541 return;
542 }
543
544 initialized = false;
545
546 #if OPAL_HAVE_DL_SUPPORT
547 opal_list_t *component_list;
548 void *node, *key;
549 size_t key_size;
550 int ret;
551
552 ret = opal_hash_table_get_first_key_ptr (&mca_base_component_repository, &key, &key_size,
553 (void **) &component_list, &node);
554 while (OPAL_SUCCESS == ret) {
555 OPAL_LIST_RELEASE(component_list);
556 ret = opal_hash_table_get_next_key_ptr (&mca_base_component_repository, &key,
557 &key_size, (void **) &component_list,
558 node, &node);
559 }
560
561 (void) mca_base_framework_close(&opal_dl_base_framework);
562 OBJ_DESTRUCT(&mca_base_component_repository);
563 #endif
564 }
565
566 #if OPAL_HAVE_DL_SUPPORT
567
568
569
570
571 static void ri_constructor (mca_base_component_repository_item_t *ri)
572 {
573 memset(ri->ri_type, 0, sizeof(ri->ri_type));
574 ri->ri_dlhandle = NULL;
575 ri->ri_component_struct = NULL;
576 ri->ri_path = NULL;
577 }
578
579
580
581
582
583 static void ri_destructor (mca_base_component_repository_item_t *ri)
584 {
585
586 mca_base_component_repository_release_internal (ri);
587
588
589
590
591
592
593 if (ri->ri_path) {
594 free (ri->ri_path);
595 }
596
597 if (ri->ri_base) {
598 free (ri->ri_base);
599 }
600 }
601
602 #endif