[SCM] CTDB repository - branch libctdb updated - ctdb-1.0.114-110-gb28816f

Ronnie Sahlberg sahlberg at samba.org
Mon May 17 02:50:35 MDT 2010


The branch, libctdb has been updated
       via  b28816fecc7c56a15f6027676c9557283ebc4338 (commit)
       via  9b78ee69040c1b28d4b9190d572795a43d5a9c57 (commit)
       via  0262c1a9a819f50517724ff6e1170be0fffcb7e8 (commit)
      from  3e9720d1dea95daf0c442eb2fbcbc1c90a0ccc47 (commit)

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


- Log -----------------------------------------------------------------
commit b28816fecc7c56a15f6027676c9557283ebc4338
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Mon May 17 18:40:24 2010 +1000

    add a function ctdb_writerecord() to write a record to the database.
    
    This function can only be called while hoilding a ctdb_readreacordlock*() handle.
    Either from the callback provided or after ctdb_readrecordlock_recv() has been called but before ctdb_free() is used to release the handle.

commit 9b78ee69040c1b28d4b9190d572795a43d5a9c57
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Mon May 17 15:55:40 2010 +1000

    move ctdb_call_recv to libctdb

commit 0262c1a9a819f50517724ff6e1170be0fffcb7e8
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Mon May 17 15:43:37 2010 +1000

    createdb and getdbpath does not need to be in the public api

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

Summary of changes:
 client/ctdb_client.c    |  175 -----------------------------------------------
 include/ctdb.h          |   85 ++++++++++++-----------
 include/ctdb_private.h  |    7 ++
 include/ctdb_protocol.h |   42 +++++++++++
 libctdb/ctdb_client.c   |  163 +++++++++++++++++++++++++++++++++++++++++++
 libctdb/libctdb.c       |  101 ++++++++++++++++++++++-----
 libctdb/tst.c           |   55 +++++++++++++--
 7 files changed, 387 insertions(+), 241 deletions(-)


Changeset truncated at 500 lines:

diff --git a/client/ctdb_client.c b/client/ctdb_client.c
index 56d8b5a..4d49293 100644
--- a/client/ctdb_client.c
+++ b/client/ctdb_client.c
@@ -33,181 +33,6 @@
 
 
 
