[SCM] CTDB repository - branch libctdb updated - ctdb-1.0.114-111-gd61fbb5

Ronnie Sahlberg sahlberg at samba.org
Mon May 17 19:13:05 MDT 2010


The branch, libctdb has been updated
       via  d61fbb5c91b1780208fc24318a2fc7cbeaefebf4 (commit)
      from  b28816fecc7c56a15f6027676c9557283ebc4338 (commit)

http://gitweb.samba.org/?p=sahlberg/ctdb.git;a=shortlog;h=libctdb


- Log -----------------------------------------------------------------
commit d61fbb5c91b1780208fc24318a2fc7cbeaefebf4
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Tue May 18 11:11:12 2010 +1000

    update getpnn to use a generic "set_callback" call to register the callback on the handle
    this allows us to have a generic signature for all callbacks instead of different types for each operation.

-----------------------------------------------------------------------

Summary of changes:
 client/ctdb_client.c |    2 +-
 include/ctdb.h       |   50 ++++++++++++++++++++---
 libctdb/libctdb.c    |  109 ++++++++++++++++++++++++++++++++-----------------
 libctdb/tst.c        |   51 +++++++++++++++++------
 4 files changed, 153 insertions(+), 59 deletions(-)


Changeset truncated at 500 lines:

diff --git a/client/ctdb_client.c b/client/ctdb_client.c
index 4d49293..6a19510 100644
--- a/client/ctdb_client.c
+++ b/client/ctdb_client.c
@@ -1112,7 +1112,7 @@ int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t
 	uint32_t pnn;
 	ctdb_handle *handle;
 
-	handle = ctdb_getpnn_send(ctdb, destnode, NULL, NULL);
+	handle = ctdb_getpnn_send(ctdb, destnode);
 	if (handle == NULL) {
 		DEBUG(DEBUG_ERR, (__location__ " Failed to send getpnn control\n"));
 		return -1;
diff --git a/include/ctdb.h b/include/ctdb.h
index d0b9507..980e855 100644
--- a/include/ctdb.h
+++ b/include/ctdb.h
@@ -23,10 +23,23 @@
 /* Functions are not thread safe so all function calls must be wrapped
  * inside a pthread_mutex for threaded applications.
  *
- * All _send() functions are guaranteed to be non-blocking and fully
+ * All *_send() functions are guaranteed to be non-blocking and fully
  * asynchronous.
  *
- * Avoid using the synchronous calls
+ * The return data from a _send() call can be accessed through two different
+ * mechanisms.
+ *
+ * 1, by calling *_recv() directly on the handle.
+ *    This function will block until the response is received so it
+ *    should be avoided.
+ *    The exception is when called from in the registered callback,
+ *    in this case the fucntion is guaranteed not to block.
+ *
+ * 2, Registering an async callback to be invoked when the call completes.
+ *    From inside the callback you use the *_recv() function to extract the
+ *    response data.
+ *
+ * After the *_recv() function returns, the handle will have been destroyed.
  */
 
 /*
@@ -65,6 +78,33 @@ typedef void ctdb_handle;
 
 
 /*
+ * After issuing a *_send() command, you can use this function to register a
+ * a callback function to be automatically called once the call
+ * finishes.
+ *
+ * Once the callback function returns, the handle will be automatically
+ * destroyed.
+ *
+ * If using ctdb_free() to abort a call in flight, you have to take care
+ * to avoid the race condition that would exist between the callback and
+ * ctdb_free().
+ *
+ * Possible method could be :
+ * * take pthreads mutex
+ * * ctdb_set_callback(handle, NULL, NULL)
+ * * verify that the callback has not yet been called
+ *     (if it has handle is no longer valid)
+ * * ctdb_free(handle)
+ * * release pthreads mutex
+ */
+typedef void (*ctdb_callback)(int32_t status, struct ctdb_context *ctdb, ctdb_handle *, void *private_data);
+
+int ctdb_set_callback(ctdb_handle *handle, ctdb_callback callback, void *private_data);
+
+
+
+
+/*
  * functions to attach to a database
  * if the database does not exist it will be created.
  *
@@ -182,13 +222,9 @@ int ctdb_send_message(struct ctdb_context *ctdb, uint32_t pnn, uint64_t srvid, T
 /*
  * functions to read the pnn number of the local node
  */
-typedef void (*ctdb_getpnn_cb)(int32_t status, int32_t pnn, void *private_data);
-
 ctdb_handle *
 ctdb_getpnn_send(struct ctdb_context *ctdb,
-		 uint32_t destnode,
-		 ctdb_getpnn_cb callback,
-		 void *private_data);
+		 uint32_t destnode);
 int ctdb_getpnn_recv(struct ctdb_context *ctdb,
 		     ctdb_handle *handle,
 		     uint32_t *pnn);
diff --git a/libctdb/libctdb.c b/libctdb/libctdb.c
index 02b40ab..a17ad14 100644
--- a/libctdb/libctdb.c
+++ b/libctdb/libctdb.c
@@ -34,6 +34,73 @@
 #include "system/filesys.h"
 
 
