All of lore.kernel.org
 help / color / mirror / Atom feed
* [Cluster-devel] [PATCH] rgmanager: dbus notifications (Merged)
@ 2011-02-03  0:37 Lon Hohberger
  2011-02-03  6:18 ` Fabio M. Di Nitto
  0 siblings, 1 reply; 2+ messages in thread
From: Lon Hohberger @ 2011-02-03  0:37 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Includes aforementioned makefile fix

Everything in one patch for easy reading.

Resolves: rhbz#657756

Signed-off-by: Lon Hohberger <lhh@redhat.com>
---
 rgmanager/include/rg_dbus.h         |   20 +++
 rgmanager/man/rgmanager.8           |    2 +
 rgmanager/src/daemons/Makefile      |    7 +-
 rgmanager/src/daemons/main.c        |   19 ++-
 rgmanager/src/daemons/update-dbus.c |  266 +++++++++++++++++++++++++++++++++++
 5 files changed, 309 insertions(+), 5 deletions(-)
 create mode 100644 rgmanager/include/rg_dbus.h
 create mode 100644 rgmanager/src/daemons/update-dbus.c

diff --git a/rgmanager/include/rg_dbus.h b/rgmanager/include/rg_dbus.h
new file mode 100644
index 0000000..3ef5ae1
--- /dev/null
+++ b/rgmanager/include/rg_dbus.h
@@ -0,0 +1,20 @@
+#ifndef _RGM_DBUS_H
+#define _RGM_DBUS_H
+
+int rgm_dbus_init(void);
+int rgm_dbus_release(void);
+extern int rgm_dbus_notify;
+
+#ifdef DBUS
+
+#define RGM_DBUS_DEFAULT 1
+#define RGM_DBUS_UPDATE (rgm_dbus_notify?rgm_dbus_update:0)
+int32_t rgm_dbus_update(char *key, uint64_t view, void *data, uint32_t size);
+
+#else
+
+#define RGM_DBUS_DEFAULT 0
+#define RGM_DBUS_UPDATE NULL
+
+#endif /* DBUS */
+#endif
diff --git a/rgmanager/man/rgmanager.8 b/rgmanager/man/rgmanager.8
index 39b2195..2b018d2 100644
--- a/rgmanager/man/rgmanager.8
+++ b/rgmanager/man/rgmanager.8
@@ -371,6 +371,8 @@ will leave the virtual machine running.
 Run in the foreground (do not fork).
 .IP \-d
 Enable debug-level logging.
+.IP \-q
+Disable DBus signals which are normally sent when services change state.
 .IP \-w
 Disable internal process monitoring (for debugging).
 .IP \-N
diff --git a/rgmanager/src/daemons/Makefile b/rgmanager/src/daemons/Makefile
index 94e0dbb..4dbbe5a 100644
--- a/rgmanager/src/daemons/Makefile
+++ b/rgmanager/src/daemons/Makefile
@@ -29,6 +29,7 @@ OBJS1=	fo_domain.o \
 	service_op.o \
 	slang_event.o \
 	event_config.o \
+	update-dbus.o \
 	watchdog.o
 
 OBJS2=	test-noccs.o \
@@ -40,12 +41,13 @@ OBJS2=	test-noccs.o \
 	rg_locks-noccs.o \
 	event_config-noccs.o
 
-CFLAGS += -DSHAREDIR=\"${sharedir}\" -D_GNU_SOURCE
+CFLAGS += -DDBUS -DSHAREDIR=\"${sharedir}\" -D_GNU_SOURCE
 CFLAGS += -fPIC
 CFLAGS += -I${ccsincdir} -I${cmanincdir} -I${dlmincdir} -I${logtincdir}
 CFLAGS += `xml2-config --cflags` -I${slangincdir}
 CFLAGS += -I$(S)/../../include
 CFLAGS += -I${incdir}
+CFLAGS += `pkg-config --cflags dbus-1`
 
 NOCCS_CFLAGS += -DNO_CCS
 
@@ -59,6 +61,7 @@ DLM_LDFLAGS += -L${dlmlibdir} -ldlm
 XML2_LDFLAGS += `xml2-config --libs`
 SLANG_LDFLAGS += -L${slanglibdir} -lslang
 EXTRA_LDFLAGS += -lpthread
+DBUS_LDFLAGS += `pkg-config --libs dbus-1`
 
 LDDEPS += ../clulib/libclulib.a
 
@@ -66,7 +69,7 @@ ${TARGET1}: ${OBJS1} ${LDDEPS}
 	$(CC) -o $@ $^ $(CCS_LDFLAGS) $(CMAN_LDFLAGS) \
 			$(DLM_LDFLAGS) $(XML2_LDFLAGS) \
 			$(SLANG_LDFLAGS) $(EXTRA_LDFLAGS) \
-			$(LOGSYS_LDFLAGS) $(LD_FLAGS)
+			$(LOGSYS_LDFLAGS) $(LD_FLAGS) $(DBUS_LDFLAGS)
 
 #
 # Our test program links against the local allocator so that
diff --git a/rgmanager/src/daemons/main.c b/rgmanager/src/daemons/main.c
index 4e34246..02cd2dc 100644
--- a/rgmanager/src/daemons/main.c
+++ b/rgmanager/src/daemons/main.c
@@ -23,6 +23,7 @@
 #include <members.h>
 #include <daemon_init.h>
 #include <groups.h>
+#include <rg_dbus.h>
 
 #ifdef WRAP_THREADS
 void dump_thread_states(FILE *);
@@ -43,7 +44,6 @@ static uint8_t ALIGNED port = RG_PORT;
 static char *rgmanager_lsname = (char *)"rgmanager"; /* XXX default */
 static int status_poll_interval = DEFAULT_CHECK_INTERVAL;
 
-
 static void
 segfault(int __attribute__ ((unused)) sig)
 {
@@ -684,6 +684,8 @@ event_loop(msgctx_t *localctx, msgctx_t *clusterctx)
 		dump_internal_state("/var/lib/cluster/rgmanager-dump");
 	}
 
+	rgm_dbus_init();
+
 	while (running && (tv.tv_sec || tv.tv_usec)) {
 		FD_ZERO(&rfds);
 		max = -1;
@@ -949,7 +951,7 @@ main(int argc, char **argv)
 	pthread_t th;
 	cman_handle_t clu = NULL;
 
-	while ((rv = getopt(argc, argv, "wfdN")) != EOF) {
+	while ((rv = getopt(argc, argv, "wfdNq")) != EOF) {
 		switch (rv) {
 		case 'w':
 			wd = 0;
@@ -963,6 +965,9 @@ main(int argc, char **argv)
 		case 'f':
 			foreground = 1;
 			break;
+		case 'q':
+			rgm_dbus_notify = 0;
+			break;
 		default:
 			return 1;
 			break;
@@ -1032,6 +1037,12 @@ main(int argc, char **argv)
 	configure_rgmanager(-1, debug, &cluster_timeout);
 	logt_print(LOG_NOTICE, "Resource Group Manager Starting\n");
 
+	if (rgm_dbus_notify && rgm_dbus_init() != 0) {
+		rgm_dbus_notify = 0;
+		logt_print(LOG_NOTICE, "Failed to initialize DBus; "
+			   "notifications disabled\n");
+	}
+
 	if (init_resource_groups(0, do_init) != 0) {
 		logt_print(LOG_CRIT, "#8: Couldn't initialize services\n");
 		goto out_ls;
@@ -1074,7 +1085,8 @@ main(int argc, char **argv)
 
 	ds_key_init("rg_lockdown", 32, 10);
 #else
-	if (vf_init(me.cn_nodeid, port, NULL, NULL, cluster_timeout) != 0) {
+	if (vf_init(me.cn_nodeid, port, NULL, RGM_DBUS_UPDATE,
+		    cluster_timeout) != 0) {
 		logt_print(LOG_CRIT, "#11: Couldn't set up VF listen socket\n");
 		goto out_ls;
 	}
@@ -1106,6 +1118,7 @@ out_ls:
 	clu_lock_finished(rgmanager_lsname);
 
 out:
+	rgm_dbus_release();
 	logt_print(LOG_NOTICE, "Shutdown complete, exiting\n");
 	cman_finish(clu);
 	
diff --git a/rgmanager/src/daemons/update-dbus.c b/rgmanager/src/daemons/update-dbus.c
new file mode 100644
index 0000000..f465d1d
--- /dev/null
+++ b/rgmanager/src/daemons/update-dbus.c
@@ -0,0 +1,266 @@
+/* DBus notifications */
+#include <stdint.h>
+#include <rg_dbus.h>
+#include <errno.h>
+
+#ifdef DBUS
+
+#include <stdio.h>
+#include <stdint.h>
+#include <resgroup.h>
+#include <poll.h>
+#include <dbus/dbus.h>
+#include <liblogthread.h>
+#include <members.h>
+
+
+#define DBUS_RGM_NAME	"com.redhat.cluster.rgmanager"
+#define DBUS_RGM_IFACE	"com.redhat.cluster.rgmanager"
+#define DBUS_RGM_PATH	"/com/redhat/cluster/rgmanager"
+
+static DBusConnection *db = NULL;
+static pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t th = 0;
+#endif
+
+/* Set this to the desired value prior to calling rgm_dbus_init() */
+int rgm_dbus_notify = RGM_DBUS_DEFAULT;
+
+
+int 
+rgm_dbus_init(void)
+#ifdef DBUS
+{
+	DBusConnection *dbc = NULL;
+	DBusError err;
+
+	if (!rgm_dbus_notify)
+		return 0;
+
+	pthread_mutex_lock(&mu);
+	if (db) {
+		pthread_mutex_unlock(&mu);
+		return 0;
+	}
+
+	dbus_error_init(&err);
+
+	dbc = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
+	if (!dbc) {
+		logt_print(LOG_DEBUG,
+			   "DBus Failed to initialize: dbus_bus_get: %s\n",
+			   err.message);
+		dbus_error_free(&err);
+		pthread_mutex_unlock(&mu);
+		return -1;
+	}
+
+	dbus_connection_set_exit_on_disconnect(dbc, FALSE);
+
+	db = dbc;
+	pthread_mutex_unlock(&mu);
+	logt_print(LOG_DEBUG, "DBus Notifications Initialized\n");
+	return 0;
+}
+#else
+{
+	errno = ENOSYS;
+	return -1;
+}
+#endif
+
+
+#ifdef DBUS
+static int
+_rgm_dbus_release(void)
+{
+	pthread_t t;
+
+	if (!db)
+		return 0;
+
+	/* tell thread to exit - not sure how to tell dbus
+	 * to wake up, so just have it poll XXX */
+
+	/* if the thread left because the dbus connection died,
+	   this block is avoided */
+	if (th) {
+		t = th;
+		th = 0;
+		pthread_join(t, NULL);
+	}
+
+	dbus_connection_close(db);
+	dbus_connection_unref(db);
+	db = NULL;
+
+	logt_print(LOG_DEBUG, "DBus Released\n");
+	return 0;
+}
+#endif
+
+
+/* Clean shutdown (e.g. when exiting */
+int
+rgm_dbus_release(void)
+#ifdef DBUS
+{
+	int ret;
+
+	pthread_mutex_lock(&mu);
+	ret = _rgm_dbus_release();
+	pthread_mutex_unlock(&mu);
+	return ret;
+}
+#else
+{
+	return 0;
+}
+#endif
+
+
+#ifdef DBUS
+/* Auto-flush thread.  Since sending only guarantees queueing,
+ * we need this thread to push things out over dbus in the
+ * background */
+static void *
+_dbus_auto_flush(void *arg)
+{
+	/* DBus connection functions are thread safe */
+	dbus_connection_ref(db);
+	while (dbus_connection_read_write(db, 500)) {
+		if (!th)
+			break;	
+	}
+
+	dbus_connection_unref(db);
+	th = 0;
+	return NULL;
+}
+
+
+static int
+_rgm_dbus_notify(const char *svcname,
+		 const char *svcstatus,
+		 const char *svcflags,
+		 const char *svcowner,
+		 const char *svclast)
+{
+	DBusMessage *msg = NULL;
+	int ret = -1;
+
+	if (!db) {
+		goto out_free;
+	}
+
+	pthread_mutex_lock(&mu);
+
+	/* Check to ensure the connection is still valid. If it
+	 * isn't, clean up and shut down the dbus connection.
+	 *
+	 * The main rgmanager thread will periodically try to
+	 * reinitialize the dbus notification subsystem unless
+	 * the administrator ran rgmanager with the -D command
+	 * line option.
+	 */
+	if (dbus_connection_get_is_connected(db) != TRUE) {
+		goto out_unlock;
+	}
+
+	if (!th) {
+		/* start auto-flush thread if needed */
+		pthread_create(&th, NULL, _dbus_auto_flush, NULL);
+	}
+
+	if (!(msg = dbus_message_new_signal(DBUS_RGM_PATH,
+	      				    DBUS_RGM_IFACE,
+	      				    "ServiceStateChange"))) {
+		goto out_unlock;
+	}
+
+	if (!dbus_message_append_args(msg,
+	 			      DBUS_TYPE_STRING, &svcname,
+	 			      DBUS_TYPE_STRING, &svcstatus,
+	 			      DBUS_TYPE_STRING, &svcflags,
+ 				      DBUS_TYPE_STRING, &svcowner,
+ 				      DBUS_TYPE_STRING, &svclast,
+	    			      DBUS_TYPE_INVALID)) {
+		goto out_unlock;
+	}
+
+	dbus_connection_send(db, msg, NULL);
+	ret = 0;
+
+out_unlock:
+	pthread_mutex_unlock(&mu);
+	if (msg)
+		dbus_message_unref(msg);
+out_free:
+	return ret;
+}
+
+
+/*
+ * view-formation callback function
+ */
+int32_t
+rgm_dbus_update(char *key, uint64_t view, void *data, uint32_t size)
+{
+	char flags[64];
+	rg_state_t *st;
+	cluster_member_list_t *m = NULL;
+	const char *owner;
+	const char *last;
+	int ret = 0;
+
+	if (!rgm_dbus_notify)
+		goto out_free;
+	if (!db)
+		goto out_free;
+	if (view == 1)
+		goto out_free;
+	if (size != (sizeof(*st)))
+		goto out_free;
+
+	st = (rg_state_t *)data;
+	swab_rg_state_t(st);
+
+	/* Don't send transitional states */
+	if (st->rs_state == RG_STATE_STARTING ||
+	    st->rs_state == RG_STATE_STOPPING)
+		goto out_free;
+
+	m = member_list();
+	if (!m)
+		goto out_free;
+
+	owner = memb_id_to_name(m, st->rs_owner);
+	last = memb_id_to_name(m, st->rs_last_owner);
+
+	if (!owner)
+		owner = "(none)";
+	if (!last)
+		last = "(none)";
+
+	flags[0] = 0;
+	rg_flags_str(flags, sizeof(flags), st->rs_flags, (char *)" ");
+	if (flags[0] == 0)
+		snprintf(flags, sizeof(flags), "(none)");
+
+	ret = _rgm_dbus_notify(st->rs_name,
+			       rg_state_str(st->rs_state),
+			       (char *)flags, owner, last);
+
+	if (ret < 0) {
+		logt_print(LOG_ERR, "Error sending update for %s; "
+			   "DBus notifications disabled\n", key);
+		rgm_dbus_release();
+	}
+
+out_free:
+	if (m)
+		free_member_list(m);
+	free(data);
+	return 0;
+}
+#endif
-- 
1.7.2.3



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [Cluster-devel] [PATCH] rgmanager: dbus notifications (Merged)
  2011-02-03  0:37 [Cluster-devel] [PATCH] rgmanager: dbus notifications (Merged) Lon Hohberger
@ 2011-02-03  6:18 ` Fabio M. Di Nitto
  0 siblings, 0 replies; 2+ messages in thread
