[SCM] CTDB repository - branch libctdb updated - ctdb-1.0.114-105-g3bda422

Ronnie Sahlberg sahlberg at samba.org
Sun May 16 20:31:58 MDT 2010


The branch, libctdb has been updated
       via  3bda422d53c481c4df638f95425e956651368819 (commit)
      from  cc0bba900d9ed79e3542eea05c05745d01f9a12a (commit)

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


- Log -----------------------------------------------------------------
commit 3bda422d53c481c4df638f95425e956651368819
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Mon May 17 12:30:22 2010 +1000

    create an async version of ctdb_attachdb_send() for libctdb

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

Summary of changes:
 client/ctdb_client.c  |   43 +---------
 include/ctdb.h        |   32 +++++++-
 libctdb/ctdb_client.c |   36 ++++++++
 libctdb/libctdb.c     |  213 ++++++++++++++++++++++++++++++++++++++++++++++++-
 libctdb/tst.c         |   12 +++
 5 files changed, 292 insertions(+), 44 deletions(-)


Changeset truncated at 500 lines:

diff --git a/client/ctdb_client.c b/client/ctdb_client.c
index 0840cfd..1552c41 100644
--- a/client/ctdb_client.c
+++ b/client/ctdb_client.c
@@ -808,7 +808,7 @@ int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint3
 	if (ret != 0) {
 		DEBUG(DEBUG_ERR,(__location__ " ctdb control for getdbpath failed\n"));
 		if (tmppath != NULL) {
-			free(discard_const(tmppath));
+			talloc_free(discard_const(tmppath));
 		}
 		return -1;
 	}
@@ -818,7 +818,7 @@ int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint3
 	}
 
 	*path = talloc_strdup(mem_ctx, (const char *)tmppath);
-	free(discard_const(tmppath));
+	talloc_free(discard_const(tmppath));
 
 	if (*path == NULL) {
 		return -1;
@@ -1039,6 +1039,8 @@ static int ctdb_fetch_func(struct ctdb_call_info *call)
 	return 0;
 }
 
+
+
 /*
   attach to a specific database - client call
 */
@@ -1112,43 +1114,6 @@ struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb, const char *name,
 }
 
 
