Просмотр исходного кода

load and unload service engines at runtime.

git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1528 fd59a12c-fef9-0310-b244-a6a79926bd2f
Steven Dake 18 лет назад
Родитель
Сommit
4ad44b9c86
11 измененных файлов с 447 добавлено и 148 удалено
  1. 76 7
      exec/cfg.c
  2. 8 0
      exec/clm.c
  3. 8 11
      exec/main.c
  4. 2 1
      exec/objdb.c
  5. 147 106
      exec/service.c
  6. 26 14
      exec/service.h
  7. 12 0
      include/cfg.h
  8. 24 0
      include/ipc_cfg.h
  9. 79 5
      lib/cfg.c
  10. 3 1
      lib/libcfg.versions
  11. 62 3
      test/openais-cfgtool.c

+ 76 - 7
exec/cfg.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2005-2006 MontaVista Software, Inc.
- * Copyright (c) 2006 Red Hat, Inc.
+ * Copyright (c) 2006-2007 Red Hat, Inc.
  * Copyright (c) 2006 Sun Microsystems, Inc.
  *
  * All rights reserved.
@@ -68,7 +68,7 @@
 #include "logsys.h"
 #include "main.h"
 
-LOGSYS_DECLARE_SUBSYS ("AMF", LOG_INFO);
+LOGSYS_DECLARE_SUBSYS ("CFG", LOG_INFO);
 
 enum cfg_message_req_types {
         MESSAGE_REQ_EXEC_CFG_RINGREENABLE = 0
@@ -115,6 +115,14 @@ static void message_handler_req_lib_cfg_administrativestateget (
 	void *conn,
 	void *msg);
 
+static void message_handler_req_lib_cfg_serviceload (
+	void *conn,
+	void *msg);
+
+static void message_handler_req_lib_cfg_serviceunload (
+	void *conn,
+	void *msg);
+
 /*
  * Service Handler Definition
  */
@@ -126,35 +134,47 @@ static struct openais_lib_handler cfg_lib_service[] =
 		.response_id		= MESSAGE_RES_CFG_RINGSTATUSGET,
 		.flow_control		= OPENAIS_FLOW_CONTROL_REQUIRED
 	},
