[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