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

This patch adds key_increment and key_decrement calls to the objdb and
confdb subsystems.

This is useful to provide atomic counters (ag handle numbers) for
long-running (though not persistent) connections. It's not currently
possible via confdb to atomically get a new number from objdb due to the
lack of locking. Doing it via increment operations in the IPC thread
provides enough atomicity to make it useful. Fabio has already
identified a use for these calls.

It could also provide some form of basic co-operative locking mechanism
for IPC-using processes (not direct objdb calls).



git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1662 fd59a12c-fef9-0310-b244-a6a79926bd2f

Christine Caulfield 17 лет назад
Родитель
Сommit
1d2d771f99

+ 5 - 5
Makefile

@@ -98,11 +98,11 @@ help:
 	@echo "  doxygen - doxygen html docs"
 	@echo 
 	@echo "Options: (* - default)"
-	@echo "  OPENCOROSYNC         [DEBUG/RELEASE*] - Enable/Disable debug symbols"
-	@echo "  DESTDIR         [directory]      - Install prefix."
-	@echo "  O               [directory]      - Locate all output files in \"dir\"."
-	@echo "  BUILD_DYNAMIC   [1*/0]           - Enable/disable dynamic loading of service handler modules"
-	@echo "  OPENCOROSYNC_PROFILE [1/0*]           - Enable profiling"
+	@echo "  COROSYNC_BUILD   [DEBUG/RELEASE*] - Enable/Disable debug symbols"
+	@echo "  DESTDIR          [directory]      - Install prefix."
+	@echo "  O                [directory]      - Locate all output files in \"dir\"."
+	@echo "  BUILD_DYNAMIC    [1*/0]           - Enable/disable dynamic loading of service handler modules"
+	@echo "  COROSYNC_PROFILE [1/0*]           - Enable profiling"
 	@echo 
  
 

+ 1 - 1
Makefile.inc

@@ -66,7 +66,7 @@ endif
 	LDFLAGS += 
 endif
 ifeq (${COROSYNC_BUILD}, DEBUG) 
-	CFLAGS += -O0 -g -Wall -DDEBUG
+	CFLAGS += -O0 -g -Wall -DDEBUG --time
 	LDFLAGS += -g
 	ifeq (${COROSYNC_COMPAT}, SOLARIS)
 		CFLAGS += -Werror -DTS_CLASS

+ 2 - 0
exec/apidef.c

@@ -124,6 +124,8 @@ void apidef_init (struct objdb_iface_ver0 *objdb) {
 	apidef_corosync_api_v1.object_track_stop = objdb->object_track_stop;
 	apidef_corosync_api_v1.object_write_config = objdb->object_write_config;
 	apidef_corosync_api_v1.object_reload_config = objdb->object_reload_config;
+	apidef_corosync_api_v1.object_key_increment = objdb->object_key_increment;
+	apidef_corosync_api_v1.object_key_decrement = objdb->object_key_decrement;
 }
 
 struct corosync_api_v1 *apidef_get (void)

+ 88 - 0
exec/objdb.c

@@ -772,6 +772,92 @@ error_exit:
 	return (-1);
 }
 