-	{ /* 0 */
+	{ /* 1 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_ringreenable,
 		.response_size		= sizeof (struct res_lib_cfg_ringreenable),
 		.response_id		= MESSAGE_RES_CFG_RINGREENABLE,
 		.flow_control		= OPENAIS_FLOW_CONTROL_REQUIRED
 	},
-	{ /* 0 */
+	{ /* 2 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_statetrack,
 		.response_size		= sizeof (struct res_lib_cfg_statetrack),
 		.response_id		= MESSAGE_RES_CFG_STATETRACKSTART,
 		.flow_control		= OPENAIS_FLOW_CONTROL_REQUIRED
 	},
-	{ /* 1 */
+	{ /* 3 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_statetrackstop,
 		.response_size		= sizeof (struct res_lib_cfg_statetrackstop),
 		.response_id		= MESSAGE_RES_CFG_STATETRACKSTOP,
 		.flow_control		= OPENAIS_FLOW_CONTROL_REQUIRED
 	},
-	{ /* 2 */
+	{ /* 4 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_administrativestateset,
 		.response_size		= sizeof (struct res_lib_cfg_administrativestateset),
 		.response_id		= MESSAGE_RES_CFG_ADMINISTRATIVESTATESET,
 		.flow_control		= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
 	},
-	{ /* 3 */
+	{ /* 5 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_administrativestateget,
 		.response_size		= sizeof (struct res_lib_cfg_administrativestateget),
 		.response_id		= MESSAGE_RES_CFG_ADMINISTRATIVESTATEGET,
 		.flow_control		= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 6 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_serviceload,
+		.response_size		= sizeof (struct res_lib_cfg_serviceload),
+		.response_id		= MESSAGE_RES_CFG_SERVICELOAD,
+		.flow_control		= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 7 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_serviceunload,
+		.response_size		= sizeof (struct res_lib_cfg_serviceunload),
+		.response_id		= MESSAGE_RES_CFG_SERVICEUNLOAD,
+		.flow_control		= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
 	}
 };
 
@@ -183,6 +203,8 @@ struct openais_service_handler cfg_service_handler = {
 	.confchg_fn				= cfg_confchg_fn,
 };
 
+static struct objdb_iface_ver0 *my_objdb;
+
 /*
  * Dynamic Loader definition
  */
@@ -231,6 +253,7 @@ struct req_exec_cfg_ringreenable {
 
 static int cfg_exec_init_fn (struct objdb_iface_ver0 *objdb)
 {
+	my_objdb = objdb;
 	return (0);
 }
 
@@ -386,3 +409,49 @@ static void message_handler_req_lib_cfg_administrativestateget (
 	LEAVE("");
 }
 
+static void message_handler_req_lib_cfg_serviceload (
+	void *conn,
+	void *msg)
+{
+	struct req_lib_cfg_serviceload *req_lib_cfg_serviceload =
+		(struct req_lib_cfg_serviceload *)msg;
+	struct res_lib_cfg_serviceload res_lib_cfg_serviceload;
+
+	ENTER("");
+	openais_service_link_and_init (
+		my_objdb,
+		(char *)req_lib_cfg_serviceload->service_name,
+		req_lib_cfg_serviceload->service_ver);
+
+	res_lib_cfg_serviceload.header.id = MESSAGE_RES_CFG_SERVICEUNLOAD;
+	res_lib_cfg_serviceload.header.size = sizeof (struct res_lib_cfg_serviceload);
+	res_lib_cfg_serviceload.header.error = SA_AIS_OK;
+	openais_conn_send_response (
+		conn,
+		&res_lib_cfg_serviceload,
+		sizeof (struct res_lib_cfg_serviceload));
+	LEAVE("");
+}
+
+static void message_handler_req_lib_cfg_serviceunload (
+	void *conn,
+	void *msg)
+{
+	struct req_lib_cfg_serviceunload *req_lib_cfg_serviceunload =
+		(struct req_lib_cfg_serviceunload *)msg;
+	struct res_lib_cfg_serviceunload res_lib_cfg_serviceunload;
+
+	ENTER("");
+	openais_service_unlink_and_exit (
+		my_objdb,
+		(char *)req_lib_cfg_serviceunload->service_name,
+		req_lib_cfg_serviceunload->service_ver);
+	res_lib_cfg_serviceunload.header.id = MESSAGE_RES_CFG_SERVICEUNLOAD;
+	res_lib_cfg_serviceunload.header.size = sizeof (struct res_lib_cfg_serviceunload);
+	res_lib_cfg_serviceunload.header.error = SA_AIS_OK;
+	openais_conn_send_response (
+		conn,
+		&res_lib_cfg_serviceunload,
+		sizeof (struct res_lib_cfg_serviceunload));
+	LEAVE("");
+}

+ 8 - 0
exec/clm.c

@@ -142,6 +142,8 @@ static void clm_sync_abort (void);
 
 static int clm_exec_init_fn (struct objdb_iface_ver0 *objdb);
 
+static int clm_exec_exit_fn (struct objdb_iface_ver0 *objdb);
+
 static int clm_lib_init_fn (void *conn);
 
 static int clm_lib_exit_fn (void *conn);
@@ -216,6 +218,7 @@ struct openais_service_handler clm_service_handler = {
 	.lib_service		= clm_lib_service,
 	.lib_service_count	= sizeof (clm_lib_service) / sizeof (struct openais_lib_handler),
 	.exec_init_fn		= clm_exec_init_fn,
+	.exec_exit_fn		= clm_exec_exit_fn,
 	.exec_dump_fn		= NULL,
 	.exec_service		= clm_exec_service,
 	.exec_service_count	= sizeof (clm_exec_service) / sizeof (struct openais_exec_handler),
@@ -355,6 +358,11 @@ static int clm_exec_init_fn (struct objdb_iface_ver0 *objdb)
 	return (0);
 }
 
+static int clm_exec_exit_fn (struct objdb_iface_ver0 *objdb)
+{
+	return (0);
+}
+
 static int clm_lib_exit_fn (void *conn)
 {
 	struct clm_pd *clm_pd = (struct clm_pd *)openais_conn_private_data_get (conn);

+ 8 - 11
exec/main.c

@@ -500,7 +500,11 @@ int main (int argc, char **argv)
 
 	objdb->objdb_init ();
 
-	/* User's bootstrap config service */
+	/*
+	 * Bootstrap in the default configuration parser or use
+	 * the openais default built in parser if the configuration parser
+	 * isn't overridden
+	 */
 	config_iface = getenv("OPENAIS_DEFAULT_CONFIG_IFACE");
 	if (!config_iface) {
 		config_iface = "aisparser";
@@ -537,14 +541,6 @@ int main (int argc, char **argv)
 	if (config_iface)
 		free(config_iface);
 
-	openais_service_default_objdb_set (objdb);
-
-	res = openais_service_link_all (objdb);
-	if (res == -1) {
-		log_printf (LOG_LEVEL_ERROR, "Could not load services\n");
-		openais_exit_error (AIS_DONE_DYNAMICLOAD);
-	}
-
 	res = openais_main_config_read (objdb, &error_string, &main_config);
 	if (res == -1) {
 		log_printf (LOG_LEVEL_ERROR, error_string);
@@ -636,12 +632,13 @@ int main (int argc, char **argv)
 	/*
 	 * This must occur after totempg is initialized because "this_ip" must be set
 	 */
-	res = openais_service_init_all (service_count, objdb);
+	res = openais_service_defaults_link_and_init (objdb);
 	if (res == -1) {
-		log_printf (LOG_LEVEL_ERROR, "Could not init services\n");
+		log_printf (LOG_LEVEL_ERROR, "Could not initialize default services\n");
 		openais_exit_error (AIS_DONE_INIT_SERVICES);
 	}
 
+
 	sync_register (openais_sync_callbacks_retrieve, openais_sync_completed,
 		totem_config.vsf_type);
 

+ 2 - 1
exec/objdb.c

@@ -73,6 +73,7 @@ static struct hdb_handle_database object_instance_database = {
 	.mutex		= PTHREAD_MUTEX_INITIALIZER
 };
 
+
 static int objdb_init (void)
 {
 	unsigned int handle;
@@ -448,7 +449,7 @@ static int object_find_reset (
 	instance->find_child_list = &instance->child_head;
 
 	hdb_handle_put (&object_instance_database, object_handle);
-	return (0);
+	return (found == 1 ? 0 : ENOENT);
 
 error_exit:
 	return (-1);

+ 147 - 106
exec/service.c

@@ -1,11 +1,10 @@
 /*
- * vi: set autoindent tabstop=4 shiftwidth=4 :
- *
  * Copyright (c) 2006 MontaVista Software, Inc.
+ * Copyright (c) 2006-2007 Red Hat, Inc.
  *
  * All rights reserved.
  *
- * Author: Steven Dake (sdake@mvista.com)
+ * Author: Steven Dake (sdake@redhat.com)
  *
  * This software licensed under BSD license, the text of which follows:
  *
@@ -99,54 +98,14 @@ static struct default_service default_services[] = {
 
 struct openais_service_handler *ais_service[SERVICE_HANDLER_MAXIMUM_COUNT];
 
-/*
- * Adds a service handler to the object database
- */
-int openais_service_objdb_add (
-	struct objdb_iface_ver0 *objdb,
-	char *name,
-	int version)
-{
-	unsigned int object_handle;
-
-	objdb->object_create (OBJECT_PARENT_HANDLE, &object_handle,
-		"service", strlen ("service"));
-	objdb->object_key_create (object_handle, "name", strlen ("name"),
-		name, strlen (name) + 1);
-	objdb->object_key_create (object_handle, "ver", strlen ("ver"),
-		&version, sizeof (version));
-
-	return (0);
-}
-
-static int service_handler_config (
-	struct openais_service_handler *handler,
-	struct objdb_iface_ver0 *objdb)
+static unsigned int default_services_requested (struct objdb_iface_ver0 *objdb)
 {
-	int res = 0;
-
-	/* Already loaded? */
-	if (ais_service[handler->id] != NULL)
-		return 0;
-
-	log_printf (LOG_LEVEL_NOTICE, "Registering service handler '%s'\n", handler->name);
-	ais_service[handler->id] = handler;
-	if (ais_service[handler->id]->config_init_fn) {
-		res = ais_service[handler->id]->config_init_fn (objdb);
-	}
-	return (res);
-}
-
-/*
- * adds the default services to the object database
- */
-int openais_service_default_objdb_set (struct objdb_iface_ver0 *objdb)
-{
-	int i;
 	unsigned int object_service_handle;
-	char *value = NULL;
+	char *value;
 
-	/* Load default services unless they have been explicitly disabled */
+	/*
+	 * Don't link default services if they have been disabled
+	 */
 	objdb->object_find_reset (OBJECT_PARENT_HANDLE);
 	if (objdb->object_find (
 		OBJECT_PARENT_HANDLE,
@@ -155,36 +114,111 @@ int openais_service_default_objdb_set (struct objdb_iface_ver0 *objdb)
 		&object_service_handle) == 0) {
 
 		if ( ! objdb->object_key_get (object_service_handle,
-					      "defaultservices",
-					      strlen ("defaultservices"),
-					      (void *)&value,
-					      NULL)) {
+			"defaultservices",
+			strlen ("defaultservices"),
+			(void *)&value,
+			NULL)) {
 
 			if (value && strcmp (value, "no") == 0) {
 				return 0;
 			}
 		}
 	}
+		return (-1);
+}
 
-	for (i = 0; i < sizeof (default_services) / sizeof (struct default_service); i++) {
-		openais_service_objdb_add (objdb, default_services[i].name, default_services[i].ver);
+unsigned int openais_service_link_and_init (
+	struct objdb_iface_ver0 *objdb,
+	char *service_name,
+	unsigned int service_ver)
+{
+	struct openais_service_handler_iface_ver0 *iface_ver0;
+	void *iface_ver0_p;
+	unsigned int handle;
+	struct openais_service_handler *service;
+	unsigned int res;
+	unsigned int object_handle;
+
+	/*
+	 * reference the service interface
+	 */
+	iface_ver0_p = NULL;
+	lcr_ifact_reference (
+		&handle,
+		service_name,
+		service_ver,
+		&iface_ver0_p,
+		(void *)0);
+
+	iface_ver0 = (struct openais_service_handler_iface_ver0 *)iface_ver0_p;
+
+	if (iface_ver0 == 0) {
+		log_printf(LOG_LEVEL_ERROR, "Service failed to load '%s'.\n", service_name);
+		return (-1);
 	}
-	return (0);
+
+
+	/*
+	 * Initialize service
+	 */
+	service = iface_ver0->openais_get_service_handler_ver0();
+
+	ais_service[service->id] = service;
+	if (service->config_init_fn) {
+		res = service->config_init_fn (objdb);
+	}
+
+	if (service->exec_init_fn) {
+		res = service->exec_init_fn (objdb);
+	}
+
+	/*
+	 * Store service in object database
+	 */
+	objdb->object_create (OBJECT_PARENT_HANDLE,
+		&object_handle,
+		"service",
+		strlen ("service"));
+
+	objdb->object_key_create (object_handle,
+		"name",
+		strlen ("name"),
+		service_name,
+		strlen (service_name) + 1);
+
+	objdb->object_key_create (object_handle,
+		"ver",
+		strlen ("ver"),
+		&service_ver,
+		sizeof (service_ver));
+
+	res = objdb->object_key_create (object_handle,
+		"handle",
+		strlen ("handle"),
+		&handle,
+		sizeof (handle));
+
+	objdb->object_key_create (object_handle,
+		"service_id",
+		strlen ("service_id"),
+		&service->id,
+		sizeof (service->id));
+
+	log_printf (LOG_LEVEL_NOTICE, "Service initialized '%s'\n", service->name);
+	return (res);
 }
 
-/*
- * Links dynamic services into the executive
- */
-int openais_service_link_all (struct objdb_iface_ver0 *objdb)
+extern unsigned int openais_service_unlink_and_exit (
+	struct objdb_iface_ver0 *objdb,
+	char *service_name,
+	unsigned int service_ver)
 {
-	char *service_name;
-	char *service_ver;
 	unsigned int object_service_handle;
-	int ret;
-	unsigned int handle;
-	struct openais_service_handler_iface_ver0 *iface_ver0;
-	void *iface_ver0_p;
-	unsigned int ver_int;
+	char *found_service_name;
+	unsigned int *found_service_ver;
+	unsigned int *found_service_handle;
+	unsigned short *service_id;
+	unsigned int res;
 
 	objdb->object_find_reset (OBJECT_PARENT_HANDLE);
 	while (objdb->object_find (
@@ -196,57 +230,64 @@ int openais_service_link_all (struct objdb_iface_ver0 *objdb)
 		objdb->object_key_get (object_service_handle,
 			"name",
 			strlen ("name"),
-			(void *)&service_name,
+			(void *)&found_service_name,
 			NULL);
 
-		ret = objdb->object_key_get (object_service_handle,
+		objdb->object_key_get (object_service_handle,
 			"ver",
 			strlen ("ver"),
-			(void *)&service_ver,
+			(void *)&found_service_ver,
 			NULL);
-
-		ver_int = atoi (service_ver);
-
+				
 		/*
-		 * reference the interface and register it
+		 * If service found and linked exit it
 		 */
-		iface_ver0_p = NULL;
-		lcr_ifact_reference (
-			&handle,
-			service_name,
-			ver_int,
-			&iface_ver0_p,
-			(void *)0);
-
-		iface_ver0 = (struct openais_service_handler_iface_ver0 *)iface_ver0_p;
-
-		if (iface_ver0 == 0) {
-			log_printf(LOG_LEVEL_ERROR, "openais component %s did not load.\n", service_name);
-			openais_exit_error (AIS_DONE_DYNAMICLOAD);
-		} else {
-			log_printf(LOG_LEVEL_NOTICE, "openais component %s loaded.\n", service_name);
-		}
+		if ((strcmp (service_name, found_service_name) == 0) &&
+			(service_ver == *found_service_ver)) {
 
-		service_handler_config (
-			iface_ver0->openais_get_service_handler_ver0(), objdb);
+			res = objdb->object_key_get (object_service_handle,
+				"handle",
+				strlen ("handle"),
+				(void *)&found_service_handle,
+				NULL);
+
+			res = objdb->object_key_get (object_service_handle,
+				"service_id",
+				strlen ("service_id"),
+				(void *)&service_id,
+				NULL);
+					
+			if (ais_service[*service_id]->exec_exit_fn) {
+				ais_service[*service_id]->exec_exit_fn (objdb);
+			}
+			ais_service[*service_id] = NULL;
+
+			res = lcr_ifact_release (*found_service_handle);	
+			objdb->object_destroy (object_service_handle);
+			return (res);
+		}
 	}
-	return (0);
+	return (-1);
 }
 
-int openais_service_init_all (int service_count,
-			      struct objdb_iface_ver0 *objdb)
+/*
+ * Links default services into the executive
+ */
+unsigned int openais_service_defaults_link_and_init (struct objdb_iface_ver0 *objdb)
 {
-	int i;
-	int res=0;
-
-	for (i = 0; i < service_count; i++) {
-		if (ais_service[i] && ais_service[i]->exec_init_fn) {
-			log_printf (LOG_LEVEL_NOTICE, "Initialising service handler '%s'\n", ais_service[i]->name);
-			res = ais_service[i]->exec_init_fn (objdb);
-			if (res != 0) {
-				break;
-			}
-		}
+	unsigned int i;
+
+	if (default_services_requested (objdb) == 0) {
+		return (0);
 	}
-	return (res);
+	for (i = 0;
+		i < sizeof (default_services) / sizeof (struct default_service); i++) {
+
+		openais_service_link_and_init (
+			objdb,
+			default_services[i].name,
+			default_services[i].ver);
+	}
+			
+	return (0);
 }

+ 26 - 14
exec/service.h

@@ -1,9 +1,10 @@
 /*
  * Copyright (c) 2002-2006 MontaVista Software, Inc.
+ * Copyright (c) 2006-2007 Red Hat, Inc.
  *
  * All rights reserved.
  *
- * Author: Steven Dake (sdake@mvista.com)
+ * Author: Steven Dake (sdake@redhat.com)
  *
  * This software licensed under BSD license, the text of which follows:
  *
@@ -65,6 +66,7 @@ struct openais_service_handler {
 	int lib_service_count;
 	struct openais_exec_handler *exec_service;
 	int (*exec_init_fn) (struct objdb_iface_ver0 *);
+	int (*exec_exit_fn) (struct objdb_iface_ver0 *);
 	int (*config_init_fn) (struct objdb_iface_ver0 *);
 	void (*exec_dump_fn) (void);
 	int exec_service_count;
@@ -81,26 +83,36 @@ struct openais_service_handler {
 };
 
 struct openais_service_handler_iface_ver0 {
-	void (*test) (void);
 	struct openais_service_handler *(*openais_get_service_handler_ver0) (void);
 };
 
-extern int openais_service_objdb_add (
-	struct objdb_iface_ver0 *objdb,
-	char *name,
-	int version);
-
+/*
+ * Link and initialize a service
+ */
+extern unsigned int openais_service_link_and_init (
+    struct objdb_iface_ver0 *objdb,
+    char *service_name,
+    unsigned int service_ver);
 
-extern int openais_service_handler_register (
-	struct openais_service_handler *handler);
+/*
+ * Unlink and exit a service
+ */
+extern unsigned int openais_service_unlink_and_exit (
+    struct objdb_iface_ver0 *objdb,
+    char *service_name,
+    unsigned int service_ver);
 
-extern int openais_service_default_objdb_set (struct objdb_iface_ver0 *objdb);
+/*
+ * Unlink and exit all openais services
+ */
+extern unsigned int openais_service_unlink_all (
+    struct objdb_iface_ver0 *objdb);
 
-extern int openais_service_link_all (
-	struct objdb_iface_ver0 *objdb);
 
-extern int openais_service_init_all (
-	int service_count,
+/*
+ * Load all of the default services
+ */
+extern unsigned int openais_service_defaults_link_and_init (
 	struct objdb_iface_ver0 *objdb);
 
 extern struct openais_service_handler *ais_service[];

+ 12 - 0
include/cfg.h

@@ -139,6 +139,18 @@ SaAisErrorT
 openais_cfg_ring_reenable (
 	openais_cfg_handle_t cfg_handle);
 
+SaAisErrorT
+openais_cfg_service_load (
+	openais_cfg_handle_t cfg_handle,
+	char *service_name,
+	unsigned int service_ver);
+
+SaAisErrorT
+openais_cfg_service_unload (
+	openais_cfg_handle_t cfg_handle,
+	char *service_name,
+	unsigned int service_ver);
+
 SaAisErrorT
 openais_cfg_administrative_state_get (
 	openais_cfg_handle_t cfg_handle,

+ 24 - 0
include/ipc_cfg.h

@@ -46,6 +46,8 @@ enum req_lib_cfg_types {
         MESSAGE_REQ_CFG_STATETRACKSTOP = 3,
         MESSAGE_REQ_CFG_ADMINISTRATIVESTATESET = 4,
         MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET = 5,
+        MESSAGE_REQ_CFG_SERVICELOAD = 6,
+        MESSAGE_REQ_CFG_SERVICEUNLOAD = 7
 };
 
 enum res_lib_cfg_types {
@@ -55,6 +57,8 @@ enum res_lib_cfg_types {
         MESSAGE_RES_CFG_STATETRACKSTOP = 3,
         MESSAGE_RES_CFG_ADMINISTRATIVESTATESET = 4,
         MESSAGE_RES_CFG_ADMINISTRATIVESTATEGET = 5,
+        MESSAGE_RES_CFG_SERVICELOAD = 6,
+        MESSAGE_RES_CFG_SERVICEUNLOAD = 7
 };
 
 struct req_lib_cfg_statetrack {
@@ -116,6 +120,26 @@ struct res_lib_cfg_ringreenable {
 	mar_res_header_t header __attribute__((aligned(8)));
 };
 
+struct req_lib_cfg_serviceload {
+	mar_res_header_t header __attribute__((aligned(8)));
+	char *service_name[256] __attribute__((aligned(8)));
+	unsigned int service_ver;
+};
+
+struct res_lib_cfg_serviceload {
+	mar_res_header_t header __attribute__((aligned(8)));
+};
+
+struct req_lib_cfg_serviceunload {
+	mar_res_header_t header __attribute__((aligned(8)));
+	char *service_name[256] __attribute__((aligned(8)));
+	unsigned int service_ver;
+};
+
+struct res_lib_cfg_serviceunload {
+	mar_res_header_t header __attribute__((aligned(8)));
+};
+
 typedef enum {
 	AIS_AMF_ADMINISTRATIVETARGET_SERVICEUNIT = 0,
 	AIS_AMF_ADMINISTRATIVETARGET_SERVICEGROUP = 1,

+ 79 - 5
lib/cfg.c

@@ -1,7 +1,6 @@
-
 /*
  * Copyright (c) 2002-2005 MontaVista Software, Inc.
- * Copyright (c) 2006 Red Hat, Inc.
+ * Copyright (c) 2006-2007 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -78,9 +77,9 @@ static void cfg_handleInstanceDestructor (void *);
  * All instances in one database
  */
 static struct saHandleDatabase cfg_hdb = {
-	.handleCount				= 0,
-	.handles					= 0,
-	.mutex						= PTHREAD_MUTEX_INITIALIZER,
+	.handleCount			= 0,
+	.handles			= 0,
+	.mutex				= PTHREAD_MUTEX_INITIALIZER,
 	.handleInstanceDestructor	= cfg_handleInstanceDestructor
 };
 
@@ -458,6 +457,81 @@ openais_cfg_ring_reenable (
 	return (error);
 }
 
+SaAisErrorT
+openais_cfg_service_load (
+	openais_cfg_handle_t cfg_handle,
+	char *service_name,
+	unsigned int service_ver)
+{
+	struct cfg_instance *cfg_instance;
+	struct req_lib_cfg_serviceload req_lib_cfg_serviceload;
+	struct res_lib_cfg_serviceload res_lib_cfg_serviceload;
+	SaAisErrorT error;
+
+	error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance);
+	if (error != SA_AIS_OK) {
+		return (error);
+	}
+
+	req_lib_cfg_serviceload.header.size = sizeof (struct req_lib_cfg_serviceload);
+	req_lib_cfg_serviceload.header.id = MESSAGE_REQ_CFG_SERVICELOAD;
+	memset (&req_lib_cfg_serviceload.service_name, 0,
+		sizeof (req_lib_cfg_serviceload.service_name));
+	strncpy ((char *)req_lib_cfg_serviceload.service_name, service_name,
+		sizeof (req_lib_cfg_serviceload.service_name) - 1);
+	req_lib_cfg_serviceload.service_ver = service_ver;
+
+	pthread_mutex_lock (&cfg_instance->response_mutex);
+
+	error = saSendReceiveReply (cfg_instance->response_fd,
+		&req_lib_cfg_serviceload,
+		sizeof (struct req_lib_cfg_serviceload),
+		&res_lib_cfg_serviceload,
+		sizeof (struct res_lib_cfg_serviceload));
+
+	pthread_mutex_unlock (&cfg_instance->response_mutex);
+	saHandleInstancePut (&cfg_hdb, cfg_handle);
+
+	return (error);
+}
+
+SaAisErrorT
+openais_cfg_service_unload (
+	openais_cfg_handle_t cfg_handle,
+	char *service_name,
+	unsigned int service_ver)
+{
+	struct cfg_instance *cfg_instance;
+	struct req_lib_cfg_serviceunload req_lib_cfg_serviceunload;
+	struct res_lib_cfg_serviceunload res_lib_cfg_serviceunload;
+	SaAisErrorT error;
+
+	error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance);
+	if (error != SA_AIS_OK) {
+		return (error);
+	}
+
+	req_lib_cfg_serviceunload.header.size = sizeof (struct req_lib_cfg_serviceunload);
+	req_lib_cfg_serviceunload.header.id = MESSAGE_REQ_CFG_SERVICEUNLOAD;
+	memset (&req_lib_cfg_serviceunload.service_name, 0,
+		sizeof (req_lib_cfg_serviceunload.service_name));
+	strncpy ((char *)req_lib_cfg_serviceunload.service_name, service_name,
+		sizeof (req_lib_cfg_serviceunload.service_name) - 1);
+	req_lib_cfg_serviceunload.service_ver = service_ver;
+
+	pthread_mutex_lock (&cfg_instance->response_mutex);
+
+	error = saSendReceiveReply (cfg_instance->response_fd,
+		&req_lib_cfg_serviceunload,
+		sizeof (struct req_lib_cfg_serviceunload),
+		&res_lib_cfg_serviceunload,
+		sizeof (struct res_lib_cfg_serviceunload));
+
+	pthread_mutex_unlock (&cfg_instance->response_mutex);
+	saHandleInstancePut (&cfg_hdb, cfg_handle);
+
+	return (error);
+}
 SaAisErrorT
 openais_cfg_state_track (
 	openais_cfg_handle_t cfg_handle,

+ 3 - 1
lib/libcfg.versions

@@ -1,6 +1,6 @@
 # Version and symbol export for libcfg.so
 
-OPENAIS_CFG_0.80 {
+OPENAIS_CFG_0.82 {
 	global:
 		openais_cfg_initialize;
 		openais_cfg_fd_get;
@@ -12,6 +12,8 @@ OPENAIS_CFG_0.80 {
 		openais_cfg_track_stop;
 		openais_cfg_ring_status_get;
 		openais_cfg_ring_reenable;
+		openais_cfg_service_load;
+		openais_cfg_service_unload;
 		
 		
 	local:

+ 62 - 3
test/openais-cfgtool.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 Red Hat Inc
+ * Copyright (c) 2006-2007 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -98,19 +98,61 @@ static void ringreenable_do (void)
 	openais_cfg_finalize (handle);
 }
 
+void service_load_do (char *service, unsigned int version)
+{
+	SaAisErrorT result;
+	openais_cfg_handle_t handle;
+
+	printf ("Loading service '%s' version '%d'\n", service, version);
+	result = openais_cfg_initialize (&handle, NULL);
+	if (result != SA_AIS_OK) {
+		printf ("Could not initialize openais configuration API error %d\n", result);
+		exit (1);
+	}
+	result = openais_cfg_service_load (handle, service, version);
+	if (result != SA_AIS_OK) {
+		printf ("Could not load service (error = %d)\n", result);
+	}
+	openais_cfg_finalize (handle);
+}
+
+void service_unload_do (char *service, unsigned int version)
+{
+	SaAisErrorT result;
+	openais_cfg_handle_t handle;
+
+	printf ("Unloading service '%s' version '%d'\n", service, version);
+	result = openais_cfg_initialize (&handle, NULL);
+	if (result != SA_AIS_OK) {
+		printf ("Could not initialize openais configuration API error %d\n", result);
+		exit (1);
+	}
+	result = openais_cfg_service_unload (handle, service, version);
+	if (result != SA_AIS_OK) {
+		printf ("Could not unload service (error = %d)\n", result);
+	}
+	openais_cfg_finalize (handle);
+}
+
 void usage_do (void)
 {
-	printf ("openais-cfgtool [-s] [-r]\n\n");
+	printf ("openais-cfgtool [-s] [-r] [-l] [-u] [service_name] [-v] [version]\n\n");
 	printf ("A tool for displaying and configuring active parameters within openais.\n");
 	printf ("options:\n");
 	printf ("\t-s\tDisplays the status of the current rings on this node.\n");
 	printf ("\t-r\tReset redundant ring state cluster wide after a fault to\n");
 	printf ("\t\tre-enable redundant ring operation.\n");
+	printf ("\t-l\tLoad a service identified by name.\n");
+	printf ("\t-u\tUnload a service identified by name.\n");
 }
 
 int main (int argc, char *argv[]) {
-	const char *options = "sr";
+	const char *options = "srl:u:v:";
 	int opt;
+	int service_load = 0;
+	int service_unload = 0;
+	char *service;
+	unsigned int version;
 
 	if (argc == 1) {
 		usage_do ();
@@ -123,8 +165,25 @@ int main (int argc, char *argv[]) {
 		case 'r':
 			ringreenable_do ();
 			break;
+		case 'l':
+			service_load = 1;
+			service = strdup (optarg);
+			break;
+		case 'u':
+			service_unload = 1;
+			service = strdup (optarg);
+			break;
+		case 'v':
+			version = atoi (optarg);
 		}
 	}
 
+	if (service_load) {
+		service_load_do (service, version);
+	} else 
+	if (service_unload) {
+		service_unload_do (service, version);
+	}
+		
 	return (0);
 }