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).

Chrissie
Index: test/testconfdb.c
===================================================================
--- test/testconfdb.c	(revision 1661)
+++ test/testconfdb.c	(working copy)
@@ -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 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 @@
 
 	/* 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.
Index: include/corosync/confdb.h
===================================================================
--- include/corosync/confdb.h	(revision 1661)
+++ include/corosync/confdb.h	(working copy)
@@ -223,6 +223,20 @@
 	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
Index: include/corosync/engine/coroapi.h
===================================================================
--- include/corosync/engine/coroapi.h	(revision 1661)
+++ include/corosync/engine/coroapi.h	(working copy)
@@ -281,6 +281,18 @@
 	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
 	 */
Index: include/corosync/engine/objdb.h
===================================================================
--- include/corosync/engine/objdb.h	(revision 1661)
+++ include/corosync/engine/objdb.h	(working copy)
@@ -211,6 +211,18 @@
 	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 */
Index: include/corosync/ipc_confdb.h
===================================================================
--- include/corosync/ipc_confdb.h	(revision 1661)
+++ include/corosync/ipc_confdb.h	(working copy)
@@ -53,7 +53,9 @@
 	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 @@
 	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 @@
 	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)));
Index: services/confdb.c
===================================================================
--- services/confdb.c	(revision 1661)
+++ services/confdb.c	(working copy)
@@ -69,6 +69,9 @@
 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 @@
 		.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 @@
 	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;
Index: exec/objdb.c
===================================================================
--- exec/objdb.c	(revision 1661)
+++ exec/objdb.c	(working copy)
@@ -772,6 +772,92 @@
 	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 @@
 	.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] = {
Index: exec/apidef.c
===================================================================
--- exec/apidef.c	(revision 1661)
+++ exec/apidef.c	(working copy)
@@ -124,6 +124,8 @@
 	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)
Index: lib/confdb.c
===================================================================
--- lib/confdb.c	(revision 1661)
+++ lib/confdb.c	(working copy)
@@ -898,7 +898,122 @@
 	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,
 	unsigned int parent_object_handle,
Index: lib/sa-confdb.c
===================================================================
--- lib/sa-confdb.c	(revision 1661)
+++ lib/sa-confdb.c	(working copy)
@@ -250,7 +250,35 @@
 	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,
 	void *key_name,
_______________________________________________
Openais mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/openais

Reply via email to