summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregor Beck <gbeck@sernet.de>2011-08-01 15:27:46 +0200
committerMichael Adam <obnox@samba.org>2011-08-08 15:27:07 +0200
commit356ed8644c0099a70ece5b7d5104662454d03ef8 (patch)
treef74f3763b3167d197adc5a74ab511672218a470c
parentdb06b61a1d3d38140578c004eb9d6cb3243d2870 (diff)
downloadsamba-356ed8644c0099a70ece5b7d5104662454d03ef8.tar.gz
samba-356ed8644c0099a70ece5b7d5104662454d03ef8.tar.bz2
samba-356ed8644c0099a70ece5b7d5104662454d03ef8.zip
s3:registry avoid updating keys which are going to be deleted in
reg_deletekey_recursive this changes the complexity from O(n^2) to O(n) and reduces the time of a 'net conf drop' with 10000 shares from 6min to 1.5s Signed-off-by: Michael Adam <obnox@samba.org>
-rw-r--r--source3/include/registry.h2
-rw-r--r--source3/registry/reg_api.c57
-rw-r--r--source3/registry/reg_backend_db.c8
-rw-r--r--source3/registry/reg_backend_smbconf.c4
-rw-r--r--source3/registry/reg_dispatcher.c4
-rw-r--r--source3/registry/reg_dispatcher.h2
6 files changed, 47 insertions, 30 deletions
diff --git a/source3/include/registry.h b/source3/include/registry.h
index c87b89af7b..f7a537ed0b 100644
--- a/source3/include/registry.h
+++ b/source3/include/registry.h
@@ -45,7 +45,7 @@ struct registry_ops {
int (*fetch_values) ( const char *key, struct regval_ctr *val );
bool (*store_subkeys)( const char *key, struct regsubkey_ctr *subkeys );
WERROR (*create_subkey)(const char *key, const char *subkey);
- WERROR (*delete_subkey)(const char *key, const char *subkey);
+ WERROR (*delete_subkey)(const char *key, const char *subkey, bool lazy);
bool (*store_values)( const char *key, struct regval_ctr *val );
bool (*reg_access_check)( const char *keyname, uint32 requested,
uint32 *granted,
diff --git a/source3/registry/reg_api.c b/source3/registry/reg_api.c
index c66a95e406..289f77df76 100644
--- a/source3/registry/reg_api.c
+++ b/source3/registry/reg_api.c
@@ -606,41 +606,29 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
return err;
}
-WERROR reg_deletekey(struct registry_key *parent, const char *path)
+static WERROR reg_deletekey_internal(TALLOC_CTX *mem_ctx,
+ struct registry_key *parent,
+ const char *path, bool lazy)
{
WERROR err;
char *name, *end;
- struct registry_key *tmp_key, *key;
- TALLOC_CTX *mem_ctx = talloc_stackframe();
-
+ struct registry_key *key;
name = talloc_strdup(mem_ctx, path);
if (name == NULL) {
err = WERR_NOMEM;
goto done;
}
- /* check if the key has subkeys */
- err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
- W_ERROR_NOT_OK_GOTO_DONE(err);
-
- err = fill_subkey_cache(key);
- W_ERROR_NOT_OK_GOTO_DONE(err);
-
- if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
- err = WERR_ACCESS_DENIED;
- goto done;
- }
-
/* no subkeys - proceed with delete */
end = strrchr(name, '\\');
if (end != NULL) {
*end = '\0';
err = reg_openkey(mem_ctx, parent, name,
- KEY_CREATE_SUB_KEY, &tmp_key);
+ KEY_CREATE_SUB_KEY, &key);
W_ERROR_NOT_OK_GOTO_DONE(err);
- parent = tmp_key;
+ parent = key;
name = end+1;
}
@@ -649,13 +637,36 @@ WERROR reg_deletekey(struct registry_key *parent, const char *path)
goto done;
}
- err = delete_reg_subkey(parent->key, name);
+ err = delete_reg_subkey(parent->key, name, lazy);
+
+done:
+ return err;
+}
+
+WERROR reg_deletekey(struct registry_key *parent, const char *path)
+{
+ WERROR err;
+ struct registry_key *key;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+ /* check if the key has subkeys */
+ err = reg_openkey(mem_ctx, parent, path, REG_KEY_READ, &key);
+ W_ERROR_NOT_OK_GOTO_DONE(err);
+
+ err = fill_subkey_cache(key);
+ W_ERROR_NOT_OK_GOTO_DONE(err);
+ if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
+ err = WERR_ACCESS_DENIED;
+ goto done;
+ }
+ err = reg_deletekey_internal(mem_ctx, parent, path, false);
done:
TALLOC_FREE(mem_ctx);
return err;
}
+
WERROR reg_setvalue(struct registry_key *key, const char *name,
const struct registry_value *val)
{
@@ -796,7 +807,7 @@ WERROR reg_deleteallvalues(struct registry_key *key)
*/
static WERROR reg_deletekey_recursive_internal(struct registry_key *parent,
const char *path,
- bool del_key)
+ bool del_key, bool lazy)
{
WERROR werr = WERR_OK;
struct registry_key *key;
@@ -819,13 +830,13 @@ static WERROR reg_deletekey_recursive_internal(struct registry_key *parent,
*/
for (i = regsubkey_ctr_numkeys(key->subkeys) ; i > 0; i--) {
subkey_name = regsubkey_ctr_specific_key(key->subkeys, i-1);
- werr = reg_deletekey_recursive_internal(key, subkey_name, true);
+ werr = reg_deletekey_recursive_internal(key, subkey_name, true, del_key);
W_ERROR_NOT_OK_GOTO_DONE(werr);
}
if (del_key) {
/* now delete the actual key */
- werr = reg_deletekey(parent, path);
+ werr = reg_deletekey_internal(mem_ctx, parent, path, lazy);
}
done:
@@ -847,7 +858,7 @@ static WERROR reg_deletekey_recursive_trans(struct registry_key *parent,
return werr;
}
- werr = reg_deletekey_recursive_internal(parent, path, del_key);
+ werr = reg_deletekey_recursive_internal(parent, path, del_key, false);
if (!W_ERROR_IS_OK(werr)) {
WERROR werr2;
diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c
index 62d482069c..57d6d3980c 100644
--- a/source3/registry/reg_backend_db.c
+++ b/source3/registry/reg_backend_db.c
@@ -1287,6 +1287,7 @@ struct regdb_delete_subkey_context {
const char *key;
const char *subkey;
const char *path;
+ bool lazy;
};
static NTSTATUS regdb_delete_subkey_action(struct db_context *db,
@@ -1302,6 +1303,10 @@ static NTSTATUS regdb_delete_subkey_action(struct db_context *db,
werr = regdb_delete_key_lists(db, delete_ctx->path);
W_ERROR_NOT_OK_GOTO_DONE(werr);
+ if (delete_ctx->lazy) {
+ goto done;
+ }
+
werr = regsubkey_ctr_init(mem_ctx, &subkeys);
W_ERROR_NOT_OK_GOTO_DONE(werr);
@@ -1323,7 +1328,7 @@ done:
return werror_to_ntstatus(werr);
}
-static WERROR regdb_delete_subkey(const char *key, const char *subkey)
+static WERROR regdb_delete_subkey(const char *key, const char *subkey, bool lazy)
{
WERROR werr;
char *path;
@@ -1349,6 +1354,7 @@ static WERROR regdb_delete_subkey(const char *key, const char *subkey)
delete_ctx.key = key;
delete_ctx.subkey = subkey;
delete_ctx.path = path;
+ delete_ctx.lazy = lazy;
werr = ntstatus_to_werror(dbwrap_trans_do(regdb,
regdb_delete_subkey_action,
diff --git a/source3/registry/reg_backend_smbconf.c b/source3/registry/reg_backend_smbconf.c
index 912f5eb1bf..11abb9cc66 100644
--- a/source3/registry/reg_backend_smbconf.c
+++ b/source3/registry/reg_backend_smbconf.c
@@ -42,9 +42,9 @@ static WERROR smbconf_create_subkey(const char *key, const char *subkey)
return regdb_ops.create_subkey(key, subkey);
}
-static WERROR smbconf_delete_subkey(const char *key, const char *subkey)
+static WERROR smbconf_delete_subkey(const char *key, const char *subkey, bool lazy)
{
- return regdb_ops.delete_subkey(key, subkey);
+ return regdb_ops.delete_subkey(key, subkey, lazy);
}
static int smbconf_fetch_values(const char *key, struct regval_ctr *val)
diff --git a/source3/registry/reg_dispatcher.c b/source3/registry/reg_dispatcher.c
index a96047817d..5b52e98e08 100644
--- a/source3/registry/reg_dispatcher.c
+++ b/source3/registry/reg_dispatcher.c
@@ -113,10 +113,10 @@ WERROR create_reg_subkey(struct registry_key_handle *key, const char *subkey)
return WERR_NOT_SUPPORTED;
}
-WERROR delete_reg_subkey(struct registry_key_handle *key, const char *subkey)
+WERROR delete_reg_subkey(struct registry_key_handle *key, const char *subkey, bool lazy)
{
if (key->ops && key->ops->delete_subkey) {
- return key->ops->delete_subkey(key->name, subkey);
+ return key->ops->delete_subkey(key->name, subkey, lazy);
}
return WERR_NOT_SUPPORTED;
diff --git a/source3/registry/reg_dispatcher.h b/source3/registry/reg_dispatcher.h
index c80ba15ec1..ec4474629c 100644
--- a/source3/registry/reg_dispatcher.h
+++ b/source3/registry/reg_dispatcher.h
@@ -25,7 +25,7 @@ bool store_reg_keys(struct registry_key_handle *key,
struct regsubkey_ctr *subkeys);
bool store_reg_values(struct registry_key_handle *key, struct regval_ctr *val);
WERROR create_reg_subkey(struct registry_key_handle *key, const char *subkey);
-WERROR delete_reg_subkey(struct registry_key_handle *key, const char *subkey);
+WERROR delete_reg_subkey(struct registry_key_handle *key, const char *subkey, bool lazy);
int fetch_reg_keys(struct registry_key_handle *key,
struct regsubkey_ctr *subkey_ctr);
int fetch_reg_values(struct registry_key_handle *key, struct regval_ctr *val);