-struct ctdb_record_handle {
-	struct ctdb_db_context *ctdb_db;
-	TDB_DATA key;
-	TDB_DATA *data;
-	struct ctdb_ltdb_header header;
-};
-
-
-/*
-  make a recv call to the local ctdb daemon - called from client context
-
-  This is called when the program wants to wait for a ctdb_call to complete and get the 
-  results. This call will block unless the call has already completed.
-*/
-int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
-{
-	if (state == NULL) {
-		return -1;
-	}
-
-	while (state->state < CTDB_CALL_DONE) {
-		event_loop_once(state->ctdb_db->ctdb->ev);
-	}
-	if (state->state != CTDB_CALL_DONE) {
-		DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
-		talloc_free(state);
-		return -1;
-	}
-
-	if (state->call->reply_data.dsize) {
-		call->reply_data.dptr = talloc_memdup(state->ctdb_db,
-						      state->call->reply_data.dptr,
-						      state->call->reply_data.dsize);
-		call->reply_data.dsize = state->call->reply_data.dsize;
-	} else {
-		call->reply_data.dptr = NULL;
-		call->reply_data.dsize = 0;
-	}
-	call->status = state->call->status;
-	talloc_free(state);
-
-	return 0;
-}
-
-
-
-
-
-
-
-/*
-  full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
-*/
-int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
-{
-	struct ctdb_client_call_state *state;
-
-	state = ctdb_call_send(ctdb_db, call);
-	return ctdb_call_recv(state, call);
-}
-
-
-
-
-
-/*
-  cancel a ctdb_fetch_lock operation, releasing the lock
- */
-static int fetch_lock_destructor(struct ctdb_record_handle *h)
-{
-	ctdb_ltdb_unlock(h->ctdb_db, h->key);
-	return 0;
-}
-
-/*
-  force the migration of a record to this node
- */
-static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
-{
-	struct ctdb_call call;
-	ZERO_STRUCT(call);
-	call.call_id = CTDB_NULL_FUNC;
-	call.key = key;
-	call.flags = CTDB_IMMEDIATE_MIGRATION;
-	return ctdb_call(ctdb_db, &call);
-}
-
-/*
-  get a lock on a record, and return the records data. Blocks until it gets the lock
- */
-struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx, 
-					   TDB_DATA key, TDB_DATA *data)
-{
-	int ret;
-	struct ctdb_record_handle *h;
-
-	/*
-	  procedure is as follows:
-
-	  1) get the chain lock. 
-	  2) check if we are dmaster
-	  3) if we are the dmaster then return handle 
-	  4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
-	     reply from ctdbd
-	  5) when we get the reply, goto (1)
-	 */
-
-	h = talloc_zero(mem_ctx, struct ctdb_record_handle);
-	if (h == NULL) {
-		return NULL;
-	}
-
-	h->ctdb_db = ctdb_db;
-	h->key     = key;
-	h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
-	if (h->key.dptr == NULL) {
-		talloc_free(h);
-		return NULL;
-	}
-	h->data    = data;
-
-	DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize, 
-		 (const char *)key.dptr));
-
-again:
-	/* step 1 - get the chain lock */
-	ret = ctdb_ltdb_lock(ctdb_db, key);
-	if (ret != 0) {
-		DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
-		talloc_free(h);
-		return NULL;
-	}
-
-	DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: got chain lock\n"));
-
-	talloc_set_destructor(h, fetch_lock_destructor);
-
-	ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data);
-
-	/* when torturing, ensure we test the remote path */
-	if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) &&
-	    random() % 5 == 0) {
-		h->header.dmaster = (uint32_t)-1;
-	}
-
-
-	DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: done local fetch\n"));
-
-	if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->pnn) {
-		ctdb_ltdb_unlock(ctdb_db, key);
-		ret = ctdb_client_force_migration(ctdb_db, key);
-		if (ret != 0) {
-			DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
-			talloc_free(h);
-			return NULL;
-		}
-		goto again;
-	}
-
-	DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
-	return h;
-}
-
-/*
-  store some data to the record that was locked with ctdb_fetch_lock()
-*/
-int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
-{
-	if (h->ctdb_db->persistent) {
-		DEBUG(DEBUG_ERR, (__location__ " ctdb_record_store prohibited for persistent dbs\n"));
-		return -1;
-	}
-
-	return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
-}
 
 /*
   non-locking fetch of a record
diff --git a/include/ctdb.h b/include/ctdb.h
index 678189e..d0b9507 100644
--- a/include/ctdb.h
+++ b/include/ctdb.h
@@ -68,11 +68,11 @@ 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.
+ * You have to free the handle with ctdb_free() when finished with it.
  */
 struct ctdb_db_context;
 
