/*
* Starts a sub transaction if they are supported by the backend
+ * and the ldb connection has not been opened in batch mode.
*/
static int ldb_kv_sub_transaction_start(struct ldb_kv_private *ldb_kv)
{
int ret = LDB_SUCCESS;
+ if (ldb_kv->batch_mode) {
+ return ret;
+ }
+
ret = ldb_kv->kv_ops->begin_nested_write(ldb_kv);
if (ret == LDB_SUCCESS) {
ret = ldb_kv_index_sub_transaction_start(ldb_kv);
/*
* Commits a sub transaction if they are supported by the backend
+ * and the ldb connection has not been opened in batch mode.
*/
static int ldb_kv_sub_transaction_commit(struct ldb_kv_private *ldb_kv)
{
int ret = LDB_SUCCESS;
+ if (ldb_kv->batch_mode) {
+ return ret;
+ }
+
ret = ldb_kv_index_sub_transaction_commit(ldb_kv);
if (ret != LDB_SUCCESS) {
return ret;
/*
* Cancels a sub transaction if they are supported by the backend
+ * and the ldb connection has not been opened in batch mode.
*/
static int ldb_kv_sub_transaction_cancel(struct ldb_kv_private *ldb_kv)
{
int ret = LDB_SUCCESS;
+ if (ldb_kv->batch_mode) {
+ return ret;
+ }
+
ret = ldb_kv_index_sub_transaction_cancel(ldb_kv);
if (ret != LDB_SUCCESS) {
struct ldb_context *ldb = ldb_module_get_ctx(ldb_kv->module);
__location__
": Unable to roll back sub transaction");
}
+ ldb_kv->operation_failed = true;
return ret;
}
ret = ldb_kv_sub_transaction_commit(ldb_kv);
__location__
": Unable to roll back sub transaction");
}
+ if (ret != LDB_ERR_NO_SUCH_OBJECT) {
+ ldb_kv->operation_failed = true;
+ }
return ret;
}
ret = ldb_kv_sub_transaction_commit(ldb_kv);
__location__
": Unable to roll back sub transaction");
}
+ if (ret != LDB_ERR_NO_SUCH_OBJECT) {
+ ldb_kv->operation_failed = true;
+ }
return ret;
}
ret = ldb_kv_sub_transaction_commit(ldb_kv);
": Unable to roll back sub transaction");
}
talloc_free(msg);
+ ldb_kv->operation_failed = true;
return ret;
}
ret = ldb_kv_sub_transaction_commit(ldb_kv);
ldb_kv->index_transaction_cache_size);
ldb_kv->reindex_failed = false;
+ ldb_kv->operation_failed = false;
return LDB_SUCCESS;
}
struct ldb_kv_private *ldb_kv =
talloc_get_type(data, struct ldb_kv_private);
+ /*
+ * If in batch mode and there has been an operation failure
+ * rollback the transaction rather than committing it to avoid
+ * any possible corruption
+ */
+ if (ldb_kv->batch_mode && ldb_kv->operation_failed) {
+ ret = ldb_kv_del_trans( module);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb_module_get_ctx(module),
+ LDB_DEBUG_FATAL,
+ "An operation failed during a batch mode "
+ "transaction. The transaction could not"
+ "be rolled back, ldb_kv_del_trans "
+ "returned (%s, %s)",
+ ldb_kv->kv_ops->errorstr(ldb_kv),
+ ldb_strerror(ret));
+ } else {
+ ldb_debug_set(ldb_module_get_ctx(module),
+ LDB_DEBUG_FATAL,
+ "An operation failed during a batch mode "
+ "transaction, the transaction was "
+ "rolled back");
+ }
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
if (!ldb_kv->prepared_commit) {
ret = ldb_kv_prepare_commit(module);
if (ret != LDB_SUCCESS) {
}
}
}
+ /*
+ * Set batch mode operation.
+ * This disables the nested sub transactions, and increases the
+ * chance of index corruption. If using this mode the transaction
+ * commit will be aborted if any operation fails.
+ */
+ {
+ const char *batch_mode = ldb_options_find(
+ ldb, options, "batch_mode");
+ if (batch_mode != NULL) {
+ ldb_kv->batch_mode = true;
+ }
+ }
return LDB_SUCCESS;
}