diff options
-rw-r--r-- | source4/lib/ldb/common/ldb.c | 37 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb_modules.c | 19 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb_module.h | 1 |
3 files changed, 51 insertions, 6 deletions
diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 38cc0c880b..dc3032643c 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -282,15 +282,20 @@ void ldb_reset_err_string(struct ldb_context *ldb) } } -#define FIRST_OP(ldb, op) do { \ +#define FIRST_OP_NOERR(ldb, op) do { \ module = ldb->modules; \ while (module && module->ops->op == NULL) module = module->next; \ - if (module == NULL) { \ +} while (0) + +#define FIRST_OP(ldb, op) do { \ + FIRST_OP_NOERR(ldb, op); \ + if (module == NULL) { \ ldb_asprintf_errstring(ldb, "unable to find module or backend to handle operation: " #op); \ return LDB_ERR_OPERATIONS_ERROR; \ } \ } while (0) + /* start a transaction */ @@ -337,6 +342,7 @@ int ldb_transaction_commit(struct ldb_context *ldb) struct ldb_module *module; int status; + ldb->transaction_active--; ldb_debug(ldb, LDB_DEBUG_TRACE, @@ -355,10 +361,30 @@ int ldb_transaction_commit(struct ldb_context *ldb) return LDB_ERR_OPERATIONS_ERROR; } - FIRST_OP(ldb, end_transaction); + /* 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); status = module->ops->end_transaction(module); if (status != LDB_SUCCESS) { if (ldb->err_string == NULL) { @@ -368,6 +394,9 @@ int ldb_transaction_commit(struct ldb_context *ldb) ldb_strerror(status), status); } + /* cancel the transaction */ + FIRST_OP(ldb, del_transaction); + module->ops->del_transaction(module); } return status; } @@ -393,7 +422,7 @@ int ldb_transaction_cancel(struct ldb_context *ldb) if (ldb->transaction_active < 0) { ldb_debug(ldb, LDB_DEBUG_FATAL, - "commit called but no ldb transactions are active!"); + "cancel called but no ldb transactions are active!"); ldb->transaction_active = 0; return LDB_ERR_OPERATIONS_ERROR; } diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 05dffd005a..b792daa913 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -472,10 +472,14 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) which makes writing a module simpler, and makes it more likely to keep working when ldb is extended */ -#define FIND_OP(module, op) do { \ - struct ldb_context *ldb = module->ldb; \ +#define FIND_OP_NOERR(module, op) do { \ module = module->next; \ while (module && module->ops->op == NULL) module = module->next; \ +} while (0) + +#define FIND_OP(module, op) do { \ + struct ldb_context *ldb = module->ldb; \ + FIND_OP_NOERR(module, op); \ if (module == NULL) { \ ldb_asprintf_errstring(ldb, "Unable to find backend operation for " #op ); \ return LDB_ERR_OPERATIONS_ERROR; \ @@ -595,6 +599,17 @@ int ldb_next_end_trans(struct ldb_module *module) return module->ops->end_transaction(module); } +int ldb_next_prepare_commit(struct ldb_module *module) +{ + FIND_OP_NOERR(module, prepare_commit); + if (module == NULL) { + /* we are allowed to have no prepare commit in + backends */ + return LDB_SUCCESS; + } + return module->ops->prepare_commit(module); +} + int ldb_next_del_trans(struct ldb_module *module) { FIND_OP(module, del_transaction); diff --git a/source4/lib/ldb/include/ldb_module.h b/source4/lib/ldb/include/ldb_module.h index cc24d8a6c0..1d6329ca2f 100644 --- a/source4/lib/ldb/include/ldb_module.h +++ b/source4/lib/ldb/include/ldb_module.h @@ -127,6 +127,7 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request); int ldb_next_start_trans(struct ldb_module *module); int ldb_next_end_trans(struct ldb_module *module); int ldb_next_del_trans(struct ldb_module *module); +int ldb_next_prepare_commit(struct ldb_module *module); int ldb_next_init(struct ldb_module *module); void ldb_set_errstring(struct ldb_context *ldb, const char *err_string); |