2003-03-15 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / bus / services.c
index 22302af..92f6cdf 100644 (file)
 
 struct BusService
 {
+  BusRegistry *registry;
   char *name;
   DBusList *owners;
   
   unsigned int prohibit_replacement : 1;
 };
 
-static DBusHashTable *service_hash = NULL;
-static DBusMemPool   *service_pool = NULL;
+struct BusRegistry
+{
+  int refcount;
+  
+  DBusHashTable *service_hash;
+  DBusMemPool   *service_pool;
+};
 
-static dbus_bool_t
-init_hash (void)
+BusRegistry*
+bus_registry_new (void)
 {
-  if (service_hash == NULL)
+  BusRegistry *registry;
+
+  registry = dbus_new0 (BusRegistry, 1);
+  if (registry == NULL)
+    return NULL;
+
+  registry->refcount = 1;
+
+  registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                                 NULL, NULL);
+  if (registry->service_hash == NULL)
+    goto failed;
+  
+  registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
+                                               TRUE);
+  if (registry->service_pool == NULL)
+    goto failed;
+
+  return registry;
+
+ failed:
+  bus_registry_unref (registry);
+  return NULL;
+}
+
+void
+bus_registry_ref (BusRegistry *registry)
+{
+  _dbus_assert (registry->refcount > 0);
+  registry->refcount += 1;
+}
+
+void
+bus_registry_unref  (BusRegistry *registry)
+{
+  _dbus_assert (registry->refcount > 0);
+  registry->refcount -= 1;
+
+  if (registry->refcount == 0)
     {
-      service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
-                                           NULL, NULL);
-      service_pool = _dbus_mem_pool_new (sizeof (BusService),
-                                         TRUE);
+      if (registry->service_hash)
+        _dbus_hash_table_unref (registry->service_hash);
+      if (registry->service_pool)
+        _dbus_mem_pool_free (registry->service_pool);
 
-      if (service_hash == NULL || service_pool == NULL)
-        {
-          if (service_hash)
-            {
-              _dbus_hash_table_unref (service_hash);
-              service_hash = NULL;
-            }
-          if (service_pool)
-            {
-              _dbus_mem_pool_free (service_pool);
-              service_pool = NULL;
-            }
-          return FALSE;
-        }
+      dbus_free (registry);
     }
-  return TRUE;
 }
 
 BusService*
