Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-object-tree.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-object-tree.c DBusObjectTree (internals of DBusConnection) 00003 * 00004 * Copyright (C) 2003 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 * 00022 */ 00023 #include "dbus-object-tree.h" 00024 #include "dbus-connection-internal.h" 00025 #include "dbus-internals.h" 00026 #include "dbus-hash.h" 00027 #include "dbus-protocol.h" 00028 #include "dbus-string.h" 00029 #include <string.h> 00030 #include <stdlib.h> 00031 00044 typedef struct DBusObjectSubtree DBusObjectSubtree; 00045 00046 static DBusObjectSubtree* _dbus_object_subtree_new (const char *name, 00047 const DBusObjectPathVTable *vtable, 00048 void *user_data); 00049 static DBusObjectSubtree* _dbus_object_subtree_ref (DBusObjectSubtree *subtree); 00050 static void _dbus_object_subtree_unref (DBusObjectSubtree *subtree); 00051 00055 struct DBusObjectTree 00056 { 00057 int refcount; 00058 DBusConnection *connection; 00060 DBusObjectSubtree *root; 00061 }; 00062 00068 struct DBusObjectSubtree 00069 { 00070 DBusAtomic refcount; 00071 DBusObjectSubtree *parent; 00072 DBusObjectPathUnregisterFunction unregister_function; 00073 DBusObjectPathMessageFunction message_function; 00074 void *user_data; 00075 DBusObjectSubtree **subtrees; 00076 int n_subtrees; 00077 unsigned int subtrees_sorted : 1; 00078 unsigned int invoke_as_fallback : 1; 00079 char name[1]; 00080 }; 00081 00089 DBusObjectTree* 00090 _dbus_object_tree_new (DBusConnection *connection) 00091 { 00092 DBusObjectTree *tree; 00093 00094 /* the connection passed in here isn't fully constructed, 00095 * so don't do anything more than store a pointer to 00096 * it 00097 */ 00098 00099 tree = dbus_new0 (DBusObjectTree, 1); 00100 if (tree == NULL) 00101 goto oom; 00102 00103 tree->refcount = 1; 00104 tree->connection = connection; 00105 tree->root = _dbus_object_subtree_new ("/", NULL, NULL); 00106 if (tree->root == NULL) 00107 goto oom; 00108 tree->root->invoke_as_fallback = TRUE; 00109 00110 return tree; 00111 00112 oom: 00113 if (tree) 00114 { 00115 dbus_free (tree); 00116 } 00117 00118 return NULL; 00119 } 00120 00126 DBusObjectTree * 00127 _dbus_object_tree_ref (DBusObjectTree *tree) 00128 { 00129 _dbus_assert (tree->refcount > 0); 00130 00131 tree->refcount += 1; 00132 00133 return tree; 00134 } 00135 00140 void 00141 _dbus_object_tree_unref (DBusObjectTree *tree) 00142 { 00143 _dbus_assert (tree->refcount > 0); 00144 00145 tree->refcount -= 1; 00146 00147 if (tree->refcount == 0) 00148 { 00149 _dbus_object_tree_free_all_unlocked (tree); 00150 00151 dbus_free (tree); 00152 } 00153 } 00154 00155 static int 00156 subtree_cmp (DBusObjectSubtree *subtree_a, 00157 DBusObjectSubtree *subtree_b) 00158 { 00159 return strcmp (subtree_a->name, subtree_b->name); 00160 } 00161 00162 static int 00163 subtree_qsort_cmp (const void *a, 00164 const void *b) 00165 { 00166 DBusObjectSubtree **subtree_a_p = (void*) a; 00167 DBusObjectSubtree **subtree_b_p = (void*) b; 00168 00169 return subtree_cmp (*subtree_a_p, *subtree_b_p); 00170 } 00171 00172 static void 00173 ensure_sorted (DBusObjectSubtree *subtree) 00174 { 00175 if (subtree->subtrees && !subtree->subtrees_sorted) 00176 { 00177 qsort (subtree->subtrees, 00178 subtree->n_subtrees, 00179 sizeof (DBusObjectSubtree*), 00180 subtree_qsort_cmp); 00181 subtree->subtrees_sorted = TRUE; 00182 } 00183 } 00184 00188 #define VERBOSE_FIND 0 00189 00190 static DBusObjectSubtree* 00191 find_subtree_recurse (DBusObjectSubtree *subtree, 00192 const char **path, 00193 dbus_bool_t create_if_not_found, 00194 int *index_in_parent, 00195 dbus_bool_t *exact_match) 00196 { 00197 int i; 00198 dbus_bool_t return_deepest_match; 00199 00200 return_deepest_match = exact_match != NULL; 00201 00202 _dbus_assert (!(return_deepest_match && create_if_not_found)); 00203 00204 if (path[0] == NULL) 00205 { 00206 #if VERBOSE_FIND 00207 _dbus_verbose (" path exhausted, returning %s\n", 00208 subtree->name); 00209 #endif 00210 if (exact_match != NULL) 00211 *exact_match = TRUE; 00212 return subtree; 00213 } 00214 00215 #if VERBOSE_FIND 00216 _dbus_verbose (" searching children of %s for %s\n", 00217 subtree->name, path[0]); 00218 #endif 00219 00220 ensure_sorted (subtree); 00221 00222 /* FIXME we should do a binary search here instead 00223 * of O(n) 00224 */ 00225 00226 i = 0; 00227 while (i < subtree->n_subtrees) 00228 { 00229 int v; 00230 00231 v = strcmp (path[0], subtree->subtrees[i]->name); 00232 00233 #if VERBOSE_FIND 00234 _dbus_verbose (" %s cmp %s = %d\n", 00235 path[0], subtree->subtrees[i]->name, 00236 v); 00237 #endif 00238 00239 if (v == 0) 00240 { 00241 if (index_in_parent) 00242 { 00243 #if VERBOSE_FIND 00244 _dbus_verbose (" storing parent index %d\n", i); 00245 #endif 00246 *index_in_parent = i; 00247 } 00248 00249 if (return_deepest_match) 00250 { 00251 DBusObjectSubtree *next; 00252 00253 next = find_subtree_recurse (subtree->subtrees[i], 00254 &path[1], create_if_not_found, 00255 index_in_parent, exact_match); 00256 if (next == NULL && 00257 subtree->invoke_as_fallback) 00258 { 00259 #if VERBOSE_FIND 00260 _dbus_verbose (" no deeper match found, returning %s\n", 00261 subtree->name); 00262 #endif 00263 if (exact_match != NULL) 00264 *exact_match = FALSE; 00265 return subtree; 00266 } 00267 else 00268 return next; 00269 } 00270 else 00271 return find_subtree_recurse (subtree->subtrees[i], 00272 &path[1], create_if_not_found, 00273 index_in_parent, exact_match); 00274 } 00275 else if (v < 0) 00276 { 00277 goto not_found; 00278 } 00279 00280 ++i; 00281 } 00282 00283 not_found: 00284 #if VERBOSE_FIND 00285 _dbus_verbose (" no match found, current tree %s, create_if_not_found = %d\n", 00286 subtree->name, create_if_not_found); 00287 #endif 00288 00289 if (create_if_not_found) 00290 { 00291 DBusObjectSubtree* child; 00292 DBusObjectSubtree **new_subtrees; 00293 int new_n_subtrees; 00294 00295 #if VERBOSE_FIND 00296 _dbus_verbose (" creating subtree %s\n", 00297 path[0]); 00298 #endif 00299 00300 child = _dbus_object_subtree_new (path[0], 00301 NULL, NULL); 00302 if (child == NULL) 00303 return NULL; 00304 00305 /* FIXME we should do the "double alloc each time" standard thing */ 00306 new_n_subtrees = subtree->n_subtrees + 1; 00307 new_subtrees = dbus_realloc (subtree->subtrees, 00308 new_n_subtrees * sizeof (DBusObjectSubtree*)); 00309 if (new_subtrees == NULL) 00310 { 00311 child->unregister_function = NULL; 00312 child->message_function = NULL; 00313 _dbus_object_subtree_unref (child); 00314 return NULL; 00315 } 00316 00317 new_subtrees[subtree->n_subtrees] = child; 00318 if (index_in_parent) 00319 *index_in_parent = subtree->n_subtrees; 00320 subtree->subtrees_sorted = FALSE; 00321 subtree->n_subtrees = new_n_subtrees; 00322 subtree->subtrees = new_subtrees; 00323 00324 child->parent = subtree; 00325 00326 return find_subtree_recurse (child, 00327 &path[1], create_if_not_found, 00328 index_in_parent, exact_match); 00329 } 00330 else 00331 { 00332 if (exact_match != NULL) 00333 *exact_match = FALSE; 00334 return (return_deepest_match && subtree->invoke_as_fallback) ? subtree : NULL; 00335 } 00336 } 00337 00338 static DBusObjectSubtree* 00339 find_subtree (DBusObjectTree *tree, 00340 const char **path, 00341 int *index_in_parent) 00342 { 00343 DBusObjectSubtree *subtree; 00344 00345 #if VERBOSE_FIND 00346 _dbus_verbose ("Looking for exact registered subtree\n"); 00347 #endif 00348 00349 subtree = find_subtree_recurse (tree->root, path, FALSE, index_in_parent, NULL); 00350 00351 if (subtree && subtree->message_function == NULL) 00352 return NULL; 00353 else 00354 return subtree; 00355 } 00356 00357 static DBusObjectSubtree* 00358 lookup_subtree (DBusObjectTree *tree, 00359 const char **path) 00360 { 00361 #if VERBOSE_FIND 00362 _dbus_verbose ("Looking for subtree\n"); 00363 #endif 00364 return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL); 00365 } 00366 00367 static DBusObjectSubtree* 00368 find_handler (DBusObjectTree *tree, 00369 const char **path, 00370 dbus_bool_t *exact_match) 00371 { 00372 #if VERBOSE_FIND 00373 _dbus_verbose ("Looking for deepest handler\n"); 00374 #endif 00375 _dbus_assert (exact_match != NULL); 00376 return find_subtree_recurse (tree->root, path, FALSE, NULL, exact_match); 00377 } 00378 00379 static DBusObjectSubtree* 00380 ensure_subtree (DBusObjectTree *tree, 00381 const char **path) 00382 { 00383 #if VERBOSE_FIND 00384 _dbus_verbose ("Ensuring subtree\n"); 00385 #endif 00386 return find_subtree_recurse (tree->root, path, TRUE, NULL, NULL); 00387 } 00388 00399 dbus_bool_t 00400 _dbus_object_tree_register (DBusObjectTree *tree, 00401 dbus_bool_t fallback, 00402 const char **path, 00403 const DBusObjectPathVTable *vtable, 00404 void *user_data) 00405 { 00406 DBusObjectSubtree *subtree; 00407 00408 _dbus_assert (tree != NULL); 00409 _dbus_assert (vtable->message_function != NULL); 00410 _dbus_assert (path != NULL); 00411 00412 subtree = ensure_subtree (tree, path); 00413 if (subtree == NULL) 00414 return FALSE; 00415 00416 #ifndef DBUS_DISABLE_CHECKS 00417 if (subtree->message_function != NULL) 00418 { 00419 _dbus_warn ("A handler is already registered for the path starting with path[0] = \"%s\"\n", 00420 path[0] ? path[0] : "null"); 00421 return FALSE; 00422 } 00423 #else 00424 _dbus_assert (subtree->message_function == NULL); 00425 #endif 00426 00427 subtree->message_function = vtable->message_function; 00428 subtree->unregister_function = vtable->unregister_function; 00429 subtree->user_data = user_data; 00430 subtree->invoke_as_fallback = fallback != FALSE; 00431 00432 return TRUE; 00433 } 00434 00442 void 00443 _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree, 00444 const char **path) 00445 { 00446 int i; 00447 DBusObjectSubtree *subtree; 00448 DBusObjectPathUnregisterFunction unregister_function; 00449 void *user_data; 00450 DBusConnection *connection; 00451 00452 _dbus_assert (path != NULL); 00453 00454 subtree = find_subtree (tree, path, &i); 00455 00456 #ifndef DBUS_DISABLE_CHECKS 00457 if (subtree == NULL) 00458 { 00459 _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered\n", 00460 path[0] ? path[0] : "null", 00461 path[1] ? path[1] : "null"); 00462 return; 00463 } 00464 #else 00465 _dbus_assert (subtree != NULL); 00466 #endif 00467 00468 _dbus_assert (subtree->parent == NULL || 00469 (i >= 0 && subtree->parent->subtrees[i] == subtree)); 00470 00471 subtree->message_function = NULL; 00472 00473 unregister_function = subtree->unregister_function; 00474 user_data = subtree->user_data; 00475 00476 subtree->unregister_function = NULL; 00477 subtree->user_data = NULL; 00478 00479 /* If we have no subtrees of our own, remove from 00480 * our parent (FIXME could also be more aggressive 00481 * and remove our parent if it becomes empty) 00482 */ 00483 if (subtree->parent && subtree->n_subtrees == 0) 00484 { 00485 /* assumes a 0-byte memmove is OK */ 00486 memmove (&subtree->parent->subtrees[i], 00487 &subtree->parent->subtrees[i+1], 00488 (subtree->parent->n_subtrees - i - 1) * 00489 sizeof (subtree->parent->subtrees[0])); 00490 subtree->parent->n_subtrees -= 1; 00491 00492 subtree->parent = NULL; 00493 00494 _dbus_object_subtree_unref (subtree); 00495 } 00496 subtree = NULL; 00497 00498 connection = tree->connection; 00499 00500 /* Unlock and call application code */ 00501 #ifdef DBUS_BUILD_TESTS 00502 if (connection) 00503 #endif 00504 { 00505 _dbus_connection_ref_unlocked (connection); 00506 _dbus_connection_unlock (connection); 00507 } 00508 00509 if (unregister_function) 00510 (* unregister_function) (connection, user_data); 00511 00512 #ifdef DBUS_BUILD_TESTS 00513 if (connection) 00514 #endif 00515 dbus_connection_unref (connection); 00516 } 00517 00518 static void 00519 free_subtree_recurse (DBusConnection *connection, 00520 DBusObjectSubtree *subtree) 00521 { 00522 /* Delete them from the end, for slightly 00523 * more robustness against odd reentrancy. 00524 */ 00525 while (subtree->n_subtrees > 0) 00526 { 00527 DBusObjectSubtree *child; 00528 00529 child = subtree->subtrees[subtree->n_subtrees - 1]; 00530 subtree->subtrees[subtree->n_subtrees - 1] = NULL; 00531 subtree->n_subtrees -= 1; 00532 child->parent = NULL; 00533 00534 free_subtree_recurse (connection, child); 00535 } 00536 00537 /* Call application code */ 00538 if (subtree->unregister_function) 00539 (* subtree->unregister_function) (connection, 00540 subtree->user_data); 00541 00542 subtree->message_function = NULL; 00543 subtree->unregister_function = NULL; 00544 subtree->user_data = NULL; 00545 00546 /* Now free ourselves */ 00547 _dbus_object_subtree_unref (subtree); 00548 } 00549 00556 void 00557 _dbus_object_tree_free_all_unlocked (DBusObjectTree *tree) 00558 { 00559 if (tree->root) 00560 free_subtree_recurse (tree->connection, 00561 tree->root); 00562 tree->root = NULL; 00563 } 00564 00565 static dbus_bool_t 00566 _dbus_object_tree_list_registered_unlocked (DBusObjectTree *tree, 00567 const char **parent_path, 00568 char ***child_entries) 00569 { 00570 DBusObjectSubtree *subtree; 00571 char **retval; 00572 00573 _dbus_assert (parent_path != NULL); 00574 _dbus_assert (child_entries != NULL); 00575 00576 *child_entries = NULL; 00577 00578 subtree = lookup_subtree (tree, parent_path); 00579 if (subtree == NULL) 00580 { 00581 retval = dbus_new0 (char *, 1); 00582 } 00583 else 00584 { 00585 int i; 00586 retval = dbus_new0 (char*, subtree->n_subtrees + 1); 00587 if (retval == NULL) 00588 goto out; 00589 i = 0; 00590 while (i < subtree->n_subtrees) 00591 { 00592 retval[i] = _dbus_strdup (subtree->subtrees[i]->name); 00593 if (retval[i] == NULL) 00594 { 00595 dbus_free_string_array (retval); 00596 retval = NULL; 00597 goto out; 00598 } 00599 ++i; 00600 } 00601 } 00602 00603 out: 00604 00605 *child_entries = retval; 00606 return retval != NULL; 00607 } 00608 00609 static DBusHandlerResult 00610 handle_default_introspect_unlocked (DBusObjectTree *tree, 00611 DBusMessage *message, 00612 const char **path) 00613 { 00614 DBusString xml; 00615 DBusHandlerResult result; 00616 char **children; 00617 int i; 00618 00619 if (!dbus_message_is_method_call (message, 00620 DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE, 00621 "Introspect")) 00622 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00623 00624 if (!_dbus_string_init (&xml)) 00625 return DBUS_HANDLER_RESULT_NEED_MEMORY; 00626 00627 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 00628 00629 children = NULL; 00630 if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children)) 00631 goto out; 00632 00633 if (!_dbus_string_append (&xml, "<node>\n")) 00634 goto out; 00635 00636 i = 0; 00637 while (children[i] != NULL) 00638 { 00639 if (!_dbus_string_append_printf (&xml, " <node name=\"%s\"/>\n", 00640 children[i])) 00641 goto out; 00642 00643 ++i; 00644 } 00645 00646 if (!_dbus_string_append (&xml, "</node>\n")) 00647 goto out; 00648 00649 result = DBUS_HANDLER_RESULT_HANDLED; 00650 00651 out: 00652 _dbus_string_free (&xml); 00653 dbus_free_string_array (children); 00654 00655 return result; 00656 } 00657 00671 DBusHandlerResult 00672 _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, 00673 DBusMessage *message) 00674 { 00675 char **path; 00676 dbus_bool_t exact_match; 00677 DBusList *list; 00678 DBusList *link; 00679 DBusHandlerResult result; 00680 DBusObjectSubtree *subtree; 00681 00682 #if 0 00683 _dbus_verbose ("Dispatch of message by object path\n"); 00684 #endif 00685 00686 path = NULL; 00687 if (!dbus_message_get_path_decomposed (message, &path)) 00688 { 00689 #ifdef DBUS_BUILD_TESTS 00690 if (tree->connection) 00691 #endif 00692 _dbus_connection_unlock (tree->connection); 00693 00694 _dbus_verbose ("No memory to get decomposed path\n"); 00695 00696 return DBUS_HANDLER_RESULT_NEED_MEMORY; 00697 } 00698 00699 if (path == NULL) 00700 { 00701 #ifdef DBUS_BUILD_TESTS 00702 if (tree->connection) 00703 #endif 00704 _dbus_connection_unlock (tree->connection); 00705 00706 _dbus_verbose ("No path field in message\n"); 00707 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00708 } 00709 00710 /* Find the deepest path that covers the path in the message */ 00711 subtree = find_handler (tree, (const char**) path, &exact_match); 00712 00713 /* Build a list of all paths that cover the path in the message */ 00714 00715 list = NULL; 00716 00717 while (subtree != NULL) 00718 { 00719 if (subtree->message_function != NULL && (exact_match || subtree->invoke_as_fallback)) 00720 { 00721 _dbus_object_subtree_ref (subtree); 00722 00723 /* run deepest paths first */ 00724 if (!_dbus_list_append (&list, subtree)) 00725 { 00726 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 00727 _dbus_object_subtree_unref (subtree); 00728 goto free_and_return; 00729 } 00730 } 00731 00732 exact_match = FALSE; 00733 subtree = subtree->parent; 00734 } 00735 00736 _dbus_verbose ("%d handlers in the path tree for this message\n", 00737 _dbus_list_get_length (&list)); 00738 00739 /* Invoke each handler in the list */ 00740 00741 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00742 00743 link = _dbus_list_get_first_link (&list); 00744 while (link != NULL) 00745 { 00746 DBusList *next = _dbus_list_get_next_link (&list, link); 00747 subtree = link->data; 00748 00749 /* message_function is NULL if we're unregistered 00750 * due to reentrancy 00751 */ 00752 if (subtree->message_function) 00753 { 00754 DBusObjectPathMessageFunction message_function; 00755 void *user_data; 00756 00757 message_function = subtree->message_function; 00758 user_data = subtree->user_data; 00759 00760 #if 0 00761 _dbus_verbose (" (invoking a handler)\n"); 00762 #endif 00763 00764 #ifdef DBUS_BUILD_TESTS 00765 if (tree->connection) 00766 #endif 00767 _dbus_connection_unlock (tree->connection); 00768 00769 /* FIXME you could unregister the subtree in another thread 00770 * before we invoke the callback, and I can't figure out a 00771 * good way to solve this. 00772 */ 00773 00774 result = (* message_function) (tree->connection, 00775 message, 00776 user_data); 00777 00778 #ifdef DBUS_BUILD_TESTS 00779 if (tree->connection) 00780 #endif 00781 _dbus_connection_lock (tree->connection); 00782 00783 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 00784 goto free_and_return; 00785 } 00786 00787 link = next; 00788 } 00789 00790 free_and_return: 00791 00792 if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 00793 { 00794 /* This hardcoded default handler does a minimal Introspect() 00795 */ 00796 result = handle_default_introspect_unlocked (tree, message, 00797 (const char**) path); 00798 } 00799 00800 #ifdef DBUS_BUILD_TESTS 00801 if (tree->connection) 00802 #endif 00803 _dbus_connection_unlock (tree->connection); 00804 00805 while (list != NULL) 00806 { 00807 link = _dbus_list_get_first_link (&list); 00808 _dbus_object_subtree_unref (link->data); 00809 _dbus_list_remove_link (&list, link); 00810 } 00811 00812 dbus_free_string_array (path); 00813 00814 return result; 00815 } 00816 00823 static DBusObjectSubtree* 00824 allocate_subtree_object (const char *name) 00825 { 00826 int len; 00827 DBusObjectSubtree *subtree; 00828 const size_t front_padding = _DBUS_STRUCT_OFFSET (DBusObjectSubtree, name); 00829 00830 _dbus_assert (name != NULL); 00831 00832 len = strlen (name); 00833 00834 subtree = dbus_malloc (front_padding + (len + 1)); 00835 00836 if (subtree == NULL) 00837 return NULL; 00838 00839 memcpy (subtree->name, name, len + 1); 00840 00841 return subtree; 00842 } 00843 00844 static DBusObjectSubtree* 00845 _dbus_object_subtree_new (const char *name, 00846 const DBusObjectPathVTable *vtable, 00847 void *user_data) 00848 { 00849 DBusObjectSubtree *subtree; 00850 00851 subtree = allocate_subtree_object (name); 00852 if (subtree == NULL) 00853 goto oom; 00854 00855 _dbus_assert (name != NULL); 00856 00857 subtree->parent = NULL; 00858 00859 if (vtable) 00860 { 00861 subtree->message_function = vtable->message_function; 00862 subtree->unregister_function = vtable->unregister_function; 00863 } 00864 else 00865 { 00866 subtree->message_function = NULL; 00867 subtree->unregister_function = NULL; 00868 } 00869 00870 subtree->user_data = user_data; 00871 subtree->refcount.value = 1; 00872 subtree->subtrees = NULL; 00873 subtree->n_subtrees = 0; 00874 subtree->subtrees_sorted = TRUE; 00875 subtree->invoke_as_fallback = FALSE; 00876 00877 return subtree; 00878 00879 oom: 00880 if (subtree) 00881 { 00882 dbus_free (subtree); 00883 } 00884 00885 return NULL; 00886 } 00887 00888 static DBusObjectSubtree * 00889 _dbus_object_subtree_ref (DBusObjectSubtree *subtree) 00890 { 00891 _dbus_assert (subtree->refcount.value > 0); 00892 _dbus_atomic_inc (&subtree->refcount); 00893 00894 return subtree; 00895 } 00896 00897 static void 00898 _dbus_object_subtree_unref (DBusObjectSubtree *subtree) 00899 { 00900 _dbus_assert (subtree->refcount.value > 0); 00901 00902 if (_dbus_atomic_dec (&subtree->refcount) == 1) 00903 { 00904 _dbus_assert (subtree->unregister_function == NULL); 00905 _dbus_assert (subtree->message_function == NULL); 00906 00907 dbus_free (subtree->subtrees); 00908 dbus_free (subtree); 00909 } 00910 } 00911 00922 dbus_bool_t 00923 _dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree, 00924 const char **parent_path, 00925 char ***child_entries) 00926 { 00927 dbus_bool_t result; 00928 00929 result = _dbus_object_tree_list_registered_unlocked (tree, 00930 parent_path, 00931 child_entries); 00932 00933 #ifdef DBUS_BUILD_TESTS 00934 if (tree->connection) 00935 #endif 00936 _dbus_connection_unlock (tree->connection); 00937 00938 return result; 00939 } 00940 00943 #ifdef DBUS_BUILD_TESTS 00944 #include "dbus-test.h" 00945 #include <stdio.h> 00946 00947 static char* 00948 flatten_path (const char **path) 00949 { 00950 DBusString str; 00951 int i; 00952 char *s; 00953 00954 if (!_dbus_string_init (&str)) 00955 return NULL; 00956 00957 i = 0; 00958 while (path[i]) 00959 { 00960 if (!_dbus_string_append_byte (&str, '/')) 00961 goto nomem; 00962 00963 if (!_dbus_string_append (&str, path[i])) 00964 goto nomem; 00965 00966 ++i; 00967 } 00968 00969 if (!_dbus_string_steal_data (&str, &s)) 00970 goto nomem; 00971 00972 _dbus_string_free (&str); 00973 00974 return s; 00975 00976 nomem: 00977 _dbus_string_free (&str); 00978 return NULL; 00979 } 00980 00981 00982 typedef enum 00983 { 00984 STR_EQUAL, 00985 STR_PREFIX, 00986 STR_DIFFERENT 00987 } StrComparison; 00988 00989 /* Returns TRUE if container is a parent of child 00990 */ 00991 static StrComparison 00992 path_contains (const char **container, 00993 const char **child) 00994 { 00995 int i; 00996 00997 i = 0; 00998 while (child[i] != NULL) 00999 { 01000 int v; 01001 01002 if (container[i] == NULL) 01003 return STR_PREFIX; /* container ran out, child continues; 01004 * thus the container is a parent of the 01005 * child. 01006 */ 01007 01008 _dbus_assert (container[i] != NULL); 01009 _dbus_assert (child[i] != NULL); 01010 01011 v = strcmp (container[i], child[i]); 01012 01013 if (v != 0) 01014 return STR_DIFFERENT; /* they overlap until here and then are different, 01015 * not overlapping 01016 */ 01017 01018 ++i; 01019 } 01020 01021 /* Child ran out; if container also did, they are equal; 01022 * otherwise, the child is a parent of the container. 01023 */ 01024 if (container[i] == NULL) 01025 return STR_EQUAL; 01026 else 01027 return STR_DIFFERENT; 01028 } 01029 01030 #if 0 01031 static void 01032 spew_subtree_recurse (DBusObjectSubtree *subtree, 01033 int indent) 01034 { 01035 int i; 01036 01037 i = 0; 01038 while (i < indent) 01039 { 01040 _dbus_verbose (" "); 01041 ++i; 01042 } 01043 01044 _dbus_verbose ("%s (%d children)\n", 01045 subtree->name, subtree->n_subtrees); 01046 01047 i = 0; 01048 while (i < subtree->n_subtrees) 01049 { 01050 spew_subtree_recurse (subtree->subtrees[i], indent + 2); 01051 01052 ++i; 01053 } 01054 } 01055 01056 static void 01057 spew_tree (DBusObjectTree *tree) 01058 { 01059 spew_subtree_recurse (tree->root, 0); 01060 } 01061 #endif 01062 01066 typedef struct 01067 { 01068 const char **path; 01069 dbus_bool_t handler_fallback; 01070 dbus_bool_t message_handled; 01071 dbus_bool_t handler_unregistered; 01072 } TreeTestData; 01073 01074 01075 static void 01076 test_unregister_function (DBusConnection *connection, 01077 void *user_data) 01078 { 01079 TreeTestData *ttd = user_data; 01080 01081 ttd->handler_unregistered = TRUE; 01082 } 01083 01084 static DBusHandlerResult 01085 test_message_function (DBusConnection *connection, 01086 DBusMessage *message, 01087 void *user_data) 01088 { 01089 TreeTestData *ttd = user_data; 01090 01091 ttd->message_handled = TRUE; 01092 01093 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 01094 } 01095 01096 static dbus_bool_t 01097 do_register (DBusObjectTree *tree, 01098 const char **path, 01099 dbus_bool_t fallback, 01100 int i, 01101 TreeTestData *tree_test_data) 01102 { 01103 DBusObjectPathVTable vtable = { test_unregister_function, 01104 test_message_function, NULL }; 01105 01106 tree_test_data[i].message_handled = FALSE; 01107 tree_test_data[i].handler_unregistered = FALSE; 01108 tree_test_data[i].handler_fallback = fallback; 01109 tree_test_data[i].path = path; 01110 01111 if (!_dbus_object_tree_register (tree, fallback, path, 01112 &vtable, 01113 &tree_test_data[i])) 01114 return FALSE; 01115 01116 return TRUE; 01117 } 01118 01119 static dbus_bool_t 01120 do_test_dispatch (DBusObjectTree *tree, 01121 const char **path, 01122 int i, 01123 TreeTestData *tree_test_data, 01124 int n_test_data) 01125 { 01126 DBusMessage *message; 01127 int j; 01128 DBusHandlerResult result; 01129 char *flat; 01130 01131 message = NULL; 01132 01133 flat = flatten_path (path); 01134 if (flat == NULL) 01135 goto oom; 01136 01137 message = dbus_message_new_method_call (NULL, 01138 flat, 01139 "org.freedesktop.TestInterface", 01140 "Foo"); 01141 dbus_free (flat); 01142 if (message == NULL) 01143 goto oom; 01144 01145 j = 0; 01146 while (j < n_test_data) 01147 { 01148 tree_test_data[j].message_handled = FALSE; 01149 ++j; 01150 } 01151 01152 result = _dbus_object_tree_dispatch_and_unlock (tree, message); 01153 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 01154 goto oom; 01155 01156 _dbus_assert (tree_test_data[i].message_handled); 01157 01158 j = 0; 01159 while (j < n_test_data) 01160 { 01161 if (tree_test_data[j].message_handled) 01162 { 01163 if (tree_test_data[j].handler_fallback) 01164 _dbus_assert (path_contains (tree_test_data[j].path, 01165 path) != STR_DIFFERENT); 01166 else 01167 _dbus_assert (path_contains (tree_test_data[j].path, path) == STR_EQUAL); 01168 } 01169 else 01170 { 01171 if (tree_test_data[j].handler_fallback) 01172 _dbus_assert (path_contains (tree_test_data[j].path, 01173 path) == STR_DIFFERENT); 01174 else 01175 _dbus_assert (path_contains (tree_test_data[j].path, path) != STR_EQUAL); 01176 } 01177 01178 ++j; 01179 } 01180 01181 dbus_message_unref (message); 01182 01183 return TRUE; 01184 01185 oom: 01186 if (message) 01187 dbus_message_unref (message); 01188 return FALSE; 01189 } 01190 01191 static size_t 01192 string_array_length (char **array) 01193 { 01194 size_t i; 01195 for (i = 0; array[i]; i++) ; 01196 return i; 01197 } 01198 01199 01200 static dbus_bool_t 01201 object_tree_test_iteration (void *data) 01202 { 01203 const char *path1[] = { "foo", NULL }; 01204 const char *path2[] = { "foo", "bar", NULL }; 01205 const char *path3[] = { "foo", "bar", "baz", NULL }; 01206 const char *path4[] = { "foo", "bar", "boo", NULL }; 01207 const char *path5[] = { "blah", NULL }; 01208 const char *path6[] = { "blah", "boof", NULL }; 01209 const char *path7[] = { "blah", "boof", "this", "is", "really", "long", NULL }; 01210 const char *path8[] = { "childless", NULL }; 01211 DBusObjectTree *tree; 01212 TreeTestData tree_test_data[8]; 01213 int i; 01214 dbus_bool_t exact_match; 01215 01216 tree = NULL; 01217 01218 tree = _dbus_object_tree_new (NULL); 01219 if (tree == NULL) 01220 goto out; 01221 01222 if (!do_register (tree, path1, TRUE, 0, tree_test_data)) 01223 goto out; 01224 01225 _dbus_assert (find_subtree (tree, path1, NULL)); 01226 _dbus_assert (!find_subtree (tree, path2, NULL)); 01227 _dbus_assert (!find_subtree (tree, path3, NULL)); 01228 _dbus_assert (!find_subtree (tree, path4, NULL)); 01229 _dbus_assert (!find_subtree (tree, path5, NULL)); 01230 _dbus_assert (!find_subtree (tree, path6, NULL)); 01231 _dbus_assert (!find_subtree (tree, path7, NULL)); 01232 _dbus_assert (!find_subtree (tree, path8, NULL)); 01233 01234 _dbus_assert (find_handler (tree, path1, &exact_match) && exact_match); 01235 _dbus_assert (find_handler (tree, path2, &exact_match) && !exact_match); 01236 _dbus_assert (find_handler (tree, path3, &exact_match) && !exact_match); 01237 _dbus_assert (find_handler (tree, path4, &exact_match) && !exact_match); 01238 _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match); 01239 _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match); 01240 _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match); 01241 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match); 01242 01243 if (!do_register (tree, path2, TRUE, 1, tree_test_data)) 01244 goto out; 01245 01246 _dbus_assert (find_subtree (tree, path1, NULL)); 01247 _dbus_assert (find_subtree (tree, path2, NULL)); 01248 _dbus_assert (!find_subtree (tree, path3, NULL)); 01249 _dbus_assert (!find_subtree (tree, path4, NULL)); 01250 _dbus_assert (!find_subtree (tree, path5, NULL)); 01251 _dbus_assert (!find_subtree (tree, path6, NULL)); 01252 _dbus_assert (!find_subtree (tree, path7, NULL)); 01253 _dbus_assert (!find_subtree (tree, path8, NULL)); 01254 01255 if (!do_register (tree, path3, TRUE, 2, tree_test_data)) 01256 goto out; 01257 01258 _dbus_assert (find_subtree (tree, path1, NULL)); 01259 _dbus_assert (find_subtree (tree, path2, NULL)); 01260 _dbus_assert (find_subtree (tree, path3, NULL)); 01261 _dbus_assert (!find_subtree (tree, path4, NULL)); 01262 _dbus_assert (!find_subtree (tree, path5, NULL)); 01263 _dbus_assert (!find_subtree (tree, path6, NULL)); 01264 _dbus_assert (!find_subtree (tree, path7, NULL)); 01265 _dbus_assert (!find_subtree (tree, path8, NULL)); 01266 01267 if (!do_register (tree, path4, TRUE, 3, tree_test_data)) 01268 goto out; 01269 01270 _dbus_assert (find_subtree (tree, path1, NULL)); 01271 _dbus_assert (find_subtree (tree, path2, NULL)); 01272 _dbus_assert (find_subtree (tree, path3, NULL)); 01273 _dbus_assert (find_subtree (tree, path4, NULL)); 01274 _dbus_assert (!find_subtree (tree, path5, NULL)); 01275 _dbus_assert (!find_subtree (tree, path6, NULL)); 01276 _dbus_assert (!find_subtree (tree, path7, NULL)); 01277 _dbus_assert (!find_subtree (tree, path8, NULL)); 01278 01279 if (!do_register (tree, path5, TRUE, 4, tree_test_data)) 01280 goto out; 01281 01282 _dbus_assert (find_subtree (tree, path1, NULL)); 01283 _dbus_assert (find_subtree (tree, path2, NULL)); 01284 _dbus_assert (find_subtree (tree, path3, NULL)); 01285 _dbus_assert (find_subtree (tree, path4, NULL)); 01286 _dbus_assert (find_subtree (tree, path5, NULL)); 01287 _dbus_assert (!find_subtree (tree, path6, NULL)); 01288 _dbus_assert (!find_subtree (tree, path7, NULL)); 01289 _dbus_assert (!find_subtree (tree, path8, NULL)); 01290 01291 _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match); 01292 _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match); 01293 _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match); 01294 _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match); 01295 _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match); 01296 _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && !exact_match); 01297 _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && !exact_match); 01298 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match); 01299 01300 if (!do_register (tree, path6, TRUE, 5, tree_test_data)) 01301 goto out; 01302 01303 _dbus_assert (find_subtree (tree, path1, NULL)); 01304 _dbus_assert (find_subtree (tree, path2, NULL)); 01305 _dbus_assert (find_subtree (tree, path3, NULL)); 01306 _dbus_assert (find_subtree (tree, path4, NULL)); 01307 _dbus_assert (find_subtree (tree, path5, NULL)); 01308 _dbus_assert (find_subtree (tree, path6, NULL)); 01309 _dbus_assert (!find_subtree (tree, path7, NULL)); 01310 _dbus_assert (!find_subtree (tree, path8, NULL)); 01311 01312 if (!do_register (tree, path7, TRUE, 6, tree_test_data)) 01313 goto out; 01314 01315 _dbus_assert (find_subtree (tree, path1, NULL)); 01316 _dbus_assert (find_subtree (tree, path2, NULL)); 01317 _dbus_assert (find_subtree (tree, path3, NULL)); 01318 _dbus_assert (find_subtree (tree, path4, NULL)); 01319 _dbus_assert (find_subtree (tree, path5, NULL)); 01320 _dbus_assert (find_subtree (tree, path6, NULL)); 01321 _dbus_assert (find_subtree (tree, path7, NULL)); 01322 _dbus_assert (!find_subtree (tree, path8, NULL)); 01323 01324 if (!do_register (tree, path8, TRUE, 7, tree_test_data)) 01325 goto out; 01326 01327 _dbus_assert (find_subtree (tree, path1, NULL)); 01328 _dbus_assert (find_subtree (tree, path2, NULL)); 01329 _dbus_assert (find_subtree (tree, path3, NULL)); 01330 _dbus_assert (find_subtree (tree, path4, NULL)); 01331 _dbus_assert (find_subtree (tree, path5, NULL)); 01332 _dbus_assert (find_subtree (tree, path6, NULL)); 01333 _dbus_assert (find_subtree (tree, path7, NULL)); 01334 _dbus_assert (find_subtree (tree, path8, NULL)); 01335 01336 _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match); 01337 _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match); 01338 _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match); 01339 _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match); 01340 _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match); 01341 _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && exact_match); 01342 _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && exact_match); 01343 _dbus_assert (find_handler (tree, path8, &exact_match) != tree->root && exact_match); 01344 01345 /* test the list_registered function */ 01346 01347 { 01348 const char *root[] = { NULL }; 01349 char **child_entries; 01350 int nb; 01351 01352 _dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries); 01353 if (child_entries != NULL) 01354 { 01355 nb = string_array_length (child_entries); 01356 _dbus_assert (nb == 1); 01357 dbus_free_string_array (child_entries); 01358 } 01359 01360 _dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries); 01361 if (child_entries != NULL) 01362 { 01363 nb = string_array_length (child_entries); 01364 _dbus_assert (nb == 2); 01365 dbus_free_string_array (child_entries); 01366 } 01367 01368 _dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries); 01369 if (child_entries != NULL) 01370 { 01371 nb = string_array_length (child_entries); 01372 _dbus_assert (nb == 0); 01373 dbus_free_string_array (child_entries); 01374 } 01375 01376 _dbus_object_tree_list_registered_unlocked (tree, root, &child_entries); 01377 if (child_entries != NULL) 01378 { 01379 nb = string_array_length (child_entries); 01380 _dbus_assert (nb == 3); 01381 dbus_free_string_array (child_entries); 01382 } 01383 } 01384 01385 /* Check that destroying tree calls unregister funcs */ 01386 _dbus_object_tree_unref (tree); 01387 01388 i = 0; 01389 while (i < (int) _DBUS_N_ELEMENTS (tree_test_data)) 01390 { 01391 _dbus_assert (tree_test_data[i].handler_unregistered); 01392 _dbus_assert (!tree_test_data[i].message_handled); 01393 ++i; 01394 } 01395 01396 /* Now start again and try the individual unregister function */ 01397 tree = _dbus_object_tree_new (NULL); 01398 if (tree == NULL) 01399 goto out; 01400 01401 if (!do_register (tree, path1, TRUE, 0, tree_test_data)) 01402 goto out; 01403 if (!do_register (tree, path2, TRUE, 1, tree_test_data)) 01404 goto out; 01405 if (!do_register (tree, path3, TRUE, 2, tree_test_data)) 01406 goto out; 01407 if (!do_register (tree, path4, TRUE, 3, tree_test_data)) 01408 goto out; 01409 if (!do_register (tree, path5, TRUE, 4, tree_test_data)) 01410 goto out; 01411 if (!do_register (tree, path6, TRUE, 5, tree_test_data)) 01412 goto out; 01413 if (!do_register (tree, path7, TRUE, 6, tree_test_data)) 01414 goto out; 01415 if (!do_register (tree, path8, TRUE, 7, tree_test_data)) 01416 goto out; 01417 01418 _dbus_object_tree_unregister_and_unlock (tree, path1); 01419 01420 _dbus_assert (!find_subtree (tree, path1, NULL)); 01421 _dbus_assert (find_subtree (tree, path2, NULL)); 01422 _dbus_assert (find_subtree (tree, path3, NULL)); 01423 _dbus_assert (find_subtree (tree, path4, NULL)); 01424 _dbus_assert (find_subtree (tree, path5, NULL)); 01425 _dbus_assert (find_subtree (tree, path6, NULL)); 01426 _dbus_assert (find_subtree (tree, path7, NULL)); 01427 _dbus_assert (find_subtree (tree, path8, NULL)); 01428 01429 _dbus_object_tree_unregister_and_unlock (tree, path2); 01430 01431 _dbus_assert (!find_subtree (tree, path1, NULL)); 01432 _dbus_assert (!find_subtree (tree, path2, NULL)); 01433 _dbus_assert (find_subtree (tree, path3, NULL)); 01434 _dbus_assert (find_subtree (tree, path4, NULL)); 01435 _dbus_assert (find_subtree (tree, path5, NULL)); 01436 _dbus_assert (find_subtree (tree, path6, NULL)); 01437 _dbus_assert (find_subtree (tree, path7, NULL)); 01438 _dbus_assert (find_subtree (tree, path8, NULL)); 01439 01440 _dbus_object_tree_unregister_and_unlock (tree, path3); 01441 01442 _dbus_assert (!find_subtree (tree, path1, NULL)); 01443 _dbus_assert (!find_subtree (tree, path2, NULL)); 01444 _dbus_assert (!find_subtree (tree, path3, NULL)); 01445 _dbus_assert (find_subtree (tree, path4, NULL)); 01446 _dbus_assert (find_subtree (tree, path5, NULL)); 01447 _dbus_assert (find_subtree (tree, path6, NULL)); 01448 _dbus_assert (find_subtree (tree, path7, NULL)); 01449 _dbus_assert (find_subtree (tree, path8, NULL)); 01450 01451 _dbus_object_tree_unregister_and_unlock (tree, path4); 01452 01453 _dbus_assert (!find_subtree (tree, path1, NULL)); 01454 _dbus_assert (!find_subtree (tree, path2, NULL)); 01455 _dbus_assert (!find_subtree (tree, path3, NULL)); 01456 _dbus_assert (!find_subtree (tree, path4, NULL)); 01457 _dbus_assert (find_subtree (tree, path5, NULL)); 01458 _dbus_assert (find_subtree (tree, path6, NULL)); 01459 _dbus_assert (find_subtree (tree, path7, NULL)); 01460 _dbus_assert (find_subtree (tree, path8, NULL)); 01461 01462 _dbus_object_tree_unregister_and_unlock (tree, path5); 01463 01464 _dbus_assert (!find_subtree (tree, path1, NULL)); 01465 _dbus_assert (!find_subtree (tree, path2, NULL)); 01466 _dbus_assert (!find_subtree (tree, path3, NULL)); 01467 _dbus_assert (!find_subtree (tree, path4, NULL)); 01468 _dbus_assert (!find_subtree (tree, path5, NULL)); 01469 _dbus_assert (find_subtree (tree, path6, NULL)); 01470 _dbus_assert (find_subtree (tree, path7, NULL)); 01471 _dbus_assert (find_subtree (tree, path8, NULL)); 01472 01473 _dbus_object_tree_unregister_and_unlock (tree, path6); 01474 01475 _dbus_assert (!find_subtree (tree, path1, NULL)); 01476 _dbus_assert (!find_subtree (tree, path2, NULL)); 01477 _dbus_assert (!find_subtree (tree, path3, NULL)); 01478 _dbus_assert (!find_subtree (tree, path4, NULL)); 01479 _dbus_assert (!find_subtree (tree, path5, NULL)); 01480 _dbus_assert (!find_subtree (tree, path6, NULL)); 01481 _dbus_assert (find_subtree (tree, path7, NULL)); 01482 _dbus_assert (find_subtree (tree, path8, NULL)); 01483 01484 _dbus_object_tree_unregister_and_unlock (tree, path7); 01485 01486 _dbus_assert (!find_subtree (tree, path1, NULL)); 01487 _dbus_assert (!find_subtree (tree, path2, NULL)); 01488 _dbus_assert (!find_subtree (tree, path3, NULL)); 01489 _dbus_assert (!find_subtree (tree, path4, NULL)); 01490 _dbus_assert (!find_subtree (tree, path5, NULL)); 01491 _dbus_assert (!find_subtree (tree, path6, NULL)); 01492 _dbus_assert (!find_subtree (tree, path7, NULL)); 01493 _dbus_assert (find_subtree (tree, path8, NULL)); 01494 01495 _dbus_object_tree_unregister_and_unlock (tree, path8); 01496 01497 _dbus_assert (!find_subtree (tree, path1, NULL)); 01498 _dbus_assert (!find_subtree (tree, path2, NULL)); 01499 _dbus_assert (!find_subtree (tree, path3, NULL)); 01500 _dbus_assert (!find_subtree (tree, path4, NULL)); 01501 _dbus_assert (!find_subtree (tree, path5, NULL)); 01502 _dbus_assert (!find_subtree (tree, path6, NULL)); 01503 _dbus_assert (!find_subtree (tree, path7, NULL)); 01504 _dbus_assert (!find_subtree (tree, path8, NULL)); 01505 01506 i = 0; 01507 while (i < (int) _DBUS_N_ELEMENTS (tree_test_data)) 01508 { 01509 _dbus_assert (tree_test_data[i].handler_unregistered); 01510 _dbus_assert (!tree_test_data[i].message_handled); 01511 ++i; 01512 } 01513 01514 /* Register it all again, and test dispatch */ 01515 01516 if (!do_register (tree, path1, FALSE, 0, tree_test_data)) 01517 goto out; 01518 if (!do_register (tree, path2, TRUE, 1, tree_test_data)) 01519 goto out; 01520 if (!do_register (tree, path3, TRUE, 2, tree_test_data)) 01521 goto out; 01522 if (!do_register (tree, path4, TRUE, 3, tree_test_data)) 01523 goto out; 01524 if (!do_register (tree, path5, TRUE, 4, tree_test_data)) 01525 goto out; 01526 if (!do_register (tree, path6, FALSE, 5, tree_test_data)) 01527 goto out; 01528 if (!do_register (tree, path7, TRUE, 6, tree_test_data)) 01529 goto out; 01530 if (!do_register (tree, path8, TRUE, 7, tree_test_data)) 01531 goto out; 01532 01533 #if 0 01534 spew_tree (tree); 01535 #endif 01536 01537 if (!do_test_dispatch (tree, path1, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 01538 goto out; 01539 if (!do_test_dispatch (tree, path2, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 01540 goto out; 01541 if (!do_test_dispatch (tree, path3, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 01542 goto out; 01543 if (!do_test_dispatch (tree, path4, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 01544 goto out; 01545 if (!do_test_dispatch (tree, path5, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 01546 goto out; 01547 if (!do_test_dispatch (tree, path6, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 01548 goto out; 01549 if (!do_test_dispatch (tree, path7, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 01550 goto out; 01551 if (!do_test_dispatch (tree, path8, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 01552 goto out; 01553 01554 out: 01555 if (tree) 01556 { 01557 /* test ref */ 01558 _dbus_object_tree_ref (tree); 01559 _dbus_object_tree_unref (tree); 01560 _dbus_object_tree_unref (tree); 01561 } 01562 01563 return TRUE; 01564 } 01565 01571 dbus_bool_t 01572 _dbus_object_tree_test (void) 01573 { 01574 _dbus_test_oom_handling ("object tree", 01575 object_tree_test_iteration, 01576 NULL); 01577 01578 return TRUE; 01579 } 01580 01581 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Oct 12 02:07:53 2004 for D-BUS by doxygen 1.3.7