-/*
-  setup a call for a database
- */
-int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
-{
-	struct ctdb_registered_call *call;
-
-#if 0
-	TDB_DATA data;
-	int32_t status;
-	struct ctdb_control_set_call c;
-	int ret;
-
-	/* this is no longer valid with the separate daemon architecture */
-	c.db_id = ctdb_db->db_id;
-	c.fn    = fn;
-	c.id    = id;
-
-	data.dptr = (uint8_t *)&c;
-	data.dsize = sizeof(c);
-
-	ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0,
-			   data, NULL, NULL, &status, NULL, NULL);
-	if (ret != 0 || status != 0) {
-		DEBUG(DEBUG_ERR,("ctdb_set_call failed for call %u\n", id));
-		return -1;
-	}
-#endif
-
-	/* also register locally */
-	call = talloc(ctdb_db, struct ctdb_registered_call);
-	call->fn = fn;
-	call->id = id;
-
-	DLIST_ADD(ctdb_db->calls, call);	
-	return 0;
-}
 
 
 struct traverse_state {
diff --git a/include/ctdb.h b/include/ctdb.h
index 7b2d5c0..7ccedaa 100644
--- a/include/ctdb.h
+++ b/include/ctdb.h
@@ -32,6 +32,8 @@
 /*
  * Connect to ctdb using the specified domain socket.
  * Returns a ctdb context if successful or NULL.
+ *
+ * Use ctdb_free() to release the returned ctdb_context when finished.
  */
 struct ctdb_context *ctdb_connect(const char *addr);
 
@@ -58,10 +60,34 @@ int ctdb_service(struct ctdb_context *ctdb);
 
 
 
+
 typedef void ctdb_handle;
 
 
 /*
+ * functions to attach to a database
+ * if the database does not exist it will be created.
+ *
+ * Use ctdb_free() to release the returned ctdb_db_context when finished.
+ */
+struct ctdb_db_context;
+
+typedef void (*ctdb_attachdb_cb)(int32_t status, struct ctdb_db_context *ctdb_db, void *private_data);
+
+ctdb_handle *
+ctdb_attachdb_send(struct ctdb_context *ctdb, uint32_t destnode,
+		   const char *name, int persistent, uint32_t tdb_flags,
+		   ctdb_attachdb_cb callback,
+		   void *private_data);
+int ctdb_attachdb_recv(struct ctdb_context *ctdb,
+		       ctdb_handle *handle, struct ctdb_db_context **);
+int ctdb_attachdb(struct ctdb_context *ctdb, uint32_t destnode,
+		  const char *name, int persistent, uint32_t tdb_flags,
+		  struct ctdb_db_context **);
+
+
+
+/*
  * messaging functions
  * these functions provide a messaging layer for applications to communicate
  * with eachother across
@@ -174,7 +200,9 @@ int ctdb_createdb(struct ctdb_context *ctdb, uint32_t destnode,
 
 /*
  * functions to find the filename of a database
- * the caller is responsible to free() path
+ *
+ * the caller is responsible to release *path when finished with it using
+ * ctdb_free()
  */
 typedef void (*ctdb_getdbpath_cb)(int32_t status, const char *path, void *private_data);
 
@@ -193,7 +221,7 @@ int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t destnode,
 /*
  * cancel a request/call
  */
-int ctdb_cancel(ctdb_handle *);
+int ctdb_free(ctdb_handle *);
 
 
 
diff --git a/libctdb/ctdb_client.c b/libctdb/ctdb_client.c
index 23faa4b..864877c 100644
--- a/libctdb/ctdb_client.c
+++ b/libctdb/ctdb_client.c
@@ -654,4 +654,40 @@ int ctdb_send_message(struct ctdb_context *ctdb, uint32_t pnn,
 
 
 
+/*
+  setup a call for a database
+ */
+int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
+{
+	struct ctdb_registered_call *call;
+
+#if 0
+	TDB_DATA data;
+	int32_t status;
+	struct ctdb_control_set_call c;
+	int ret;
+
+	/* this is no longer valid with the separate daemon architecture */
+	c.db_id = ctdb_db->db_id;
+	c.fn    = fn;
+	c.id    = id;
 
+	data.dptr = (uint8_t *)&c;
+	data.dsize = sizeof(c);
+
+	ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0,
+			   data, NULL, NULL, &status, NULL, NULL);
+	if (ret != 0 || status != 0) {
+		DEBUG(DEBUG_ERR,("ctdb_set_call failed for call %u\n", id));
+		return -1;
+	}
+#endif
+
+	/* also register locally */
+	call = talloc(ctdb_db, struct ctdb_registered_call);
+	call->fn = fn;
+	call->id = id;
+
+	DLIST_ADD(ctdb_db->calls, call);	
+	return 0;
+}
diff --git a/libctdb/libctdb.c b/libctdb/libctdb.c
index fa76559..3f8ac64 100644
--- a/libctdb/libctdb.c
+++ b/libctdb/libctdb.c
@@ -21,12 +21,36 @@
 
 #include <poll.h>
 #include "includes.h"
+#include "db_wrap.h"
+#include "lib/tdb/include/tdb.h"
+#include "lib/util/dlinklist.h"
 #include "lib/events/events.h"
 #include "lib/events/events_internal.h"
 #include "include/ctdb.h"
 #include "include/ctdb_protocol.h"
 #include "include/ctdb_private.h"
 #include <sys/time.h>
+#include "system/filesys.h"
+
+
+/*
+  this is the dummy null procedure that all databases support
+*/
+static int ctdb_null_func(struct ctdb_call_info *call)
+{
+	return 0;
+}
+
+/*
+  this is a plain fetch procedure that all databases support
+*/
+static int ctdb_fetch_func(struct ctdb_call_info *call)
+{
+	call->reply_data = &call->record_data;
+	return 0;
+}
+
+
 
 struct ctdb_context *ctdb_connect(const char *addr)
 {
@@ -134,7 +158,7 @@ int ctdb_service(struct ctdb_context *ctdb)
 
 
 
-int ctdb_cancel(ctdb_handle *handle)
+int ctdb_free(ctdb_handle *handle)
 {
 	talloc_free(handle);
 	return 0;
@@ -619,7 +643,7 @@ ctdb_getdbpath_recv_cb(struct ctdb_client_control_state *state)
 		return;
 	}
 
-	callback(state->status, strdup((char *)state->outdata.dptr), cb_data->private_data);
+	callback(state->status, talloc_strdup(state->ctdb, (char *)state->outdata.dptr), cb_data->private_data);
 }
 
 ctdb_handle *
@@ -675,7 +699,7 @@ int ctdb_getdbpath_recv(struct ctdb_context *ctdb, ctdb_handle *handle, const ch
 	}
 
 	if (state->status == 0 && path != NULL) {
-		*path = strdup((char *)data.dptr);
+		*path = talloc_strdup(ctdb, (char *)data.dptr);
 	}
 
 	talloc_free(tmp_ctx);
@@ -697,3 +721,186 @@ int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t destnode,
 	return ctdb_getdbpath_recv(ctdb, state, path);
 }
 