-bus_service_lookup (const DBusString *service_name)
+bus_registry_lookup (BusRegistry      *registry,
+                     const DBusString *service_name)
 {
   const char *c_name;
   BusService *service;
   
-  if (!init_hash ())
-    return NULL;
-  
   _dbus_string_get_const_data (service_name, &c_name);
 
-  service = _dbus_hash_table_lookup_string (service_hash,
+  service = _dbus_hash_table_lookup_string (registry->service_hash,
                                             c_name);
 
   return service;
 }
 
 BusService*
-bus_service_ensure (const DBusString          *service_name,
-                    DBusConnection            *owner_if_created,
-                    BusTransaction            *transaction,
-                    DBusError                 *error)
+bus_registry_ensure (BusRegistry               *registry,
+                     const DBusString          *service_name,
+                     DBusConnection            *owner_if_created,
+                     BusTransaction            *transaction,
+                     DBusError                 *error)
 {
   const char *c_name;
   BusService *service;
@@ -98,27 +127,26 @@ bus_service_ensure (const DBusString          *service_name,
   _dbus_assert (owner_if_created != NULL);
   _dbus_assert (transaction != NULL);
   
-  if (!init_hash ())
-    return NULL;
-  
   _dbus_string_get_const_data (service_name, &c_name);
 
-  service = _dbus_hash_table_lookup_string (service_hash,
+  service = _dbus_hash_table_lookup_string (registry->service_hash,
                                             c_name);
   if (service != NULL)
     return service;
   
-  service = _dbus_mem_pool_alloc (service_pool);
+  service = _dbus_mem_pool_alloc (registry->service_pool);
   if (service == NULL)
     {
       BUS_SET_OOM (error);
       return NULL;
     }
 
+  service->registry = registry;  
+
   service->name = _dbus_strdup (c_name);
   if (service->name == NULL)
     {
-      _dbus_mem_pool_dealloc (service_pool, service);
+      _dbus_mem_pool_dealloc (registry->service_pool, service);
       BUS_SET_OOM (error);
       return NULL;
     }
@@ -126,7 +154,7 @@ bus_service_ensure (const DBusString          *service_name,
   if (!bus_driver_send_service_created (service->name, transaction, error))
     {
       dbus_free (service->name);
-      _dbus_mem_pool_dealloc (service_pool, service);
+      _dbus_mem_pool_dealloc (registry->service_pool, service);
       return NULL;
     }
 
@@ -134,17 +162,19 @@ bus_service_ensure (const DBusString          *service_name,
                               transaction, error))
     {
       dbus_free (service->name);
-      _dbus_mem_pool_dealloc (service_pool, service);
+      _dbus_mem_pool_dealloc (registry->service_pool, service);
       return NULL;
     }
   
-  if (!_dbus_hash_table_insert_string (service_hash,
+  if (!_dbus_hash_table_insert_string (registry->service_hash,
                                        service->name,
                                        service))
     {
+      bus_connection_remove_owned_service (owner_if_created,
+                                           service);
       _dbus_list_clear (&service->owners);
       dbus_free (service->name);
-      _dbus_mem_pool_dealloc (service_pool, service);
+      _dbus_mem_pool_dealloc (registry->service_pool, service);
       BUS_SET_OOM (error);
       return NULL;
     }
@@ -152,6 +182,66 @@ bus_service_ensure (const DBusString          *service_name,
   return service;
 }
 
+void
+bus_registry_foreach (BusRegistry               *registry,
+                      BusServiceForeachFunction  function,
+                      void                      *data)
+{
+  DBusHashIter iter;
+  
+  _dbus_hash_iter_init (registry->service_hash, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      BusService *service = _dbus_hash_iter_get_value (&iter);
+
+      (* function) (service, data);
+    }
+}
+
+dbus_bool_t
+bus_registry_list_services (BusRegistry *registry,
+                            char      ***listp,
+                            int         *array_len)
+{
+  int i, j, len;
+  char **retval;
+  DBusHashIter iter;
+   
+  len = _dbus_hash_table_get_n_entries (registry->service_hash);
+  retval = dbus_new (char *, len + 1);
+
+  if (retval == NULL)
+    return FALSE;
+
+  _dbus_hash_iter_init (registry->service_hash, &iter);
+  i = 0;
+  while (_dbus_hash_iter_next (&iter))
+    {
+      BusService *service = _dbus_hash_iter_get_value (&iter);
+
+      retval[i] = _dbus_strdup (service->name);
+      if (retval[i] == NULL)
+       goto error;
+
+      i++;
+    }
+
+  retval[i] = NULL;
+  
+  if (array_len)
+    *array_len = len;
+  
+  *listp = retval;
+  return TRUE;
+  
+ error:
+  for (j = 0; j < i; j++)
+    dbus_free (retval[i]);
+  dbus_free (retval);
+
+  return FALSE;
+}
+
 dbus_bool_t
 bus_service_add_owner (BusService     *service,
                        DBusConnection *owner,
@@ -202,7 +292,11 @@ bus_service_remove_owner (BusService     *service,
         return FALSE;
     }
 
-  if (_dbus_list_length_is_one (&service->owners))
+  if (service->owners == NULL)
+    {
+      _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
+    }
+  else if (_dbus_list_length_is_one (&service->owners))
     {
       /* We are the only owner - send service deleted */
       if (!bus_driver_send_service_deleted (service->name,
@@ -213,6 +307,7 @@ bus_service_remove_owner (BusService     *service,
     {
       DBusList *link;
       link = _dbus_list_get_first (&service->owners);
+      _dbus_assert (link != NULL);
       link = _dbus_list_get_next_link (&service->owners, link);
 
       if (link != NULL)
@@ -232,10 +327,11 @@ bus_service_remove_owner (BusService     *service,
   if (service->owners == NULL)
     {
       /* Delete service (already sent message that it was deleted above) */
-      _dbus_hash_table_remove_string (service_hash, service->name);
+      _dbus_hash_table_remove_string (service->registry->service_hash,
+                                      service->name);
       
       dbus_free (service->name);
-      _dbus_mem_pool_dealloc (service_pool, service);
+      _dbus_mem_pool_dealloc (service->registry->service_pool, service);
     }
 
   return TRUE;
@@ -254,65 +350,6 @@ bus_service_get_name (BusService *service)
 }
 
 void
-bus_service_foreach (BusServiceForeachFunction  function,
-                     void                      *data)
-{
-  DBusHashIter iter;
-  
-  if (service_hash == NULL)
-    return;
-  
-  _dbus_hash_iter_init (service_hash, &iter);
-  while (_dbus_hash_iter_next (&iter))
-    {
-      BusService *service = _dbus_hash_iter_get_value (&iter);
-
-      (* function) (service, data);
-    }
-}
-
-char **
-bus_services_list (int *array_len)
-{
-  int i, j, len;
-  char **retval;
-  DBusHashIter iter;
-   
-  len = _dbus_hash_table_get_n_entries (service_hash);
-  retval = dbus_new (char *, len + 1);
-
-  if (retval == NULL)
-    return NULL;
-
-  _dbus_hash_iter_init (service_hash, &iter);
-  i = 0;
-  while (_dbus_hash_iter_next (&iter))
-    {
-      BusService *service = _dbus_hash_iter_get_value (&iter);
-
-      retval[i] = _dbus_strdup (service->name);
-      if (retval[i] == NULL)
-       goto error;
-
-      i++;
-    }
-
-  retval[i] = NULL;
-  
-  if (array_len)
-    *array_len = len;
-  
-  return retval;
-  
- error:
-  for (j = 0; j < i; j++)
-    dbus_free (retval[i]);
-  dbus_free (retval);
-
-  return NULL;
-}
-
-void
 bus_service_set_prohibit_replacement (BusService  *service,
                                      dbus_bool_t  prohibit_replacement)
 {