s3:registry: use transaction wrapper in regdb_store_keys_internal().
authorMichael Adam <obnox@samba.org>
Thu, 9 Jul 2009 08:28:29 +0000 (10:28 +0200)
committerMichael Adam <obnox@samba.org>
Wed, 15 Jul 2009 12:01:53 +0000 (14:01 +0200)
Michael

source3/registry/reg_backend_db.c

index 6bf98d4c7564004c702e921e5459a8c09141f004..5c714a40b46f7c36b078121685b929d715e8fd0c 100644 (file)
@@ -725,76 +725,32 @@ done:
  do not currently exist
  ***********************************************************************/
 
-static bool regdb_store_keys_internal(struct db_context *db, const char *key,
-                                     struct regsubkey_ctr *ctr)
+struct regdb_store_keys_context {
+       const char *key;
+       struct regsubkey_ctr *ctr;
+};
+
+static NTSTATUS regdb_store_keys_action(struct db_context *db,
+                                       void *private_data)
 {
-       int num_subkeys, old_num_subkeys, i;
+       struct regdb_store_keys_context *store_ctx;
+       WERROR werr;
+       int num_subkeys, i;
        char *path = NULL;
        struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL;
        char *oldkeyname = NULL;
-       TALLOC_CTX *ctx = talloc_stackframe();
-       WERROR werr;
-       bool ret = false;
-
-       if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) {
-               goto done;
-       }
-
-       /*
-        * fetch a list of the old subkeys so we can determine if anything has
-        * changed
-        */
-
-       werr = regsubkey_ctr_init(ctx, &old_subkeys);
-       if (!W_ERROR_IS_OK(werr)) {
-               DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
-               goto done;
-       }
-
-       regdb_fetch_keys_internal(db, key, old_subkeys);
-
-       num_subkeys = regsubkey_ctr_numkeys(ctr);
-       old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
-       if ((num_subkeys && old_num_subkeys) &&
-           (num_subkeys == old_num_subkeys)) {
-
-               for (i = 0; i < num_subkeys; i++) {
-                       if (strcmp(regsubkey_ctr_specific_key(ctr, i),
-                                  regsubkey_ctr_specific_key(old_subkeys, i))
-                           != 0)
-                       {
-                               break;
-                       }
-               }
-               if (i == num_subkeys) {
-                       /*
-                        * Nothing changed, no point to even start a tdb
-                        * transaction
-                        */
-
-                       ret = true;
-                       goto done;
-               }
-       }
-
-       TALLOC_FREE(old_subkeys);
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (db->transaction_start(db) != 0) {
-               DEBUG(0, ("regdb_store_keys: transaction_start failed\n"));
-               goto done;
-       }
+       store_ctx = (struct regdb_store_keys_context *)private_data;
 
        /*
         * Re-fetch the old keys inside the transaction
         */
 
-       werr = regsubkey_ctr_init(ctx, &old_subkeys);
-       if (!W_ERROR_IS_OK(werr)) {
-               DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
-               goto cancel;
-       }
+       werr = regsubkey_ctr_init(mem_ctx, &old_subkeys);
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
 
-       regdb_fetch_keys_internal(db, key, old_subkeys);
+       regdb_fetch_keys_internal(db, store_ctx->key, old_subkeys);
 
        /*
         * Make the store operation as safe as possible without transactions:
@@ -823,21 +779,22 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,
        for (i=0; i<num_subkeys; i++) {
                oldkeyname = regsubkey_ctr_specific_key(old_subkeys, i);
 
-               if (regsubkey_ctr_key_exists(ctr, oldkeyname)) {
+               if (regsubkey_ctr_key_exists(store_ctx->ctr, oldkeyname)) {
                        /*
                         * It's still around, don't delete
                         */
-
                        continue;
                }
 
-               path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname);
+               path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key,
+                                      oldkeyname);
                if (!path) {
-                       goto cancel;
+                       werr = WERR_NOMEM;
+                       goto done;
                }
 
                werr = regdb_delete_key_lists(db, path);
-               W_ERROR_NOT_OK_GOTO(werr, cancel);
+               W_ERROR_NOT_OK_GOTO_DONE(werr);
 
                TALLOC_FREE(path);
        }
@@ -846,47 +803,41 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,
 
        /* (2) store the subkey list for the parent */
 
-       werr = regdb_store_keys_internal2(db, key, ctr);
+       werr = regdb_store_keys_internal2(db, store_ctx->key, store_ctx->ctr);
        if (!W_ERROR_IS_OK(werr)) {
                DEBUG(0,("regdb_store_keys: Failed to store new subkey list "
-                        "for parent [%s]: %s\n", key, win_errstr(werr)));
-               goto cancel;
+                        "for parent [%s]: %s\n", store_ctx->key,
+                        win_errstr(werr)));
+               goto done;
        }
 
        /* (3) now create records for any subkeys that don't already exist */
 
