Patch for reloading service files

Mikael Hallendal micke@imendio.com
Wed Mar 10 18:03:11 PST 2004


--=-LPai3344JAvyUFLvxkbi
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi!

This is a patch for making the bus reload and update service files
without restarting the bus. The behaviour was explained in another email
and the tests that are carried out are.

 * Lookup services by name with existing files
 * Lookup services by service name with no existing files
 * Create files, check that they can be found after adding
 * Remove files, check that they are not found
 * Edit files and check that the information is updated correctly

I've used 'stat(2)' in the code and 'rmdir(2)' and 'fopen()' in the
tests. Not sure if these should be in dbus-sysdeps instead, let me know
if they should be moved there.

Otherwise, can I commit?

Regards,
  Mikael Hallendal

-- 
Mikael Hallendal               micke@imendio.com
Imendio HB                     http://www.imendio.com
Phone: +46 (0)709 718 918


--=-LPai3344JAvyUFLvxkbi
Content-Disposition: attachment; filename=dbus-reload.patch
Content-Type: text/x-patch; name=dbus-reload.patch; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit

? .svn
? py-compile
? bus/.svn
? bus/core.12298
? bus/core.12578
? bus/core.12859
? bus/core.13140
? bus/core.22030
? bus/core.22310
? dbus/.svn
? doc/.svn
? doc/dbus-tutorial.html
? gcj/.svn
? gcj/org/.svn
? gcj/org/freedesktop/.svn
? gcj/org/freedesktop/dbus/.svn
? glib/.svn
? mono/.svn
? python/.deps
? python/.libs
? python/.svn
? python/Makefile
? python/Makefile.in
? python/dbus_bindings.c
? python/dbus_bindings.la
? python/dbus_bindings.lo
? python/dbus_bindings.pyx
? python/examples/.svn
? qt/.svn
? test/.svn
? test/data/.svn
? test/data/auth/.svn
? test/data/incomplete-messages/.svn
? test/data/invalid-messages/.svn
? test/data/sha-1/.svn
? test/data/valid-config-files/.svn
? test/data/valid-config-files/basic.d/.svn
? test/data/valid-config-files/system.d/.svn
? test/data/valid-messages/.svn
? test/data/valid-service-files/.svn
? test/glib/.deps
? test/glib/.libs
? test/glib/.svn
? test/glib/Makefile
? test/glib/Makefile.in
? test/glib/run-test.conf
? test/glib/test-dbus-glib
? test/glib/test-profile
? test/glib/test-service-glib
? test/glib/test-thread-client
? test/glib/test-thread-server
? tools/.svn
? tools/dbus-viewer
Index: bus/Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/bus/Makefile.am,v
retrieving revision 1.29
diff -u -b -B -p -r1.29 Makefile.am
Index: bus/activation.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/activation.c,v
retrieving revision 1.31
diff -u -b -B -p -r1.31 activation.c
--- a/bus/activation.c	2 Dec 2003 10:44:21 -0000	1.31
+++ b/bus/activation.c	10 Mar 2004 17:56:48 -0000
@@ -24,6 +24,7 @@
 #include "activation.h"
 #include "desktop-file.h"
 #include "services.h"
+#include "test.h"
 #include "utils.h"
 #include <dbus/dbus-internals.h>
 #include <dbus/dbus-hash.h>
@@ -32,7 +33,11 @@
 #include <dbus/dbus-timeout.h>
 #include <sys/types.h>
 #include <dirent.h>
+#include <sys/stat.h>
+#include <time.h>
 #include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
 
 #define DBUS_SERVICE_SECTION "D-BUS Service"
 #define DBUS_SERVICE_NAME "Name"
@@ -49,12 +54,17 @@ struct BusActivation
                               * i.e. number of pending activation requests, not pending
                               * activations per se
                               */
+  DBusList *directories;
+  DBusHashTable *path_to_entries;
 };
 
 typedef struct
 {
+  int refcount;
   char *name;
   char *exec;
+  time_t mtime;
+  char *full_path;
 } BusActivationEntry;
 
 typedef struct BusPendingActivationEntry BusPendingActivationEntry;
