2003-03-31 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / bus / test.c
index 09e40f3..d669708 100644 (file)
  */
 static DBusList *clients = NULL;
 
-static void
+static dbus_bool_t
 client_watch_callback (DBusWatch     *watch,
                            unsigned int   condition,
                            void          *data)
 {
   DBusConnection *connection = data;
-
+  dbus_bool_t retval;
+  
   dbus_connection_ref (connection);
   
-  dbus_connection_handle_watch (connection, watch, condition);
+  retval = dbus_connection_handle_watch (connection, watch, condition);
 
   dbus_connection_unref (connection);
+
+  return retval;
 }
 
 static dbus_bool_t
@@ -71,7 +74,8 @@ client_timeout_callback (DBusTimeout   *timeout,
   DBusConnection *connection = data;
 
   dbus_connection_ref (connection);
-  
+
+  /* can return FALSE on OOM but we just let it fire again later */
   dbus_timeout_handle (timeout);
 
   dbus_connection_unref (connection);
@@ -108,6 +112,49 @@ client_disconnect_handler (DBusMessageHandler *handler,
 }
 
 static int handler_slot = -1;
+static int handler_slot_refcount = 0;
+
+static dbus_bool_t
+handler_slot_ref (void)
+{
+  if (handler_slot < 0)
+    {
+      handler_slot = dbus_connection_allocate_data_slot ();
+      
+      if (handler_slot < 0)
+        return FALSE;
+
+      _dbus_assert (handler_slot_refcount == 0);
+    }  
+
+  handler_slot_refcount += 1;
+
+  return TRUE;
+
+}
+
+static void
+handler_slot_unref (void)
+{
+  _dbus_assert (handler_slot_refcount > 0);
+
+  handler_slot_refcount -= 1;
+  
+  if (handler_slot_refcount == 0)
+    {
+      dbus_connection_free_data_slot (handler_slot);
+      handler_slot = -1;
+    }
+}
+
+static void
+free_handler (void *data)
+{
+  DBusMessageHandler *handler = data;
+
+  dbus_message_handler_unref (handler);
+  handler_slot_unref ();
+}
 
 dbus_bool_t
 bus_setup_debug_client (DBusConnection *connection)
@@ -115,11 +162,6 @@ bus_setup_debug_client (DBusConnection *connection)
   DBusMessageHandler *disconnect_handler;
   const char *to_handle[] = { DBUS_MESSAGE_LOCAL_DISCONNECT };
   dbus_bool_t retval;
-
-  if (handler_slot < 0)
-    handler_slot = dbus_connection_allocate_data_slot ();
-  if (handler_slot < 0)
-    return FALSE;
   
   disconnect_handler = dbus_message_handler_new (client_disconnect_handler,
                                                  NULL, NULL);
@@ -156,12 +198,17 @@ bus_setup_debug_client (DBusConnection *connection)
   if (!_dbus_list_append (&clients, connection))
     goto out;
 
-  /* Set up handler to be destroyed */
+  if (!handler_slot_ref ())
+    goto out;
+
+  /* Set up handler to be destroyed */  
   if (!dbus_connection_set_data (connection, handler_slot,
                                  disconnect_handler,
-                                 (DBusFreeFunction)
-                                 dbus_message_handler_unref))
-    goto out;
+                                 free_handler))
+    {
+      handler_slot_unref ();
+      goto out;
+    }
   
   retval = TRUE;
   
@@ -220,4 +267,77 @@ bus_test_client_listed (DBusConnection *connection)
   return FALSE;
 }
 
+void
+bus_test_flush_bus (BusContext *context)
+{
+  /* This is race condition city, obviously. since we're all in one
+   * process we can't block, we just have to wait for data we put in
+   * one end of the debug pipe to come out the other end...
+   * a more robust setup would be good. Blocking on the other
+   * end of pipes we've pushed data into or something.
+   * A simple hack might be to just make the debug server always
+   * poll for read on the other end of the pipe after writing.
+   */
+  while (bus_loop_iterate (FALSE))
+    ;
+#if 0
+  _dbus_sleep_milliseconds (15);
+#endif
+  while (bus_loop_iterate (FALSE))
+    ;
+}
+
+BusContext*
+bus_context_new_test (const DBusString *test_data_dir,
+                      const char       *filename)
+{
+  DBusError error;
+  DBusString config_file;
+  DBusString relative;
+  BusContext *context;
+  
+  if (!_dbus_string_init (&config_file))
+    {
+      _dbus_warn ("No memory\n");
+      return NULL;
+    }
+
+  if (!_dbus_string_copy (test_data_dir, 0,
+                          &config_file, 0))
+    {
+      _dbus_warn ("No memory\n");
+      _dbus_string_free (&config_file);
+      return NULL;
+    }
+
+  _dbus_string_init_const (&relative, filename);
+
+  if (!_dbus_concat_dir_and_file (&config_file, &relative))
+    {
+      _dbus_warn ("No memory\n");
+      _dbus_string_free (&config_file);
+      return NULL;
+    }
+  
+  dbus_error_init (&error);
+  context = bus_context_new (&config_file, &error);
+  if (context == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&error);
+      
+      _dbus_warn ("Failed to create debug bus context from configuration file %s: %s\n",
+                  filename, error.message);
+
+      dbus_error_free (&error);
+      
+      _dbus_string_free (&config_file);
+      
+      return NULL;
+    }
+
+  _dbus_string_free (&config_file);
+  
+  return context;
+}
+
 #endif