-       num_subkeys = regsubkey_ctr_numkeys(ctr);
+       num_subkeys = regsubkey_ctr_numkeys(store_ctx->ctr);
 
        if (num_subkeys == 0) {
-               werr = regsubkey_ctr_init(ctx, &subkeys);
-               if (!W_ERROR_IS_OK(werr)) {
-                       DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
-                       goto cancel;
-               }
+               werr = regsubkey_ctr_init(mem_ctx, &subkeys);
+               W_ERROR_NOT_OK_GOTO_DONE(werr);
 
-               werr = regdb_store_keys_internal2(db, key, subkeys);
+               werr = regdb_store_keys_internal2(db, store_ctx->key, subkeys);
                if (!W_ERROR_IS_OK(werr)) {
                        DEBUG(0,("regdb_store_keys: Failed to store "
-                                "new record for key [%s]: %s\n", key,
-                                win_errstr(werr)));
-                       goto cancel;
+                                "new record for key [%s]: %s\n",
+                                store_ctx->key, win_errstr(werr)));
+                       goto done;
                }
                TALLOC_FREE(subkeys);
-
        }
 
        for (i=0; i<num_subkeys; i++) {
-               path = talloc_asprintf(ctx, "%s/%s",
-                                       key,
-                                       regsubkey_ctr_specific_key(ctr, i));
+               path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key,
+                               regsubkey_ctr_specific_key(store_ctx->ctr, i));
                if (!path) {
-                       goto cancel;
-               }
-               werr = regsubkey_ctr_init(ctx, &subkeys);
-               if (!W_ERROR_IS_OK(werr)) {
-                       DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
-                       goto cancel;
+                       werr = WERR_NOMEM;
+                       goto done;
                }
+               werr = regsubkey_ctr_init(mem_ctx, &subkeys);
+               W_ERROR_NOT_OK_GOTO_DONE(werr);
 
                if (regdb_fetch_keys_internal(db, path, subkeys) == -1) {
                        /* create a record with 0 subkeys */
@@ -895,7 +846,7 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,
                                DEBUG(0,("regdb_store_keys: Failed to store "
                                         "new record for key [%s]: %s\n", path,
                                         win_errstr(werr)));
-                               goto cancel;
+                               goto done;
                        }
                }
 
@@ -903,20 +854,75 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,
                TALLOC_FREE(path);
        }
 
-       if (db->transaction_commit(db) != 0) {
-               DEBUG(0, ("regdb_store_keys: Could not commit transaction\n"));
+       werr = WERR_OK;
+
+done:
+       talloc_free(mem_ctx);
+       return werror_to_ntstatus(werr);
+}
+
+static bool regdb_store_keys_internal(struct db_context *db, const char *key,
+                                     struct regsubkey_ctr *ctr)
+{
+       int num_subkeys, old_num_subkeys, i;
+       struct regsubkey_ctr *old_subkeys = NULL;
+       TALLOC_CTX *ctx = talloc_stackframe();
+       WERROR werr;
+       bool ret = false;
+       struct regdb_store_keys_context store_ctx;
+
+       if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) {
                goto done;
        }
 
-       ret = true;
-       goto done;
+       /*
+        * fetch a list of the old subkeys so we can determine if anything has
+        * changed
+        */
 
-cancel:
-       ret = false;
-       if (db->transaction_cancel(db) != 0) {
-               smb_panic("regdb_store_keys: transaction_cancel failed\n");
+       werr = regsubkey_ctr_init(ctx, &old_subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
+               goto done;
        }
 
+       regdb_fetch_keys_internal(db, key, old_subkeys);
+
+       num_subkeys = regsubkey_ctr_numkeys(ctr);
+       old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
+       if ((num_subkeys && old_num_subkeys) &&
+           (num_subkeys == old_num_subkeys)) {
+
+               for (i = 0; i < num_subkeys; i++) {
+                       if (strcmp(regsubkey_ctr_specific_key(ctr, i),
+                                  regsubkey_ctr_specific_key(old_subkeys, i))
+                           != 0)
+                       {
+                               break;
+                       }
+               }
+               if (i == num_subkeys) {
+                       /*
+                        * Nothing changed, no point to even start a tdb
+                        * transaction
+                        */
+
+                       ret = true;
+                       goto done;
+               }
+       }
+
+       TALLOC_FREE(old_subkeys);
+
+       store_ctx.key = key;
+       store_ctx.ctr = ctr;
+
+       werr = ntstatus_to_werror(dbwrap_trans_do(db,
+                                                 regdb_store_keys_action,
+                                                 &store_ctx));
+
+       ret = W_ERROR_IS_OK(werr);
+
 done:
        TALLOC_FREE(ctx);