+
+
+/*
+ * Attach to a database
+ */
+
+struct ctdb_attachdb_state {
+	uint32_t destnode;
+	struct ctdb_context *ctdb;
+	struct ctdb_db_context *ctdb_db;
+	struct ctdb_client_control_state *cdb_state;
+	struct ctdb_client_control_state *gdp_state;
+	bool persistent;
+	uint32_t tdb_flags;
+	ctdb_attachdb_cb callback;
+	void *private_data;
+};	
+
+
+static void
+ctdb_attachdb_recv2_cb(struct ctdb_client_control_state *state)
+{
+	struct ctdb_attachdb_state *adb_state = 
+			talloc_get_type(state->async.private_data,
+					struct ctdb_attachdb_state);
+	ctdb_attachdb_cb callback = (ctdb_attachdb_cb)adb_state->callback;
+
+	struct ctdb_db_context *ctdb_db =
+			talloc_get_type(adb_state->ctdb_db,
+					struct ctdb_db_context);
+	struct ctdb_context *ctdb = 
+			talloc_get_type(ctdb_db->ctdb,
+			struct ctdb_context);
+
+	uint32_t tdb_flags = adb_state->tdb_flags;
+	bool persistent = adb_state->persistent;
+
+	if (state->state != CTDB_CONTROL_DONE || state->status != 0) {
+		DEBUG(DEBUG_ERR,(__location__ " getdbpath control failed with state:%d and status:%d\n", state->state, state->status));
+		callback(-1, NULL, adb_state->private_data);
+		talloc_free(adb_state);
+		return;
+	}
+	ctdb_db->db_path = talloc_strdup(ctdb_db, (char *)state->outdata.dptr);
+
+	tdb_flags = persistent?TDB_DEFAULT:TDB_NOSYNC;
+	if (ctdb->valgrinding) {
+		tdb_flags |= TDB_NOMMAP;
+	}
+	tdb_flags |= TDB_DISALLOW_NESTING;
+
+	ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, tdb_flags, O_RDWR, 0);
+	if (ctdb_db->ltdb == NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " Failed to open tdb '%s'\n", ctdb_db->db_path));
+		callback(-1, NULL, adb_state->private_data);
+		talloc_free(adb_state);
+		return;
+	}
+
+	ctdb_db->persistent = persistent;
+
+	DLIST_ADD(ctdb->db_list, ctdb_db);
+
+	/* add well known functions */
+	ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
+	ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
+
+
+	talloc_steal(ctdb, ctdb_db);
+	callback(0, ctdb_db, adb_state->private_data);
+
+	talloc_free(adb_state);
+}
+
+static void
+ctdb_attachdb_recv1_cb(struct ctdb_client_control_state *state)
+{
+	struct ctdb_attachdb_state *adb_state =
+			talloc_get_type(state->async.private_data,
+			struct ctdb_attachdb_state);
+	ctdb_attachdb_cb callback = (ctdb_attachdb_cb)adb_state->callback;
+
+	if (state->state != CTDB_CONTROL_DONE) {
+		DEBUG(DEBUG_ERR,(__location__ " createdb control failed with state:%d and status:%d\n", state->state, state->status));
+		callback(-1, NULL, adb_state->private_data);
+		talloc_free(adb_state);
+		return;
+	}
+
+	if (state->outdata.dsize != sizeof(uint32_t)) {
+		DEBUG(DEBUG_ERR, (__location__ " Wrong size of data returned for CREATEDB control. Got %zd bytes but expected %zd\n", state->outdata.dsize, sizeof(uint32_t)));
+		callback(-1, NULL, adb_state->private_data);
+		talloc_free(adb_state);
+		return;
+	}
+
+	adb_state->ctdb_db->db_id = *(uint32_t *)state->outdata.dptr;
+
+	adb_state->gdp_state = ctdb_getdbpath_send(adb_state->ctdb, adb_state->destnode, adb_state->ctdb_db->db_id, NULL, NULL);
+	if (state == NULL) {
+		DEBUG(DEBUG_ERR,(__location__ " ctdb_getdbpath_send() failed.\n"));
+		callback(-1, NULL, adb_state->private_data);
+		talloc_free(adb_state);
+		return;
+	}
+	talloc_steal(adb_state, adb_state->gdp_state);
+
+	adb_state->gdp_state->async.fn           = ctdb_attachdb_recv2_cb;
+	adb_state->gdp_state->async.private_data = adb_state;
+}
+
+ctdb_handle *
+ctdb_attachdb_send(struct ctdb_context *ctdb, uint32_t destnode,
+		   const char *name, int persistent, uint32_t tdb_flags,
+		   ctdb_attachdb_cb callback,
+		   void *private_data)
+{
+	struct ctdb_attachdb_state *state;
+	struct ctdb_db_context *ctdb_db;
+
+
+	ctdb_db = ctdb_db_handle(ctdb, name);
+	if (ctdb_db != NULL) {
+		return ctdb_db;
+	}
+
+	state = talloc_zero(ctdb, struct ctdb_attachdb_state);
+	if (state == NULL) {
+		DEBUG(DEBUG_ERR,(__location__ " Failed to allocate attachdb_state\n"));
+		return NULL;
+	}
+
+	ctdb_db = talloc_zero(state, struct ctdb_db_context);
+	if (ctdb_db == NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " Failed to allocate ctdb db context\n"));
+		talloc_free(state);
+		return NULL;
+	}
+
+	state->ctdb       = ctdb;	
+	state->ctdb_db    = ctdb_db;
+	state->destnode   = destnode;
+	state->tdb_flags  = tdb_flags;
+	state->persistent = persistent?True:False;
+
+	ctdb_db->ctdb    = ctdb;
+	ctdb_db->db_name = talloc_strdup(ctdb_db, name);
+	if (ctdb_db->db_name == NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " Failed to strdup db name\n"));
+		talloc_free(state);
+		return NULL;
+	}
+
+	state->cdb_state = ctdb_createdb_send(ctdb, CTDB_CURRENT_NODE,
+				    name, persistent, tdb_flags,
+				    NULL, NULL);
+	if (state->cdb_state == NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " Failed to send CREATEDB control\n"));
+		talloc_free(ctdb_db);
+		return NULL;
+	}
+	talloc_steal(state, state->cdb_state);
+
+	if (callback != NULL) {
+		state->callback     = callback;
+		state->private_data = private_data;
+
+		state->cdb_state->async.fn           = ctdb_attachdb_recv1_cb;
+		state->cdb_state->async.private_data = state;
+	}
+
+	return (ctdb_handle *)state;
+}
+
+
+
+
+int ctdb_attachdb_recv(struct ctdb_context *ctdb,
+		       ctdb_handle *handle, struct ctdb_db_context **);
+int ctdb_attachdb(struct ctdb_context *ctdb, uint32_t destnode,
+		  const char *name, int persistent, uint32_t tdb_flags,
+		  struct ctdb_db_context **);
+
diff --git a/libctdb/tst.c b/libctdb/tst.c
index 821ea7f..08d515e 100644
--- a/libctdb/tst.c
+++ b/libctdb/tst.c
@@ -23,6 +23,12 @@ void rm_cb(int32_t status, int32_t recmaster, void *private_data)
 	printf("status:%d recmaster:%d\n", status, recmaster);
 }
 
+void adb_cb(int32_t status, struct ctdb_db_context *ctdb_db, void *private_data)
+{
+	printf("status:%d db:%p\n", status, ctdb_db);
+}
+
+
 int main(int argc, char *argv[])
 {
 	struct ctdb_context *ctdb_context;
@@ -65,6 +71,12 @@ int main(int argc, char *argv[])
 		exit(10);
 	}
 
+	handle = ctdb_attachdb_send(ctdb_context, CTDB_CURRENT_NODE, "test_test.tdb", 0,0, adb_cb, NULL);
+	if (handle == NULL) {
+		printf("Failed to send attachdb control\n");
+		exit(10);
+	}
+
 	pfd.fd = ctdb_get_fd(ctdb_context);
 	for (;;) {
 	  pfd.events = ctdb_which_events(ctdb_context);


-- 
CTDB repository


More information about the samba-cvs mailing list