+static int object_key_increment (
+	unsigned int object_handle,
+	void *key_name,
+	int key_len,
+	unsigned int *value)
+{
+	unsigned int res = 0;
+	struct object_instance *instance;
+	struct object_key *object_key = NULL;
+	struct list_head *list;
+	int found = 0;
+
+	res = hdb_handle_get (&object_instance_database,
+		object_handle, (void *)&instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	for (list = instance->key_head.next;
+		list != &instance->key_head; list = list->next) {
+
+		object_key = list_entry (list, struct object_key, list);
+
+		if ((object_key->key_len == key_len) &&
+			(memcmp (object_key->key_name, key_name, key_len) == 0)) {
+			found = 1;
+			break;
+		}
+	}
+	if (found && object_key->value_len == sizeof(int)) {
+		(*(int *)object_key->value)++;
+		*value = *(int *)object_key->value;
+	}
+	else {
+		res = -1;
+	}
+
+	hdb_handle_put (&object_instance_database, object_handle);
+	return (res);
+
+error_exit:
+	return (-1);
+}
+
+static int object_key_decrement (
+	unsigned int object_handle,
+	void *key_name,
+	int key_len,
+	unsigned int *value)
+{
+	unsigned int res = 0;
+	struct object_instance *instance;
+	struct object_key *object_key = NULL;
+	struct list_head *list;
+	int found = 0;
+
+	res = hdb_handle_get (&object_instance_database,
+		object_handle, (void *)&instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	for (list = instance->key_head.next;
+		list != &instance->key_head; list = list->next) {
+
+		object_key = list_entry (list, struct object_key, list);
+
+		if ((object_key->key_len == key_len) &&
+			(memcmp (object_key->key_name, key_name, key_len) == 0)) {
+			found = 1;
+			break;
+		}
+	}
+	if (found && object_key->value_len == sizeof(int)) {
+		(*(int *)object_key->value)--;
+		*value = *(int *)object_key->value;
+	}
+	else {
+		res = -1;
+	}
+
+	hdb_handle_put (&object_instance_database, object_handle);
+	return (res);
+
+error_exit:
+	return (-1);
+}
+
 static int object_key_delete (
 	unsigned int object_handle,
 	void *key_name,
@@ -1306,6 +1392,8 @@ struct objdb_iface_ver0 objdb_iface = {
 	.object_dump	        = object_dump,
 	.object_write_config    = object_write_config,
 	.object_reload_config   = object_reload_config,
+	.object_key_increment   = object_key_increment,
+	.object_key_decrement   = object_key_decrement,
 };
 
 struct lcr_iface objdb_iface_ver0[1] = {

+ 14 - 0
include/corosync/confdb.h

@@ -223,6 +223,20 @@ confdb_error_t confdb_key_replace (
 	void *new_value,
 	int new_value_len);
 
+confdb_error_t confdb_key_increment (
+	confdb_handle_t handle,
+	unsigned int parent_object_handle,
+	void *key_name,
+	int key_name_len,
+	unsigned int *value);
+
+confdb_error_t confdb_key_decrement (
+	confdb_handle_t handle,
+	unsigned int parent_object_handle,
+	void *key_name,
+	int key_name_len,
+	unsigned int *value);
+
 /*
  * Object queries
  * "find" loops through all objects of a given name and is also

+ 12 - 0
include/corosync/engine/coroapi.h

@@ -281,6 +281,18 @@ struct corosync_api_v1 {
 	int (*object_reload_config) (int flush,
 				     char **error_string);
 
+	int (*object_key_increment) (
+		unsigned int object_handle,
+		void *key_name,
+		int key_len,
+		unsigned int *value);
+
+	int (*object_key_decrement) (
+		unsigned int object_handle,
+		void *key_name,
+		int key_len,
+		unsigned int *value);
+
 	/*
 	 * Time and timer APIs
 	 */

+ 12 - 0
include/corosync/engine/objdb.h

@@ -211,6 +211,18 @@ struct objdb_iface_ver0 {
 	int (*object_reload_config) (
 		int flush,
 		char **error_string);
+
+	int (*object_key_increment) (
+		unsigned int object_handle,
+		void *key_name,
+		int key_len,
+		unsigned int *value);
+
+	int (*object_key_decrement) (
+		unsigned int object_handle,
+		void *key_name,
+		int key_len,
+		unsigned int *value);
 };
 
 #endif /* OBJDB_H_DEFINED */

+ 11 - 2
include/corosync/ipc_confdb.h

@@ -53,7 +53,9 @@ enum req_confdb_types {
 	MESSAGE_REQ_CONFDB_TRACK_STOP = 11,
 	MESSAGE_REQ_CONFDB_WRITE = 12,
 	MESSAGE_REQ_CONFDB_RELOAD = 13,
-	MESSAGE_REQ_CONFDB_OBJECT_FIND_DESTROY = 14
+	MESSAGE_REQ_CONFDB_OBJECT_FIND_DESTROY = 14,
+	MESSAGE_REQ_CONFDB_KEY_INCREMENT = 15,
+	MESSAGE_REQ_CONFDB_KEY_DECREMENT = 16
 };
 
 enum res_confdb_types {
@@ -74,7 +76,9 @@ enum res_confdb_types {
 	MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK = 14,
 	MESSAGE_RES_CONFDB_WRITE = 15,
 	MESSAGE_RES_CONFDB_RELOAD = 16,
-	MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY = 17
+	MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY = 17,
+	MESSAGE_RES_CONFDB_KEY_INCREMENT = 18,
+	MESSAGE_RES_CONFDB_KEY_DECREMENT = 19
 };
 
 
@@ -181,6 +185,11 @@ struct res_lib_confdb_key_get {
 	mar_name_t value __attribute__((aligned(8)));
 };
 
+struct res_lib_confdb_key_incdec {
+	mar_res_header_t header __attribute__((aligned(8)));
+	mar_uint32_t value __attribute__((aligned(8)));
+};
+
 struct res_lib_confdb_write {
 	mar_res_header_t header __attribute__((aligned(8)));
 	mar_name_t error __attribute__((aligned(8)));

+ 115 - 0
lib/confdb.c

@@ -898,6 +898,121 @@ error_exit:
 	return (error);
 }
 
+confdb_error_t confdb_key_increment (
+	confdb_handle_t handle,
+	unsigned int parent_object_handle,
+	void *key_name,
+	int key_name_len,
+	unsigned int *value)
+{
+	confdb_error_t error;
+	struct confdb_inst *confdb_inst;
+	struct iovec iov[2];
+	struct req_lib_confdb_key_get req_lib_confdb_key_get;
+	struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec;
+
+	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+	if (error != SA_AIS_OK) {
+		return (error);
+	}
+
+	if (confdb_inst->standalone) {
+		error = SA_AIS_OK;
+
+		if (confdb_sa_key_increment(parent_object_handle,
+					    key_name, key_name_len,
+					    value))
+			error = SA_AIS_ERR_ACCESS;
+		goto error_exit;
+	}
+
+	req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get);
+	req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_INCREMENT;
+	req_lib_confdb_key_get.parent_object_handle = parent_object_handle;
+	memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len);
+	req_lib_confdb_key_get.key_name.length = key_name_len;
+
+	iov[0].iov_base = (char *)&req_lib_confdb_key_get;
+	iov[0].iov_len = sizeof (struct req_lib_confdb_key_get);
+
+	pthread_mutex_lock (&confdb_inst->response_mutex);
+
+	error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+		&res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec));
+
+	pthread_mutex_unlock (&confdb_inst->response_mutex);
+	if (error != SA_AIS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_confdb_key_incdec.header.error;
+	if (error == SA_AIS_OK) {
+		*value = res_lib_confdb_key_incdec.value;
+	}
+
+error_exit:
+	saHandleInstancePut (&confdb_handle_t_db, handle);
+
+	return (error);
+}
+
+confdb_error_t confdb_key_decrement (
+	confdb_handle_t handle,
+	unsigned int parent_object_handle,
+	void *key_name,
+	int key_name_len,
+	unsigned int *value)
+{
+	confdb_error_t error;
+	struct confdb_inst *confdb_inst;
+	struct iovec iov[2];
+	struct req_lib_confdb_key_get req_lib_confdb_key_get;
+	struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec;
+
+	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+	if (error != SA_AIS_OK) {
+		return (error);
+	}
+
+	if (confdb_inst->standalone) {
+		error = SA_AIS_OK;
+
+		if (confdb_sa_key_decrement(parent_object_handle,
+					    key_name, key_name_len,
+					    value))
+			error = SA_AIS_ERR_ACCESS;
+		goto error_exit;
+	}
+
+	req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get);
+	req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_DECREMENT;
+	req_lib_confdb_key_get.parent_object_handle = parent_object_handle;
+	memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len);
+	req_lib_confdb_key_get.key_name.length = key_name_len;
+
+	iov[0].iov_base = (char *)&req_lib_confdb_key_get;
+	iov[0].iov_len = sizeof (struct req_lib_confdb_key_get);
+
+	pthread_mutex_lock (&confdb_inst->response_mutex);
+
+	error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+		&res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec));
+
+	pthread_mutex_unlock (&confdb_inst->response_mutex);
+	if (error != SA_AIS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_confdb_key_incdec.header.error;
+	if (error == SA_AIS_OK) {
+		*value = res_lib_confdb_key_incdec.value;
+	}
+
+error_exit:
+	saHandleInstancePut (&confdb_handle_t_db, handle);
+
+	return (error);
+}
 
 confdb_error_t confdb_key_replace (
 	confdb_handle_t handle,

+ 28 - 0
lib/sa-confdb.c

@@ -250,6 +250,34 @@ int confdb_sa_key_get (
 	return res;
 }
 
+int confdb_sa_key_increment (
+	unsigned int parent_object_handle,
+	void *key_name,
+	int key_name_len,
+	unsigned int *value)
+{
+	int res;
+
+	res = objdb->object_key_increment(parent_object_handle,
+					  key_name, key_name_len,
+					  value);
+	return res;
+}
+
+int confdb_sa_key_decrement (
+	unsigned int parent_object_handle,
+	void *key_name,
+	int key_name_len,
+	unsigned int *value)
+{
+	int res;
+
+	res = objdb->object_key_decrement(parent_object_handle,
+					  key_name, key_name_len,
+					  value);
+	return res;
+}
+
 
 int confdb_sa_key_replace (
 	unsigned int parent_object_handle,

+ 55 - 0
services/confdb.c

@@ -69,6 +69,9 @@ static void message_handler_req_lib_confdb_key_replace (void *conn, void *messag
 static void message_handler_req_lib_confdb_key_delete (void *conn, void *message);
 static void message_handler_req_lib_confdb_key_iter (void *conn, void *message);
 
+static void message_handler_req_lib_confdb_key_increment (void *conn, void *message);
+static void message_handler_req_lib_confdb_key_decrement (void *conn, void *message);
+
 static void message_handler_req_lib_confdb_object_iter (void *conn, void *message);
 static void message_handler_req_lib_confdb_object_find (void *conn, void *message);
 
@@ -189,6 +192,18 @@ static struct corosync_lib_handler confdb_lib_engine[] =
 		.response_id				= MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY,
 		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
+	{ /* 15 */
+		.lib_handler_fn				= message_handler_req_lib_confdb_key_increment,
+		.response_size				= sizeof (struct res_lib_confdb_key_incdec),
+		.response_id				= MESSAGE_RES_CONFDB_KEY_INCREMENT,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 16 */
+		.lib_handler_fn				= message_handler_req_lib_confdb_key_decrement,
+		.response_size				= sizeof (struct res_lib_confdb_key_incdec),
+		.response_id				= MESSAGE_RES_CONFDB_KEY_DECREMENT,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
 };
 
 
@@ -365,6 +380,46 @@ static void message_handler_req_lib_confdb_key_get (void *conn, void *message)
 	api->ipc_conn_send_response(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get));
 }
 
+static void message_handler_req_lib_confdb_key_increment (void *conn, void *message)
+{
+	struct req_lib_confdb_key_get *req_lib_confdb_key_get = (struct req_lib_confdb_key_get *)message;
+	struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec;
+	int value_len;
+	void *value;
+	int ret = SA_AIS_OK;
+
+	if (api->object_key_increment(req_lib_confdb_key_get->parent_object_handle,
+				      req_lib_confdb_key_get->key_name.value,
+				      req_lib_confdb_key_get->key_name.length,
+				      &res_lib_confdb_key_incdec.value))
+		ret = SA_AIS_ERR_ACCESS;
+
+	res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec);
+	res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_INCREMENT;
+	res_lib_confdb_key_incdec.header.error = ret;
+	api->ipc_conn_send_response(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec));
+}
+
+static void message_handler_req_lib_confdb_key_decrement (void *conn, void *message)
+{
+	struct req_lib_confdb_key_get *req_lib_confdb_key_get = (struct req_lib_confdb_key_get *)message;
+	struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec;
+	int value_len;
+	void *value;
+	int ret = SA_AIS_OK;
+
+	if (api->object_key_decrement(req_lib_confdb_key_get->parent_object_handle,
+				      req_lib_confdb_key_get->key_name.value,
+				      req_lib_confdb_key_get->key_name.length,
+				      &res_lib_confdb_key_incdec.value))
+		ret = SA_AIS_ERR_ACCESS;
+
+	res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec);
+	res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_DECREMENT;
+	res_lib_confdb_key_incdec.header.error = ret;
+	api->ipc_conn_send_response(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec));
+}
+
 static void message_handler_req_lib_confdb_key_replace (void *conn, void *message)
 {
 	struct req_lib_confdb_key_replace *req_lib_confdb_key_replace = (struct req_lib_confdb_key_replace *)message;

+ 29 - 0
test/testconfdb.c

@@ -44,6 +44,7 @@
 #include <corosync/saAis.h>
 #include <corosync/confdb.h>
 
+#define INCDEC_VALUE 45
 
 /* Callbacks are not supported yet */
 confdb_callbacks_t callbacks = {
@@ -109,6 +110,7 @@ static void print_config_tree(confdb_handle_t handle, unsigned int parent_object
 static void do_write_tests(confdb_handle_t handle)
 {
 	int res;
+	unsigned int incdec_value;
 	unsigned int object_handle;
 	char error_string[1024];
 
@@ -147,6 +149,33 @@ static void do_write_tests(confdb_handle_t handle)
 
 	/* Print it for verification */
 	print_config_tree(handle, object_handle, 0);
+
+	incdec_value = INCDEC_VALUE;
+	res = confdb_key_create(handle, object_handle, "incdec", strlen("incdec"), &incdec_value, sizeof(incdec_value));
+	if (res != SA_AIS_OK) {
+		printf( "error creating 'testconfdb' key 4: %d\n", res);
+		return;
+	}
+	res = confdb_key_increment(handle, object_handle, "incdec", strlen("incdec"), &incdec_value);
+	if (res != SA_AIS_OK) {
+		printf( "error incrementing 'testconfdb' key 4: %d\n", res);
+		return;
+	}
+	if (incdec_value == INCDEC_VALUE+1)
+		printf("incremented value = %d\n", incdec_value);
+	else
+		printf("ERROR: incremented value = %d (should be %d)\n", incdec_value, INCDEC_VALUE+1);
+
+	res = confdb_key_decrement(handle, object_handle, "incdec", strlen("incdec"), &incdec_value);
+	if (res != SA_AIS_OK) {
+		printf( "error decrementing 'testconfdb' key 4: %d\n", res);
+		return;
+	}
+	if (incdec_value == INCDEC_VALUE)
+		printf("decremented value = %d\n", incdec_value);
+	else
+		printf("ERROR: decremented value = %d (should be %d)\n", incdec_value, INCDEC_VALUE);
+
 	printf("-------------------------\n");
 
 	/* Remove it.