diff options
author | Volker Lendecke <vl@samba.org> | 2009-02-22 10:11:29 +0100 |
---|---|---|
committer | Michael Adam <obnox@samba.org> | 2009-02-26 11:05:22 +0100 |
commit | 170830c0089088e7e30a3aa2d0c6d65b01ab83a0 (patch) | |
tree | e7c8f52c6671666fb7dea1510d44f8d95f1e83d7 | |
parent | 5c91cdcc47dc22330839113b37d250b472fb0487 (diff) | |
download | samba-170830c0089088e7e30a3aa2d0c6d65b01ab83a0.tar.gz samba-170830c0089088e7e30a3aa2d0c6d65b01ab83a0.tar.xz samba-170830c0089088e7e30a3aa2d0c6d65b01ab83a0.zip |
Wrap creating the sorted subkey cache in a transaction
Signed-off-by: Michael Adam <obnox@samba.org>
-rw-r--r-- | source3/registry/reg_backend_db.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index 344bc4124d..689bd1038e 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -920,9 +920,15 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) int i, res; size_t len; + if (regdb->transaction_start(regdb) != 0) { + DEBUG(0, ("create_sorted_subkeys: transaction_start " + "failed\n")); + return false; + } + ctr = talloc(talloc_tos(), REGSUBKEY_CTR); if (ctr == NULL) { - return false; + goto fail; } res = regdb_fetch_keys(key, ctr); @@ -963,15 +969,37 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) p += strlen(sorted_subkeys[i]) + 1; } - status = dbwrap_trans_store_bystring( + status = dbwrap_store_bystring( regdb, sorted_keyname, make_tdb_data((uint8_t *)buf, len), TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { - goto fail; + /* + * Don't use a "goto fail;" here, this would commit the broken + * transaction. See below for an explanation. + */ + if (regdb->transaction_cancel(regdb) == -1) { + DEBUG(0, ("create_sorted_subkeys: transaction_cancel " + "failed\n")); + } + TALLOC_FREE(ctr); + return false; } result = true; fail: + /* + * We only get here via the "goto fail" when we did not write anything + * yet. Using transaction_commit even in a failure case is necessary + * because this (disposable) call might be nested in other + * transactions. Doing a cancel here would destroy the possibility of + * a transaction_commit for transactions that we might be wrapped in. + */ + if (regdb->transaction_commit(regdb) == -1) { + DEBUG(0, ("create_sorted_subkeys: transaction_start " + "failed\n")); + goto fail; + } + TALLOC_FREE(ctr); return result; } |