-typedef void (*ctdb_attachdb_cb)(int32_t status, struct ctdb_db_context *ctdb_db, void *private_data);
+typedef void (*ctdb_attachdb_cb)(int32_t status, ctdb_handle *, struct ctdb_db_context *ctdb_db, void *private_data);
 
 ctdb_handle *
 ctdb_attachdb_send(struct ctdb_context *ctdb,
@@ -86,6 +86,47 @@ int ctdb_attachdb(struct ctdb_context *ctdb,
 		  struct ctdb_db_context **);
 
 
+/*
+ * functions to read a record from the database
+ * when the callback is invoked, the client will hold an exclusive lock
+ * on the record, until the handle is ctdb_free()d.
+ * the client MUST NOT block during holding this lock and MUST
+ * release it quickly by performing ctdb_free(handle).
+ *
+ * When the handle is freed, data is freed too, so make sure to copy the data
+ * before freeing the handle.
+ */
+typedef void (*ctdb_readrecordlock_cb)(int32_t status, ctdb_handle *handle, TDB_DATA data, void *private_data);
+
+ctdb_handle *
+ctdb_readrecordlock_send(struct ctdb_context *ctdb,
+		struct ctdb_db_context *ctdb_db_context,
+		TDB_DATA key,
+		ctdb_readrecordlock_cb callback,
+		void *private_data);
+int ctdb_readrecordlock_recv(struct ctdb_context *ctdb,
+		ctdb_handle *handle,
+		TDB_DATA **data);
+int ctdb_readrecordlock(struct ctdb_context *ctdb,
+		struct ctdb_db_context *ctdb_db_context,
+		TDB_DATA key,
+		TDB_DATA **data);
+
+
+
+/*
+ * Function to write data to a record
+ * This function may ONLY be called while holding a lock to the record 
+ * created by ctdb_readrecordlock*
+ * Either from the callback provided to ctdb_readrecordlock_send()
+ * or after calling ctdb_readrecordlock_recv() but before calling
+ * ctdb_free() to release the handle.
+ */
+int ctdb_writerecord(ctdb_handle *handle,
+		TDB_DATA key,
+		TDB_DATA data);
+
+
 
 /*
  * messaging functions
@@ -179,46 +220,6 @@ int ctdb_getrecmaster(struct ctdb_context *ctdb,
 
 
 /*
- * functions to create a database
- * if the database already exists this function is a NOP
- */
-typedef void (*ctdb_createdb_cb)(int32_t status, uint32_t db_id, void *private_data);
-
-ctdb_handle *
-ctdb_createdb_send(struct ctdb_context *ctdb, uint32_t destnode,
-		   const char *name, int persistent, uint32_t tdb_flags,
-		   ctdb_createdb_cb callback,
-		   void *private_data);
-int ctdb_createdb_recv(struct ctdb_context *ctdb,
-		       ctdb_handle *handle, uint32_t *db_id);
-int ctdb_createdb(struct ctdb_context *ctdb, uint32_t destnode,
-		  const char *name, int persistent, uint32_t tdb_flags,
-		  uint32_t *db_id);
-
-
-
-
-/*
- * functions to find the filename of a database
- *
- * 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);
-
-ctdb_handle *
-ctdb_getdbpath_send(struct ctdb_context *ctdb, uint32_t destnode,
-		    uint32_t db_id,
-		    ctdb_getdbpath_cb callback,
-		    void *private_data);
-int ctdb_getdbpath_recv(struct ctdb_context *ctdb,
-			ctdb_handle *handle, const char **path);
-int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t destnode,
-		   uint32_t db_id,
-		   const char **path);
-
-
-/*
  * cancel a request/call
  */
 int ctdb_free(ctdb_handle *);
diff --git a/include/ctdb_private.h b/include/ctdb_private.h
index 90d4c13..ab60a9d 100644
--- a/include/ctdb_private.h
+++ b/include/ctdb_private.h
@@ -1652,4 +1652,11 @@ void ctdb_control_timeout_func(struct event_context *ev,
 
 void ctdb_invoke_control_callback(struct event_context *ev, struct timed_event *te, struct timeval t, void *private_data);
 
+struct ctdb_record_handle {
+	struct ctdb_db_context *ctdb_db;
+	TDB_DATA key;
+	TDB_DATA *data;
+	struct ctdb_ltdb_header header;
+};
+
 #endif
diff --git a/include/ctdb_protocol.h b/include/ctdb_protocol.h
index 694fdae..8eda5d4 100644
--- a/include/ctdb_protocol.h
+++ b/include/ctdb_protocol.h
@@ -721,4 +721,46 @@ struct ctdb_db_priority {
 int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio);
 int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority);
 
+
+/*
+ * functions to create a database
+ * if the database already exists this function is a NOP
+ */
+typedef void (*ctdb_createdb_cb)(int32_t status, uint32_t db_id, void *private_data);
+
+ctdb_handle *
+ctdb_createdb_send(struct ctdb_context *ctdb, uint32_t destnode,
+		   const char *name, int persistent, uint32_t tdb_flags,
+		   ctdb_createdb_cb callback,
+		   void *private_data);
+int ctdb_createdb_recv(struct ctdb_context *ctdb,
+		       ctdb_handle *handle, uint32_t *db_id);
+int ctdb_createdb(struct ctdb_context *ctdb, uint32_t destnode,
+		  const char *name, int persistent, uint32_t tdb_flags,
+		  uint32_t *db_id);
+
+
+
+
+/*
+ * functions to find the filename of a database
+ *
+ * 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);
+
+ctdb_handle *
+ctdb_getdbpath_send(struct ctdb_context *ctdb, uint32_t destnode,
+		    uint32_t db_id,
+		    ctdb_getdbpath_cb callback,
+		    void *private_data);
+int ctdb_getdbpath_recv(struct ctdb_context *ctdb,
+			ctdb_handle *handle, const char **path);
+int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t destnode,
+		   uint32_t db_id,
+		   const char **path);
+
+
+
 #endif
diff --git a/libctdb/ctdb_client.c b/libctdb/ctdb_client.c
index 864877c..a7b2112 100644
--- a/libctdb/ctdb_client.c
+++ b/libctdb/ctdb_client.c
@@ -625,6 +625,55 @@ struct ctdb_client_call_state *ctdb_call_send(struct ctdb_db_context *ctdb_db,
 }
 
 /*
+  make a recv call to the local ctdb daemon - called from client context
+
+  This is called when the program wants to wait for a ctdb_call to complete and get the 
+  results. This call will block unless the call has already completed.
+*/
+int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
+{
+	if (state == NULL) {
+		return -1;
+	}
+
+	while (state->state < CTDB_CALL_DONE) {
+		event_loop_once(state->ctdb_db->ctdb->ev);
+	}
+	if (state->state != CTDB_CALL_DONE) {
+		DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
+		talloc_free(state);
+		return -1;
+	}
+
+	if (state->call->reply_data.dsize) {
+		call->reply_data.dptr = talloc_memdup(state->ctdb_db,
+						      state->call->reply_data.dptr,
+						      state->call->reply_data.dsize);
+		call->reply_data.dsize = state->call->reply_data.dsize;
+	} else {
+		call->reply_data.dptr = NULL;
+		call->reply_data.dsize = 0;
+	}
+	call->status = state->call->status;
+	talloc_free(state);
+
+	return 0;
+}
+
+/*
+  full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
+*/
+int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
+{
+	struct ctdb_client_call_state *state;
+
+	state = ctdb_call_send(ctdb_db, call);
+	return ctdb_call_recv(state, call);
+}
+
+
+
+/*
   send a message - from client context
  */
 int ctdb_send_message(struct ctdb_context *ctdb, uint32_t pnn,
@@ -691,3 +740,117 @@ int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
 	DLIST_ADD(ctdb_db->calls, call);	
 	return 0;
 }
+
+
+
+/*
+  store some data to the record that was locked with ctdb_fetch_lock()
+*/
+int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
+{
+	if (h->ctdb_db->persistent) {
+		DEBUG(DEBUG_ERR, (__location__ " ctdb_record_store prohibited for persistent dbs\n"));
+		return -1;
+	}
+
+	return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
+}
+
+/*
+  cancel a ctdb_fetch_lock operation, releasing the lock
+ */
+static int fetch_lock_destructor(struct ctdb_record_handle *h)
+{
+	ctdb_ltdb_unlock(h->ctdb_db, h->key);
+	return 0;
+}
+
+
+/*
+  force the migration of a record to this node
+ */
+static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
+{
+	struct ctdb_call call;
+	ZERO_STRUCT(call);
+	call.call_id = CTDB_NULL_FUNC;
+	call.key = key;
+	call.flags = CTDB_IMMEDIATE_MIGRATION;
+	return ctdb_call(ctdb_db, &call);
+}
+
+/*
+  get a lock on a record, and return the records data. Blocks until it gets the lock
+ */
+struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx, 
+					   TDB_DATA key, TDB_DATA *data)
+{
+	int ret;
+	struct ctdb_record_handle *h;
+
+	/*
+	  procedure is as follows:
+
+	  1) get the chain lock. 
+	  2) check if we are dmaster
+	  3) if we are the dmaster then return handle 
+	  4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
+	     reply from ctdbd
+	  5) when we get the reply, goto (1)
+	 */
+
+	h = talloc_zero(mem_ctx, struct ctdb_record_handle);
+	if (h == NULL) {
+		return NULL;
+	}
+
+	h->ctdb_db = ctdb_db;
+	h->key     = key;
+	h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
+	if (h->key.dptr == NULL) {
+		talloc_free(h);
+		return NULL;


-- 
CTDB repository


More information about the samba-cvs mailing list