summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-09-15 14:07:06 -0700
committerAndrew Tridgell <tridge@samba.org>2009-09-15 18:45:43 -0700
commit03d0005b250ebd7e632e5cd5cbb8e76fceb1bbee (patch)
treee4feb54e37c0d4e0c6250b71bb1ac6e04495bf64
parent458dda1f15db3db674cf8846b3c08340378a29a8 (diff)
downloadsamba-03d0005b250ebd7e632e5cd5cbb8e76fceb1bbee.tar.gz
samba-03d0005b250ebd7e632e5cd5cbb8e76fceb1bbee.tar.bz2
samba-03d0005b250ebd7e632e5cd5cbb8e76fceb1bbee.zip
s4-ldb: expose ldb_transaction_prepare_commit() in ldb
It is useful to be able to control the 2 phase commit from application code (s4 replication uses it)
-rw-r--r--source4/lib/ldb/common/ldb.c78
-rw-r--r--source4/lib/ldb/include/ldb.h5
-rw-r--r--source4/lib/ldb/include/ldb_private.h2
3 files changed, 64 insertions, 21 deletions
diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c
index 6939cefb59..613451a7c2 100644
--- a/source4/lib/ldb/common/ldb.c
+++ b/source4/lib/ldb/common/ldb.c
@@ -316,6 +316,7 @@ int ldb_transaction_start(struct ldb_context *ldb)
/* start a new transaction */
ldb->transaction_active++;
+ ldb->prepare_commit_done = false;
FIRST_OP(ldb, start_transaction);
@@ -335,6 +336,57 @@ int ldb_transaction_start(struct ldb_context *ldb)
}
/*
+ prepare for transaction commit (first phase of two phase commit)
+*/
+int ldb_transaction_prepare_commit(struct ldb_context *ldb)
+{
+ struct ldb_module *module;
+ int status;
+
+ if (ldb->prepare_commit_done) {
+ return LDB_SUCCESS;
+ }
+
+ /* commit only when all nested transactions are complete */
+ if (ldb->transaction_active > 1) {
+ return LDB_SUCCESS;
+ }
+
+ ldb->prepare_commit_done = true;
+
+ if (ldb->transaction_active < 0) {
+ ldb_debug(ldb, LDB_DEBUG_FATAL,
+ "prepare commit called but no ldb transactions are active!");
+ ldb->transaction_active = 0;
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* call prepare transaction if available */
+ FIRST_OP_NOERR(ldb, prepare_commit);
+ if (module == NULL) {
+ return LDB_SUCCESS;
+ }
+
+ status = module->ops->prepare_commit(module);
+ if (status != LDB_SUCCESS) {
+ /* if a module fails the prepare then we need
+ to call the end transaction for everyone */
+ FIRST_OP(ldb, end_transaction);
+ module->ops->end_transaction(module);
+ if (ldb->err_string == NULL) {
+ /* no error string was setup by the backend */
+ ldb_asprintf_errstring(ldb,
+ "ldb transaction prepare commit: %s (%d)",
+ ldb_strerror(status),
+ status);
+ }
+ }
+
+ return status;
+}
+
+
+/*
commit a transaction
*/
int ldb_transaction_commit(struct ldb_context *ldb)
@@ -342,6 +394,10 @@ int ldb_transaction_commit(struct ldb_context *ldb)
struct ldb_module *module;
int status;
+ status = ldb_transaction_prepare_commit(ldb);
+ if (status != LDB_SUCCESS) {
+ return status;
+ }
ldb->transaction_active--;
@@ -361,27 +417,6 @@ int ldb_transaction_commit(struct ldb_context *ldb)
return LDB_ERR_OPERATIONS_ERROR;
}
- /* call prepare transaction if available */
- FIRST_OP_NOERR(ldb, prepare_commit);
- if (module != NULL) {
- status = module->ops->prepare_commit(module);
- if (status != LDB_SUCCESS) {
- /* if a module fails the prepare then we need
- to call the end transaction for everyone */
- /* preserve err string */
- FIRST_OP(ldb, end_transaction);
- module->ops->end_transaction(module);
- if (ldb->err_string == NULL) {
- /* no error string was setup by the backend */
- ldb_asprintf_errstring(ldb,
- "ldb transaction prepare commit: %s (%d)",
- ldb_strerror(status),
- status);
- }
- return status;
- }
- }
-
ldb_reset_err_string(ldb);
FIRST_OP(ldb, end_transaction);
@@ -401,6 +436,7 @@ int ldb_transaction_commit(struct ldb_context *ldb)
return status;
}
+
/*
cancel a transaction
*/
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index 04b0a22fc1..2c89031919 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -1284,6 +1284,11 @@ int ldb_sequence_number(struct ldb_context *ldb, enum ldb_sequence_type type, ui
int ldb_transaction_start(struct ldb_context *ldb);
/**
+ first phase of two phase commit
+ */
+int ldb_transaction_prepare_commit(struct ldb_context *ldb);
+
+/**
commit a transaction
*/
int ldb_transaction_commit(struct ldb_context *ldb);
diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h
index c12f33495b..1fb3109b1b 100644
--- a/source4/lib/ldb/include/ldb_private.h
+++ b/source4/lib/ldb/include/ldb_private.h
@@ -114,6 +114,8 @@ struct ldb_context {
char *modules_dir;
struct tevent_context *ev_ctx;
+
+ bool prepare_commit_done;
};
/* The following definitions come from lib/ldb/common/ldb.c */