@@ -166,20 +176,37 @@ bus_pending_activation_unref (BusPending
   dbus_free (pending_activation);
 }
 
+static BusActivationEntry *
+bus_activation_entry_ref (BusActivationEntry *entry)
+{
+  _dbus_assert (entry->refcount > 0);
+  entry->refcount++;
+
+  return entry;
+}
+
 static void
-bus_activation_entry_free (BusActivationEntry *entry)
+bus_activation_entry_unref (BusActivationEntry *entry)
 {
-  if (!entry)
+  if (entry == 0) /* hash table requires this */
+    return;
+  
+  _dbus_assert (entry->refcount > 0);
+  entry->refcount--;
+  
+  if (entry->refcount > 0) 
     return;
   
   dbus_free (entry->name);
   dbus_free (entry->exec);
+  dbus_free (entry->full_path);
 
   dbus_free (entry);
 }
 
 static dbus_bool_t
-add_desktop_file_entry (BusActivation  *activation,
+update_desktop_file_entry (BusActivation  *activation,
+			   const char     *path,
                         BusDesktopFile *desktop_file,
                         DBusError      *error)
 {
@@ -212,6 +239,9 @@ add_desktop_file_entry (BusActivation  *
       goto failed;
     }
 
+  entry = _dbus_hash_table_lookup_string (activation->path_to_entries, path);
+  if (entry == NULL) /* New file */
+    { 
   /* FIXME we need a better-defined algorithm for which service file to
    * pick than "whichever one is first in the directory listing"
    */
@@ -231,30 +261,158 @@ add_desktop_file_entry (BusActivation  *
   
   entry->name = name;
   entry->exec = exec;
+      entry->refcount = 1;
 
-  if (!_dbus_hash_table_insert_string (activation->entries, entry->name, entry))
+      entry->full_path = _dbus_strdup (path);
+      if (!entry->full_path)
     {
       BUS_SET_OOM (error);
       goto failed;
     }
 
+      if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry)))
+	{
+	  BUS_SET_OOM (error);
+	  goto failed;
+	}
+     
+      if (!_dbus_hash_table_insert_string (activation->path_to_entries, entry->full_path, bus_activation_entry_ref (entry)))
+	{
+	  /* Revert the insertion in the entries table */
+	  _dbus_hash_table_remove_string (activation->entries, entry->name);
+	  BUS_SET_OOM (error);
+	  goto failed;
+	}
+
   _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
+    }
+  else /* Just update the entry */
+    {
+      bus_activation_entry_ref (entry);
+      _dbus_hash_table_remove_string (activation->entries, entry->name);
+
+      if (_dbus_hash_table_lookup_string (activation->entries, name))
+	{
+	  _dbus_verbose ("The new service name \"%s\" of service file \"%s\" already in cache, ignoring\n",
+			 name, entry->full_path);
+	  goto failed;
+	}
+ 
+      dbus_free (entry->name);
+      dbus_free (entry->exec);
+      entry->name = name;
+      entry->exec = exec;
+      if (!_dbus_hash_table_insert_string (activation->entries,
+					   entry->name, bus_activation_entry_ref(entry)))
+	{
+	  BUS_SET_OOM (error);
+	  /* Also remove path to entries hash since we want this in sync with
+	   * the entries hash table */
+	  _dbus_hash_table_remove_string (activation->path_to_entries, 
+					  entry->full_path);
+	  bus_activation_entry_unref (entry);
+	  return FALSE;
+	}
+    }
+  
+  entry->mtime = time (NULL);
+  bus_activation_entry_unref (entry);
   
   return TRUE;
 
  failed:
   dbus_free (name);
   dbus_free (exec);
-  dbus_free (entry);
+  if (entry)
+    bus_activation_entry_unref (entry);
   
   return FALSE;
 }
 