+struct ctdb_control_cb_data {
+	void *callback;
+	void *private_data;
+	uint32_t db_id;
+};
+
+
+static void
+ctdb_control_cb(struct ctdb_client_control_state *state)
+{
+	struct ctdb_control_cb_data *cb_data = state->async.private_data;
+	ctdb_callback callback = (ctdb_callback)cb_data->callback;
+
+	/* dont recurse */
+	state->async.fn = NULL;
+
+	if (state->state != CTDB_CONTROL_DONE) {
+		DEBUG(DEBUG_ERR, (__location__ " ctdb_getpnn_recv_cb failed with state:%d\n", state->state));
+		callback(-1, NULL, NULL, cb_data->private_data);
+		return;
+	}
+
+	callback(0, state->ctdb, state, cb_data->private_data);
+}
+
+
+/*
+ * This function is used to set the callback action for a handle
+ */
+int ctdb_set_callback(ctdb_handle *handle, ctdb_callback callback, void *private_data)
+{
+	struct ctdb_client_control_state *control_state = talloc_get_type(handle, struct ctdb_client_control_state);
+
+	if (control_state != NULL) {
+		struct ctdb_control_cb_data *cb_data;
+
+		if (callback == NULL) {
+			if (control_state->async.private_data != NULL) {
+				talloc_free(control_state->async.private_data);
+				control_state->async.private_data = NULL;
+			}
+			control_state->async.fn           = NULL;
+
+			return 0;
+		}
+
+		cb_data = talloc(control_state, struct ctdb_control_cb_data);
+		if (cb_data == NULL) {
+			DEBUG(DEBUG_ERR, (__location__ " Failed to alloc cb_data\n"));
+			return -1;
+		}
+
+		cb_data->callback     = callback;
+		cb_data->private_data = private_data;
+
+		control_state->async.fn           = ctdb_control_cb;
+		control_state->async.private_data = cb_data;
+
+		return 0;
+	}
+
+	DEBUG(DEBUG_ERR, (__location__ " Unknown type of handle passed to ctdb_set_callback.\n"));
+	return -1;
+}
+
+
+
 /*
   this is the dummy null procedure that all databases support
 */
@@ -165,41 +232,17 @@ int ctdb_free(ctdb_handle *handle)
 	return 0;
 }
 
-struct ctdb_control_cb_data {
-	void *callback;
-	void *private_data;
-	uint32_t db_id;
-};
-
 
 
 
 /*************************
  * GET PNN of local node *
  *************************/
