From: Michael Adam Date: Fri, 1 Jul 2011 11:37:41 +0000 (+0200) Subject: s3:registry: remove the code to create and search the sorted subkeys cache records X-Git-Url: http://git.samba.org/?p=metze%2Fsamba%2Fwip.git;a=commitdiff_plain;h=50add4091aff69e70263fbb46d30bad8f420759c s3:registry: remove the code to create and search the sorted subkeys cache records This is not needed any more. Pair-Programmed-With: Gregor Beck --- diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index a9e06b30486f..d9204a5a41ee 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -49,7 +49,6 @@ static int regdb_fetch_values_internal(struct db_context *db, const char* key, static bool regdb_store_values_internal(struct db_context *db, const char *key, struct regval_ctr *values); -static NTSTATUS create_sorted_subkeys(const char *key); static WERROR regdb_create_basekey(struct db_context *db, const char *key); static WERROR regdb_create_subkey_internal(struct db_context *db, const char *key, @@ -1314,281 +1313,6 @@ done: return ret; } -/* - * regdb_key_exists() is a very frequent operation. It can be quite - * time-consuming to fully fetch the parent's subkey list, talloc_strdup all - * subkeys and then compare the keyname linearly to all the parent's subkeys. - * - * The following code tries to make this operation as efficient as possible: - * Per registry key we create a list of subkeys that is very efficient to - * search for existence of a subkey. Its format is: - * - * 4 bytes num_subkeys - * 4*num_subkey bytes offset into the string array - * then follows a sorted list of subkeys in uppercase - * - * This record is created by create_sorted_subkeys() on demand if it does not - * exist. scan_parent_subkeys() uses regdb->parse_record to search the sorted - * list, the parsing code and the binary search can be found in - * parent_subkey_scanner. The code uses parse_record() to avoid a memcpy of - * the potentially large subkey record. - * - * The sorted subkey record is deleted in regdb_store_keys_internal2 and - * recreated on demand. - */ - -static int cmp_keynames(char **p1, char **p2) -{ - return strcasecmp_m(*p1, *p2); -} - -struct create_sorted_subkeys_context { - const char *key; - const char *sorted_keyname; -}; - -static NTSTATUS create_sorted_subkeys_action(struct db_context *db, - void *private_data) -{ - char **sorted_subkeys; - struct regsubkey_ctr *ctr; - NTSTATUS status; - char *buf; - char *p; - int i; - size_t len; - int num_subkeys; - struct create_sorted_subkeys_context *sorted_ctx; - - sorted_ctx = (struct create_sorted_subkeys_context *)private_data; - - /* - * In this function, we only treat failing of the actual write to - * the db as a real error. All preliminary errors, at a stage when - * nothing has been written to the DB yet are treated as success - * to be committed (as an empty transaction). - * - * The reason is that 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. - */ - - status = werror_to_ntstatus(regsubkey_ctr_init(talloc_tos(), &ctr)); - if (!NT_STATUS_IS_OK(status)) { - /* don't treat this as an error */ - status = NT_STATUS_OK; - goto done; - } - - status = werror_to_ntstatus(regdb_fetch_keys_internal(db, - sorted_ctx->key, - ctr)); - if (!NT_STATUS_IS_OK(status)) { - /* don't treat this as an error */ - status = NT_STATUS_OK; - goto done; - } - - num_subkeys = regsubkey_ctr_numkeys(ctr); - sorted_subkeys = talloc_array(ctr, char *, num_subkeys); - if (sorted_subkeys == NULL) { - /* don't treat this as an error */ - goto done; - } - - len = 4 + 4*num_subkeys; - - for (i = 0; i < num_subkeys; i++) { - sorted_subkeys[i] = talloc_strdup_upper(sorted_subkeys, - regsubkey_ctr_specific_key(ctr, i)); - if (sorted_subkeys[i] == NULL) { - /* don't treat this as an error */ - goto done; - } - len += strlen(sorted_subkeys[i])+1; - } - - TYPESAFE_QSORT(sorted_subkeys, num_subkeys, cmp_keynames); - - buf = talloc_array(ctr, char, len); - if (buf == NULL) { - /* don't treat this as an error */ - goto done; - } - p = buf + 4 + 4*num_subkeys; - - SIVAL(buf, 0, num_subkeys); - - for (i=0; i < num_subkeys; i++) { - ptrdiff_t offset = p - buf; - SIVAL(buf, 4 + 4*i, offset); - strlcpy(p, sorted_subkeys[i], len-offset); - p += strlen(sorted_subkeys[i]) + 1; - } - - status = dbwrap_store_bystring( - db, sorted_ctx->sorted_keyname, make_tdb_data((uint8_t *)buf, - len), - TDB_REPLACE); - -done: - talloc_free(ctr); - return status; -} - -static NTSTATUS create_sorted_subkeys_internal(const char *key, - const char *sorted_keyname) -{ - NTSTATUS status; - struct create_sorted_subkeys_context sorted_ctx; - - sorted_ctx.key = key; - sorted_ctx.sorted_keyname = sorted_keyname; - - status = dbwrap_trans_do(regdb, - create_sorted_subkeys_action, - &sorted_ctx); - - return status; -} - -static NTSTATUS create_sorted_subkeys(const char *key) -{ - char *sorted_subkeys_keyname; - NTSTATUS status; - - sorted_subkeys_keyname = talloc_asprintf(talloc_tos(), "%s\\%s", - REG_SORTED_SUBKEYS_PREFIX, - key); - if (sorted_subkeys_keyname == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - status = create_sorted_subkeys_internal(key, sorted_subkeys_keyname); - -done: - return status; -} - -struct scan_subkey_state { - char *name; - bool scanned; - bool found; -}; - -static int parent_subkey_scanner(TDB_DATA key, TDB_DATA data, - void *private_data) -{ - struct scan_subkey_state *state = - (struct scan_subkey_state *)private_data; - uint32_t num_subkeys; - uint32_t l, u; - - if (data.dsize < sizeof(uint32_t)) { - return -1; - } - - state->scanned = true; - state->found = false; - - tdb_unpack(data.dptr, data.dsize, "d", &num_subkeys); - - l = 0; - u = num_subkeys; - - while (l < u) { - uint32_t idx = (l+u)/2; - char *s = (char *)data.dptr + IVAL(data.dptr, 4 + 4*idx); - int comparison = strcmp(state->name, s); - - if (comparison < 0) { - u = idx; - } else if (comparison > 0) { - l = idx + 1; - } else { - state->found = true; - return 0; - } - } - return 0; -} - -static bool scan_parent_subkeys(struct db_context *db, const char *parent, - const char *name) -{ - char *path = NULL; - char *key = NULL; - struct scan_subkey_state state = { 0, }; - bool result = false; - int res; - - state.name = NULL; - - path = normalize_reg_path(talloc_tos(), parent); - if (path == NULL) { - goto fail; - } - - key = talloc_asprintf(talloc_tos(), "%s\\%s", - REG_SORTED_SUBKEYS_PREFIX, path); - if (key == NULL) { - goto fail; - } - - state.name = talloc_strdup_upper(talloc_tos(), name); - if (state.name == NULL) { - goto fail; - } - state.scanned = false; - - res = db->parse_record(db, string_term_tdb_data(key), - parent_subkey_scanner, &state); - - if (state.scanned) { - result = state.found; - } else { - NTSTATUS status; - - res = db->transaction_start(db); - if (res != 0) { - DEBUG(0, ("error starting transaction\n")); - goto fail; - } - - DEBUG(2, (__location__ " WARNING: recreating the sorted " - "subkeys cache for key '%s' from scan_parent_subkeys " - "this should not happen (too frequently)...\n", - path)); - - status = create_sorted_subkeys_internal(path, key); - if (!NT_STATUS_IS_OK(status)) { - res = db->transaction_cancel(db); - if (res != 0) { - smb_panic("Failed to cancel transaction."); - } - goto fail; - } - - res = db->parse_record(db, string_term_tdb_data(key), - parent_subkey_scanner, &state); - if ((res == 0) && (state.scanned)) { - result = state.found; - } - - res = db->transaction_commit(db); - if (res != 0) { - DEBUG(0, ("error committing transaction\n")); - result = false; - } - } - - fail: - TALLOC_FREE(path); - TALLOC_FREE(state.name); - return result; -} - /** * Check for the existence of a key. *