From: Fabio M. Di Nitto @ 2011-02-03  6:18 UTC (permalink / raw)
  To: cluster-devel.redhat.com

You  might as well cherry pick the build system patch to enable/disable
dbus in the same patch set.

That way we have no delta and we can avoid possible merge conflicts later.

Fabio

On 02/03/2011 01:37 AM, Lon Hohberger wrote:
> Includes aforementioned makefile fix
> 
> Everything in one patch for easy reading.
> 
> Resolves: rhbz#657756
> 
> Signed-off-by: Lon Hohberger <lhh@redhat.com>
> ---
>  rgmanager/include/rg_dbus.h         |   20 +++
>  rgmanager/man/rgmanager.8           |    2 +
>  rgmanager/src/daemons/Makefile      |    7 +-
>  rgmanager/src/daemons/main.c        |   19 ++-
>  rgmanager/src/daemons/update-dbus.c |  266 +++++++++++++++++++++++++++++++++++
>  5 files changed, 309 insertions(+), 5 deletions(-)
>  create mode 100644 rgmanager/include/rg_dbus.h
>  create mode 100644 rgmanager/src/daemons/update-dbus.c
> 
> diff --git a/rgmanager/include/rg_dbus.h b/rgmanager/include/rg_dbus.h
> new file mode 100644
> index 0000000..3ef5ae1
> --- /dev/null
> +++ b/rgmanager/include/rg_dbus.h
> @@ -0,0 +1,20 @@
> +#ifndef _RGM_DBUS_H
> +#define _RGM_DBUS_H
> +
> +int rgm_dbus_init(void);
> +int rgm_dbus_release(void);
> +extern int rgm_dbus_notify;
> +
> +#ifdef DBUS
> +
> +#define RGM_DBUS_DEFAULT 1
> +#define RGM_DBUS_UPDATE (rgm_dbus_notify?rgm_dbus_update:0)
> +int32_t rgm_dbus_update(char *key, uint64_t view, void *data, uint32_t size);
> +
> +#else
> +
> +#define RGM_DBUS_DEFAULT 0
> +#define RGM_DBUS_UPDATE NULL
> +
> +#endif /* DBUS */
> +#endif
> diff --git a/rgmanager/man/rgmanager.8 b/rgmanager/man/rgmanager.8
> index 39b2195..2b018d2 100644
> --- a/rgmanager/man/rgmanager.8
> +++ b/rgmanager/man/rgmanager.8
> @@ -371,6 +371,8 @@ will leave the virtual machine running.
>  Run in the foreground (do not fork).
>  .IP \-d
>  Enable debug-level logging.
> +.IP \-q
> +Disable DBus signals which are normally sent when services change state.
>  .IP \-w
>  Disable internal process monitoring (for debugging).
>  .IP \-N
> diff --git a/rgmanager/src/daemons/Makefile b/rgmanager/src/daemons/Makefile
> index 94e0dbb..4dbbe5a 100644
> --- a/rgmanager/src/daemons/Makefile
> +++ b/rgmanager/src/daemons/Makefile
> @@ -29,6 +29,7 @@ OBJS1=	fo_domain.o \
>  	service_op.o \
>  	slang_event.o \
>  	event_config.o \
> +	update-dbus.o \
>  	watchdog.o
>  
>  OBJS2=	test-noccs.o \
> @@ -40,12 +41,13 @@ OBJS2=	test-noccs.o \
>  	rg_locks-noccs.o \
>  	event_config-noccs.o
>  
> -CFLAGS += -DSHAREDIR=\"${sharedir}\" -D_GNU_SOURCE
> +CFLAGS += -DDBUS -DSHAREDIR=\"${sharedir}\" -D_GNU_SOURCE
>  CFLAGS += -fPIC
>  CFLAGS += -I${ccsincdir} -I${cmanincdir} -I${dlmincdir} -I${logtincdir}
>  CFLAGS += `xml2-config --cflags` -I${slangincdir}
>  CFLAGS += -I$(S)/../../include
>  CFLAGS += -I${incdir}
> +CFLAGS += `pkg-config --cflags dbus-1`
>  
>  NOCCS_CFLAGS += -DNO_CCS
>  
> @@ -59,6 +61,7 @@ DLM_LDFLAGS += -L${dlmlibdir} -ldlm
>  XML2_LDFLAGS += `xml2-config --libs`
>  SLANG_LDFLAGS += -L${slanglibdir} -lslang
>  EXTRA_LDFLAGS += -lpthread
> +DBUS_LDFLAGS += `pkg-config --libs dbus-1`
>  
>  LDDEPS += ../clulib/libclulib.a
>  
> @@ -66,7 +69,7 @@ ${TARGET1}: ${OBJS1} ${LDDEPS}
>  	$(CC) -o $@ $^ $(CCS_LDFLAGS) $(CMAN_LDFLAGS) \
>  			$(DLM_LDFLAGS) $(XML2_LDFLAGS) \
>  			$(SLANG_LDFLAGS) $(EXTRA_LDFLAGS) \
> -			$(LOGSYS_LDFLAGS) $(LD_FLAGS)
> +			$(LOGSYS_LDFLAGS) $(LD_FLAGS) $(DBUS_LDFLAGS)
>  
>  #
>  # Our test program links against the local allocator so that
> diff --git a/rgmanager/src/daemons/main.c b/rgmanager/src/daemons/main.c
> index 4e34246..02cd2dc 100644
> --- a/rgmanager/src/daemons/main.c
> +++ b/rgmanager/src/daemons/main.c
> @@ -23,6 +23,7 @@
>  #include <members.h>
>  #include <daemon_init.h>
>  #include <groups.h>
> +#include <rg_dbus.h>
>  
>  #ifdef WRAP_THREADS
>  void dump_thread_states(FILE *);
> @@ -43,7 +44,6 @@ static uint8_t ALIGNED port = RG_PORT;
>  static char *rgmanager_lsname = (char *)"rgmanager"; /* XXX default */
>  static int status_poll_interval = DEFAULT_CHECK_INTERVAL;
>  
> -
>  static void
>  segfault(int __attribute__ ((unused)) sig)
>  {
> @@ -684,6 +684,8 @@ event_loop(msgctx_t *localctx, msgctx_t *clusterctx)
>  		dump_internal_state("/var/lib/cluster/rgmanager-dump");
>  	}
>  
> +	rgm_dbus_init();
> +
>  	while (running && (tv.tv_sec || tv.tv_usec)) {
>  		FD_ZERO(&rfds);
>  		max = -1;
> @@ -949,7 +951,7 @@ main(int argc, char **argv)
>  	pthread_t th;
>  	cman_handle_t clu = NULL;
>  
> -	while ((rv = getopt(argc, argv, "wfdN")) != EOF) {
> +	while ((rv = getopt(argc, argv, "wfdNq")) != EOF) {
>  		switch (rv) {
>  		case 'w':
>  			wd = 0;
> @@ -963,6 +965,9 @@ main(int argc, char **argv)
>  		case 'f':
>  			foreground = 1;
>  			break;
> +		case 'q':
> +			rgm_dbus_notify = 0;
> +			break;
>  		default:
>  			return 1;
>  			break;
> @@ -1032,6 +1037,12 @@ main(int argc, char **argv)
>  	configure_rgmanager(-1, debug, &cluster_timeout);
>  	logt_print(LOG_NOTICE, "Resource Group Manager Starting\n");
>  
> +	if (rgm_dbus_notify && rgm_dbus_init() != 0) {
> +		rgm_dbus_notify = 0;
> +		logt_print(LOG_NOTICE, "Failed to initialize DBus; "
> +			   "notifications disabled\n");
> +	}
> +
>  	if (init_resource_groups(0, do_init) != 0) {
>  		logt_print(LOG_CRIT, "#8: Couldn't initialize services\n");
>  		goto out_ls;
> @@ -1074,7 +1085,8 @@ main(int argc, char **argv)
>  
>  	ds_key_init("rg_lockdown", 32, 10);
>  #else
> -	if (vf_init(me.cn_nodeid, port, NULL, NULL, cluster_timeout) != 0) {
> +	if (vf_init(me.cn_nodeid, port, NULL, RGM_DBUS_UPDATE,
> +		    cluster_timeout) != 0) {
>  		logt_print(LOG_CRIT, "#11: Couldn't set up VF listen socket\n");
>  		goto out_ls;
>  	}
> @@ -1106,6 +1118,7 @@ out_ls:
>  	clu_lock_finished(rgmanager_lsname);
>  
>  out:
> +	rgm_dbus_release();
>  	logt_print(LOG_NOTICE, "Shutdown complete, exiting\n");
>  	cman_finish(clu);
>  	
> diff --git a/rgmanager/src/daemons/update-dbus.c b/rgmanager/src/daemons/update-dbus.c
> new file mode 100644
> index 0000000..f465d1d
> --- /dev/null
> +++ b/rgmanager/src/daemons/update-dbus.c
> @@ -0,0 +1,266 @@
> +/* DBus notifications */
> +#include <stdint.h>
> +#include <rg_dbus.h>
> +#include <errno.h>
> +
> +#ifdef DBUS
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <resgroup.h>
> +#include <poll.h>
> +#include <dbus/dbus.h>
> +#include <liblogthread.h>
> +#include <members.h>
> +
> +
> +#define DBUS_RGM_NAME	"com.redhat.cluster.rgmanager"
> +#define DBUS_RGM_IFACE	"com.redhat.cluster.rgmanager"
> +#define DBUS_RGM_PATH	"/com/redhat/cluster/rgmanager"
> +
> +static DBusConnection *db = NULL;
> +static pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
> +static pthread_t th = 0;
> +#endif
> +
> +/* Set this to the desired value prior to calling rgm_dbus_init() */
> +int rgm_dbus_notify = RGM_DBUS_DEFAULT;
> +
> +
> +int 
> +rgm_dbus_init(void)
> +#ifdef DBUS
> +{
> +	DBusConnection *dbc = NULL;
> +	DBusError err;
> +
> +	if (!rgm_dbus_notify)
> +		return 0;
> +
> +	pthread_mutex_lock(&mu);
> +	if (db) {
> +		pthread_mutex_unlock(&mu);
> +		return 0;
> +	}
> +
> +	dbus_error_init(&err);
> +
> +	dbc = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
> +	if (!dbc) {
> +		logt_print(LOG_DEBUG,
> +			   "DBus Failed to initialize: dbus_bus_get: %s\n",
> +			   err.message);
> +		dbus_error_free(&err);
> +		pthread_mutex_unlock(&mu);
> +		return -1;
> +	}
> +
> +	dbus_connection_set_exit_on_disconnect(dbc, FALSE);
> +
> +	db = dbc;
> +	pthread_mutex_unlock(&mu);
> +	logt_print(LOG_DEBUG, "DBus Notifications Initialized\n");
> +	return 0;
> +}
> +#else
> +{
> +	errno = ENOSYS;
> +	return -1;
> +}
> +#endif
> +
> +
> +#ifdef DBUS
> +static int
> +_rgm_dbus_release(void)
> +{
> +	pthread_t t;
> +
> +	if (!db)
> +		return 0;
> +
> +	/* tell thread to exit - not sure how to tell dbus
> +	 * to wake up, so just have it poll XXX */
> +
> +	/* if the thread left because the dbus connection died,
> +	   this block is avoided */
> +	if (th) {
> +		t = th;
> +		th = 0;
> +		pthread_join(t, NULL);
> +	}
> +
> +	dbus_connection_close(db);
> +	dbus_connection_unref(db);
> +	db = NULL;
> +
> +	logt_print(LOG_DEBUG, "DBus Released\n");
> +	return 0;
> +}
> +#endif
> +
> +
> +/* Clean shutdown (e.g. when exiting */
> +int
> +rgm_dbus_release(void)
> +#ifdef DBUS
> +{
> +	int ret;
> +
> +	pthread_mutex_lock(&mu);
> +	ret = _rgm_dbus_release();
> +	pthread_mutex_unlock(&mu);
> +	return ret;
> +}
> +#else
> +{
> +	return 0;
> +}
> +#endif
> +
> +
> +#ifdef DBUS
> +/* Auto-flush thread.  Since sending only guarantees queueing,
> + * we need this thread to push things out over dbus in the
> + * background */
> +static void *
> +_dbus_auto_flush(void *arg)
> +{
> +	/* DBus connection functions are thread safe */
> +	dbus_connection_ref(db);
> +	while (dbus_connection_read_write(db, 500)) {
> +		if (!th)
> +			break;	
> +	}
> +
> +	dbus_connection_unref(db);
> +	th = 0;
> +	return NULL;
> +}
> +
> +
> +static int
> +_rgm_dbus_notify(const char *svcname,
> +		 const char *svcstatus,
> +		 const char *svcflags,
> +		 const char *svcowner,
> +		 const char *svclast)
> +{
> +	DBusMessage *msg = NULL;
> +	int ret = -1;
> +
> +	if (!db) {
> +		goto out_free;
> +	}
> +
> +	pthread_mutex_lock(&mu);
> +
> +	/* Check to ensure the connection is still valid. If it
> +	 * isn't, clean up and shut down the dbus connection.
> +	 *
> +	 * The main rgmanager thread will periodically try to
> +	 * reinitialize the dbus notification subsystem unless
> +	 * the administrator ran rgmanager with the -D command
> +	 * line option.
> +	 */
> +	if (dbus_connection_get_is_connected(db) != TRUE) {
> +		goto out_unlock;
> +	}
> +
> +	if (!th) {
> +		/* start auto-flush thread if needed */
> +		pthread_create(&th, NULL, _dbus_auto_flush, NULL);
> +	}
> +
> +	if (!(msg = dbus_message_new_signal(DBUS_RGM_PATH,
> +	      				    DBUS_RGM_IFACE,
> +	      				    "ServiceStateChange"))) {
> +		goto out_unlock;
> +	}
> +
> +	if (!dbus_message_append_args(msg,
> +	 			      DBUS_TYPE_STRING, &svcname,
> +	 			      DBUS_TYPE_STRING, &svcstatus,
> +	 			      DBUS_TYPE_STRING, &svcflags,
> + 				      DBUS_TYPE_STRING, &svcowner,
> + 				      DBUS_TYPE_STRING, &svclast,
> +	    			      DBUS_TYPE_INVALID)) {
> +		goto out_unlock;
> +	}
> +
> +	dbus_connection_send(db, msg, NULL);
> +	ret = 0;
> +
> +out_unlock:
> +	pthread_mutex_unlock(&mu);
> +	if (msg)
> +		dbus_message_unref(msg);
> +out_free:
> +	return ret;
> +}
> +
> +
> +/*
> + * view-formation callback function
> + */
> +int32_t
> +rgm_dbus_update(char *key, uint64_t view, void *data, uint32_t size)
> +{
> +	char flags[64];
> +	rg_state_t *st;
> +	cluster_member_list_t *m = NULL;
> +	const char *owner;
> +	const char *last;
> +	int ret = 0;
> +
> +	if (!rgm_dbus_notify)
> +		goto out_free;
> +	if (!db)
> +		goto out_free;
> +	if (view == 1)
> +		goto out_free;
> +	if (size != (sizeof(*st)))
> +		goto out_free;
> +
> +	st = (rg_state_t *)data;
> +	swab_rg_state_t(st);
> +
> +	/* Don't send transitional states */
> +	if (st->rs_state == RG_STATE_STARTING ||
> +	    st->rs_state == RG_STATE_STOPPING)
> +		goto out_free;
> +
> +	m = member_list();
> +	if (!m)
> +		goto out_free;
> +
> +	owner = memb_id_to_name(m, st->rs_owner);
> +	last = memb_id_to_name(m, st->rs_last_owner);
> +
> +	if (!owner)
> +		owner = "(none)";
> +	if (!last)
> +		last = "(none)";
> +
> +	flags[0] = 0;
> +	rg_flags_str(flags, sizeof(flags), st->rs_flags, (char *)" ");
> +	if (flags[0] == 0)
> +		snprintf(flags, sizeof(flags), "(none)");
> +
> +	ret = _rgm_dbus_notify(st->rs_name,
> +			       rg_state_str(st->rs_state),
> +			       (char *)flags, owner, last);
> +
> +	if (ret < 0) {
> +		logt_print(LOG_ERR, "Error sending update for %s; "
> +			   "DBus notifications disabled\n", key);
> +		rgm_dbus_release();
> +	}
> +
> +out_free:
> +	if (m)
> +		free_member_list(m);
> +	free(data);
> +	return 0;
> +}
> +#endif



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-02-03  6:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-03  0:37 [Cluster-devel] [PATCH] rgmanager: dbus notifications (Merged) Lon Hohberger
2011-02-03  6:18 ` Fabio M. Di Nitto

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.