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
This commit is contained in:
Christine Caulfield 2008-09-03 07:58:08 +00:00
parent c60fc43bcb
commit 1d2d771f99
12 changed files with 372 additions and 8 deletions

View File

@ -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

View File

@ -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

View File

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

View File

@ -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] = {

View File

@ -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

View File

@ -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
*/

View File

@ -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 */

View File

@ -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)));

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

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