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