From 529ce66c4498e661281b83852cfbde03a918956e Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 15:04:20 -0600 Subject: API changes required to have locations for the entries. --- libindicator/indicator-object.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libindicator/indicator-object.h b/libindicator/indicator-object.h index c100d02..0356d1c 100644 --- a/libindicator/indicator-object.h +++ b/libindicator/indicator-object.h @@ -40,6 +40,8 @@ G_BEGIN_DECLS #define INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, INDICATOR_OBJECT_TYPE)) #define INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED "entry-removed" #define INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, INDICATOR_OBJECT_TYPE)) +#define INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED "entry-moved" +#define INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, INDICATOR_OBJECT_TYPE)) typedef struct _IndicatorObject IndicatorObject; typedef struct _IndicatorObjectClass IndicatorObjectClass; @@ -62,12 +64,14 @@ typedef struct _IndicatorObjectEntry IndicatorObjectEntry; a #GList of #IndicatorObjectEntries. The list should be under the ownership of the caller but the entires will not be. + @get_location: Returns the location that a particular entry + should be placed in. This is really only relevant for + indicators that have more than one entry. @entry_added: Slot for #IndicatorObject::entry-added @entry_removed: Slot for #IndicatorObject::entry-removed + @entry_moved: Slot for #IndicatorObject::entry-moved @indicator_object_reserved_1: Reserved for future use @indicator_object_reserved_2: Reserved for future use - @indicator_object_reserved_3: Reserved for future use - @indicator_object_reserved_4: Reserved for future use */ struct _IndicatorObjectClass { GObjectClass parent_class; @@ -78,16 +82,16 @@ struct _IndicatorObjectClass { GtkMenu * (*get_menu) (IndicatorObject * io); GList * (*get_entries) (IndicatorObject * io); + guint (*get_location) (IndicatorObject * io, IndicatorObjectEntry * entry); /* Signals */ void (*entry_added) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); void (*entry_removed) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); + void (*entry_moved) (IndicatorObject * io, IndicatorObjectEntry * entry, guint old_pos, guint new_pos, gpointer user_data); /* Reserved */ void (* indicator_object_reserved_1) (void); void (* indicator_object_reserved_2) (void); - void (* indicator_object_reserved_3) (void); - void (* indicator_object_reserved_4) (void); }; /** @@ -117,6 +121,7 @@ GType indicator_object_get_type (void); IndicatorObject * indicator_object_new_from_file (const gchar * file); GList * indicator_object_get_entries (IndicatorObject * io); +guint indicator_object_get_location (IndicatorObject * io, IndicatorObjectEntry * entry); G_END_DECLS -- cgit v1.2.3 From 14b58238f792f17285dc61c6adb00ca764a5a3b6 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 15:16:30 -0600 Subject: Setting up the move signal, which required custom marshallers. --- .bzrignore | 4 +++ Makefile.am.marshal | 45 ++++++++++++++++++++++++++++++ configure.ac | 2 ++ libindicator/Makefile.am | 8 ++++++ libindicator/indicator-object-marshal.list | 1 + libindicator/indicator-object.c | 16 +++++++++++ 6 files changed, 76 insertions(+) create mode 100644 Makefile.am.marshal create mode 100644 libindicator/indicator-object-marshal.list diff --git a/.bzrignore b/.bzrignore index 1d9c02d..22df703 100644 --- a/.bzrignore +++ b/.bzrignore @@ -143,3 +143,7 @@ tests/service-version-manager tests/service-version-tester tests/service-manager-connect-nostart-tester tests/service-manager-nostart-connect +libindicator/indicator-object-marshal.c +libindicator/indicator-object-marshal.h +libindicator/libindicator_la-indicator-object-marshal.lo +libindicator/stamp-marshal diff --git a/Makefile.am.marshal b/Makefile.am.marshal new file mode 100644 index 0000000..a6ab024 --- /dev/null +++ b/Makefile.am.marshal @@ -0,0 +1,45 @@ +# Rules for generating marshal files using glib-genmarshal +# +# Define: +# glib_marshal_list = marshal list file +# glib_marshal_prefix = prefix for marshal functions +# +# before including Makefile.am.marshal. You will also need to have +# the following targets already defined: +# +# CLEANFILES +# DISTCLEANFILES +# BUILT_SOURCES +# EXTRA_DIST +# +# Author: Emmanuele Bassi + +marshal_h = $(glib_marshal_list:.list=.h) +marshal_c = $(glib_marshal_list:.list=.c) + +CLEANFILES += stamp-marshal +DISTCLEANFILES += $(marshal_h) $(marshal_c) +BUILT_SOURCES += $(marshal_h) $(marshal_c) +EXTRA_DIST += $(glib_marshal_list) + +stamp-marshal: $(glib_marshal_list) + $(QUIET_GEN)$(GLIB_GENMARSHAL) \ + --prefix=$(glib_marshal_prefix) \ + --header \ + $(srcdir)/$(glib_marshal_list) > xgen-mh \ + && (cmp -s xgen-mh $(marshal_h) || cp -f xgen-mh $(marshal_h)) \ + && rm -f xgen-mh \ + && echo timestamp > $(@F) + +$(marshal_h): stamp-marshal + @true + +$(marshal_c): $(marshal_h) + $(QUIET_GEN)(echo "#include \"$(marshal_h)\"" ; \ + $(GLIB_GENMARSHAL) \ + --prefix=$(glib_marshal_prefix) \ + --body \ + $(srcdir)/$(glib_marshal_list)) > xgen-mc \ + && cp xgen-mc $(marshal_c) \ + && rm -f xgen-mc + diff --git a/configure.ac b/configure.ac index 676af4e..04d7d38 100644 --- a/configure.ac +++ b/configure.ac @@ -15,6 +15,8 @@ AM_PROG_CC_C_O AC_STDC_HEADERS AC_PROG_LIBTOOL +AC_PATH_PROG([GLIB_GENMARSHAL], [glib-genmarshal]) + AC_SUBST(VERSION) AC_CONFIG_MACRO_DIR([m4]) diff --git a/libindicator/Makefile.am b/libindicator/Makefile.am index 6d5c627..19247ce 100644 --- a/libindicator/Makefile.am +++ b/libindicator/Makefile.am @@ -1,8 +1,11 @@ BUILT_SOURCES = CLEANFILES = +DISTCLEANFILES = EXTRA_DIST = \ indicator.pc.in +include $(top_srcdir)/Makefile.am.marshal + libindicatorincludedir=$(includedir)/libindicator-0.3/libindicator indicator_headers = \ @@ -21,6 +24,8 @@ libindicator_la_SOURCES = \ $(indicator_headers) \ dbus-shared.h \ indicator-object.c \ + indicator-object-marshal.h \ + indicator-object-marshal.c \ indicator-service.c \ indicator-service-manager.c @@ -35,6 +40,9 @@ libindicator_la_LIBADD = \ pkgconfig_DATA = indicator.pc pkgconfigdir = $(libdir)/pkgconfig +glib_marshal_list = indicator-object-marshal.list +glib_marshal_prefix = _indicator_object_marshal + ################################## # DBus Specs ################################## diff --git a/libindicator/indicator-object-marshal.list b/libindicator/indicator-object-marshal.list new file mode 100644 index 0000000..5c11033 --- /dev/null +++ b/libindicator/indicator-object-marshal.list @@ -0,0 +1 @@ +VOID: POINTER, UINT, UINT diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index e87fa5f..8e1edef 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -27,6 +27,7 @@ License along with this library. If not, see #include "indicator.h" #include "indicator-object.h" +#include "indicator-object-marshal.h" /** IndicatorObjectPrivate: @@ -54,6 +55,7 @@ struct _IndicatorObjectPrivate { enum { ENTRY_ADDED, ENTRY_REMOVED, + ENTRY_MOVED, LAST_SIGNAL }; @@ -116,6 +118,20 @@ indicator_object_class_init (IndicatorObjectClass *klass) NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); + /** + IndicatorObject::entry-moved: + @arg0: The #IndicatorObject object + + Signaled when an entry is removed and should + be removed by the person using this object. + */ + signals[ENTRY_MOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_moved), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT_UINT, + G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_NONE); return; } -- cgit v1.2.3 From d334db5071495817e9dea5b50a2fc27709058410 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 15:28:31 -0600 Subject: Fixing the signal comments. --- libindicator/indicator-object.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index 8e1edef..3b00c97 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -92,7 +92,9 @@ indicator_object_class_init (IndicatorObjectClass *klass) /** IndicatorObject::entry-added: @arg0: The #IndicatorObject object - + @arg1: A pointer to the #IndicatorObjectEntry that + is being added. + Signaled when a new entry is added and should be shown by the person using this object. */ @@ -107,7 +109,9 @@ indicator_object_class_init (IndicatorObjectClass *klass) /** IndicatorObject::entry-removed: @arg0: The #IndicatorObject object - + @arg1: A pointer to the #IndicatorObjectEntry that + is being removed. + Signaled when an entry is removed and should be removed by the person using this object. */ @@ -121,9 +125,13 @@ indicator_object_class_init (IndicatorObjectClass *klass) /** IndicatorObject::entry-moved: @arg0: The #IndicatorObject object - - Signaled when an entry is removed and should - be removed by the person using this object. + @arg1: A pointer to the #IndicatorObjectEntry that + is being moved. + @arg2: The old location of the entry + @arg3: The new location of the entry + + When the order of the entries change, then this signal + is sent to tell the new location. */ signals[ENTRY_MOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, G_TYPE_FROM_CLASS(klass), -- cgit v1.2.3 From 308e4db1bc070b6f548817fa6fe9297e64434613 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 15:35:55 -0600 Subject: Fleshing out the get_location function as much as they're implemented here. --- libindicator/indicator-object.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index 3b00c97..f186a4f 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -88,6 +88,7 @@ indicator_object_class_init (IndicatorObjectClass *klass) klass->get_image = NULL; klass->get_entries = get_entries_default; + klass->get_location = NULL; /** IndicatorObject::entry-added: @@ -366,3 +367,29 @@ indicator_object_get_entries (IndicatorObject * io) g_error("No get_entries function on object. It must have been deleted?!?!"); return NULL; } + +/** + indicator_object_get_location: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry to look for. + + This function looks on the class for the object and calls + it's #IndicatorObjectClass::get_location function. If the + function doesn't exist it returns zero. + + Return value: Location of the @entry in the display or + zero if no location is specified. +*/ +guint +indicator_object_get_location (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), 0); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->get_location) { + return class->get_location(io, entry); + } + + g_error("No get_entries function on object. It must have been deleted?!?!"); + return 0; +} -- cgit v1.2.3 From cb5f34b94c8455e8b33e69d94803f5fa2c5d9d11 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 15:58:56 -0600 Subject: Basic location checking test. --- tests/test-loader.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test-loader.c b/tests/test-loader.c index 485a951..ee362bf 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -38,6 +38,23 @@ test_loader_filename_dummy_signaler (void) return; } +void +test_loader_filename_dummy_simple_location (void) +{ + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); + g_assert(object != NULL); + + GList * entries = indicator_object_get_entries(object); + g_assert(entries != NULL); + g_assert(g_list_length(entries) == 1); + + g_assert(indicator_object_get_location(object, (IndicatorObjectEntry *)entries->data) == 0); + g_assert(indicator_object_get_location(object, NULL) == 0); + + g_object_unref(object); + + return; +} void test_loader_filename_dummy_simple_accessors (void) @@ -125,6 +142,7 @@ test_loader_creation_deletion_suite (void) g_test_add_func ("/libindicator/loader/dummy/blank_load", test_loader_filename_dummy_null); g_test_add_func ("/libindicator/loader/dummy/simple_load", test_loader_filename_dummy_simple); g_test_add_func ("/libindicator/loader/dummy/simple_accessors", test_loader_filename_dummy_simple_accessors); + g_test_add_func ("/libindicator/loader/dummy/simple_location", test_loader_filename_dummy_simple_location); g_test_add_func ("/libindicator/loader/dummy/signaler", test_loader_filename_dummy_signaler); return; -- cgit v1.2.3 From c25db995a7c12f9b0460e903633d01926c9b4aed Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 16:08:35 -0600 Subject: No error on not having a get_location function. We'll just return zero. --- libindicator/indicator-object.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index f186a4f..87cd648 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -390,6 +390,5 @@ indicator_object_get_location (IndicatorObject * io, IndicatorObjectEntry * entr return class->get_location(io, entry); } - g_error("No get_entries function on object. It must have been deleted?!?!"); return 0; } -- cgit v1.2.3 From d7635fc9b4ca515f631fb5c496bacc7da5ad4b31 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 16:11:42 -0600 Subject: Having the signaller test check the 'moved' signal as well as the others. --- tests/dummy-indicator-signaler.c | 1 + tests/test-loader.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/dummy-indicator-signaler.c b/tests/dummy-indicator-signaler.c index 0444110..9bd01bf 100644 --- a/tests/dummy-indicator-signaler.c +++ b/tests/dummy-indicator-signaler.c @@ -81,6 +81,7 @@ idle_signal (gpointer data) g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID, 0, GUINT_TO_POINTER(5), TRUE); g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID, 0, GUINT_TO_POINTER(5), TRUE); + g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED_ID, 0, GUINT_TO_POINTER(5), 0, 1, TRUE); return FALSE; /* Don't queue again */ } diff --git a/tests/test-loader.c b/tests/test-loader.c index ee362bf..f5e05dc 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -11,16 +11,23 @@ entry_change_cb (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer da return; } +void +entry_move_cb (IndicatorObject * io, IndicatorObjectEntry * entry, gint old, gint new, gpointer data) +{ + return entry_change_cb(io, entry, data); +} + void test_loader_filename_dummy_signaler (void) { IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-signaler.so"); g_assert(object != NULL); - gpointer added_value = NULL, removed_value = NULL; + gpointer added_value = NULL, removed_value = NULL, moved_value = NULL; g_signal_connect(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(entry_change_cb), &added_value); g_signal_connect(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, G_CALLBACK(entry_change_cb), &removed_value); + g_signal_connect(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, G_CALLBACK(entry_move_cb), &moved_value); GList * list = indicator_object_get_entries(object); g_assert(list != NULL); @@ -32,6 +39,7 @@ test_loader_filename_dummy_signaler (void) g_assert(GPOINTER_TO_UINT(added_value) == 5); g_assert(GPOINTER_TO_UINT(removed_value) == 5); + g_assert(GPOINTER_TO_UINT(moved_value) == 5); g_object_unref(object); -- cgit v1.2.3 From 41559b3cc70cffacc023a6a21cca41b5b1070447 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 19:54:42 -0600 Subject: Getting a multiplier, and providing a way to override it using an environment variable. --- libindicator/indicator-service-manager.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index 69b1343..ee29767 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -25,6 +25,8 @@ License along with this library. If not, see #include "config.h" #endif +#include + #include #include @@ -60,6 +62,10 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; +/* We multiply our timeouts by in ms. This can be overriden by + the environment variable INDICATOR_SERVICE_RESTART_TIMEOUT. */ +static guint timeout_multiplier = 100; +#define TIMEOUT_ENV_NAME "INDICATOR_SERVICE_RESTART_TIMEOUT" /* Properties */ /* Enum for the properties so that they can be quickly @@ -136,6 +142,15 @@ indicator_service_manager_class_init (IndicatorServiceManagerClass *klass) 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* Look to see if there is an environment variable effecting + the restart interval. This is in the class init as it should + only happen once. */ + const gchar * restart_env = g_getenv(TIMEOUT_ENV_NAME); + if (restart_env != NULL) { + timeout_multiplier = atoi(restart_env); + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Time out multipler set to: %d", timeout_multiplier); + } + return; } -- cgit v1.2.3 From b9344c35f45a52ab15462746998d1b11b63e5928 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 20:38:04 -0600 Subject: Reset the restart_count when we start, and start to bring in 'start_service_again' to begin to throttle the restarts. --- libindicator/indicator-service-manager.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index ee29767..6c6dca9 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -43,6 +43,7 @@ License along with this library. If not, see @connected: Whether we're connected to the service or not. @this_service_version: The version of the service that we're looking for. @bus: A reference to the bus so we don't have to keep getting it. + @restart_count: The number of times we've restarted this service. */ typedef struct _IndicatorServiceManagerPrivate IndicatorServiceManagerPrivate; struct _IndicatorServiceManagerPrivate { @@ -52,6 +53,7 @@ struct _IndicatorServiceManagerPrivate { gboolean connected; guint this_service_version; DBusGConnection * bus; + guint restart_count; }; /* Signals Stuff */ @@ -93,6 +95,7 @@ static void indicator_service_manager_finalize (GObject *object); static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void start_service (IndicatorServiceManager * service); +static void start_service_again (IndicatorServiceManager * manager); G_DEFINE_TYPE (IndicatorServiceManager, indicator_service_manager, G_TYPE_OBJECT); @@ -169,6 +172,7 @@ indicator_service_manager_init (IndicatorServiceManager *self) priv->connected = FALSE; priv->this_service_version = 0; priv->bus = NULL; + priv->restart_count = 0; /* Start talkin' dbus */ GError * error = NULL; @@ -327,6 +331,12 @@ watch_cb (DBusGProxy * proxy, guint service_api_version, guint this_service_vers return; } + /* We've done it, now let's stop counting. */ + /* Note: we're not checking versions. Because, the hope is that + the guy holding the name we want with the wrong version will + drop and we can start another service quickly. */ + priv->restart_count = 0; + if (service_api_version != INDICATOR_SERVICE_VERSION) { g_warning("Service is using a different version of the service interface. Expecting %d and got %d.", INDICATOR_SERVICE_VERSION, service_api_version); dbus_g_proxy_call_no_reply(priv->service_proxy, "UnWatch", G_TYPE_INVALID); @@ -358,11 +368,13 @@ start_service_cb (DBusGProxy * proxy, guint status, GError * error, gpointer use if (error != NULL) { g_warning("Unable to start service '%s': %s", priv->name, error->message); + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); return; } if (status != DBUS_START_REPLY_SUCCESS && status != DBUS_START_REPLY_ALREADY_RUNNING) { g_warning("Status of starting the process '%s' was an error: %d", priv->name, status); + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); return; } @@ -423,6 +435,18 @@ start_service (IndicatorServiceManager * service) return; } +/* This function tries to start a new service, perhaps + after a timeout that it determines. The real issue + here is that it throttles restarting if we're not + being successful. */ +static void +start_service_again (IndicatorServiceManager * manager) +{ + + + return; +} + /* API */ /** -- cgit v1.2.3 From 2ce95b0279e75123beef7cdc1b440b03ffb56c55 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 21:15:30 -0600 Subject: Filling out the function to start it again, and adding in the function to respond to the timeout. --- libindicator/indicator-service-manager.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index 6c6dca9..0c552d4 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -435,6 +435,18 @@ start_service (IndicatorServiceManager * service) return; } +/* The callback that starts the service for real after + the timeout as determined in 'start_service_again'. + This could be in the idle or a timer. */ +static gboolean +start_service_again_cb (gpointer data) +{ + IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(data); + priv->restart_count++; + start_service(INDICATOR_SERVICE_MANAGER(data)); + return FALSE; +} + /* This function tries to start a new service, perhaps after a timeout that it determines. The real issue here is that it throttles restarting if we're not @@ -442,7 +454,17 @@ start_service (IndicatorServiceManager * service) static void start_service_again (IndicatorServiceManager * manager) { + IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(manager); + if (priv->restart_count == 0) { + /* First time, do it in idle */ + g_idle_add(start_service_again_cb, manager); + } else { + /* Not our first time 'round the block. Let's slow this down. */ + if (priv->restart_count > 16) + priv->restart_count = 16; /* Not more than 1024x */ + g_timeout_add((1 << priv->restart_count) * timeout_multiplier, start_service_again_cb, manager); + } return; } -- cgit v1.2.3 From 9bccc146b8f1ee955d713fec30d7f5faf2ce88c1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 21:25:48 -0600 Subject: Setting up the signal for when the proxies falls down, we restart. --- libindicator/indicator-service-manager.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index 0c552d4..1a8db07 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -94,6 +94,7 @@ static void indicator_service_manager_finalize (GObject *object); /* Prototypes */ static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static void service_proxy_destroyed (DBusGProxy * proxy, gpointer user_data); static void start_service (IndicatorServiceManager * service); static void start_service_again (IndicatorServiceManager * manager); @@ -385,6 +386,7 @@ start_service_cb (DBusGProxy * proxy, guint status, GError * error, gpointer use INDICATOR_SERVICE_INTERFACE, &error); g_object_add_weak_pointer(G_OBJECT(priv->service_proxy), (gpointer *)&(priv->service_proxy)); + g_signal_connect(G_OBJECT(priv->service_proxy), "destroy", G_CALLBACK(service_proxy_destroyed), user_data); org_ayatana_indicator_service_watch_async(priv->service_proxy, watch_cb, @@ -423,6 +425,7 @@ start_service (IndicatorServiceManager * service) service); } else { g_object_add_weak_pointer(G_OBJECT(priv->service_proxy), (gpointer *)&(priv->service_proxy)); + g_signal_connect(G_OBJECT(priv->service_proxy), "destroy", G_CALLBACK(service_proxy_destroyed), service); /* If we got a proxy just because we're good people then we need to call watch on it just like 'start_service_cb' @@ -435,6 +438,14 @@ start_service (IndicatorServiceManager * service) return; } +/* Responds to the destory event of the proxy and starts + setting up to restart the service. */ +static void +service_proxy_destroyed (DBusGProxy * proxy, gpointer user_data) +{ + return start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); +} + /* The callback that starts the service for real after the timeout as determined in 'start_service_again'. This could be in the idle or a timer. */ -- cgit v1.2.3 From deabfe64bf3b306c1c068665c4d8324dee7f5435 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 21:40:03 -0600 Subject: Switching what our enviroment variable is for, let's just stop the whole thing instead of playing with it. --- libindicator/indicator-service-manager.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index 1a8db07..42160ee 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -64,10 +64,9 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -/* We multiply our timeouts by in ms. This can be overriden by - the environment variable INDICATOR_SERVICE_RESTART_TIMEOUT. */ -static guint timeout_multiplier = 100; -#define TIMEOUT_ENV_NAME "INDICATOR_SERVICE_RESTART_TIMEOUT" +/* If this env variable is set, we don't restart */ +#define TIMEOUT_ENV_NAME "INDICATOR_SERVICE_RESTART_DISABLE" +#define TIMEOUT_MULTIPLIER 100 /* In ms */ /* Properties */ /* Enum for the properties so that they can be quickly @@ -146,15 +145,6 @@ indicator_service_manager_class_init (IndicatorServiceManagerClass *klass) 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /* Look to see if there is an environment variable effecting - the restart interval. This is in the class init as it should - only happen once. */ - const gchar * restart_env = g_getenv(TIMEOUT_ENV_NAME); - if (restart_env != NULL) { - timeout_multiplier = atoi(restart_env); - g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Time out multipler set to: %d", timeout_multiplier); - } - return; } @@ -465,6 +455,11 @@ start_service_again_cb (gpointer data) static void start_service_again (IndicatorServiceManager * manager) { + /* Allow the restarting to be disabled */ + if (g_getenv(TIMEOUT_ENV_NAME)) { + return; + } + IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(manager); if (priv->restart_count == 0) { @@ -474,7 +469,7 @@ start_service_again (IndicatorServiceManager * manager) /* Not our first time 'round the block. Let's slow this down. */ if (priv->restart_count > 16) priv->restart_count = 16; /* Not more than 1024x */ - g_timeout_add((1 << priv->restart_count) * timeout_multiplier, start_service_again_cb, manager); + g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager); } return; -- cgit v1.2.3 From f8d47e919d46d5daccb76958bb27064cea0f337c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 21:45:58 -0600 Subject: releasing version 0.3.0-0ubuntu2~ppa1~restart1 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 395dd92..1a58ef8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -libindicator (0.3.0-0ubuntu2~ppa1~restart1) UNRELEASED; urgency=low +libindicator (0.3.0-0ubuntu2~ppa1~restart1) karmic; urgency=low * Upstream Merge * Adding in the code to restart services - -- Ted Gould Fri, 15 Jan 2010 21:44:22 -0600 + -- Ted Gould Fri, 15 Jan 2010 21:45:56 -0600 libindicator (0.3.0-0ubuntu1) karmic; urgency=low -- cgit v1.2.3 From 62d8c1c86b21ab250342900324565f1b95ac2da8 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 22:16:45 -0600 Subject: Handling the connected signal as well, making sure we emit it. --- libindicator/indicator-service-manager.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index 42160ee..9d56a9f 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -455,18 +455,24 @@ start_service_again_cb (gpointer data) static void start_service_again (IndicatorServiceManager * manager) { + IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(manager); + /* Allow the restarting to be disabled */ if (g_getenv(TIMEOUT_ENV_NAME)) { + priv->connected = FALSE; + g_signal_emit(manager, signals[CONNECTION_CHANGE], 0, FALSE, TRUE); return; } - IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(manager); - if (priv->restart_count == 0) { /* First time, do it in idle */ g_idle_add(start_service_again_cb, manager); } else { /* Not our first time 'round the block. Let's slow this down. */ + if (priv->connected) { + priv->connected = FALSE; + g_signal_emit(manager, signals[CONNECTION_CHANGE], 0, FALSE, TRUE); + } if (priv->restart_count > 16) priv->restart_count = 16; /* Not more than 1024x */ g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager); -- cgit v1.2.3 From faa40d719e92f3b27d796313ff38d41c0cc702a5 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 22:19:16 -0600 Subject: releasing version 0.3.0-0ubuntu2~ppa1~restart2 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 132367f..3d170bd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -libindicator (0.3.0-0ubuntu2~ppa1~restart2) UNRELEASED; urgency=low +libindicator (0.3.0-0ubuntu2~ppa1~restart2) karmic; urgency=low * Upstream Merge * Emitting the connection changed signal better. - -- Ted Gould Fri, 15 Jan 2010 22:17:01 -0600 + -- Ted Gould Fri, 15 Jan 2010 22:19:13 -0600 libindicator (0.3.0-0ubuntu2~ppa1~restart1) karmic; urgency=low -- cgit v1.2.3 From 079c2b517deba95385ac47eea1fd6560aef3aacb Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 15 Jan 2010 22:28:13 -0600 Subject: It's a fundamental mistake to believe that we can protect people using this interface from the disconnection. We have no information to say that the new service starting will come up in the same state as the one before it. We need the individual implementers to verify that. Now we need to fix that. This commit does so. --- libindicator/indicator-service-manager.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index 9d56a9f..891f49e 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -433,6 +433,11 @@ start_service (IndicatorServiceManager * service) static void service_proxy_destroyed (DBusGProxy * proxy, gpointer user_data) { + IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(user_data); + if (priv->connected) { + priv->connected = FALSE; + g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, FALSE, TRUE); + } return start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); } @@ -459,8 +464,6 @@ start_service_again (IndicatorServiceManager * manager) /* Allow the restarting to be disabled */ if (g_getenv(TIMEOUT_ENV_NAME)) { - priv->connected = FALSE; - g_signal_emit(manager, signals[CONNECTION_CHANGE], 0, FALSE, TRUE); return; } @@ -469,10 +472,6 @@ start_service_again (IndicatorServiceManager * manager) g_idle_add(start_service_again_cb, manager); } else { /* Not our first time 'round the block. Let's slow this down. */ - if (priv->connected) { - priv->connected = FALSE; - g_signal_emit(manager, signals[CONNECTION_CHANGE], 0, FALSE, TRUE); - } if (priv->restart_count > 16) priv->restart_count = 16; /* Not more than 1024x */ g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager); -- cgit v1.2.3 From 2265c847c4fa5d092e72d3e4b6bfb3938371ecb1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 18 Jan 2010 12:57:38 -0600 Subject: releasing version 0.3.0-0ubuntu2~ppa1 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 586f1b4..d11b29b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -libindicator (0.3.0-0ubuntu2~ppa1) UNRELEASED; urgency=low +libindicator (0.3.0-0ubuntu2~ppa1) karmic; urgency=low * Upstream Merge * Adding in the code to restart services - -- Ted Gould Mon, 18 Jan 2010 12:54:33 -0600 + -- Ted Gould Mon, 18 Jan 2010 12:57:31 -0600 libindicator (0.3.0-0ubuntu1) karmic; urgency=low -- cgit v1.2.3 From 292d5b0d5a8b7fd40fd8a2b713652a25890e1d72 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 18 Jan 2010 14:07:03 -0600 Subject: releasing version 0.3.0-0ubuntu2~ppa2~ordering1 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 701af78..e8e9ac2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -libindicator (0.3.0-0ubuntu2~ppa2~ordering1) UNRELEASED; urgency=low +libindicator (0.3.0-0ubuntu2~ppa2~ordering1) karmic; urgency=low * Upstream Merge * Adding in entry ordering. - -- Ted Gould Mon, 18 Jan 2010 14:05:32 -0600 + -- Ted Gould Mon, 18 Jan 2010 14:06:59 -0600 libindicator (0.3.0-0ubuntu2~ppa1) karmic; urgency=low -- cgit v1.2.3 From 38d6422c9ed920b979029dfb3896093c95e75660 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 19 Jan 2010 09:00:53 -0600 Subject: releasing version 0.3.0-0ubuntu2~ppa2 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index e55be1c..bc3fa16 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -libindicator (0.3.0-0ubuntu2~ppa2) UNRELEASED; urgency=low +libindicator (0.3.0-0ubuntu2~ppa2) karmic; urgency=low * Upstream Merge * Adding in entry ordering. - -- Ted Gould Tue, 19 Jan 2010 08:58:40 -0600 + -- Ted Gould Tue, 19 Jan 2010 09:00:50 -0600 libindicator (0.3.0-0ubuntu2~ppa1) karmic; urgency=low -- cgit v1.2.3 From c72ff4f03fb1fb7c28c2c8c5dda429dc12f45cd5 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 21 Jan 2010 09:49:02 -0600 Subject: Setting up the watch_cb function so that in errors it'll try to restart. As most errors will be fixed by trying again. --- libindicator/indicator-service-manager.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index 891f49e..a06e192 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -67,6 +67,10 @@ static guint signals[LAST_SIGNAL] = { 0 }; /* If this env variable is set, we don't restart */ #define TIMEOUT_ENV_NAME "INDICATOR_SERVICE_RESTART_DISABLE" #define TIMEOUT_MULTIPLIER 100 /* In ms */ +/* What to reset the restart_count to if we know that we're + in a recoverable error condition, but waiting a little bit + will probably make things better. 5 ~= 3 sec. */ +#define TIMEOUT_A_LITTLE_WHILE 5 /* Properties */ /* Enum for the properties so that they can be quickly @@ -319,6 +323,7 @@ watch_cb (DBusGProxy * proxy, guint service_api_version, guint this_service_vers if (error != NULL) { g_warning("Unable to set watch on '%s': '%s'", priv->name, error->message); g_error_free(error); + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); return; } @@ -331,12 +336,20 @@ watch_cb (DBusGProxy * proxy, guint service_api_version, guint this_service_vers if (service_api_version != INDICATOR_SERVICE_VERSION) { g_warning("Service is using a different version of the service interface. Expecting %d and got %d.", INDICATOR_SERVICE_VERSION, service_api_version); dbus_g_proxy_call_no_reply(priv->service_proxy, "UnWatch", G_TYPE_INVALID); + + /* Let's make us wait a little while, then try again */ + priv->restart_count = TIMEOUT_A_LITTLE_WHILE; + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); return; } if (this_service_version != priv->this_service_version) { g_warning("Service is using a different API version than the manager. Expecting %d and got %d.", priv->this_service_version, this_service_version); dbus_g_proxy_call_no_reply(priv->service_proxy, "UnWatch", G_TYPE_INVALID); + + /* Let's make us wait a little while, then try again */ + priv->restart_count = TIMEOUT_A_LITTLE_WHILE; + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); return; } -- cgit v1.2.3 From 4a7af569bd96c25cbf028fd7144fd2f5d6262a3c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 21 Jan 2010 10:25:27 -0600 Subject: In case we're restarting because of the 'Watch' returning failure we'd have a valid 'service_proxy' object to kill --- libindicator/indicator-service-manager.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index a06e192..5d1bd91 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -411,6 +411,11 @@ start_service (IndicatorServiceManager * service) g_return_if_fail(priv->dbus_proxy != NULL); g_return_if_fail(priv->name != NULL); + if (priv->service_proxy != NULL) { + g_object_unref(priv->service_proxy); + priv->service_proxy = NULL; + } + /* Check to see if we can get a proxy to it first. */ priv->service_proxy = dbus_g_proxy_new_for_name_owner(priv->bus, priv->name, -- cgit v1.2.3 From 0219e0e7d51086cc691367e8deda356ac2b6aabc Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 21 Jan 2010 10:30:52 -0600 Subject: Adding in tracking of the restart idle function and making sure we don't do it twice. --- libindicator/indicator-service-manager.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libindicator/indicator-service-manager.c b/libindicator/indicator-service-manager.c index 5d1bd91..7bb9a9b 100644 --- a/libindicator/indicator-service-manager.c +++ b/libindicator/indicator-service-manager.c @@ -54,6 +54,7 @@ struct _IndicatorServiceManagerPrivate { guint this_service_version; DBusGConnection * bus; guint restart_count; + gint restart_source; }; /* Signals Stuff */ @@ -168,6 +169,7 @@ indicator_service_manager_init (IndicatorServiceManager *self) priv->this_service_version = 0; priv->bus = NULL; priv->restart_count = 0; + priv->restart_source = 0; /* Start talkin' dbus */ GError * error = NULL; @@ -201,6 +203,13 @@ indicator_service_manager_dispose (GObject *object) { IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(object); + /* Removing the idle task to restart if it exists. */ + if (priv->restart_source != 0) { + g_source_remove(priv->restart_source); + } + /* Block any restart calls */ + priv->restart_source = -1; + /* If we were connected we need to make sure to tell people that it's no longer the case. */ if (priv->connected) { @@ -468,6 +477,7 @@ start_service_again_cb (gpointer data) IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(data); priv->restart_count++; start_service(INDICATOR_SERVICE_MANAGER(data)); + priv->restart_source = 0; return FALSE; } @@ -480,6 +490,12 @@ start_service_again (IndicatorServiceManager * manager) { IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(manager); + /* If we've already got a restart source running then + let's not do this again. */ + if (priv->restart_source != 0) { + return; + } + /* Allow the restarting to be disabled */ if (g_getenv(TIMEOUT_ENV_NAME)) { return; @@ -492,7 +508,7 @@ start_service_again (IndicatorServiceManager * manager) /* Not our first time 'round the block. Let's slow this down. */ if (priv->restart_count > 16) priv->restart_count = 16; /* Not more than 1024x */ - g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager); + priv->restart_source = g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager); } return; -- cgit v1.2.3 From f5232a315c253f98b08aee7bb3ec4e5613340c6b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 21 Jan 2010 13:01:01 -0600 Subject: 0.3.1 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 04d7d38..1f0ad9a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,10 @@ -AC_INIT(libindicator, 0.3.0, ted@canonical.com) +AC_INIT(libindicator, 0.3.1, ted@canonical.com) AC_PREREQ(2.53) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(libindicator, 0.3.0) +AM_INIT_AUTOMAKE(libindicator, 0.3.1) AM_MAINTAINER_MODE m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES]) -- cgit v1.2.3 From 8f6a206a4689150d8887dd653f13e72b2d320a15 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 21 Jan 2010 13:15:10 -0600 Subject: releasing version 0.3.1-0ubuntu1~ppa1 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 4c44446..bf71422 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,10 @@ -libindicator (0.3.1-0ubuntu1~ppa1) UNRELEASED; urgency=low +libindicator (0.3.1-0ubuntu1~ppa1) karmic; urgency=low * Upstream release 0.3.1 * Adding in entry ordering. * Adding in the code to restart services - -- Ted Gould Thu, 21 Jan 2010 13:03:32 -0600 + -- Ted Gould Thu, 21 Jan 2010 13:15:07 -0600 libindicator (0.3.0-0ubuntu1) lucid; urgency=low -- cgit v1.2.3