diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/partition.c | 63 | ||||
-rw-r--r-- | source4/lib/ldb/configure.ac | 2 | ||||
-rw-r--r-- | source4/lib/ldb/external/libtdb.m4 | 2 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb_module.h | 1 | ||||
-rw-r--r-- | source4/lib/ldb/ldb.mk | 2 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.c | 33 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.h | 1 | ||||
-rw-r--r-- | source4/min_versions.m4 | 4 |
8 files changed, 87 insertions, 21 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 71a1b8e942..3231f7ab0f 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -73,11 +73,14 @@ static struct partition_context *partition_init_ctx(struct ldb_module *module, s return ac; } -#define PARTITION_FIND_OP(module, op) do { \ - struct ldb_context *ldbctx = module->ldb; \ +#define PARTITION_FIND_OP_NOERROR(module, op) do { \ while (module && module->ops->op == NULL) module = module->next; \ +} while (0) + +#define PARTITION_FIND_OP(module, op) do { \ + PARTITION_FIND_OP_NOERROR(module, op); \ if (module == NULL) { \ - ldb_asprintf_errstring(ldbctx, \ + ldb_asprintf_errstring(module->ldb, \ "Unable to find backend operation for " #op ); \ return LDB_ERR_OPERATIONS_ERROR; \ } \ @@ -654,7 +657,7 @@ static int partition_start_trans(struct ldb_module *module) /* end a transaction */ static int partition_end_trans(struct ldb_module *module) { - int i, ret; + int i, ret, final_ret; struct partition_private_data *data = talloc_get_type(module->private_data, struct partition_private_data); ret = ldb_next_end_trans(module); @@ -662,28 +665,60 @@ static int partition_end_trans(struct ldb_module *module) return ret; } + /* if the backend has a prepare_commit op then use that, to ensure + that all partitions are committed safely together */ + for (i=0; data && data->partitions && data->partitions[i]; i++) { + struct ldb_module *next_end = data->partitions[i]->module; + struct ldb_module *next_prepare = data->partitions[i]->module; + struct ldb_module *next_del = data->partitions[i]->module; + + PARTITION_FIND_OP_NOERROR(next_prepare, prepare_commit); + if (next_prepare == NULL) { + continue; + } + + PARTITION_FIND_OP(next_end, end_transaction); + PARTITION_FIND_OP(next_del, del_transaction); + + if (next_end != next_prepare || next_del != next_end) { + ldb_asprintf_errstring(module->ldb, "ERROR: Mismatch between prepare and commit ops in ldb module"); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = next_prepare->ops->prepare_commit(next_prepare); + if (ret != LDB_SUCCESS) { + /* if one fails, cancel all but this one */ + int j; + for (j=0; data->partitions[j]; j++) { + if (j == i) continue; + next_del = data->partitions[j]->module; + PARTITION_FIND_OP(next_del, del_transaction); + next_del->ops->del_transaction(next_del); + } + ldb_next_del_trans(module); + return ret; + } + } + /* Look at base DN */ /* Figure out which partition it is under */ /* Skip the lot if 'data' isn't here yet (initialistion) */ + final_ret = LDB_SUCCESS; + for (i=0; data && data->partitions && data->partitions[i]; i++) { struct ldb_module *next = data->partitions[i]->module; PARTITION_FIND_OP(next, end_transaction); ret = next->ops->end_transaction(next); if (ret != LDB_SUCCESS) { - /* Back it out, if it fails on one */ - for (i--; i >= 0; i--) { - next = data->partitions[i]->module; - PARTITION_FIND_OP(next, del_transaction); - - next->ops->del_transaction(next); - } - ldb_next_del_trans(module); - return ret; + /* this should only be happening if we had a serious + OS or hardware error */ + ldb_asprintf_errstring(module->ldb, "ERROR: partition commit error"); + final_ret = ret; } } - return LDB_SUCCESS; + return final_ret; } /* delete a transaction */ diff --git a/source4/lib/ldb/configure.ac b/source4/lib/ldb/configure.ac index d61b31afd4..b98cc88537 100644 --- a/source4/lib/ldb/configure.ac +++ b/source4/lib/ldb/configure.ac @@ -11,7 +11,7 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) AC_DEFUN([SMB_EXT_LIB], [echo -n ""]) AC_DEFUN([SMB_ENABLE], [echo -n ""]) -AC_INIT(ldb, 0.9.3) +AC_INIT(ldb, 0.9.4) AC_CONFIG_SRCDIR([common/ldb.c]) AC_LIBREPLACE_ALL_CHECKS diff --git a/source4/lib/ldb/external/libtdb.m4 b/source4/lib/ldb/external/libtdb.m4 index 8c2cab702f..cdfc5ea2fb 100644 --- a/source4/lib/ldb/external/libtdb.m4 +++ b/source4/lib/ldb/external/libtdb.m4 @@ -4,4 +4,4 @@ AC_SUBST(TDB_LIBS) AC_CHECK_HEADER(tdb.h, [AC_CHECK_LIB(tdb, tdb_open, [TDB_LIBS="-ltdb"]) ], - [PKG_CHECK_MODULES(TDB, tdb >= 1.1.0)]) + [PKG_CHECK_MODULES(TDB, tdb >= 1.1.4)]) diff --git a/source4/lib/ldb/include/ldb_module.h b/source4/lib/ldb/include/ldb_module.h index 4e1019184d..e07fd43e27 100644 --- a/source4/lib/ldb/include/ldb_module.h +++ b/source4/lib/ldb/include/ldb_module.h @@ -52,6 +52,7 @@ struct ldb_module_ops { int (*request)(struct ldb_module *, struct ldb_request *); /* match any other operation */ int (*extended)(struct ldb_module *, struct ldb_request *); /* extended operations */ int (*start_transaction)(struct ldb_module *); + int (*prepare_commit)(struct ldb_module *); int (*end_transaction)(struct ldb_module *); int (*del_transaction)(struct ldb_module *); int (*sequence_number)(struct ldb_module *, struct ldb_request *); diff --git a/source4/lib/ldb/ldb.mk b/source4/lib/ldb/ldb.mk index ff8c1f3baf..0589baf5d4 100644 --- a/source4/lib/ldb/ldb.mk +++ b/source4/lib/ldb/ldb.mk @@ -66,7 +66,7 @@ build-python:: ldb.$(SHLIBEXT) pyldb.o: $(ldbdir)/pyldb.c $(CC) $(PICFLAG) -c $(ldbdir)/pyldb.c $(CFLAGS) `$(PYTHON_CONFIG) --cflags` - + ldb.$(SHLIBEXT): pyldb.o $(SHLD) $(SHLD_FLAGS) -o ldb.$(SHLIBEXT) pyldb.o $(LIB_FLAGS) `$(PYTHON_CONFIG) --ldflags` diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 9df62be936..0f84b67afa 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -857,18 +857,46 @@ static int ltdb_start_trans(struct ldb_module *module) return LDB_SUCCESS; } -static int ltdb_end_trans(struct ldb_module *module) +static int ltdb_prepare_commit(struct ldb_module *module) { void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); - ltdb->in_transaction--; + if (ltdb->in_transaction != 1) { + return LDB_SUCCESS; + } if (ltdb_index_transaction_commit(module) != 0) { tdb_transaction_cancel(ltdb->tdb); + ltdb->in_transaction--; + return ltdb_err_map(tdb_error(ltdb->tdb)); + } + + if (tdb_transaction_prepare_commit(ltdb->tdb) != 0) { + ltdb->in_transaction--; return ltdb_err_map(tdb_error(ltdb->tdb)); } + ltdb->prepared_commit = true; + + return LDB_SUCCESS; +} + +static int ltdb_end_trans(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); + + if (!ltdb->prepared_commit) { + int ret = ltdb_prepare_commit(module); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + ltdb->in_transaction--; + ltdb->prepared_commit = false; + if (tdb_transaction_commit(ltdb->tdb) != 0) { return ltdb_err_map(tdb_error(ltdb->tdb)); } @@ -1209,6 +1237,7 @@ static const struct ldb_module_ops ltdb_ops = { .extended = ltdb_handle_request, .start_transaction = ltdb_start_trans, .end_transaction = ltdb_end_trans, + .prepare_commit = ltdb_prepare_commit, .del_transaction = ltdb_del_trans, }; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 5a1c8fee2d..370cd0729b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -30,6 +30,7 @@ struct ltdb_private { bool check_base; struct ltdb_idxptr *idxptr; + bool prepared_commit; }; /* diff --git a/source4/min_versions.m4 b/source4/min_versions.m4 index 1dd3501b99..0469fb827a 100644 --- a/source4/min_versions.m4 +++ b/source4/min_versions.m4 @@ -1,6 +1,6 @@ # Minimum and exact required versions for various libraries # if we use the ones installed in the system. -define(TDB_MIN_VERSION,1.1.3) +define(TDB_MIN_VERSION,1.1.4) define(TALLOC_MIN_VERSION,1.3.0) -define(LDB_REQUIRED_VERSION,0.9.3) +define(LDB_REQUIRED_VERSION,0.9.4) define(TEVENT_REQUIRED_VERSION,0.9.5) |