From 356ed8644c0099a70ece5b7d5104662454d03ef8 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Mon, 1 Aug 2011 15:27:46 +0200 Subject: 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 --- source3/include/registry.h | 2 +- source3/registry/reg_api.c | 57 ++++++++++++++++++++-------------- source3/registry/reg_backend_db.c | 8 ++++- source3/registry/reg_backend_smbconf.c | 4 +-- source3/registry/reg_dispatcher.c | 4 +-- source3/registry/reg_dispatcher.h | 2 +- 6 files changed, 47 insertions(+), 30 deletions(-) (limited to 'source3') 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); -- cgit