This source file includes following definitions.
- infosubscriber_construct
- infosubscriber_destruct
- opal_callback_list_item_destruct
- opal_infosubscribe_inform_subscribers
- opal_infosubscribe_testcallback
- opal_infosubscribe_testregister
- save_original_key_val
- opal_infosubscribe_change_info
- opal_infosubscribe_subscribe
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 <string.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 #include <limits.h>
35 #include <ctype.h>
36 #ifdef HAVE_SYS_UTSNAME_H
37 #include <sys/utsname.h>
38 #endif
39 #include <assert.h>
40
41 #include "opal/util/argv.h"
42 #include "opal/util/opal_getcwd.h"
43 #include "opal/util/output.h"
44 #include "opal/util/info_subscriber.h"
45
46 static char* opal_infosubscribe_inform_subscribers(opal_infosubscriber_t * object, char *key, char *new_value, int *found_callback);
47 static void infosubscriber_construct(opal_infosubscriber_t *obj);
48 static void infosubscriber_destruct(opal_infosubscriber_t *obj);
49
50
51
52
53
54 typedef struct opal_callback_list_t opal_callback_list_t;
55
56 struct opal_callback_list_item_t {
57 opal_list_item_t super;
58 char *default_value;
59 opal_key_interest_callback_t *callback;
60 };
61 typedef struct opal_callback_list_item_t opal_callback_list_item_t;
62
63 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_infosubscriber_t);
64 OBJ_CLASS_INSTANCE(opal_infosubscriber_t,
65 opal_object_t,
66 infosubscriber_construct,
67 infosubscriber_destruct);
68
69 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_callback_list_item_t);
70 static void opal_callback_list_item_destruct(opal_callback_list_item_t *obj);
71 OBJ_CLASS_INSTANCE(opal_callback_list_item_t,
72 opal_list_item_t,
73 NULL,
74 opal_callback_list_item_destruct);
75
76 static void infosubscriber_construct(opal_infosubscriber_t *obj) {
77 OBJ_CONSTRUCT(&obj->s_subscriber_table, opal_hash_table_t);
78 opal_hash_table_init(&obj->s_subscriber_table, 10);
79 }
80
81 static void infosubscriber_destruct(opal_infosubscriber_t *obj) {
82 opal_hash_table_t *table = &obj->s_subscriber_table;
83 void *node = NULL;
84 int err;
85 char *next_key;
86 size_t key_size;
87 opal_list_t *list = NULL;
88
89 err = opal_hash_table_get_first_key_ptr(table,
90 (void**) &next_key, &key_size, (void**) &list, &node);
91 while (list && err == OPAL_SUCCESS) {
92 OPAL_LIST_RELEASE(list);
93
94 err = opal_hash_table_get_next_key_ptr(table,
95 (void**) &next_key, &key_size, (void**) &list, node, &node);
96 }
97
98 OBJ_DESTRUCT(&obj->s_subscriber_table);
99
100 if (NULL != obj->s_info) {
101 OBJ_RELEASE(obj->s_info);
102 }
103 }
104
105 static void opal_callback_list_item_destruct(opal_callback_list_item_t *obj) {
106 if (obj->default_value) {
107 free(obj->default_value);
108 }
109 }
110
111 static char* opal_infosubscribe_inform_subscribers(opal_infosubscriber_t *object, char *key, char *new_value, int *found_callback)
112 {
113 opal_hash_table_t *table = &object->s_subscriber_table;
114 opal_list_t *list = NULL;
115 opal_callback_list_item_t *item;
116 char *updated_value = NULL;
117
118 if (found_callback) { *found_callback = 0; }
119
120
121
122
123
124
125
126 if (table) {
127 opal_hash_table_get_value_ptr(table, key, strlen(key), (void**) &list);
128
129 if (list) {
130 updated_value = new_value;
131 OPAL_LIST_FOREACH(item, list, opal_callback_list_item_t) {
132 updated_value = item->callback(object, key, updated_value);
133 if (found_callback) { *found_callback = 1; }
134 }
135 }
136 }
137
138 return updated_value;
139 }
140
141
142
143
144
145
146
147
148
149 static int ntesting_callbacks = 0;
150 static opal_key_interest_callback_t *testing_callbacks[5];
151 static char *testing_keys[5];
152 static char *testing_initialvals[5];
153
154
155 int opal_infosubscribe_testcallback(opal_key_interest_callback_t *callback,
156 char *key, char *val);
157
158 int
159 opal_infosubscribe_testcallback(opal_key_interest_callback_t *callback,
160 char *key, char *val)
161 {
162 int i = ntesting_callbacks;
163 if (ntesting_callbacks >= 5) { return -1; }
164
165 testing_callbacks[i] = callback;
166 testing_keys[i] = key;
167 testing_initialvals[i] = val;
168 ++ntesting_callbacks;
169 return 0;
170 }
171
172 int opal_infosubscribe_testregister(opal_infosubscriber_t *object);
173 int
174 opal_infosubscribe_testregister(opal_infosubscriber_t *object)
175 {
176 opal_hash_table_t *table = &object->s_subscriber_table;
177 opal_callback_list_item_t *item;
178 opal_list_t *list = NULL;
179
180
181
182 if (ntesting_callbacks != 0) {
183 int i;
184 for (i=0; i<ntesting_callbacks; ++i) {
185
186
187
188 int found = 0;
189 opal_hash_table_get_value_ptr(table, testing_keys[i],
190 strlen(testing_keys[i]), (void**) &list);
191 if (list) {
192 OPAL_LIST_FOREACH(item, list, opal_callback_list_item_t) {
193 if (0 ==
194 strcmp(item->default_value, testing_initialvals[i])
195 &&
196 item->callback == testing_callbacks[i])
197 {
198 found = 1;
199 }
200 }
201 }
202 list = NULL;
203
204 if (!found) {
205 opal_infosubscribe_subscribe(object,
206 testing_keys[i],
207 testing_initialvals[i], testing_callbacks[i]);
208 }
209 }
210 }
211
212
213
214 if (ntesting_callbacks != 0) {
215 int err;
216 void *node = NULL;
217 size_t key_size;
218 char *next_key;
219 opal_callback_list_item_t *item1, *item2;
220
221 err = opal_hash_table_get_first_key_ptr(table, (void**) &next_key,
222 &key_size, (void**) &list, &node);
223 while (list && err == OPAL_SUCCESS) {
224 int counter = 0;
225 OPAL_LIST_FOREACH(item1, list, opal_callback_list_item_t) {
226 OPAL_LIST_FOREACH(item2, list, opal_callback_list_item_t) {
227 if (0 ==
228 strcmp(item1->default_value, item2->default_value)
229 &&
230 item1->callback == item2->callback)
231 {
232 ++counter;
233 }
234 }
235 }
236 if (counter > 1) {
237 printf("ERROR: duplicate info key/val subscription found "
238 "in hash table\n");
239 exit(-1);
240 }
241
242 err = opal_hash_table_get_next_key_ptr(table,
243 (void**) &next_key, &key_size, (void**) &list, node, &node);
244 }
245 }
246
247 return OPAL_SUCCESS;
248 }
249
250
251
252
253
254
255
256
257 static int
258 save_original_key_val(opal_info_t *info, char *key, char *val, int overwrite)
259 {
260 char modkey[OPAL_MAX_INFO_KEY];
261 int flag, err;
262
263
264
265 if (strlen(key) + strlen(OPAL_INFO_SAVE_PREFIX) < OPAL_MAX_INFO_KEY) {
266 snprintf(modkey, OPAL_MAX_INFO_KEY,
267 OPAL_INFO_SAVE_PREFIX "%s", key);
268
269 flag = 0;
270 opal_info_get(info, modkey, 0, NULL, &flag);
271 if (!flag || overwrite) {
272 err = opal_info_set(info, modkey, val);
273 if (OPAL_SUCCESS != err) {
274 return err;
275 }
276 }
277
278
279
280
281 #ifdef OMPI_DEBUG
282 } else {
283 printf("WARNING: Unexpected key length [%s]\n", key);
284 #endif
285 }
286 return OPAL_SUCCESS;
287 }
288
289 int
290 opal_infosubscribe_change_info(opal_infosubscriber_t *object, opal_info_t *new_info)
291 {
292 int err;
293 opal_info_entry_t *iterator;
294 char *updated_value;
295
296
297 int found_callback;
298
299 if (!object->s_info) {
300 object->s_info = OBJ_NEW(opal_info_t);
301 }
302
303 if (NULL != new_info) {
304 OPAL_LIST_FOREACH(iterator, &new_info->super, opal_info_entry_t) {
305
306 updated_value = opal_infosubscribe_inform_subscribers(object, iterator->ie_key, iterator->ie_value, &found_callback);
307 if (updated_value) {
308 err = opal_info_set(object->s_info, iterator->ie_key, updated_value);
309 } else {
310
311
312
313
314
315 err = opal_info_delete(object->s_info, iterator->ie_key);
316 err = OPAL_SUCCESS;
317 }
318 if (OPAL_SUCCESS != err) {
319 return err;
320 }
321
322
323
324 save_original_key_val(object->s_info,
325 iterator->ie_key, iterator->ie_value, 1);
326 }}
327
328 return OPAL_SUCCESS;
329 }
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 int opal_infosubscribe_subscribe(opal_infosubscriber_t *object, char *key, char *value, opal_key_interest_callback_t *callback)
350 {
351 opal_list_t *list = NULL;
352 opal_hash_table_t *table = &object->s_subscriber_table;
353 opal_callback_list_item_t *callback_list_item;
354 size_t max_len = OPAL_MAX_INFO_KEY - strlen(OPAL_INFO_SAVE_PREFIX);
355
356 if (strlen(key) > max_len) {
357 opal_output(0, "DEVELOPER WARNING: Unexpected MPI info key length [%s]: "
358 "OMPI internal callback keys are limited to %" PRIsize_t " chars.",
359 key, max_len);
360 #if OPAL_ENABLE_DEBUG
361 opal_output(0, "Aborting because this is a developer / debugging build. Go fix this error.");
362
363 exit(1);
364 #else
365 opal_output(0, "The \"%s\" MPI info key almost certainly will not work properly. You should inform an Open MPI developer about this.", key);
366 key[max_len] = '\0';
367 #endif
368 }
369
370 if (table) {
371 opal_hash_table_get_value_ptr(table, key, strlen(key), (void**) &list);
372
373 if (!list) {
374 list = OBJ_NEW(opal_list_t);
375 opal_hash_table_set_value_ptr(table, key, strlen(key), list);
376 }
377
378 callback_list_item = OBJ_NEW(opal_callback_list_item_t);
379 callback_list_item->callback = callback;
380 if (value) {
381 callback_list_item->default_value = strdup(value);
382 } else {
383 callback_list_item->default_value = NULL;
384 }
385
386 opal_list_append(list, (opal_list_item_t*) callback_list_item);
387
388
389
390
391
392
393
394
395
396 if (NULL == object->s_info) {
397 object->s_info = OBJ_NEW(opal_info_t);
398 }
399
400
401 char *buffer = malloc(OPAL_MAX_INFO_VAL+1);
402 char *val = value;
403 int flag = 0;
404 char *updated_value;
405 int err;
406 opal_info_get(object->s_info, key, OPAL_MAX_INFO_VAL, buffer, &flag);
407 if (flag) {
408 val = buffer;
409 }
410
411 updated_value = callback(object, key, val);
412 if (updated_value) {
413 err = opal_info_set(object->s_info, key, updated_value);
414 } else {
415 err = opal_info_delete(object->s_info, key);
416 err = OPAL_SUCCESS;
417 }
418 if (OPAL_SUCCESS != err) {
419 free(buffer);
420 return err;
421 }
422
423
424
425
426
427
428
429 save_original_key_val(object->s_info, key, val, 0);
430
431 free(buffer);
432 } else {
433
434
435
436 }
437
438 return OPAL_SUCCESS;
439 }
440
441
442
443
444
445