+static dbus_bool_t
+check_service_file (BusActivation       *activation,
+		    BusActivationEntry  *entry,
+		    BusActivationEntry **updated_entry,
+		    DBusError           *error)
+{
+  struct stat stat_buf;
+  dbus_bool_t retval = TRUE;
+  BusActivationEntry *tmp_entry = entry;
+ 
+  if (stat (entry->full_path, &stat_buf) == -1) 
+    {
+      if (errno == ENOENT) 
+	{
+	  _dbus_verbose ("****** File \"%s\" has been removed, removing from cache\n",
+
+			 entry->full_path);
+	  _dbus_hash_table_remove_string (activation->entries, entry->name);
+	  _dbus_hash_table_remove_string (activation->path_to_entries, entry->full_path);
+
+	  tmp_entry = NULL;
+	  retval = TRUE;
+	  goto out;
+	}
+    }
+  else 
+    {
+      if (stat_buf.st_mtime > entry->mtime) 
+	{
+	  BusDesktopFile *desktop_file;
+	  DBusError tmp_error;
+	  DBusString full_path;
+	  
+	  _dbus_string_init_const (&full_path, entry->full_path);
+	  
+	  dbus_error_init (&tmp_error);
+	  
+	  desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
+	  if (desktop_file == NULL)
+	    {
+	      _dbus_verbose ("Could not load %s: %s\n",
+			     entry->full_path, tmp_error.message);
+	      if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+		{
+		  dbus_move_error (&tmp_error, error);
+		  retval = FALSE;
+		  goto out;
+		}
+	      dbus_error_free (&tmp_error);
+	      retval = TRUE;
+	      goto out;
+	    }
+	  
+	  if (!update_desktop_file_entry (activation, entry->full_path, desktop_file, &tmp_error))
+	    {
+	      bus_desktop_file_free (desktop_file);
+	      if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+		{
+		  dbus_move_error (&tmp_error, error);
+		  retval = FALSE;
+		  goto out;
+		}
+	      dbus_error_free (&tmp_error);
+	      retval = TRUE;
+	      goto out;
+	    }
+	 
+	  bus_desktop_file_free (desktop_file);
+	  retval = TRUE;
+	}
+    }
+  
+out:
+  if (updated_entry != NULL)
+    *updated_entry = tmp_entry;
+  return retval;
+}
+
+
 /* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
  * hash entries it already added.
  */
 static dbus_bool_t