-static void
-ctdb_getpnn_recv_cb(struct ctdb_client_control_state *state)
-{
-	struct ctdb_control_cb_data *cb_data = state->async.private_data;
-	ctdb_getpnn_cb callback = (ctdb_getpnn_cb)cb_data->callback;
-
-	if (state->state != CTDB_CONTROL_DONE) {
-		DEBUG(DEBUG_ERR, (__location__ " ctdb_getpnn_recv_cb failed with state:%d\n", state->state));
-		callback(-1, 0, cb_data->private_data);
-		return;
-	}
-
-	callback(0, state->status, cb_data->private_data);
-}
-
 ctdb_handle *
 ctdb_getpnn_send(struct ctdb_context *ctdb,
-			uint32_t destnode,
-			ctdb_getpnn_cb callback,
-			void *private_data)
+			uint32_t destnode)
 {
 	struct ctdb_client_control_state *state;
-	struct ctdb_control_cb_data *cb_data;
 
 	state = ctdb_control_send(ctdb, destnode, 0, 
 			   CTDB_CONTROL_GET_PNN, 0, tdb_null, 
@@ -210,15 +253,6 @@ ctdb_getpnn_send(struct ctdb_context *ctdb,
 		return NULL;
 	}
 
-	if (callback != NULL) {
-		cb_data = talloc(state, struct ctdb_control_cb_data);
-		cb_data->callback     = callback;
-		cb_data->private_data = private_data;
-
-		state->async.fn           = ctdb_getpnn_recv_cb;
-		state->async.private_data = cb_data;
-	}
-
 	return (ctdb_handle *)state;
 }
 
@@ -226,16 +260,15 @@ int ctdb_getpnn_recv(struct ctdb_context *ctdb, ctdb_handle *handle, uint32_t *p
 {
 	struct ctdb_client_control_state *state = talloc_get_type(handle, struct ctdb_client_control_state);
 	int ret;
-	int32_t res;
 
-	ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
+	ret = ctdb_control_recv(ctdb, state, state, NULL, NULL, NULL);
 	if (ret != 0) {
 		DEBUG(DEBUG_ERR,(__location__ " ctdb_getpnn_recv failed\n"));
 		return -1;
 	}
 
 	if (pnn != NULL) {
-		*pnn = (uint32_t)res;
+		*pnn = (uint32_t)state->status;
 	}
 
 	return 0;
@@ -245,7 +278,7 @@ int ctdb_getpnn(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *pnn)
 {
 	struct ctdb_client_control_state *state;
 	
-	state = ctdb_getpnn_send(ctdb, destnode, NULL, NULL);
+	state = ctdb_getpnn_send(ctdb, destnode);
 	if (state == NULL) {
 		DEBUG(DEBUG_ERR,(__location__ " ctdb_getpnn_send() failed.\n"));
 		return -1;
diff --git a/libctdb/tst.c b/libctdb/tst.c
index 452ebe1..f8e8f7f 100644
--- a/libctdb/tst.c
+++ b/libctdb/tst.c
@@ -15,8 +15,22 @@ void msg_h(struct ctdb_context *ctdb, uint64_t srvid, TDB_DATA data, void *priva
 }
 
 
-void pnn_cb(int32_t status, int32_t pnn, void *private_data)
+void pnn_cb(int32_t status, struct ctdb_context *ctdb, ctdb_handle *handle, void *private_data)
 {
+	uint32_t pnn;
+	int ret;
+
+	if (status != 0) {
+		printf("Error reading PNN\n");
+		return;
+	}
+
+	ret = ctdb_getpnn_recv(ctdb, handle, &pnn);
+	if (ret != 0) {
+		printf("Failed to read getpnn reply\n");
+		return;
+	}
+
 	printf("status:%d pnn:%d\n", status, pnn);
 }
 
@@ -67,7 +81,7 @@ void rrl_cb(int32_t status, ctdb_handle *handle, TDB_DATA outdata, void *private
 
 int main(int argc, char *argv[])
 {
-	struct ctdb_context *ctdb_context;
+	struct ctdb_context *ctdb;
 	struct ctdb_db_context *ctdb_db_context;
 	ctdb_handle *handle;
 	struct pollfd pfd;
@@ -77,14 +91,14 @@ int main(int argc, char *argv[])
 	key.dptr  = "Test Record";
 	key.dsize = strlen(key.dptr);
 
-	ctdb_context = ctdb_connect("/tmp/ctdb.socket");
+	ctdb = ctdb_connect("/tmp/ctdb.socket");
 
-	handle = ctdb_set_message_handler_send(ctdb_context, 55, NULL, msg_h, NULL);
+	handle = ctdb_set_message_handler_send(ctdb, 55, NULL, msg_h, NULL);
 	if (handle == NULL) {
 		printf("Failed to register message port\n");
 		exit(10);
 	}
-	ret = ctdb_set_message_handler_recv(ctdb_context, handle);
+	ret = ctdb_set_message_handler_recv(ctdb, handle);
 	if (ret != 0) {
 		printf("Failed to receive set_message_handler reply\n");
 		exit(10);
@@ -93,44 +107,55 @@ int main(int argc, char *argv[])
 	msg.dptr="HelloWorld";
 	msg.dsize = strlen(msg.dptr);
 
-	ret = ctdb_send_message(ctdb_context, 0, 55, msg);
+	ret = ctdb_send_message(ctdb, 0, 55, msg);
 	if (ret != 0) {
 		printf("Failed to send message. Aborting\n");
 		exit(10);
 	}
 
-	handle = ctdb_attachdb_send(ctdb_context, "test_test.tdb", 0, 0, NULL, NULL);
+	handle = ctdb_attachdb_send(ctdb, "test_test.tdb", 0, 0, NULL, NULL);
 	if (handle == NULL) {
 		printf("Failed to send attachdb control\n");
 		exit(10);
 	}
-	ret = ctdb_attachdb_recv(ctdb_context, handle, &ctdb_db_context);
+	ret = ctdb_attachdb_recv(ctdb, handle, &ctdb_db_context);
 	if (ret != 0 ) {
 		printf("Failed to attach to database\n");
 		exit(10);
 	}
 
 
-	handle = ctdb_getpnn_send(ctdb_context, CTDB_CURRENT_NODE, pnn_cb, NULL);
+
+
+	handle = ctdb_getpnn_send(ctdb, CTDB_CURRENT_NODE);
 	if (handle == NULL) {
 		printf("Failed to send get_pnn control\n");
 		exit(10);
 	}
+	ret = ctdb_set_callback(handle, pnn_cb, NULL);
+	if (ret != 0) {
+		printf("Failed to set callback for getpnn\n");
+		ctdb_free(handle);
+		exit(10);
+	}
+
+
+
 
-	handle = ctdb_readrecordlock_send(ctdb_context, ctdb_db_context, key, rrl_cb, NULL);
+	handle = ctdb_readrecordlock_send(ctdb, ctdb_db_context, key, rrl_cb, NULL);
 	if (handle == NULL) {
 		printf("Failed to send READRECORDLOCK\n");
 		exit(10);
 	}
 
-	pfd.fd = ctdb_get_fd(ctdb_context);
+	pfd.fd = ctdb_get_fd(ctdb);
 	for (;;) {
-	  pfd.events = ctdb_which_events(ctdb_context);
+	  pfd.events = ctdb_which_events(ctdb);
 	  if (poll(&pfd, 1, -1) < 0) {
 	    printf("Poll failed");
 	    exit(10);
 	  }
-	  ctdb_service(ctdb_context);
+	  ctdb_service(ctdb);
 	}
 
 	return 0;


-- 
CTDB repository


More information about the samba-cvs mailing list