1 /*
2 * Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2011 Oak Ridge National Labs. All rights reserved.
4 * Copyright (c) 2012 The University of Tennessee and The University
5 * of Tennessee Research Foundation. All rights
6 * reserved.
7 * Copyright (c) 2013 Cisco Systems, Inc. All rights reserved.
8 * Copyright (c) 2014 Research Organization for Information Science
9 * and Technology (RIST). All rights reserved.
10 * $COPYRIGHT$
11 *
12 * Additional copyrights may follow
13 *
14 * $HEADER$
15 */
16
17 #include "opal_config.h"
18
19 #include "opal/class/opal_tree.h"
20 #include "opal/constants.h"
21
22 /*
23 * List classes
24 */
25
26 static void opal_tree_item_construct(opal_tree_item_t*);
27 static void opal_tree_item_destruct(opal_tree_item_t*);
28
29 OBJ_CLASS_INSTANCE(
30 opal_tree_item_t,
31 opal_object_t,
32 opal_tree_item_construct,
33 opal_tree_item_destruct
34 );
35
36 static void opal_tree_construct(opal_tree_t*);
37 static void opal_tree_destruct(opal_tree_t*);
38
39 OBJ_CLASS_INSTANCE(
40 opal_tree_t,
41 opal_object_t,
42 opal_tree_construct,
43 opal_tree_destruct
44 );
45
46
47 /*
48 *
49 * opal_tree_item_t interface
50 *
51 */
52
opal_tree_item_construct(opal_tree_item_t * item)53 static void opal_tree_item_construct(opal_tree_item_t *item)
54 {
55 item->opal_tree_parent = NULL;
56 item->opal_tree_num_ancestors = 0;
57 item->opal_tree_sibling_rank = 0xdeadbeef;
58 item->opal_tree_next_sibling = item->opal_tree_prev_sibling = NULL;
59 item->opal_tree_num_children = 0;
60 item->opal_tree_first_child = item->opal_tree_last_child = NULL;
61 #if OPAL_ENABLE_DEBUG
62 item->opal_tree_item_refcount = 0;
63 item->opal_tree_item_belong_to = NULL;
64 #endif
65 }
66
opal_tree_item_destruct(opal_tree_item_t * item)67 static void opal_tree_item_destruct(opal_tree_item_t *item)
68 {
69 #if OPAL_ENABLE_DEBUG
70 assert( 0 == item->opal_tree_item_refcount );
71 assert( NULL == item->opal_tree_item_belong_to );
72 #endif /* OPAL_ENABLE_DEBUG */
73 }
74
75
76 /*
77 *
78 * opal_tree_t interface
79 *
80 */
81
opal_tree_construct(opal_tree_t * tree)82 static void opal_tree_construct(opal_tree_t *tree)
83 {
84 OBJ_CONSTRUCT( &(tree->opal_tree_sentinel), opal_tree_item_t );
85
86 #if OPAL_ENABLE_DEBUG
87 /* These refcounts should never be used in assertions because they
88 should never be removed from this list, added to another list,
89 etc. So set them to sentinel values. */
90
91 tree->opal_tree_sentinel.opal_tree_item_refcount = 1;
92 tree->opal_tree_sentinel.opal_tree_item_belong_to = tree;
93 #endif
94 tree->opal_tree_sentinel.opal_tree_container = tree;
95 tree->opal_tree_sentinel.opal_tree_parent = &tree->opal_tree_sentinel;
96 tree->opal_tree_sentinel.opal_tree_num_ancestors = -1;
97
98 tree->opal_tree_sentinel.opal_tree_next_sibling =
99 &tree->opal_tree_sentinel;
100 tree->opal_tree_sentinel.opal_tree_prev_sibling =
101 &tree->opal_tree_sentinel;
102
103 tree->opal_tree_sentinel.opal_tree_first_child = &tree->opal_tree_sentinel;
104 tree->opal_tree_sentinel.opal_tree_last_child = &tree->opal_tree_sentinel;
105
106 tree->opal_tree_num_items = 0;
107 tree->comp = NULL;
108 tree->serialize = NULL;
109 tree->deserialize = NULL;
110 tree->get_key = NULL;
111 }
112
113 /*
114 * Reset all the pointers to be NULL -- do not actually destroy
115 * anything.
116 */
opal_tree_destruct(opal_tree_t * tree)117 static void opal_tree_destruct(opal_tree_t *tree)
118 {
119 opal_tree_construct(tree);
120 }
121
122 /*
123 * initialize tree container
124 */
opal_tree_init(opal_tree_t * tree,opal_tree_comp_fn_t comp,opal_tree_item_serialize_fn_t serialize,opal_tree_item_deserialize_fn_t deserialize,opal_tree_get_key_fn_t get_key)125 void opal_tree_init(opal_tree_t *tree, opal_tree_comp_fn_t comp,
126 opal_tree_item_serialize_fn_t serialize,
127 opal_tree_item_deserialize_fn_t deserialize,
128 opal_tree_get_key_fn_t get_key)
129 {
130 tree->comp = comp;
131 tree->serialize = serialize;
132 tree->deserialize = deserialize;
133 tree->get_key = get_key;
134 }
135
136 /*
137 * count all the descendants from our level and below
138 */
count_descendants(opal_tree_item_t * item)139 static int count_descendants(opal_tree_item_t* item)
140 {
141 int current_count = 0;
142
143 /* loop over all siblings for descendants to count */
144 while (item) {
145 current_count += count_descendants(opal_tree_get_first_child(item));
146 current_count++; /* count ourselves */
147 item = opal_tree_get_next_sibling(item);
148 }
149 return(current_count);
150 }
151
152 /*
153 * get size of tree
154 */
opal_tree_get_size(opal_tree_t * tree)155 size_t opal_tree_get_size(opal_tree_t* tree)
156 {
157 #if OPAL_ENABLE_DEBUG
158 /* not sure if we really want this running in devel, as it does
159 * slow things down. Wanted for development of splice / join to
160 * make sure length was reset properly
161 */
162 size_t check_len = 0;
163 opal_tree_item_t *root;
164
165 if (!opal_tree_is_empty(tree)) {
166 /* tree has entries so count up items */
167 root = opal_tree_get_root(tree);
168 check_len = count_descendants(root);
169 }
170
171 if (check_len != tree->opal_tree_num_items) {
172 fprintf(stderr," Error :: opal_tree_get_size - opal_tree_num_items does not match actual tree length\n");
173 fflush(stderr);
174 abort();
175 }
176 #endif
177
178 return tree->opal_tree_num_items;
179 }
180
181 /*
182 * add item to parent's child list
183 */
opal_tree_add_child(opal_tree_item_t * parent_item,opal_tree_item_t * new_item)184 void opal_tree_add_child(opal_tree_item_t *parent_item,
185 opal_tree_item_t *new_item)
186 {
187 #if OPAL_ENABLE_DEBUG
188 /* Spot check: ensure that this item is previously on no lists */
189
190 assert(0 == new_item->opal_tree_item_refcount);
191 assert( NULL == new_item->opal_tree_item_belong_to );
192 #endif
193
194 new_item->opal_tree_parent = parent_item;
195 new_item->opal_tree_num_ancestors = parent_item->opal_tree_num_ancestors+1;
196 if (parent_item->opal_tree_num_children) {
197 /* append item to end of children and sibling lists */
198 new_item->opal_tree_prev_sibling = parent_item->opal_tree_last_child;
199 parent_item->opal_tree_last_child->opal_tree_next_sibling = new_item;
200 } else {
201 /* no children existing on parent */
202 parent_item->opal_tree_first_child = new_item;
203 }
204 parent_item->opal_tree_last_child = new_item;
205 parent_item->opal_tree_num_children++;
206 new_item->opal_tree_container = parent_item->opal_tree_container;
207 new_item->opal_tree_container->opal_tree_num_items++;
208
209 #if OPAL_ENABLE_DEBUG
210 /* Spot check: ensure this item is only on the list that we just
211 appended it to */
212
213 OPAL_THREAD_ADD_FETCH32( &(new_item->opal_tree_item_refcount), 1 );
214 assert(1 == new_item->opal_tree_item_refcount);
215 new_item->opal_tree_item_belong_to = new_item->opal_tree_container;
216 #endif
217 }
218
219 /*
220 * check to see if item is in tree
221 */
222 #if OPAL_ENABLE_DEBUG
item_in_tree(opal_tree_item_t * item,opal_tree_item_t * search_item)223 static bool item_in_tree(opal_tree_item_t *item, opal_tree_item_t *search_item)
224 {
225 bool result = false;
226 opal_tree_item_t *first_child;
227
228 while (!result && item) {
229 /* check for item match */
230 result = (item == search_item) ? true : false;
231 if (!result && (first_child = opal_tree_get_first_child(item))) {
232 /* search descendants for match */
233 result = item_in_tree(first_child, search_item);
234 }
235 if (!result) {
236 /* didn't find match at our node or descending so check sibling */
237 item = opal_tree_get_next_sibling(item);
238 }
239 }
240 return(result);
241 }
242 #endif /* OPAL_ENABLE_DEBUG */
243
244 /*
245 * remove item and all items below it from tree and return it to the caller
246 */
opal_tree_remove_subtree(opal_tree_item_t * item)247 opal_tree_item_t *opal_tree_remove_subtree(opal_tree_item_t *item)
248 {
249 opal_tree_item_t *parent_item = NULL;
250
251 #if OPAL_ENABLE_DEBUG
252 /* validate that item does exist on tree */
253 if (NULL != item->opal_tree_container) {
254 /* we point to a container, check if we can find item in tree */
255 if (!item_in_tree(opal_tree_get_root(item->opal_tree_container), item)) {
256 return(NULL);
257 }
258 } else {
259 return (NULL);
260 }
261 #endif
262
263 parent_item = item->opal_tree_parent;
264
265 /* remove from parent */
266 /* If item is the only child, set _first_child and _last_child to
267 be item's _first_child and _last_child */
268 if (parent_item->opal_tree_first_child == item &&
269 parent_item->opal_tree_last_child == item) {
270 parent_item->opal_tree_first_child = item->opal_tree_first_child;
271 parent_item->opal_tree_last_child = item->opal_tree_last_child;
272 } else {
273 /* Otherwise, there are multiple children of this parent. If
274 this item is the first or last child of this parent, then
275 ensure that the parent gets a valid first / last child:
276 - If I have children, then my first/last child
277 - If I have no children, then my immediate sibling */
278 if (item->opal_tree_parent->opal_tree_first_child == item) {
279 if (item->opal_tree_num_children > 0) {
280 parent_item->opal_tree_first_child =
281 item->opal_tree_next_sibling;
282 } else {
283 parent_item->opal_tree_first_child =
284 opal_tree_get_next_sibling(item);
285 }
286 } else if (parent_item->opal_tree_last_child == item) {
287 if (item->opal_tree_num_children > 0) {
288 parent_item->opal_tree_last_child =
289 item->opal_tree_last_child;
290 } else {
291 parent_item->opal_tree_last_child =
292 opal_tree_get_prev_sibling(item);
293 }
294 }
295 }
296 item->opal_tree_parent->opal_tree_num_children--;
297
298 /* remove from sibling pointers */
299 if (NULL != item->opal_tree_prev_sibling) {
300 item->opal_tree_prev_sibling->opal_tree_next_sibling=
301 item->opal_tree_next_sibling;
302 }
303 if (NULL != item->opal_tree_next_sibling) {
304 item->opal_tree_next_sibling->opal_tree_prev_sibling=
305 item->opal_tree_prev_sibling;
306 }
307 item->opal_tree_prev_sibling = NULL;
308 item->opal_tree_next_sibling = NULL;
309
310 /* adjust items relating to container */
311 item->opal_tree_container->opal_tree_num_items -= count_descendants(item);
312 item->opal_tree_container = NULL;
313
314 return(item);
315 }
316
opal_tree_remove_item(opal_tree_t * tree,opal_tree_item_t * item)317 int opal_tree_remove_item(opal_tree_t *tree,
318 opal_tree_item_t *item)
319 {
320 opal_tree_item_t *parent_item = NULL, *child = NULL;
321
322 parent_item = (opal_tree_item_t*)item->opal_tree_parent;
323
324 /*
325 * Point each of my children to my parent
326 */
327 for(child = opal_tree_get_first_child(item);
328 child != NULL;
329 child = opal_tree_get_next_sibling(child)) {
330 child->opal_tree_parent = parent_item;
331 child->opal_tree_num_ancestors--;
332
333 parent_item->opal_tree_num_children++;
334 }
335
336 /*
337 * My first child points to my 'prev' sibling
338 */
339 child = opal_tree_get_first_child(item);
340 if( NULL != child ) {
341 child->opal_tree_prev_sibling = item->opal_tree_prev_sibling;
342 }
343 if( NULL != item->opal_tree_prev_sibling ) {
344 (item->opal_tree_prev_sibling)->opal_tree_next_sibling = child;
345 }
346
347 child = opal_tree_get_last_child(item);
348 if( NULL != child ) {
349 child->opal_tree_next_sibling = item->opal_tree_next_sibling;
350 }
351 if( NULL != item->opal_tree_next_sibling ) {
352 (item->opal_tree_next_sibling)->opal_tree_prev_sibling = child;
353 }
354
355 /*
356 * Remove me from my parent. If I was the only child, then make
357 * the first child be my first child, and make the last child be
358 * my last child.
359 */
360 if( parent_item->opal_tree_first_child == item &&
361 parent_item->opal_tree_last_child == item ) {
362 parent_item->opal_tree_first_child = opal_tree_get_first_child(item);
363 parent_item->opal_tree_last_child = opal_tree_get_last_child(item);
364 } else {
365 /* There were multiple children. If I was the first or last,
366 then ensure the parent gets a valid first or last child:
367 - If I have children, then my first/last
368 - If I have no childen, then my immediate sibling */
369 if (parent_item->opal_tree_first_child == item) {
370 if (item->opal_tree_num_children > 0) {
371 parent_item->opal_tree_first_child =
372 item->opal_tree_first_child;
373 } else {
374 parent_item->opal_tree_first_child =
375 opal_tree_get_next_sibling(item);
376 }
377 } else if (parent_item->opal_tree_last_child == item) {
378 if (item->opal_tree_num_children > 0) {
379 parent_item->opal_tree_last_child =
380 item->opal_tree_last_child;
381 } else {
382 parent_item->opal_tree_last_child =
383 opal_tree_get_prev_sibling(item);
384 }
385 }
386 }
387 parent_item->opal_tree_num_children--;
388
389 return OPAL_SUCCESS;
390 }
391
392 /* delimeter characters that mark items in a serialized stream */
393 static char *start_lvl = "[";
394 static char *end_lvl = "]";
395 static char *end_stream = "E";
396
397 /*
398 * add item to opal buffer that represents all items of a sub-tree from the
399 * item passed in on down. We exit out of converting tree items once we've
400 * done the last child of the tree_item and we are at depth 1.
401 */
add_tree_item2buf(opal_tree_item_t * tree_item,opal_buffer_t * buf,opal_tree_item_serialize_fn_t fn,int depth)402 static int add_tree_item2buf(opal_tree_item_t *tree_item,
403 opal_buffer_t *buf,
404 opal_tree_item_serialize_fn_t fn,
405 int depth
406 )
407 {
408 opal_tree_item_t *first_child;
409 int rc;
410
411 do {
412 /* add start delim to buffer */
413 if (OPAL_SUCCESS !=
414 (rc = opal_dss.pack(buf, &start_lvl, 1, OPAL_STRING))){
415 return(rc);
416 }
417 /* add item to opal buffer from class creator */
418 fn(tree_item, buf);
419
420 if ((first_child = opal_tree_get_first_child(tree_item))) {
421 /* add items for our children */
422 if (OPAL_SUCCESS !=
423 (rc = add_tree_item2buf(first_child, buf, fn, depth+1))){
424 return(rc);
425 }
426 if (OPAL_SUCCESS !=
427 (rc = opal_dss.pack(buf, &end_lvl, 1, OPAL_STRING))){
428 return(rc);
429 }
430 } else {
431 /* end item entry */
432 if (OPAL_SUCCESS !=
433 (rc = opal_dss.pack(buf, &end_lvl, 1, OPAL_STRING))){
434 return(rc);
435 }
436 }
437
438 /* advance to next sibling, if none we'll drop out of
439 * loop and return to our parent
440 */
441 tree_item = opal_tree_get_next_sibling(tree_item);
442 } while (tree_item && 1 < depth);
443
444 return(OPAL_SUCCESS);
445 }
446
447 /*
448 * serialize tree data
449 */
opal_tree_serialize(opal_tree_item_t * start_item,opal_buffer_t * buffer)450 int opal_tree_serialize(opal_tree_item_t *start_item, opal_buffer_t *buffer)
451 {
452 int rc;
453
454 if (OPAL_SUCCESS !=
455 (rc = add_tree_item2buf(start_item, buffer,
456 start_item->opal_tree_container->serialize,
457 1))){
458 return(rc);
459 }
460 if (OPAL_SUCCESS !=
461 (rc = opal_dss.pack(buffer, &end_stream, 1, OPAL_STRING))){
462 return(rc);
463 }
464 return(OPAL_SUCCESS);
465 }
466
deserialize_add_tree_item(opal_buffer_t * data,opal_tree_item_t * parent_item,opal_tree_item_deserialize_fn_t deserialize,char ** curr_delim,int depth)467 static int deserialize_add_tree_item(opal_buffer_t *data,
468 opal_tree_item_t *parent_item,
469 opal_tree_item_deserialize_fn_t deserialize,
470 char **curr_delim,
471 int depth)
472 {
473 int idx = 1, rc;
474 opal_tree_item_t *new_item = NULL;
475 int level = 0; /* 0 - one up 1 - curr, 2 - one down */
476
477 if (!*curr_delim) {
478 if (OPAL_SUCCESS !=
479 (rc = opal_dss.unpack(data, curr_delim, &idx, OPAL_STRING))) {
480 return(rc);
481 }
482 }
483 while(*curr_delim[0] != end_stream[0]) {
484 if (*curr_delim[0] == start_lvl[0]) {
485 level++;
486 } else {
487 level--;
488 }
489
490 switch (level) {
491 case 0:
492 if (1 < depth) {
493 /* done with this level go up one level */
494 return(OPAL_SUCCESS);
495 }
496 break;
497 case 1:
498 /* add found child at this level */
499 deserialize(data, &new_item);
500 opal_tree_add_child(parent_item, new_item);
501 break;
502 case 2:
503 /* need to add child one level down */
504 deserialize_add_tree_item(data, new_item, deserialize, curr_delim,
505 depth+1);
506 level--;
507 break;
508 }
509 if (OPAL_SUCCESS !=
510 (rc = opal_dss.unpack(data, curr_delim, &idx, OPAL_STRING))) {
511 return(rc);
512 }
513 }
514 return(OPAL_SUCCESS);
515 }
516
517 /*
518 * deserialize tree data
519 */
opal_tree_deserialize(opal_buffer_t * serialized_data,opal_tree_item_t * start_item)520 int opal_tree_deserialize(opal_buffer_t *serialized_data,
521 opal_tree_item_t *start_item)
522 {
523 char * null = NULL;
524 deserialize_add_tree_item(serialized_data,
525 start_item,
526 start_item->opal_tree_container->deserialize,
527 &null,
528 1);
529 return OPAL_SUCCESS;
530 }
531
opal_tree_get_key(opal_tree_t * tree,opal_tree_item_t * item)532 void * opal_tree_get_key(opal_tree_t *tree, opal_tree_item_t *item)
533 {
534 return tree->get_key(item);
535 }
536
opal_tree_dup(opal_tree_t * from,opal_tree_t * to)537 int opal_tree_dup(opal_tree_t *from, opal_tree_t *to)
538 {
539 int ret;
540 opal_buffer_t *buffer = NULL;
541
542 opal_tree_init(to,
543 from->comp,
544 from->serialize,
545 from->deserialize,
546 from->get_key);
547
548 buffer = OBJ_NEW(opal_buffer_t);
549
550 opal_tree_serialize(opal_tree_get_root(from), buffer);
551 ret = opal_tree_deserialize(buffer, opal_tree_get_root(to));
552
553 OBJ_RELEASE(buffer);
554 return ret;
555 }
556
opal_tree_copy_subtree(opal_tree_t * from_tree,opal_tree_item_t * from_item,opal_tree_t * to_tree,opal_tree_item_t * to_parent)557 int opal_tree_copy_subtree(opal_tree_t *from_tree, opal_tree_item_t *from_item,
558 opal_tree_t *to_tree, opal_tree_item_t *to_parent)
559 {
560 int ret;
561 opal_buffer_t *buffer = NULL;
562
563 buffer = OBJ_NEW(opal_buffer_t);
564
565 opal_tree_serialize(from_item, buffer);
566 ret = opal_tree_deserialize(buffer, to_parent);
567
568 OBJ_RELEASE(buffer);
569 return ret;
570 }
571
opal_tree_dup_item(opal_tree_t * base,opal_tree_item_t * from)572 opal_tree_item_t *opal_tree_dup_item(opal_tree_t *base, opal_tree_item_t *from)
573 {
574 opal_buffer_t *buffer = NULL;
575 opal_tree_item_t *new_item = NULL;
576
577 buffer = OBJ_NEW(opal_buffer_t);
578
579 opal_tree_serialize(from, buffer);
580
581 new_item = OBJ_NEW(opal_tree_item_t);
582 opal_tree_deserialize(buffer, new_item);
583
584 OBJ_RELEASE(buffer);
585 return new_item;
586 }
587
opal_tree_num_children(opal_tree_item_t * parent)588 int opal_tree_num_children(opal_tree_item_t *parent)
589 {
590 opal_tree_item_t *child = NULL;
591 int i = 0;
592
593 for(child = opal_tree_get_first_child(parent);
594 child != NULL;
595 child = opal_tree_get_next_sibling(child) ) {
596 ++i;
597 }
598
599 return i;
600 }
601
opal_tree_compare_subtrees(opal_tree_t * tree_left,opal_tree_t * tree_right,opal_tree_item_t * left,opal_tree_item_t * right)602 static int opal_tree_compare_subtrees(opal_tree_t *tree_left, opal_tree_t *tree_right,
603 opal_tree_item_t *left, opal_tree_item_t *right)
604 {
605 int ret;
606 opal_tree_item_t *left_child = NULL, *right_child = NULL;
607
608 /* Basecase */
609 if( NULL == left && NULL == right ) {
610 return 0; /* Match */
611 }
612
613 /* Compare: Depth */
614 if( NULL == left && NULL != right ) {
615 return -1;
616 }
617 else if( NULL != left && NULL == right ) {
618 return 1;
619 }
620
621 /* Compare: Keys */
622 if( 0 != tree_left->comp(right, opal_tree_get_key(tree_left, left)) ) {
623 return -2;
624 }
625
626 /* Compare: Number of children */
627 if( opal_tree_num_children(left) != opal_tree_num_children(right) ) {
628 return 2;
629 }
630
631 /* Recursively compare all children */
632 for(left_child = opal_tree_get_first_child(left), right_child = opal_tree_get_first_child(right);
633 left_child != NULL && right_child != NULL;
634 left_child = opal_tree_get_next_sibling(left_child), right_child = opal_tree_get_next_sibling(right_child) ) {
635 /* On first difference, return the result */
636 if( 0 != (ret = opal_tree_compare_subtrees(tree_left, tree_right, left_child, right_child)) ) {
637 return ret;
638 }
639 }
640
641 return 0;
642 }
643
opal_tree_compare(opal_tree_t * left,opal_tree_t * right)644 int opal_tree_compare(opal_tree_t *left, opal_tree_t *right)
645 {
646 return opal_tree_compare_subtrees(left, right, opal_tree_get_root(left), opal_tree_get_root(right));
647 }
648
649 /*
650 * search myself, descendants and siblings for item matching key
651 */
find_in_descendants(opal_tree_item_t * item,void * key)652 static opal_tree_item_t *find_in_descendants(opal_tree_item_t* item, void *key)
653 {
654 opal_tree_item_t *result = NULL, *first_child;
655
656 while (!result && item) {
657 /* check for item match */
658 result = (item->opal_tree_container->comp(item, key) == 0) ?
659 item : NULL;
660 if (!result && (first_child = opal_tree_get_first_child(item))) {
661 /* search descendants for match */
662 result = find_in_descendants(first_child, key);
663 }
664 if (!result) {
665 /* didn't find match at our node or descending so check sibling */
666 item = opal_tree_get_next_sibling(item);
667 }
668 }
669 return(result);
670 }
671
672 /*
673 * return next tree item that matches key
674 */
opal_tree_find_with(opal_tree_item_t * item,void * key)675 opal_tree_item_t *opal_tree_find_with(opal_tree_item_t *item, void *key)
676 {
677 opal_tree_item_t *curr_item = item, *result = NULL;
678
679 if (!opal_tree_is_empty(item->opal_tree_container)) {
680 /* check my descendant for a match */
681 result = find_in_descendants(opal_tree_get_first_child(item), key);
682
683 if (!result) {
684 /* check my siblings for match */
685 if (NULL != (curr_item = opal_tree_get_next_sibling(curr_item))) {
686 result = find_in_descendants(curr_item, key);
687 }
688 }
689
690 /* check my ancestors (uncles) for match */
691 curr_item = item;
692 while (!result && curr_item && curr_item->opal_tree_num_ancestors > 0){
693 curr_item = opal_tree_get_next_sibling(item->opal_tree_parent);
694 while (NULL == curr_item &&
695 item->opal_tree_parent->opal_tree_num_ancestors > 0) {
696 item = item->opal_tree_parent;
697 curr_item = opal_tree_get_next_sibling(item->opal_tree_parent);
698 }
699 if (curr_item) {
700 /* search ancestors descendants for match */
701 result = find_in_descendants(curr_item, key);
702 }
703 }
704 }
705
706 return(result);
707 }
708