-load_directory (BusActivation *activation,
+update_directory (BusActivation *activation,
                 const char    *directory,
                 DBusError     *error)
 {
@@ -264,14 +422,17 @@ load_directory (BusActivation *activatio
   BusDesktopFile *desktop_file;
   DBusError tmp_error;
   dbus_bool_t retval;
+  BusActivationEntry *entry;
   
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  _dbus_string_init_const (&dir, directory);
+  //_dbus_string_init_const (&dir, directory);
 
   iter = NULL;
   desktop_file = NULL;
   
+  _dbus_string_init_const (&dir, directory);
+  
   if (!_dbus_string_init (&filename))
     {
       BUS_SET_OOM (error);
@@ -293,7 +454,8 @@ load_directory (BusActivation *activatio
   if (iter == NULL)
     {
       _dbus_verbose ("Failed to open directory %s: %s\n",
-                     directory, error ? error->message : "unknown");
+		     directory, 
+		     error ? error->message : "unknown");
       goto out;
     }
   
@@ -319,8 +481,17 @@ load_directory (BusActivation *activatio
           continue;
 	}
       
-      desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
+      entry = _dbus_hash_table_lookup_string (activation->path_to_entries, _dbus_string_get_const_data (&full_path));
+      if (entry) /* Already has this service file in the cache */ 
+	{
+	  if (!check_service_file (activation, entry, NULL, error))
+	    goto out;
 
+	  continue;
+	}
+	
+      /* New file */
+      desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
       if (desktop_file == NULL)
 	{
 	  _dbus_verbose ("Could not load %s: %s\n",
@@ -337,7 +508,7 @@ load_directory (BusActivation *activatio
 	  continue;
 	}
 
-      if (!add_desktop_file_entry (activation, desktop_file, &tmp_error))
+      if (!update_desktop_file_entry (activation, _dbus_string_get_const_data (&full_path), desktop_file, &tmp_error))
 	{
           bus_desktop_file_free (desktop_file);
           desktop_file = NULL;
@@ -394,6 +565,7 @@ bus_activation_new (BusContext        *c
 {
   BusActivation *activation;
   DBusList *link;
+  char          *dir;
   
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
@@ -415,7 +587,7 @@ bus_activation_new (BusContext        *c
     }
   
   activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
-                                             (DBusFreeFunction)bus_activation_entry_free);
+                                             (DBusFreeFunction)bus_activation_entry_unref);
   if (activation->entries == NULL)
     {      
       BUS_SET_OOM (error);
@@ -431,12 +603,37 @@ bus_activation_new (BusContext        *c
       goto failed;
     }
   
+  activation->path_to_entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
+						      (DBusFreeFunction)bus_activation_entry_unref);
+  
+  if (activation->path_to_entries == NULL) 
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+  
   /* Load service files */
+  activation->directories = NULL;
   link = _dbus_list_get_first_link (directories);
   while (link != NULL)
     {
-      if (!load_directory (activation, link->data, error))
+      if (!update_directory (activation, (const char *) link->data, error))
+        goto failed;
+      
+      dir = _dbus_strdup ((const char *) link->data);
+      if (!dir)
+	{
+	  BUS_SET_OOM (error);
+	  goto failed;
+	}
+
+      if (!_dbus_list_append (&activation->directories, dir))
+	{
+	  dbus_free (dir);
+	  BUS_SET_OOM (error);
         goto failed;
+	}
+      
       link = _dbus_list_get_next_link (directories, link);
     }
 
@@ -460,19 +657,33 @@ bus_activation_ref (BusActivation *activ
 void
 bus_activation_unref (BusActivation *activation)
 {
+  DBusList *link;
+  
   _dbus_assert (activation->refcount > 0);
 
   activation->refcount -= 1;
 
-  if (activation->refcount == 0)
-    {
+  if (activation->refcount > 0)
+    return;
+  
       dbus_free (activation->server_address);
+  if (activation->path_to_entries)
+    _dbus_hash_table_unref (activation->path_to_entries);
       if (activation->entries)
         _dbus_hash_table_unref (activation->entries);
       if (activation->pending_activations)
 	_dbus_hash_table_unref (activation->pending_activations);
-      dbus_free (activation);
+  
+  link = _dbus_list_get_first_link (&activation->directories);
+  while (link != NULL)
+    {
+      dbus_free (link->data);
+      
+      link = _dbus_list_get_next_link (&activation->directories, link);
     }
+  _dbus_list_clear (&activation->directories);
+  
+  dbus_free (activation);
 }
 
 static void
@@ -840,6 +1051,75 @@ add_cancel_pending_to_transaction (BusTr
   return TRUE;
 }
 
+static dbus_bool_t 
+update_service_cache (BusActivation *activation, DBusError *error)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (&activation->directories);
+  while (link != NULL)
+    {
+      DBusError tmp_error;
+     
+      dbus_error_init (&tmp_error);
+      if (!update_directory (activation, (const char *) link->data, &tmp_error))
+	{
+	  if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+	    {
+	      dbus_move_error (&tmp_error, error);
+	      return FALSE;
+	    }
+
+	  dbus_error_free (&tmp_error);
+	  continue;
+	}
+      link = _dbus_list_get_next_link (&activation->directories, link);
+    }
+  
+  return TRUE;
+}
+
+static BusActivationEntry *
+activation_find_entry (BusActivation *activation, 
+		       const char    *service_name,
+		       DBusError     *error)
+{
+  BusActivationEntry *entry = NULL;
+ 
+  entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
+  if (!entry)
+    { 
+      if (!update_service_cache (activation, error)) 
+	{
+	  return NULL;
+	}
+     
+      entry = _dbus_hash_table_lookup_string (activation->entries,
+					      service_name);
+    }
+  else 
+    {
+      BusActivationEntry *updated_entry;
+     
+      if (!check_service_file (activation, entry, &updated_entry, error)) 
+	{
+	  return NULL;
+	}
+
+      entry = updated_entry;
+    }
+  
+  if (!entry) 
+    {
+      dbus_set_error (error, DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND,
+		      "The service %s was not found in the activation entry list",
+		      service_name);
+      return NULL;
+    }
+
+  return entry;
+}
+
 dbus_bool_t
 bus_activation_activate_service (BusActivation  *activation,
 				 DBusConnection *connection,
@@ -867,13 +1147,9 @@ bus_activation_activate_service (BusActi
       return FALSE;
     }
   
-  entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
-
+  entry = activation_find_entry (activation, service_name, error);
   if (!entry)
     {
-      dbus_set_error (error, DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND,
-		      "The service %s was not found in the activation entry list",
-		      service_name);
       return FALSE;
     }
 
@@ -1066,3 +1342,336 @@ bus_activation_activate_service (BusActi
   
   return TRUE;
 }
+
+#ifdef DBUS_BUILD_TESTS
+
+#define SERVICE_NAME_1 "MyService1"
+#define SERVICE_NAME_2 "MyService2"
+#define SERVICE_NAME_3 "MyService3"
+
+#define SERVICE_FILE_1 "service-1.service"
+#define SERVICE_FILE_2 "service-2.service"
+#define SERVICE_FILE_3 "service-3.service"
+
+static dbus_bool_t
+test_create_service_file (DBusString *dir,
+			  const char *filename, 
+			  const char *name, 
+			  const char *exec)
+{
+  DBusString  file_name, full_path;
+  FILE        *file;
+  dbus_bool_t  ret_val = TRUE;
+ 
+  _dbus_string_init_const (&file_name, filename);
+
+  if (!_dbus_string_init (&full_path))
+    return FALSE;
+
+  if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
+      !_dbus_concat_dir_and_file (&full_path, &file_name))
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+  
+  file = fopen (_dbus_string_get_const_data (&full_path), "w");
+  if (!file)
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+  fprintf (file, "[D-BUS Service]\nName=%s\nExec=%s\n", name, exec);
+  fclose (file);
+
+out:
+  _dbus_string_free (&full_path);
+  return ret_val;
+}
+
+static dbus_bool_t
+test_remove_service_file (DBusString *dir, const char *filename)
+{
+  DBusString   file_name, full_path;
+  dbus_bool_t  ret_val = TRUE;
+ 
+  _dbus_string_init_const (&file_name, filename);
+
+  if (!_dbus_string_init (&full_path))
+    return FALSE;
+
+  if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
+      !_dbus_concat_dir_and_file (&full_path, &file_name))
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+  if (!_dbus_delete_file (&full_path, NULL))
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+out:
+  _dbus_string_free (&full_path);
+  return ret_val;
+}
+
+static dbus_bool_t
+test_remove_directory (DBusString *dir)
+{
+  DBusDirIter *iter;
+  DBusString   filename, full_path;
+  dbus_bool_t  ret_val = TRUE;
+  
+  if (rmdir (_dbus_string_get_const_data (dir)) != 0)
+    {
+      if (errno != ENOTEMPTY)
+	return FALSE;
+    }
+  else
+    return TRUE;
+
+  if (!_dbus_string_init (&filename))
+    return FALSE;
+
+  if (!_dbus_string_init (&full_path))
+    {
+      _dbus_string_free (&filename);
+      return FALSE;
+    }
+    
+  iter = _dbus_directory_open (dir, NULL);
+  if (iter == NULL)
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+  
+  while (_dbus_directory_get_next_file (iter, &filename, NULL)) 
+    {
+      if (!test_remove_service_file (dir, _dbus_string_get_const_data (&filename)))
+	{
+	  ret_val = FALSE;
+	  goto out;
+	}
+    }
+  _dbus_directory_close (iter);
+
+  if (rmdir (_dbus_string_get_const_data (dir)) != 0)
+    { 
+      ret_val = FALSE;
+      goto out;
+    }
+
+out:
+  _dbus_string_free (&filename);
+  _dbus_string_free (&full_path);
+
+  return ret_val;
+}
+
+static dbus_bool_t
+init_service_reload_test (DBusString *dir)
+{
+  struct stat stat_buf;
+ 
+  if (stat (_dbus_string_get_const_data (dir), &stat_buf) == -1)
+    {
+      if (!_dbus_create_directory (dir, NULL))
+	return FALSE;
+    }
+  else 
+    {
+      if (!test_remove_directory (dir))
+	return FALSE;
+
+      if (!_dbus_create_directory (dir, NULL))
+	return FALSE;
+    }
+
+  /* Create one initial file */
+  if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1"))
+    return FALSE;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+cleanup_service_reload_test (DBusString *dir)
+{
+  if (!test_remove_directory (dir))
+    return FALSE;
+
+  return TRUE;
+}
+
+typedef struct 
+{
+  BusActivation *activation;
+  const char    *service_name;
+  dbus_bool_t    expecting_find;
+} CheckData;
+
+static dbus_bool_t
+check_func (void *data)
+{
+  CheckData          *d;
+  BusActivationEntry *entry;
+  DBusError           error;
+  dbus_bool_t         ret_val = TRUE;
+
+  d = data;
+  
+  dbus_error_init (&error);
+ 
+  entry = activation_find_entry (d->activation, d->service_name, &error);
+  if (entry == NULL)
+    {
+      if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 
+	ret_val = TRUE;
+
+      dbus_error_free (&error);
+      if (d->expecting_find)
+	ret_val = FALSE;
+    }
+  else 
+    {
+      if (!d->expecting_find)
+	ret_val = FALSE;
+    }
+
+  return ret_val;
+}
+
+static dbus_bool_t
+do_test (const char *description, dbus_bool_t oom_test, CheckData *data)
+{
+  dbus_bool_t err;
+
+  if (oom_test)
+    err = !_dbus_test_oom_handling (description, check_func, data);
+  else
+    err = !check_func (data);
+
+  if (err) 
+    _dbus_assert_not_reached ("Test failed");
+
+  return TRUE;
+}
+
+static dbus_bool_t
+do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
+{
+  BusActivation *activation;
+  DBusString     address;
+  DBusList      *directories = NULL;
+  CheckData      d;
+  
+  _dbus_string_init_const (&address, "");
+ 
+  if (!_dbus_list_append (&directories, _dbus_string_get_data (dir)))
+    return FALSE; 
+
+  activation = bus_activation_new (NULL, &address, &directories, NULL);
+  if (!activation)
+    return FALSE;
+
+  d.activation = activation;
+  
+  /* Check for existing service file */
+  d.expecting_find = TRUE;
+  d.service_name = SERVICE_NAME_1;
+
+  if (!do_test ("Existing service file", oom_test, &d))
+    return FALSE;
+
+  /* Check for non-existing service file */
+  d.expecting_find = FALSE;
+  d.service_name = SERVICE_NAME_3;
+
+  if (!do_test ("Nonexisting service file", oom_test, &d))
+    return FALSE;
+
+  /* Check for added service file */
+  if (!test_create_service_file (dir, SERVICE_FILE_2, SERVICE_NAME_2, "exec-2"))
+    return FALSE;
+
+  d.expecting_find = TRUE;
+  d.service_name = SERVICE_NAME_2;
+  
+  if (!do_test ("Added service file", oom_test, &d))
+    return FALSE;
+  
+  /* Check for removed service file */
+  if (!test_remove_service_file (dir, SERVICE_FILE_2))
+    return FALSE;
+
+  d.expecting_find = FALSE;
+  d.service_name = SERVICE_FILE_2;
+
+  if (!do_test ("Removed service file", oom_test, &d))
+    return FALSE;
+  
+  /* Check for updated service file */
+  
+  sleep (1); /* Sleep a second to make sure the mtime is updated */
+  if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_3, "exec-3"))
+    return FALSE;
+
+  d.expecting_find = TRUE;
+  d.service_name = SERVICE_NAME_3;
+
+  if (!do_test ("Updated service file, part 1", oom_test, &d))
+    return FALSE;
+
+  d.expecting_find = FALSE;
+  d.service_name = SERVICE_NAME_1;
+
+  if (!do_test ("Updated service file, part 2", oom_test, &d))
+    return FALSE; 
+
+  bus_activation_unref (activation);
+  _dbus_list_clear (&directories);
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_activation_service_reload_test (const DBusString *test_data_dir)
+{
+  DBusString  directory;
+ 
+  if (!_dbus_string_init (&directory))
+    return FALSE;
+
+  if (!_dbus_string_append (&directory, "/tmp/dbus-reload-test-") ||
+      !_dbus_generate_random_ascii (&directory, 6))
+     {
+       return FALSE;
+     }
+   
+  /* Do normal tests */
+  if (!init_service_reload_test (&directory))
+    _dbus_assert_not_reached ("could not initiate service reload test");
+ 
+  if (!do_service_reload_test (&directory, FALSE));
+  
+  /* Do OOM tests */
+  if (!init_service_reload_test (&directory))
+    _dbus_assert_not_reached ("could not initiate service reload test");
+ 
+  if (!do_service_reload_test (&directory, TRUE));
+ 
+  /* Cleanup test directory */
+  if (!cleanup_service_reload_test (&directory))
+    return FALSE;
+  
+  _dbus_string_free (&directory);
+  
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
Index: bus/test-main.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/test-main.c,v
retrieving revision 1.15
diff -u -b -B -p -r1.15 test-main.c
--- a/bus/test-main.c	2 Dec 2003 10:44:21 -0000	1.15
+++ b/bus/test-main.c	10 Mar 2004 17:56:48 -0000
@@ -106,13 +106,18 @@ main (int argc, char **argv)
     die ("sha1");
 
   check_memleaks (argv[0]);
-  
   printf ("%s: Running message dispatch test\n", argv[0]);
   if (!bus_dispatch_test (&test_data_dir))
     die ("dispatch");
 
   check_memleaks (argv[0]);
   
+  printf ("%s: Running service files reloading test\n", argv[0]);
+  if (!bus_activation_service_reload_test (&test_data_dir))
+    die ("service reload");
+
+  check_memleaks (argv[0]);
+  
   printf ("%s: Success\n", argv[0]);
   
   return 0;
Index: bus/test.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/test.h,v
retrieving revision 1.13
diff -u -b -B -p -r1.13 test.h
--- a/bus/test.h	2 Dec 2003 10:44:21 -0000	1.13
+++ b/bus/test.h	10 Mar 2004 17:56:48 -0000
@@ -38,6 +38,7 @@ dbus_bool_t bus_policy_test           (c
 dbus_bool_t bus_config_parser_test    (const DBusString             *test_data_dir);
 dbus_bool_t bus_signals_test          (const DBusString             *test_data_dir);
 dbus_bool_t bus_expire_list_test      (const DBusString             *test_data_dir);
+dbus_bool_t bus_activation_service_reload_test (const DBusString    *test_data_dir);
 dbus_bool_t bus_setup_debug_client    (DBusConnection               *connection);
 void        bus_test_clients_foreach  (BusConnectionForeachFunction  function,
                                        void                         *data);
Index: dbus/dbus-memory.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-memory.c,v
retrieving revision 1.22
diff -u -b -B -p -r1.22 dbus-memory.c

--=-LPai3344JAvyUFLvxkbi--





More information about the dbus mailing list