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 <ronniesahlb...@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 <ronniesahlb...@gmail.com>
Date:   Mon May 17 15:55:40 2010 +1000

    move ctdb_call_recv to libctdb

commit 0262c1a9a819f50517724ff6e1170be0fffcb7e8
Author: Ronnie Sahlberg <ronniesahlb...@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

Reply via email to