From 6be547d32f018c23ba56426a0bccd08baa2cf440 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 11 Apr 2003 00:03:06 +0000 Subject: 2003-04-10 Havoc Pennington * dbus/dbus-connection.c (dbus_connection_flush): don't spin on the connection if it's disconnected * bus/activation.c (bus_activation_service_created): use new transaction features to roll back removal of pending activation if we don't successfully create the service after all. Don't remove pending activation if the function fails. * dbus/dbus-list.c (_dbus_list_insert_before_link) (_dbus_list_insert_after_link): new code to facilitate services.c fixes * dbus/dbus-hash.c (_dbus_hash_table_insert_string_preallocated): new functionality, so we can preallocate the ability to insert into a hash table. * bus/connection.c (bus_transaction_add_cancel_hook): new function allowing us to put custom hooks in a transaction to be used for cancelling said transaction * doc/dbus-specification.sgml: add some discussion of secondary service owners, and disallow zero-length service names * bus/services.c (bus_registry_acquire_service): new function, splits out part of bus_driver_handle_acquire_service() and fixes a bug where we didn't remove the service doing the acquiring from the secondary queue if we failed to remove the current owner from the front of the queue. --- dbus/dbus-connection.c | 5 +- dbus/dbus-hash.c | 256 +++++++++++++++++++++++++++++++++++-------------- dbus/dbus-hash.h | 11 +++ dbus/dbus-list.c | 36 +++++++ dbus/dbus-list.h | 76 ++++++++------- dbus/dbus-spawn.c | 6 +- 6 files changed, 277 insertions(+), 113 deletions(-) (limited to 'dbus') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 0961e49d..5a6277de 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -558,7 +558,7 @@ _dbus_connection_do_iteration (DBusConnection *connection, flags &= ~DBUS_ITERATION_DO_WRITING; if (_dbus_connection_acquire_io_path (connection, - (flags & DBUS_ITERATION_BLOCK)?timeout_milliseconds:0)) + (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0)) { _dbus_transport_do_iteration (connection->transport, flags, timeout_milliseconds); @@ -1596,7 +1596,8 @@ dbus_connection_flush (DBusConnection *connection) DBusDispatchStatus status; dbus_mutex_lock (connection->mutex); - while (connection->n_outgoing > 0) + while (connection->n_outgoing > 0 && + dbus_connection_get_is_connected (connection)) _dbus_connection_do_iteration (connection, DBUS_ITERATION_DO_READING | DBUS_ITERATION_DO_WRITING | diff --git a/dbus/dbus-hash.c b/dbus/dbus-hash.c index ff3f3b08..8d2747b4 100644 --- a/dbus/dbus-hash.c +++ b/dbus/dbus-hash.c @@ -152,10 +152,11 @@ struct DBusHashEntry /** * Function used to find and optionally create a hash entry. */ -typedef DBusHashEntry* (* DBusFindEntryFunction) (DBusHashTable *table, - void *key, - dbus_bool_t create_if_not_found, - DBusHashEntry ***bucket); +typedef DBusHashEntry* (* DBusFindEntryFunction) (DBusHashTable *table, + void *key, + dbus_bool_t create_if_not_found, + DBusHashEntry ***bucket, + DBusPreallocatedHash *preallocated); /** * @brief Internals of DBusHashTable. @@ -220,24 +221,27 @@ typedef struct int n_entries_on_init; /**< used to detect table resize since initialization */ } DBusRealHashIter; -static DBusHashEntry* find_direct_function (DBusHashTable *table, - void *key, - dbus_bool_t create_if_not_found, - DBusHashEntry ***bucket); -static DBusHashEntry* find_string_function (DBusHashTable *table, - void *key, - dbus_bool_t create_if_not_found, - DBusHashEntry ***bucket); -static unsigned int string_hash (const char *str); -static void rebuild_table (DBusHashTable *table); -static DBusHashEntry* alloc_entry (DBusHashTable *table); -static void remove_entry (DBusHashTable *table, - DBusHashEntry **bucket, - DBusHashEntry *entry); -static void free_entry (DBusHashTable *table, - DBusHashEntry *entry); -static void free_entry_data (DBusHashTable *table, - DBusHashEntry *entry); +static DBusHashEntry* find_direct_function (DBusHashTable *table, + void *key, + dbus_bool_t create_if_not_found, + DBusHashEntry ***bucket, + DBusPreallocatedHash *preallocated); +static DBusHashEntry* find_string_function (DBusHashTable *table, + void *key, + dbus_bool_t create_if_not_found, + DBusHashEntry ***bucket, + DBusPreallocatedHash *preallocated); +static unsigned int string_hash (const char *str); +static void rebuild_table (DBusHashTable *table); +static DBusHashEntry* alloc_entry (DBusHashTable *table); +static void remove_entry (DBusHashTable *table, + DBusHashEntry **bucket, + DBusHashEntry *entry); +static void free_entry (DBusHashTable *table, + DBusHashEntry *entry); +static void free_entry_data (DBusHashTable *table, + DBusHashEntry *entry); + /** @} */ @@ -725,7 +729,7 @@ _dbus_hash_iter_lookup (DBusHashTable *table, real = (DBusRealHashIter*) iter; - entry = (* table->find_function) (table, key, create_if_not_found, &bucket); + entry = (* table->find_function) (table, key, create_if_not_found, &bucket, NULL); if (entry == NULL) return FALSE; @@ -742,22 +746,14 @@ _dbus_hash_iter_lookup (DBusHashTable *table, return TRUE; } -static DBusHashEntry* -add_entry (DBusHashTable *table, - unsigned int idx, - void *key, - DBusHashEntry ***bucket) +static void +add_allocated_entry (DBusHashTable *table, + DBusHashEntry *entry, + unsigned int idx, + void *key, + DBusHashEntry ***bucket) { - DBusHashEntry *entry; - DBusHashEntry **b; - - entry = alloc_entry (table); - if (entry == NULL) - { - if (bucket) - *bucket = NULL; - return NULL; - } + DBusHashEntry **b; entry->key = key; @@ -776,10 +772,37 @@ add_entry (DBusHashTable *table, if (table->n_entries >= table->hi_rebuild_size || table->n_entries < table->lo_rebuild_size) rebuild_table (table); +} + +static DBusHashEntry* +add_entry (DBusHashTable *table, + unsigned int idx, + void *key, + DBusHashEntry ***bucket, + DBusPreallocatedHash *preallocated) +{ + DBusHashEntry *entry; + + if (preallocated == NULL) + { + entry = alloc_entry (table); + if (entry == NULL) + { + if (bucket) + *bucket = NULL; + return NULL; + } + } + else + { + entry = (DBusHashEntry*) preallocated; + } + + add_allocated_entry (table, entry, idx, key, bucket); return entry; } - + static unsigned int string_hash (const char *str) { @@ -802,6 +825,8 @@ string_hash (const char *str) * works well both for decimal and non-decimal strings. */ + /* FIXME the hash function in GLib is better than this one */ + result = 0; while (TRUE) { @@ -817,10 +842,11 @@ string_hash (const char *str) } static DBusHashEntry* -find_string_function (DBusHashTable *table, - void *key, - dbus_bool_t create_if_not_found, - DBusHashEntry ***bucket) +find_string_function (DBusHashTable *table, + void *key, + dbus_bool_t create_if_not_found, + DBusHashEntry ***bucket, + DBusPreallocatedHash *preallocated) { DBusHashEntry *entry; unsigned int idx; @@ -838,6 +864,10 @@ find_string_function (DBusHashTable *table, { if (bucket) *bucket = &(table->buckets[idx]); + + if (preallocated) + _dbus_hash_table_free_preallocated_entry (table, preallocated); + return entry; } @@ -845,16 +875,19 @@ find_string_function (DBusHashTable *table, } if (create_if_not_found) - entry = add_entry (table, idx, key, bucket); + entry = add_entry (table, idx, key, bucket, preallocated); + else if (preallocated) + _dbus_hash_table_free_preallocated_entry (table, preallocated); return entry; } static DBusHashEntry* -find_direct_function (DBusHashTable *table, - void *key, - dbus_bool_t create_if_not_found, - DBusHashEntry ***bucket) +find_direct_function (DBusHashTable *table, + void *key, + dbus_bool_t create_if_not_found, + DBusHashEntry ***bucket, + DBusPreallocatedHash *preallocated) { DBusHashEntry *entry; unsigned int idx; @@ -872,6 +905,10 @@ find_direct_function (DBusHashTable *table, { if (bucket) *bucket = &(table->buckets[idx]); + + if (preallocated) + _dbus_hash_table_free_preallocated_entry (table, preallocated); + return entry; } @@ -880,7 +917,9 @@ find_direct_function (DBusHashTable *table, /* Entry not found. Add a new one to the bucket. */ if (create_if_not_found) - entry = add_entry (table, idx, key, bucket); + entry = add_entry (table, idx, key, bucket, preallocated); + else if (preallocated) + _dbus_hash_table_free_preallocated_entry (table, preallocated); return entry; } @@ -1022,7 +1061,7 @@ _dbus_hash_table_lookup_string (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_STRING); - entry = (* table->find_function) (table, (char*) key, FALSE, NULL); + entry = (* table->find_function) (table, (char*) key, FALSE, NULL, NULL); if (entry) return entry->value; @@ -1047,7 +1086,7 @@ _dbus_hash_table_lookup_int (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_INT); - entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, NULL); + entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, NULL, NULL); if (entry) return entry->value; @@ -1072,7 +1111,7 @@ _dbus_hash_table_lookup_pointer (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_POINTER); - entry = (* table->find_function) (table, key, FALSE, NULL); + entry = (* table->find_function) (table, key, FALSE, NULL, NULL); if (entry) return entry->value; @@ -1097,7 +1136,7 @@ _dbus_hash_table_lookup_ulong (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_ULONG); - entry = (* table->find_function) (table, (void*) key, FALSE, NULL); + entry = (* table->find_function) (table, (void*) key, FALSE, NULL, NULL); if (entry) return entry->value; @@ -1122,7 +1161,7 @@ _dbus_hash_table_remove_string (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_STRING); - entry = (* table->find_function) (table, (char*) key, FALSE, &bucket); + entry = (* table->find_function) (table, (char*) key, FALSE, &bucket, NULL); if (entry) { @@ -1150,7 +1189,7 @@ _dbus_hash_table_remove_int (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_INT); - entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, &bucket); + entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, &bucket, NULL); if (entry) { @@ -1178,7 +1217,7 @@ _dbus_hash_table_remove_pointer (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_POINTER); - entry = (* table->find_function) (table, key, FALSE, &bucket); + entry = (* table->find_function) (table, key, FALSE, &bucket, NULL); if (entry) { @@ -1207,7 +1246,7 @@ _dbus_hash_table_remove_ulong (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_ULONG); - entry = (* table->find_function) (table, (void*) key, FALSE, &bucket); + entry = (* table->find_function) (table, (void*) key, FALSE, &bucket, NULL); if (entry) { @@ -1238,24 +1277,17 @@ _dbus_hash_table_insert_string (DBusHashTable *table, char *key, void *value) { - DBusHashEntry *entry; + DBusPreallocatedHash *preallocated; _dbus_assert (table->key_type == DBUS_HASH_STRING); - - entry = (* table->find_function) (table, key, TRUE, NULL); - - if (entry == NULL) - return FALSE; /* no memory */ - - if (table->free_key_function && entry->key != key) - (* table->free_key_function) (entry->key); - if (table->free_value_function && entry->value != value) - (* table->free_value_function) (entry->value); - - entry->key = key; - entry->value = value; + preallocated = _dbus_hash_table_preallocate_entry (table); + if (preallocated == NULL) + return FALSE; + _dbus_hash_table_insert_string_preallocated (table, preallocated, + key, value); + return TRUE; } @@ -1283,7 +1315,7 @@ _dbus_hash_table_insert_int (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_INT); - entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), TRUE, NULL); + entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), TRUE, NULL, NULL); if (entry == NULL) return FALSE; /* no memory */ @@ -1324,7 +1356,7 @@ _dbus_hash_table_insert_pointer (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_POINTER); - entry = (* table->find_function) (table, key, TRUE, NULL); + entry = (* table->find_function) (table, key, TRUE, NULL, NULL); if (entry == NULL) return FALSE; /* no memory */ @@ -1366,7 +1398,7 @@ _dbus_hash_table_insert_ulong (DBusHashTable *table, _dbus_assert (table->key_type == DBUS_HASH_ULONG); - entry = (* table->find_function) (table, (void*) key, TRUE, NULL); + entry = (* table->find_function) (table, (void*) key, TRUE, NULL, NULL); if (entry == NULL) return FALSE; /* no memory */ @@ -1383,6 +1415,82 @@ _dbus_hash_table_insert_ulong (DBusHashTable *table, return TRUE; } +/** + * Preallocate an opaque data blob that allows us to insert into the + * hash table at a later time without allocating any memory. + * + * @param table the hash table + * @returns the preallocated data, or #NULL if no memory + */ +DBusPreallocatedHash* +_dbus_hash_table_preallocate_entry (DBusHashTable *table) +{ + DBusHashEntry *entry; + + entry = alloc_entry (table); + + return (DBusPreallocatedHash*) entry; +} + +/** + * Frees an opaque DBusPreallocatedHash that was *not* used + * in order to insert into the hash table. + * + * @param table the hash table + * @param preallocated the preallocated data + */ +void +_dbus_hash_table_free_preallocated_entry (DBusHashTable *table, + DBusPreallocatedHash *preallocated) +{ + DBusHashEntry *entry; + + _dbus_assert (preallocated != NULL); + + entry = (DBusHashEntry*) preallocated; + + /* Don't use free_entry(), since this entry has no key/data */ + _dbus_mem_pool_dealloc (table->entry_pool, entry); +} + +/** + * Inserts a string-keyed entry into the hash table, using a + * preallocated data block from + * _dbus_hash_table_preallocate_entry(). This function cannot fail due + * to lack of memory. The DBusPreallocatedHash object is consumed and + * should not be reused or freed. Otherwise this function works + * just like _dbus_hash_table_insert_string(). + * + * @param table the hash table + * @param preallocated the preallocated data + * @param key the hash key + * @param value the value + */ +void +_dbus_hash_table_insert_string_preallocated (DBusHashTable *table, + DBusPreallocatedHash *preallocated, + char *key, + void *value) +{ + DBusHashEntry *entry; + + _dbus_assert (table->key_type == DBUS_HASH_STRING); + _dbus_assert (preallocated != NULL); + + entry = (* table->find_function) (table, key, TRUE, NULL, preallocated); + + _dbus_assert (entry != NULL); + + if (table->free_key_function && entry->key != key) + (* table->free_key_function) (entry->key); + + if (table->free_value_function && entry->value != value) + (* table->free_value_function) (entry->value); + + entry->key = key; + entry->value = value; +} + /** * Gets the number of hash entries in a hash table. * diff --git a/dbus/dbus-hash.h b/dbus/dbus-hash.h index b9efcebb..566d4021 100644 --- a/dbus/dbus-hash.h +++ b/dbus/dbus-hash.h @@ -108,6 +108,17 @@ dbus_bool_t _dbus_hash_table_insert_ulong (DBusHashTable *table, int _dbus_hash_table_get_n_entries (DBusHashTable *table); +/* Preallocation */ +typedef struct DBusPreallocatedHash DBusPreallocatedHash; + +DBusPreallocatedHash *_dbus_hash_table_preallocate_entry (DBusHashTable *table); +void _dbus_hash_table_free_preallocated_entry (DBusHashTable *table, + DBusPreallocatedHash *preallocated); +void _dbus_hash_table_insert_string_preallocated (DBusHashTable *table, + DBusPreallocatedHash *preallocated, + char *key, + void *value); + DBUS_END_DECLS; diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c index c6205971..5f4c67ca 100644 --- a/dbus/dbus-list.c +++ b/dbus/dbus-list.c @@ -371,6 +371,42 @@ _dbus_list_insert_after (DBusList **list, return TRUE; } +/** + * Inserts a link into the list before the given existing link. + * + * @param list the list to modify + * @param before_this_link existing link to insert before, or #NULL to append + * @param link the link to insert + */ +void +_dbus_list_insert_before_link (DBusList **list, + DBusList *before_this_link, + DBusList *link) +{ + if (before_this_link == NULL) + _dbus_list_append_link (list, link); + else + link_before (list, before_this_link, link); +} + +/** + * Inserts a link into the list after the given existing link. + * + * @param list the list to modify + * @param after_this_link existing link to insert after, or #NULL to prepend + * @param link the link to insert + */ +void +_dbus_list_insert_after_link (DBusList **list, + DBusList *after_this_link, + DBusList *link) +{ + if (after_this_link == NULL) + _dbus_list_prepend_link (list, link); + else + link_after (list, after_this_link, link); +} + /** * Removes a value from the list. Only removes the * first value equal to the given data pointer, diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h index 5f42ca3c..ad74dfd0 100644 --- a/dbus/dbus-list.h +++ b/dbus/dbus-list.h @@ -38,44 +38,50 @@ struct DBusList DBusList *next; /**< Next list node. */ void *data; /**< Data stored at this element. */ }; +dbus_bool_t _dbus_list_append (DBusList **list, + void *data); +dbus_bool_t _dbus_list_prepend (DBusList **list, + void *data); +dbus_bool_t _dbus_list_insert_before (DBusList **list, + DBusList *before_this_link, + void *data); +dbus_bool_t _dbus_list_insert_after (DBusList **list, + DBusList *after_this_link, + void *data); +void _dbus_list_insert_before_link (DBusList **list, + DBusList *before_this_link, + DBusList *link); +void _dbus_list_insert_after_link (DBusList **list, + DBusList *after_this_link, + DBusList *link); +dbus_bool_t _dbus_list_remove (DBusList **list, + void *data); +dbus_bool_t _dbus_list_remove_last (DBusList **list, + void *data); +void _dbus_list_remove_link (DBusList **list, + DBusList *link); +void _dbus_list_clear (DBusList **list); +DBusList* _dbus_list_get_first_link (DBusList **list); +DBusList* _dbus_list_get_last_link (DBusList **list); +void* _dbus_list_get_last (DBusList **list); +void* _dbus_list_get_first (DBusList **list); +void* _dbus_list_pop_first (DBusList **list); +void* _dbus_list_pop_last (DBusList **list); +DBusList* _dbus_list_pop_first_link (DBusList **list); +DBusList* _dbus_list_pop_last_link (DBusList **list); +dbus_bool_t _dbus_list_copy (DBusList **list, + DBusList **dest); +int _dbus_list_get_length (DBusList **list); +DBusList* _dbus_list_alloc_link (void *data); +void _dbus_list_free_link (DBusList *link); +void _dbus_list_append_link (DBusList **list, + DBusList *link); +void _dbus_list_prepend_link (DBusList **list, + DBusList *link); +dbus_bool_t _dbus_list_length_is_one (DBusList **list); -dbus_bool_t _dbus_list_append (DBusList **list, - void *data); -dbus_bool_t _dbus_list_prepend (DBusList **list, - void *data); -dbus_bool_t _dbus_list_insert_before (DBusList **list, - DBusList *before_this_link, - void *data); -dbus_bool_t _dbus_list_insert_after (DBusList **list, - DBusList *after_this_link, - void *data); -dbus_bool_t _dbus_list_remove (DBusList **list, - void *data); -dbus_bool_t _dbus_list_remove_last (DBusList **list, - void *data); -void _dbus_list_remove_link (DBusList **list, - DBusList *link); -void _dbus_list_clear (DBusList **list); -DBusList* _dbus_list_get_first_link (DBusList **list); -DBusList* _dbus_list_get_last_link (DBusList **list); -void* _dbus_list_get_last (DBusList **list); -void* _dbus_list_get_first (DBusList **list); -void* _dbus_list_pop_first (DBusList **list); -void* _dbus_list_pop_last (DBusList **list); -DBusList* _dbus_list_pop_first_link (DBusList **list); -DBusList* _dbus_list_pop_last_link (DBusList **list); -dbus_bool_t _dbus_list_copy (DBusList **list, - DBusList **dest); -int _dbus_list_get_length (DBusList **list); -DBusList* _dbus_list_alloc_link (void *data); -void _dbus_list_free_link (DBusList *link); -void _dbus_list_append_link (DBusList **list, - DBusList *link); -void _dbus_list_prepend_link (DBusList **list, - DBusList *link); -dbus_bool_t _dbus_list_length_is_one (DBusList **list); void _dbus_list_foreach (DBusList **list, DBusForeachFunction function, diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c index 87e1ffc2..0e08cd78 100644 --- a/dbus/dbus-spawn.c +++ b/dbus/dbus-spawn.c @@ -879,6 +879,8 @@ check_babysit_events (pid_t grandchild_pid, else if (ret == grandchild_pid) { /* Child exited */ + _dbus_verbose ("reaped child pid %ld\n", (long) ret); + write_status_and_exit (parent_pipe, status); } else @@ -890,13 +892,13 @@ check_babysit_events (pid_t grandchild_pid, if (revents & _DBUS_POLLIN) { - /* Data to read from parent */ - + _dbus_verbose ("babysitter got POLLIN from parent pipe\n"); } if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP)) { /* Parent is gone, so we just exit */ + _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n"); _exit (0); } } -- cgit