From 03d0005b250ebd7e632e5cd5cbb8e76fceb1bbee Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 15 Sep 2009 14:07:06 -0700 Subject: 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) --- source4/lib/ldb/common/ldb.c | 78 +++++++++++++++++++++++++---------- source4/lib/ldb/include/ldb.h | 5 +++ source4/lib/ldb/include/ldb_private.h | 2 + 3 files changed, 64 insertions(+), 21 deletions(-) (limited to 'source4/lib') 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); @@ -334,6 +335,57 @@ int ldb_transaction_start(struct ldb_context *ldb) return status; } +/* + 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 */ @@ -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 @@ -1283,6 +1283,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 */ 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 */ -- cgit