mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Refactor and simplify isc_symtab
This commit does several changes to isc_symtab: 1. Rewrite the isc_symtab to internally use isc_hashmap instead of hand-stiched hashtable. 2. Create a new isc_symtab_define_and_return() api, which returns the already defined symvalue on ISC_R_EXISTS; this allows users of the API to skip the isc_symtab_lookup()+isc_symtab_define() calls and directly call isc_symtab_define_and_return(). 3. Merge isccc_symtab into isc_symtab - the only missing function was isccc_symtab_foreach() that was merged into isc_symtab API. 4. Add full set of unit tests for the isc_symtab API.
This commit is contained in:
parent
ebf1606f38
commit
53991ecc14
12 changed files with 630 additions and 557 deletions
|
|
@ -112,8 +112,7 @@ add(char *key, int value) {
|
|||
}
|
||||
|
||||
if (symtab == NULL) {
|
||||
isc_symtab_create(sym_mctx, 100, freekey, sym_mctx, false,
|
||||
&symtab);
|
||||
isc_symtab_create(sym_mctx, freekey, sym_mctx, false, &symtab);
|
||||
}
|
||||
|
||||
key = isc_mem_strdup(sym_mctx, key);
|
||||
|
|
|
|||
|
|
@ -31,13 +31,13 @@
|
|||
#include <isc/result.h>
|
||||
#include <isc/stdtime.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/symtab.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <isccc/alist.h>
|
||||
#include <isccc/cc.h>
|
||||
#include <isccc/ccmsg.h>
|
||||
#include <isccc/sexpr.h>
|
||||
#include <isccc/symtab.h>
|
||||
#include <isccc/util.h>
|
||||
|
||||
#include <isccfg/check.h>
|
||||
|
|
@ -108,7 +108,7 @@ struct named_controls {
|
|||
controllistenerlist_t listeners;
|
||||
bool shuttingdown;
|
||||
isc_mutex_t symtab_lock;
|
||||
isccc_symtab_t *symtab;
|
||||
isc_symtab_t *symtab;
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
|
|
@ -1336,7 +1336,6 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
isc_result_t
|
||||
named_controls_create(named_server_t *server, named_controls_t **ctrlsp) {
|
||||
isc_mem_t *mctx = server->mctx;
|
||||
isc_result_t result;
|
||||
named_controls_t *controls = isc_mem_get(mctx, sizeof(*controls));
|
||||
|
||||
*controls = (named_controls_t){
|
||||
|
|
@ -1347,14 +1346,9 @@ named_controls_create(named_server_t *server, named_controls_t **ctrlsp) {
|
|||
|
||||
isc_mutex_init(&controls->symtab_lock);
|
||||
LOCK(&controls->symtab_lock);
|
||||
result = isccc_cc_createsymtab(&controls->symtab);
|
||||
isccc_cc_createsymtab(mctx, &controls->symtab);
|
||||
UNLOCK(&controls->symtab_lock);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mutex_destroy(&controls->symtab_lock);
|
||||
isc_mem_put(server->mctx, controls, sizeof(*controls));
|
||||
return result;
|
||||
}
|
||||
*ctrlsp = controls;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
@ -1368,7 +1362,7 @@ named_controls_destroy(named_controls_t **ctrlsp) {
|
|||
REQUIRE(ISC_LIST_EMPTY(controls->listeners));
|
||||
|
||||
LOCK(&controls->symtab_lock);
|
||||
isccc_symtab_destroy(&controls->symtab);
|
||||
isc_symtab_destroy(&controls->symtab);
|
||||
UNLOCK(&controls->symtab_lock);
|
||||
isc_mutex_destroy(&controls->symtab_lock);
|
||||
isc_mem_put(controls->server->mctx, controls, sizeof(*controls));
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@
|
|||
/*! \file isc/symtab.h
|
||||
* \brief Provides a simple memory-based symbol table.
|
||||
*
|
||||
* Keys are C strings, and key comparisons are case-insensitive. A type may
|
||||
* be specified when looking up, defining, or undefining. A type value of
|
||||
* 0 means "match any type"; any other value will only match the given
|
||||
* type.
|
||||
* Keys are C strings, and key comparisons are either case-insensitive or
|
||||
* case-sensitive (decided when the symtab is created). A type must be
|
||||
* specified when looking up, defining, or undefining.
|
||||
*
|
||||
* It's possible that a client will attempt to define a <key, type, value>
|
||||
* tuple when a tuple with the given key and type already exists in the table.
|
||||
|
|
@ -33,51 +32,25 @@
|
|||
*\li #isc_symexists_replace Replace the old value with the new. The
|
||||
* undefine action (if provided) will be called
|
||||
* with the old <key, type, value> tuple.
|
||||
*\li #isc_symexists_add Add the new tuple, leaving the old tuple in
|
||||
* the table. Subsequent lookups will retrieve
|
||||
* the most-recently-defined tuple.
|
||||
*
|
||||
* A lookup of a key using type 0 will return the most-recently defined
|
||||
* symbol with that key. An undefine of a key using type 0 will undefine the
|
||||
* most-recently defined symbol with that key. Trying to define a key with
|
||||
* type 0 is illegal.
|
||||
*
|
||||
* The symbol table library does not make a copy the key field, so the
|
||||
* caller must ensure that any key it passes to isc_symtab_define() will not
|
||||
* change until it calls isc_symtab_undefine() or isc_symtab_destroy().
|
||||
* The symbol table library does not make a copy the key field, so the caller
|
||||
* must ensure that any key it passes to isc_symtab_define() will not change
|
||||
* or become undefined until it calls isc_symtab_undefine()
|
||||
* or isc_symtab_destroy().
|
||||
*
|
||||
* A user-specified action will be called (if provided) when a symbol is
|
||||
* undefined. It can be used to free memory associated with keys and/or
|
||||
* values.
|
||||
*
|
||||
* A symbol table is implemented as a hash table of lists; the size of the
|
||||
* hash table is set by the 'size' parameter to isc_symtbl_create(). When
|
||||
* the number of entries in the symbol table reaches three quarters of this
|
||||
* value, the hash table is reallocated with size doubled, in order to
|
||||
* optimize lookup performance. This has a negative effect on insertion
|
||||
* performance, which can be mitigated by sizing the table appropriately
|
||||
* when creating it.
|
||||
*
|
||||
* \li MP:
|
||||
* The callers of this module must ensure any required synchronization.
|
||||
*
|
||||
* \li Reliability:
|
||||
* No anticipated impact.
|
||||
*
|
||||
* \li Resources:
|
||||
* TBS
|
||||
*
|
||||
* \li Security:
|
||||
* No anticipated impact.
|
||||
*
|
||||
* \li Standards:
|
||||
* None.
|
||||
* A symbol table is implemented as a isc_hashmap; the bits of the
|
||||
* hashmap is set by the 'size' parameter to isc_symtbl_create().
|
||||
*/
|
||||
|
||||
/***
|
||||
*** Imports.
|
||||
***/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/types.h>
|
||||
|
|
@ -87,45 +60,120 @@
|
|||
***/
|
||||
/*% Symbol table value. */
|
||||
typedef union isc_symvalue {
|
||||
void *as_pointer;
|
||||
const void *as_cpointer;
|
||||
int as_integer;
|
||||
unsigned int as_uinteger;
|
||||
void *as_pointer;
|
||||
const void *as_cpointer;
|
||||
intmax_t as_integer;
|
||||
uintmax_t as_uinteger;
|
||||
} isc_symvalue_t;
|
||||
|
||||
typedef void (*isc_symtabaction_t)(char *key, unsigned int type,
|
||||
isc_symvalue_t value, void *userarg);
|
||||
|
||||
typedef bool (*isc_symtabforeachaction_t)(char *key, unsigned int type,
|
||||
isc_symvalue_t value, void *userarg);
|
||||
|
||||
/*% Symbol table exists. */
|
||||
typedef enum {
|
||||
isc_symexists_reject = 0, /*%< Disallow the define */
|
||||
isc_symexists_replace = 1, /*%< Replace the old value with the new */
|
||||
isc_symexists_add = 2 /*%< Add the new tuple */
|
||||
} isc_symexists_t;
|
||||
|
||||
/*% Create a symbol table. */
|
||||
void
|
||||
isc_symtab_create(isc_mem_t *mctx, unsigned int size,
|
||||
isc_symtabaction_t undefine_action, void *undefine_arg,
|
||||
bool case_sensitive, isc_symtab_t **symtabp);
|
||||
isc_symtab_create(isc_mem_t *mctx, isc_symtabaction_t undefine_action,
|
||||
void *undefine_arg, bool case_sensitive,
|
||||
isc_symtab_t **symtabp);
|
||||
/*!<
|
||||
* \brief Create a symbol table.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'mctx' is valid memory context
|
||||
* \li 'symtabp' is not NULL, `*symtabp' is NULL
|
||||
*/
|
||||
|
||||
/*% Destroy a symbol table. */
|
||||
void
|
||||
isc_symtab_destroy(isc_symtab_t **symtabp);
|
||||
/*!<
|
||||
* \brief Destroy a symbol table.
|
||||
*
|
||||
* Requires:
|
||||
* \li '*symtabp' is a valid symbol table
|
||||
*/
|
||||
|
||||
/*% Lookup a symbol table. */
|
||||
isc_result_t
|
||||
isc_symtab_lookup(isc_symtab_t *symtab, const char *key, unsigned int type,
|
||||
isc_symvalue_t *value);
|
||||
isc_symvalue_t *found);
|
||||
/*!<
|
||||
* \brief Lookup a symbol table.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'symtab' is a valid symbol table
|
||||
* \li 'key' is a valid C-string
|
||||
* \li 'type' is not 0
|
||||
* \li 'found' is either NULL or a pointer to isc_symvalue_t
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS Symbol has been deleted from the symbol table
|
||||
* \li #ISC_R_NOTFOUND Symbol not found in the symbol table
|
||||
*
|
||||
* Note:
|
||||
* \li On success, if '*found' is not-NULL, it will be filled with value found
|
||||
*/
|
||||
|
||||
/*% Define a symbol table. */
|
||||
isc_result_t
|
||||
isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
|
||||
isc_symvalue_t value, isc_symexists_t exists_policy);
|
||||
|
||||
/*% Undefine a symbol table. */
|
||||
isc_result_t
|
||||
isc_symtab_define_and_return(isc_symtab_t *symtab, const char *key,
|
||||
unsigned int type, isc_symvalue_t value,
|
||||
isc_symexists_t exists_policy,
|
||||
isc_symvalue_t *found);
|
||||
/*!<
|
||||
* \brief Define a symbol table.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'symtab' is a valid symbol table
|
||||
* \li 'key' is a valid C-string
|
||||
* \li 'type' is not 0
|
||||
* \li 'exists_policy' is valid isc_symexist_t value
|
||||
* \li 'found' is either NULL or a pointer to isc_symvalue_t
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS Symbol added to the symbol table
|
||||
* \li #ISC_R_EXISTS Symbol already defined in the symbol table
|
||||
*
|
||||
* Note:
|
||||
* \li On success, if '*found' is not-NULL, it will be filled with value added
|
||||
* \li On exists, if '*found' is not-NULL, it will be fileed with value found
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type);
|
||||
/*!<
|
||||
* \brief Undefine a symbol table.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'symtab' is a valid symbol table
|
||||
* \li 'key' is a valid C-string
|
||||
* \li 'type' is not 0
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS Symbol has been deleted from the symbol table
|
||||
* \li #ISC_R_NOTFOUND Symbol not found in the symbol table
|
||||
*/
|
||||
|
||||
/*% Return the number of items in a symbol table. */
|
||||
unsigned int
|
||||
isc_symtab_count(isc_symtab_t *symtab);
|
||||
/*!<
|
||||
* \brief Return the number of items in a symbol table.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'symtab' is a valid symbol table
|
||||
*
|
||||
* Returns:
|
||||
* \li number of items in a symbol table
|
||||
*/
|
||||
|
||||
void
|
||||
isc_symtab_foreach(isc_symtab_t *symtab, isc_symtabforeachaction_t action,
|
||||
void *arg);
|
||||
|
|
|
|||
363
lib/isc/symtab.c
363
lib/isc/symtab.c
|
|
@ -16,6 +16,8 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include <isc/ascii.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/hashmap.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/string.h>
|
||||
|
|
@ -23,233 +25,205 @@
|
|||
#include <isc/util.h>
|
||||
|
||||
typedef struct elt {
|
||||
char *key;
|
||||
void *key;
|
||||
size_t size;
|
||||
unsigned int type;
|
||||
isc_symvalue_t value;
|
||||
LINK(struct elt) link;
|
||||
} elt_t;
|
||||
|
||||
typedef LIST(elt_t) eltlist_t;
|
||||
|
||||
#define SYMTAB_MAGIC ISC_MAGIC('S', 'y', 'm', 'T')
|
||||
#define VALID_SYMTAB(st) ISC_MAGIC_VALID(st, SYMTAB_MAGIC)
|
||||
/* 7 bits means 128 entries at creation, which matches the common use of
|
||||
* symtab */
|
||||
#define ISC_SYMTAB_INIT_HASH_BITS 7
|
||||
#define SYMTAB_MAGIC ISC_MAGIC('S', 'y', 'm', 'T')
|
||||
#define VALID_SYMTAB(st) ISC_MAGIC_VALID(st, SYMTAB_MAGIC)
|
||||
|
||||
struct isc_symtab {
|
||||
/* Unlocked. */
|
||||
unsigned int magic;
|
||||
isc_mem_t *mctx;
|
||||
unsigned int size;
|
||||
unsigned int count;
|
||||
unsigned int maxload;
|
||||
eltlist_t *table;
|
||||
isc_symtabaction_t undefine_action;
|
||||
void *undefine_arg;
|
||||
|
||||
isc_hashmap_t *hashmap;
|
||||
bool case_sensitive;
|
||||
};
|
||||
|
||||
void
|
||||
isc_symtab_create(isc_mem_t *mctx, unsigned int size,
|
||||
isc_symtabaction_t undefine_action, void *undefine_arg,
|
||||
bool case_sensitive, isc_symtab_t **symtabp) {
|
||||
isc_symtab_t *symtab;
|
||||
unsigned int i;
|
||||
static void
|
||||
elt_destroy(isc_symtab_t *symtab, elt_t *elt) {
|
||||
if (symtab->undefine_action != NULL) {
|
||||
(symtab->undefine_action)(elt->key, elt->type, elt->value,
|
||||
symtab->undefine_arg);
|
||||
}
|
||||
isc_mem_put(symtab->mctx, elt, sizeof(*elt));
|
||||
}
|
||||
|
||||
void
|
||||
isc_symtab_create(isc_mem_t *mctx, isc_symtabaction_t undefine_action,
|
||||
void *undefine_arg, bool case_sensitive,
|
||||
isc_symtab_t **symtabp) {
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(symtabp != NULL && *symtabp == NULL);
|
||||
REQUIRE(size > 0); /* Should be prime. */
|
||||
|
||||
symtab = isc_mem_get(mctx, sizeof(*symtab));
|
||||
isc_symtab_t *symtab = isc_mem_get(mctx, sizeof(*symtab));
|
||||
*symtab = (isc_symtab_t){
|
||||
.undefine_action = undefine_action,
|
||||
.undefine_arg = undefine_arg,
|
||||
.case_sensitive = case_sensitive,
|
||||
.magic = SYMTAB_MAGIC,
|
||||
};
|
||||
|
||||
symtab->mctx = NULL;
|
||||
isc_mem_attach(mctx, &symtab->mctx);
|
||||
symtab->table = isc_mem_cget(mctx, size, sizeof(eltlist_t));
|
||||
for (i = 0; i < size; i++) {
|
||||
INIT_LIST(symtab->table[i]);
|
||||
}
|
||||
symtab->size = size;
|
||||
symtab->count = 0;
|
||||
symtab->maxload = size * 3 / 4;
|
||||
symtab->undefine_action = undefine_action;
|
||||
symtab->undefine_arg = undefine_arg;
|
||||
symtab->case_sensitive = case_sensitive;
|
||||
symtab->magic = SYMTAB_MAGIC;
|
||||
isc_hashmap_create(symtab->mctx, ISC_SYMTAB_INIT_HASH_BITS,
|
||||
&symtab->hashmap);
|
||||
|
||||
*symtabp = symtab;
|
||||
}
|
||||
|
||||
void
|
||||
isc_symtab_destroy(isc_symtab_t **symtabp) {
|
||||
isc_symtab_t *symtab;
|
||||
unsigned int i;
|
||||
elt_t *elt, *nelt;
|
||||
REQUIRE(symtabp != NULL && VALID_SYMTAB(*symtabp));
|
||||
|
||||
REQUIRE(symtabp != NULL);
|
||||
symtab = *symtabp;
|
||||
isc_result_t result;
|
||||
isc_hashmap_iter_t *it = NULL;
|
||||
isc_symtab_t *symtab = *symtabp;
|
||||
*symtabp = NULL;
|
||||
REQUIRE(VALID_SYMTAB(symtab));
|
||||
|
||||
for (i = 0; i < symtab->size; i++) {
|
||||
for (elt = HEAD(symtab->table[i]); elt != NULL; elt = nelt) {
|
||||
nelt = NEXT(elt, link);
|
||||
if (symtab->undefine_action != NULL) {
|
||||
(symtab->undefine_action)(elt->key, elt->type,
|
||||
elt->value,
|
||||
symtab->undefine_arg);
|
||||
}
|
||||
isc_mem_put(symtab->mctx, elt, sizeof(*elt));
|
||||
}
|
||||
}
|
||||
isc_mem_cput(symtab->mctx, symtab->table, symtab->size,
|
||||
sizeof(eltlist_t));
|
||||
symtab->magic = 0;
|
||||
|
||||
isc_hashmap_iter_create(symtab->hashmap, &it);
|
||||
for (result = isc_hashmap_iter_first(it); result == ISC_R_SUCCESS;
|
||||
result = isc_hashmap_iter_delcurrent_next(it))
|
||||
{
|
||||
elt_t *elt = NULL;
|
||||
isc_hashmap_iter_current(it, (void **)&elt);
|
||||
elt_destroy(symtab, elt);
|
||||
}
|
||||
INSIST(result == ISC_R_NOMORE);
|
||||
isc_hashmap_iter_destroy(&it);
|
||||
|
||||
isc_hashmap_destroy(&symtab->hashmap);
|
||||
|
||||
isc_mem_putanddetach(&symtab->mctx, symtab, sizeof(*symtab));
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hash(const char *key, bool case_sensitive) {
|
||||
const char *s;
|
||||
unsigned int h = 0;
|
||||
static bool
|
||||
elt__match(void *node, const void *key0, bool case_sensitive) {
|
||||
const elt_t *elt = node;
|
||||
const elt_t *key = key0;
|
||||
|
||||
/*
|
||||
* This hash function is similar to the one Ousterhout
|
||||
* uses in Tcl.
|
||||
*/
|
||||
if (elt->size != key->size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (elt->type != key->type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (case_sensitive) {
|
||||
for (s = key; *s != '\0'; s++) {
|
||||
h += (h << 3) + *s;
|
||||
}
|
||||
return memcmp(elt->key, key->key, key->size) == 0;
|
||||
} else {
|
||||
for (s = key; *s != '\0'; s++) {
|
||||
h += (h << 3) + isc_ascii_tolower(*s);
|
||||
}
|
||||
return isc_ascii_lowercmp(elt->key, key->key, key->size) == 0;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
#define FIND(s, k, t, b, e) \
|
||||
b = hash((k), (s)->case_sensitive) % (s)->size; \
|
||||
if ((s)->case_sensitive) { \
|
||||
for (e = HEAD((s)->table[b]); e != NULL; e = NEXT(e, link)) { \
|
||||
if (((t) == 0 || e->type == (t)) && \
|
||||
strcmp(e->key, (k)) == 0) \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
for (e = HEAD((s)->table[b]); e != NULL; e = NEXT(e, link)) { \
|
||||
if (((t) == 0 || e->type == (t)) && \
|
||||
strcasecmp(e->key, (k)) == 0) \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
static bool
|
||||
elt_match_case(void *node, const void *key) {
|
||||
return elt__match(node, key, true);
|
||||
}
|
||||
|
||||
static bool
|
||||
elt_match_nocase(void *node, const void *key) {
|
||||
return elt__match(node, key, false);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
elt_hash(elt_t *elt, bool case_sensitive) {
|
||||
isc_hash32_t hash;
|
||||
|
||||
isc_hash32_init(&hash);
|
||||
isc_hash32_hash(&hash, elt->key, elt->size, case_sensitive);
|
||||
isc_hash32_hash(&hash, &elt->type, sizeof(elt->type), false);
|
||||
return isc_hash32_finalize(&hash);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_symtab_lookup(isc_symtab_t *symtab, const char *key, unsigned int type,
|
||||
isc_symvalue_t *value) {
|
||||
unsigned int bucket;
|
||||
elt_t *elt;
|
||||
|
||||
isc_symvalue_t *valuep) {
|
||||
REQUIRE(VALID_SYMTAB(symtab));
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(type != 0);
|
||||
|
||||
FIND(symtab, key, type, bucket, elt);
|
||||
elt_t *found = NULL;
|
||||
elt_t elt = {
|
||||
.key = UNCONST(key),
|
||||
.size = strlen(key),
|
||||
.type = type,
|
||||
};
|
||||
uint32_t elt_hashval = elt_hash(&elt, symtab->case_sensitive);
|
||||
isc_hashmap_match_fn elt_match = symtab->case_sensitive
|
||||
? elt_match_case
|
||||
: elt_match_nocase;
|
||||
isc_result_t result = isc_hashmap_find(
|
||||
symtab->hashmap, elt_hashval, elt_match, &elt, (void **)&found);
|
||||
|
||||
if (elt == NULL) {
|
||||
return ISC_R_NOTFOUND;
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
SET_IF_NOT_NULL(valuep, found->value);
|
||||
}
|
||||
|
||||
SET_IF_NOT_NULL(value, elt->value);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
grow_table(isc_symtab_t *symtab) {
|
||||
eltlist_t *newtable;
|
||||
unsigned int i, newsize, newmax;
|
||||
|
||||
REQUIRE(symtab != NULL);
|
||||
|
||||
newsize = symtab->size * 2;
|
||||
newmax = newsize * 3 / 4;
|
||||
INSIST(newsize > 0U && newmax > 0U);
|
||||
|
||||
newtable = isc_mem_cget(symtab->mctx, newsize, sizeof(eltlist_t));
|
||||
|
||||
for (i = 0; i < newsize; i++) {
|
||||
INIT_LIST(newtable[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < symtab->size; i++) {
|
||||
elt_t *elt, *nelt;
|
||||
|
||||
for (elt = HEAD(symtab->table[i]); elt != NULL; elt = nelt) {
|
||||
unsigned int hv;
|
||||
|
||||
nelt = NEXT(elt, link);
|
||||
|
||||
UNLINK(symtab->table[i], elt, link);
|
||||
hv = hash(elt->key, symtab->case_sensitive);
|
||||
APPEND(newtable[hv % newsize], elt, link);
|
||||
}
|
||||
}
|
||||
|
||||
isc_mem_cput(symtab->mctx, symtab->table, symtab->size,
|
||||
sizeof(eltlist_t));
|
||||
|
||||
symtab->table = newtable;
|
||||
symtab->size = newsize;
|
||||
symtab->maxload = newmax;
|
||||
return result;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
|
||||
isc_symvalue_t value, isc_symexists_t exists_policy) {
|
||||
unsigned int bucket;
|
||||
elt_t *elt;
|
||||
return isc_symtab_define_and_return(symtab, key, type, value,
|
||||
exists_policy, NULL);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_symtab_define_and_return(isc_symtab_t *symtab, const char *key,
|
||||
unsigned int type, isc_symvalue_t value,
|
||||
isc_symexists_t exists_policy,
|
||||
isc_symvalue_t *valuep) {
|
||||
REQUIRE(VALID_SYMTAB(symtab));
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(type != 0);
|
||||
|
||||
FIND(symtab, key, type, bucket, elt);
|
||||
isc_result_t result;
|
||||
elt_t *found = NULL;
|
||||
elt_t *elt = isc_mem_get(symtab->mctx, sizeof(*elt));
|
||||
*elt = (elt_t){
|
||||
.key = UNCONST(key),
|
||||
.size = strlen(key),
|
||||
.type = type,
|
||||
.value = value,
|
||||
};
|
||||
uint32_t elt_hashval = elt_hash(elt, symtab->case_sensitive);
|
||||
isc_hashmap_match_fn elt_match = symtab->case_sensitive
|
||||
? elt_match_case
|
||||
: elt_match_nocase;
|
||||
again:
|
||||
result = isc_hashmap_add(symtab->hashmap, elt_hashval, elt_match, elt,
|
||||
(void *)elt, (void *)&found);
|
||||
|
||||
if (exists_policy != isc_symexists_add && elt != NULL) {
|
||||
if (exists_policy == isc_symexists_reject) {
|
||||
return ISC_R_EXISTS;
|
||||
}
|
||||
INSIST(exists_policy == isc_symexists_replace);
|
||||
UNLINK(symtab->table[bucket], elt, link);
|
||||
if (symtab->undefine_action != NULL) {
|
||||
(symtab->undefine_action)(elt->key, elt->type,
|
||||
elt->value,
|
||||
symtab->undefine_arg);
|
||||
}
|
||||
} else {
|
||||
elt = isc_mem_get(symtab->mctx, sizeof(*elt));
|
||||
ISC_LINK_INIT(elt, link);
|
||||
symtab->count++;
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
SET_IF_NOT_NULL(valuep, elt->value);
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Though the "key" can be const coming in, it is not stored as const
|
||||
* so that the calling program can easily have writable access to
|
||||
* it in its undefine_action function. In the event that it *was*
|
||||
* truly const coming in and then the caller modified it anyway ...
|
||||
* well, don't do that!
|
||||
*/
|
||||
elt->key = UNCONST(key);
|
||||
elt->type = type;
|
||||
elt->value = value;
|
||||
|
||||
/*
|
||||
* We prepend so that the most recent definition will be found.
|
||||
*/
|
||||
PREPEND(symtab->table[bucket], elt, link);
|
||||
|
||||
if (symtab->count > symtab->maxload) {
|
||||
grow_table(symtab);
|
||||
switch (exists_policy) {
|
||||
case isc_symexists_reject:
|
||||
SET_IF_NOT_NULL(valuep, found->value);
|
||||
isc_mem_put(symtab->mctx, elt, sizeof(*elt));
|
||||
return ISC_R_EXISTS;
|
||||
case isc_symexists_replace:
|
||||
result = isc_hashmap_delete(symtab->hashmap, elt_hashval,
|
||||
elt_match, elt);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
elt_destroy(symtab, found);
|
||||
goto again;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
|
|
@ -257,25 +231,33 @@ isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
|
|||
|
||||
isc_result_t
|
||||
isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type) {
|
||||
unsigned int bucket;
|
||||
elt_t *elt;
|
||||
|
||||
REQUIRE(VALID_SYMTAB(symtab));
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(type != 0);
|
||||
|
||||
FIND(symtab, key, type, bucket, elt);
|
||||
elt_t *found = NULL;
|
||||
elt_t elt = {
|
||||
.key = UNCONST(key),
|
||||
.size = strlen(key),
|
||||
.type = type,
|
||||
};
|
||||
uint32_t elt_hashval = elt_hash(&elt, symtab->case_sensitive);
|
||||
isc_hashmap_match_fn elt_match = symtab->case_sensitive
|
||||
? elt_match_case
|
||||
: elt_match_nocase;
|
||||
|
||||
if (elt == NULL) {
|
||||
isc_result_t result = isc_hashmap_find(
|
||||
symtab->hashmap, elt_hashval, elt_match, &elt, (void **)&found);
|
||||
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
if (symtab->undefine_action != NULL) {
|
||||
(symtab->undefine_action)(elt->key, elt->type, elt->value,
|
||||
symtab->undefine_arg);
|
||||
}
|
||||
UNLINK(symtab->table[bucket], elt, link);
|
||||
isc_mem_put(symtab->mctx, elt, sizeof(*elt));
|
||||
symtab->count--;
|
||||
result = isc_hashmap_delete(symtab->hashmap, elt_hashval, elt_match,
|
||||
&elt);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
elt_destroy(symtab, found);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
@ -283,5 +265,30 @@ isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type) {
|
|||
unsigned int
|
||||
isc_symtab_count(isc_symtab_t *symtab) {
|
||||
REQUIRE(VALID_SYMTAB(symtab));
|
||||
return symtab->count;
|
||||
|
||||
return isc_hashmap_count(symtab->hashmap);
|
||||
}
|
||||
|
||||
void
|
||||
isc_symtab_foreach(isc_symtab_t *symtab, isc_symtabforeachaction_t action,
|
||||
void *arg) {
|
||||
REQUIRE(VALID_SYMTAB(symtab));
|
||||
REQUIRE(action != NULL);
|
||||
|
||||
isc_result_t result;
|
||||
isc_hashmap_iter_t *it = NULL;
|
||||
|
||||
isc_hashmap_iter_create(symtab->hashmap, &it);
|
||||
for (result = isc_hashmap_iter_first(it); result == ISC_R_SUCCESS;) {
|
||||
elt_t *elt = NULL;
|
||||
isc_hashmap_iter_current(it, (void **)&elt);
|
||||
if ((action)(elt->key, elt->type, elt->value, arg)) {
|
||||
elt_destroy(symtab, elt);
|
||||
result = isc_hashmap_iter_delcurrent_next(it);
|
||||
} else {
|
||||
result = isc_hashmap_iter_next(it);
|
||||
}
|
||||
}
|
||||
INSIST(result == ISC_R_NOMORE);
|
||||
isc_hashmap_iter_destroy(&it);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ libisccc_la_HEADERS = \
|
|||
include/isccc/cc.h \
|
||||
include/isccc/ccmsg.h \
|
||||
include/isccc/sexpr.h \
|
||||
include/isccc/symtab.h \
|
||||
include/isccc/symtype.h \
|
||||
include/isccc/types.h \
|
||||
include/isccc/util.h
|
||||
|
|
@ -20,8 +19,7 @@ libisccc_la_SOURCES = \
|
|||
base64.c \
|
||||
cc.c \
|
||||
ccmsg.c \
|
||||
sexpr.c \
|
||||
symtab.c
|
||||
sexpr.c
|
||||
|
||||
libisccc_la_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@
|
|||
#include <isc/hmac.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/safe.h>
|
||||
#include <isc/symtab.h>
|
||||
|
||||
#include <isccc/alist.h>
|
||||
#include <isccc/base64.h>
|
||||
#include <isccc/cc.h>
|
||||
#include <isccc/sexpr.h>
|
||||
#include <isccc/symtab.h>
|
||||
#include <isccc/symtype.h>
|
||||
#include <isccc/util.h>
|
||||
|
||||
|
|
@ -938,8 +938,7 @@ isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key, uint32_t *uintp) {
|
|||
}
|
||||
|
||||
static void
|
||||
symtab_undefine(char *key, unsigned int type, isccc_symvalue_t value,
|
||||
void *arg) {
|
||||
symtab_undefine(char *key, unsigned int type, isc_symvalue_t value, void *arg) {
|
||||
UNUSED(type);
|
||||
UNUSED(value);
|
||||
UNUSED(arg);
|
||||
|
|
@ -948,7 +947,7 @@ symtab_undefine(char *key, unsigned int type, isccc_symvalue_t value,
|
|||
}
|
||||
|
||||
static bool
|
||||
symtab_clean(char *key, unsigned int type, isccc_symvalue_t value, void *arg) {
|
||||
symtab_clean(char *key, unsigned int type, isc_symvalue_t value, void *arg) {
|
||||
isccc_time_t *now;
|
||||
|
||||
UNUSED(key);
|
||||
|
|
@ -965,15 +964,14 @@ symtab_clean(char *key, unsigned int type, isccc_symvalue_t value, void *arg) {
|
|||
return true;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isccc_cc_createsymtab(isccc_symtab_t **symtabp) {
|
||||
return isccc_symtab_create(11897, symtab_undefine, NULL, false,
|
||||
symtabp);
|
||||
void
|
||||
isccc_cc_createsymtab(isc_mem_t *mctx, isc_symtab_t **symtabp) {
|
||||
isc_symtab_create(mctx, symtab_undefine, NULL, false, symtabp);
|
||||
}
|
||||
|
||||
void
|
||||
isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now) {
|
||||
isccc_symtab_foreach(symtab, symtab_clean, &now);
|
||||
isccc_cc_cleansymtab(isc_symtab_t *symtab, isccc_time_t now) {
|
||||
isc_symtab_foreach(symtab, symtab_clean, &now);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -992,7 +990,7 @@ has_whitespace(const char *str) {
|
|||
}
|
||||
|
||||
isc_result_t
|
||||
isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message,
|
||||
isccc_cc_checkdup(isc_symtab_t *symtab, isccc_sexpr_t *message,
|
||||
isccc_time_t now) {
|
||||
const char *_frm;
|
||||
const char *_to;
|
||||
|
|
@ -1000,7 +998,7 @@ isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message,
|
|||
isc_result_t result;
|
||||
char *key;
|
||||
size_t len;
|
||||
isccc_symvalue_t value;
|
||||
isc_symvalue_t value;
|
||||
isccc_sexpr_t *_ctrl;
|
||||
|
||||
_ctrl = isccc_alist_lookup(message, "_ctrl");
|
||||
|
|
@ -1047,8 +1045,8 @@ isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message,
|
|||
}
|
||||
snprintf(key, len, "%s;%s;%s;%s", _frm, _to, _ser, _tim);
|
||||
value.as_uinteger = now;
|
||||
result = isccc_symtab_define(symtab, key, ISCCC_SYMTYPE_CCDUP, value,
|
||||
isccc_symexists_reject);
|
||||
result = isc_symtab_define(symtab, key, ISCCC_SYMTYPE_CCDUP, value,
|
||||
isc_symexists_reject);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
free(key);
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/symtab.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
|
|
@ -114,14 +115,14 @@ isc_result_t
|
|||
isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key, uint32_t *uintp);
|
||||
|
||||
/*% Create Symbol Table */
|
||||
isc_result_t
|
||||
isccc_cc_createsymtab(isccc_symtab_t **symtabp);
|
||||
void
|
||||
isccc_cc_createsymtab(isc_mem_t *mctx, isc_symtab_t **symtabp);
|
||||
|
||||
/*% Clean up Symbol Table */
|
||||
void
|
||||
isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now);
|
||||
isccc_cc_cleansymtab(isc_symtab_t *symtab, isccc_time_t now);
|
||||
|
||||
/*% Check for Duplicates */
|
||||
isc_result_t
|
||||
isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message,
|
||||
isccc_cc_checkdup(isc_symtab_t *symtab, isccc_sexpr_t *message,
|
||||
isccc_time_t now);
|
||||
|
|
|
|||
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 AND ISC
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Nominum, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
*****/
|
||||
|
||||
/*! \file isccc/symtab.h
|
||||
* \brief
|
||||
* Provides a simple memory-based symbol table.
|
||||
*
|
||||
* Keys are C strings. A type may be specified when looking up,
|
||||
* defining, or undefining. A type value of 0 means "match any type";
|
||||
* any other value will only match the given type.
|
||||
*
|
||||
* It's possible that a client will attempt to define a <key, type,
|
||||
* value> tuple when a tuple with the given key and type already
|
||||
* exists in the table. What to do in this case is specified by the
|
||||
* client. Possible policies are:
|
||||
*
|
||||
*\li isccc_symexists_reject Disallow the define, returning #ISC_R_EXISTS
|
||||
*\li isccc_symexists_replace Replace the old value with the new. The
|
||||
* undefine action (if provided) will be called
|
||||
* with the old <key, type, value> tuple.
|
||||
*\li isccc_symexists_add Add the new tuple, leaving the old tuple in
|
||||
* the table. Subsequent lookups will retrieve
|
||||
* the most-recently-defined tuple.
|
||||
*
|
||||
* A lookup of a key using type 0 will return the most-recently
|
||||
* defined symbol with that key. An undefine of a key using type 0
|
||||
* will undefine the most-recently defined symbol with that key.
|
||||
* Trying to define a key with type 0 is illegal.
|
||||
*
|
||||
* The symbol table library does not make a copy the key field, so the
|
||||
* caller must ensure that any key it passes to isccc_symtab_define()
|
||||
* will not change until it calls isccc_symtab_undefine() or
|
||||
* isccc_symtab_destroy().
|
||||
*
|
||||
* A user-specified action will be called (if provided) when a symbol
|
||||
* is undefined. It can be used to free memory associated with keys
|
||||
* and/or values.
|
||||
*/
|
||||
|
||||
/***
|
||||
*** Imports.
|
||||
***/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isccc/types.h>
|
||||
|
||||
/***
|
||||
*** Symbol Tables.
|
||||
***/
|
||||
|
||||
typedef union isccc_symvalue {
|
||||
void *as_pointer;
|
||||
int as_integer;
|
||||
unsigned int as_uinteger;
|
||||
} isccc_symvalue_t;
|
||||
|
||||
typedef void (*isccc_symtabundefaction_t)(char *key, unsigned int type,
|
||||
isccc_symvalue_t value,
|
||||
void *userarg);
|
||||
|
||||
typedef bool (*isccc_symtabforeachaction_t)(char *key, unsigned int type,
|
||||
isccc_symvalue_t value,
|
||||
void *userarg);
|
||||
|
||||
typedef enum {
|
||||
isccc_symexists_reject = 0,
|
||||
isccc_symexists_replace = 1,
|
||||
isccc_symexists_add = 2
|
||||
} isccc_symexists_t;
|
||||
|
||||
isc_result_t
|
||||
isccc_symtab_create(unsigned int size,
|
||||
isccc_symtabundefaction_t undefine_action,
|
||||
void *undefine_arg, bool case_sensitive,
|
||||
isccc_symtab_t **symtabp);
|
||||
|
||||
void
|
||||
isccc_symtab_destroy(isccc_symtab_t **symtabp);
|
||||
|
||||
isc_result_t
|
||||
isccc_symtab_lookup(isccc_symtab_t *symtab, const char *key, unsigned int type,
|
||||
isccc_symvalue_t *value);
|
||||
|
||||
isc_result_t
|
||||
isccc_symtab_define(isccc_symtab_t *symtab, char *key, unsigned int type,
|
||||
isccc_symvalue_t value, isccc_symexists_t exists_policy);
|
||||
|
||||
isc_result_t
|
||||
isccc_symtab_undefine(isccc_symtab_t *symtab, const char *key,
|
||||
unsigned int type);
|
||||
|
||||
void
|
||||
isccc_symtab_foreach(isccc_symtab_t *symtab, isccc_symtabforeachaction_t action,
|
||||
void *arg);
|
||||
|
|
@ -42,8 +42,6 @@ typedef uint32_t isccc_time_t;
|
|||
typedef struct isccc_sexpr isccc_sexpr_t;
|
||||
/*% isccc_dottedpair_t typedef */
|
||||
typedef struct isccc_dottedpair isccc_dottedpair_t;
|
||||
/*% isccc_symtab_t typedef */
|
||||
typedef struct isccc_symtab isccc_symtab_t;
|
||||
|
||||
/*% iscc region structure */
|
||||
typedef struct isccc_region {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
/*! \file */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -469,7 +468,7 @@ exists(const cfg_obj_t *obj, const char *name, int value, isc_symtab_t *symtab,
|
|||
static isc_result_t
|
||||
checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
|
||||
const cfg_obj_t *voptions, const cfg_obj_t *config, isc_mem_t *mctx) {
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const cfg_obj_t *aclobj = NULL;
|
||||
const cfg_obj_t *options;
|
||||
dns_acl_t *acl = NULL;
|
||||
|
|
@ -1003,7 +1002,7 @@ kasp_name_allowed(const cfg_listelt_t *element) {
|
|||
|
||||
static const cfg_obj_t *
|
||||
find_maplist(const cfg_obj_t *config, const char *listname, const char *name) {
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const cfg_obj_t *maplist = NULL;
|
||||
const cfg_listelt_t *elt = NULL;
|
||||
|
||||
|
|
@ -1166,7 +1165,7 @@ check_listeners(const cfg_obj_t *list, const cfg_obj_t *config,
|
|||
static isc_result_t
|
||||
check_port(const cfg_obj_t *options, const char *type, in_port_t *portp) {
|
||||
const cfg_obj_t *portobj = NULL;
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
result = cfg_map_get(options, type, &portobj);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -2049,7 +2048,7 @@ static isc_result_t
|
|||
check_remoteserverlist(const cfg_obj_t *cctx, const char *list,
|
||||
isc_symtab_t *symtab, isc_mem_t *mctx) {
|
||||
isc_symvalue_t symvalue;
|
||||
isc_result_t result, tresult;
|
||||
isc_result_t result = ISC_R_SUCCESS, tresult;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
const cfg_listelt_t *elt;
|
||||
|
||||
|
|
@ -2105,7 +2104,7 @@ check_remoteserverlists(const cfg_obj_t *cctx, isc_mem_t *mctx) {
|
|||
isc_result_t result = ISC_R_SUCCESS, tresult;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
|
||||
isc_symtab_create(mctx, 100, freekey, mctx, false, &symtab);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &symtab);
|
||||
|
||||
tresult = check_remoteserverlist(cctx, "remote-servers", symtab, mctx);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
|
|
@ -2131,7 +2130,7 @@ check_remoteserverlists(const cfg_obj_t *cctx, isc_mem_t *mctx) {
|
|||
#if HAVE_LIBNGHTTP2
|
||||
static isc_result_t
|
||||
check_httpserver(const cfg_obj_t *http, isc_symtab_t *symtab) {
|
||||
isc_result_t result, tresult;
|
||||
isc_result_t result = ISC_R_SUCCESS, tresult;
|
||||
const char *name = cfg_obj_asstring(cfg_map_getname(http));
|
||||
const cfg_obj_t *eps = NULL;
|
||||
const cfg_listelt_t *elt = NULL;
|
||||
|
|
@ -2193,12 +2192,12 @@ check_httpserver(const cfg_obj_t *http, isc_symtab_t *symtab) {
|
|||
|
||||
static isc_result_t
|
||||
check_httpservers(const cfg_obj_t *config, isc_mem_t *mctx) {
|
||||
isc_result_t result, tresult;
|
||||
isc_result_t result = ISC_R_SUCCESS, tresult;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
const cfg_listelt_t *elt = NULL;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
|
||||
isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab);
|
||||
isc_symtab_create(mctx, NULL, NULL, false, &symtab);
|
||||
|
||||
result = cfg_map_get(config, "http", &obj);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -2223,7 +2222,7 @@ done:
|
|||
static isc_result_t
|
||||
check_tls_defintion(const cfg_obj_t *tlsobj, const char *name,
|
||||
isc_symtab_t *symtab) {
|
||||
isc_result_t result, tresult;
|
||||
isc_result_t result = ISC_R_SUCCESS, tresult;
|
||||
const cfg_obj_t *tls_proto_list = NULL, *tls_key = NULL,
|
||||
*tls_cert = NULL, *tls_ciphers = NULL,
|
||||
*tls_cipher_suites = NULL;
|
||||
|
|
@ -2357,7 +2356,7 @@ check_tls_defintion(const cfg_obj_t *tlsobj, const char *name,
|
|||
|
||||
static isc_result_t
|
||||
check_tls_definitions(const cfg_obj_t *config, isc_mem_t *mctx) {
|
||||
isc_result_t result, tresult;
|
||||
isc_result_t result = ISC_R_SUCCESS, tresult;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
const cfg_listelt_t *elt = NULL;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
|
|
@ -2368,7 +2367,7 @@ check_tls_definitions(const cfg_obj_t *config, isc_mem_t *mctx) {
|
|||
return result;
|
||||
}
|
||||
|
||||
isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab);
|
||||
isc_symtab_create(mctx, NULL, NULL, false, &symtab);
|
||||
|
||||
for (elt = cfg_list_first(obj); elt != NULL; elt = cfg_list_next(elt)) {
|
||||
const char *name;
|
||||
|
|
@ -2388,7 +2387,7 @@ check_tls_definitions(const cfg_obj_t *config, isc_mem_t *mctx) {
|
|||
static isc_result_t
|
||||
get_remotes(const cfg_obj_t *cctx, const char *list, const char *name,
|
||||
const cfg_obj_t **ret) {
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
const cfg_listelt_t *elt = NULL;
|
||||
|
||||
|
|
@ -2449,7 +2448,7 @@ validate_remotes(const cfg_obj_t *obj, const cfg_obj_t *config,
|
|||
const cfg_obj_t *listobj;
|
||||
|
||||
REQUIRE(countp != NULL);
|
||||
isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab);
|
||||
isc_symtab_create(mctx, NULL, NULL, false, &symtab);
|
||||
|
||||
newlist:
|
||||
listobj = cfg_tuple_get(obj, "addresses");
|
||||
|
|
@ -2833,7 +2832,7 @@ check_recursion(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
|||
isc_mem_t *mctx) {
|
||||
dns_acl_t *acl = NULL;
|
||||
const cfg_obj_t *obj;
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
bool retval = true;
|
||||
|
||||
/*
|
||||
|
|
@ -3175,7 +3174,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
|||
RUNTIME_CHECK(n > 0 && (size_t)n < len);
|
||||
switch (ztype) {
|
||||
case CFG_ZONE_INVIEW:
|
||||
tresult = isc_symtab_lookup(inview, key, 0, NULL);
|
||||
tresult = isc_symtab_lookup(inview, key, 1, NULL);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(inviewobj, ISC_LOG_ERROR,
|
||||
"'in-view' zone '%s' "
|
||||
|
|
@ -3913,7 +3912,7 @@ isccfg_check_key(const cfg_obj_t *key) {
|
|||
const char *algorithm;
|
||||
int i;
|
||||
size_t len = 0;
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_buffer_t buf;
|
||||
unsigned char secretbuf[1024];
|
||||
static const algorithmtable algorithms[] = {
|
||||
|
|
@ -4003,50 +4002,67 @@ isccfg_check_key(const cfg_obj_t *key) {
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
typedef enum symtab_file_type {
|
||||
READ_ONLY = 1,
|
||||
WRITEABLE = 2,
|
||||
} symtab_file_type_t;
|
||||
|
||||
static isc_result_t
|
||||
fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable) {
|
||||
isc_result_t result;
|
||||
isc_symvalue_t symvalue;
|
||||
isc_result_t result_ro, result_w;
|
||||
isc_symvalue_t symvalue_ro, symvalue_w;
|
||||
unsigned int line;
|
||||
const char *file;
|
||||
|
||||
result = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), 0, &symvalue);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (writeable) {
|
||||
file = cfg_obj_file(symvalue.as_cpointer);
|
||||
line = cfg_obj_line(symvalue.as_cpointer);
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"writeable file '%s': already in use: "
|
||||
"%s:%u",
|
||||
cfg_obj_asstring(obj), file, line);
|
||||
return ISC_R_EXISTS;
|
||||
}
|
||||
result = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), 2,
|
||||
&symvalue);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
file = cfg_obj_file(symvalue.as_cpointer);
|
||||
line = cfg_obj_line(symvalue.as_cpointer);
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"writeable file '%s': already in use: "
|
||||
"%s:%u",
|
||||
cfg_obj_asstring(obj), file, line);
|
||||
return ISC_R_EXISTS;
|
||||
}
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
/*
|
||||
* Since symtab doesn't let us query the file type, we need to query
|
||||
* twice. Once per type.
|
||||
*/
|
||||
result_ro = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), READ_ONLY,
|
||||
&symvalue_ro);
|
||||
result_w = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), WRITEABLE,
|
||||
&symvalue_w);
|
||||
|
||||
symvalue.as_cpointer = obj;
|
||||
result = isc_symtab_define(symtab, cfg_obj_asstring(obj),
|
||||
writeable ? 2 : 1, symvalue,
|
||||
isc_symexists_reject);
|
||||
return result;
|
||||
bool found_read_only = result_ro == ISC_R_SUCCESS;
|
||||
bool found_writable = result_w == ISC_R_SUCCESS;
|
||||
|
||||
/*
|
||||
* If either the new file, the old file or both files are writeable,
|
||||
* bail out.
|
||||
*/
|
||||
if ((writeable && found_read_only) || found_writable) {
|
||||
isc_symvalue_t symvalue = (writeable && found_read_only)
|
||||
? symvalue_ro
|
||||
: symvalue_w;
|
||||
|
||||
file = cfg_obj_file(symvalue.as_cpointer);
|
||||
line = cfg_obj_line(symvalue.as_cpointer);
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"writeable file '%s': already in use: "
|
||||
"%s:%u",
|
||||
cfg_obj_asstring(obj), file, line);
|
||||
return ISC_R_EXISTS;
|
||||
} else if (found_read_only) {
|
||||
/* If a read only file is already in the hashtable, we have
|
||||
* nothing to do */
|
||||
return ISC_R_SUCCESS;
|
||||
} else {
|
||||
/* If the file was not present already in the hashmap, add it */
|
||||
isc_symvalue_t symvalue =
|
||||
(isc_symvalue_t){ .as_cpointer = obj };
|
||||
symtab_file_type_t type = writeable ? WRITEABLE : READ_ONLY;
|
||||
isc_result_t result =
|
||||
isc_symtab_define(symtab, cfg_obj_asstring(obj), type,
|
||||
symvalue, isc_symexists_reject);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
keydirexist(const cfg_obj_t *zcfg, const char *optname, dns_name_t *zname,
|
||||
const char *dirname, const char *kaspnamestr, isc_symtab_t *symtab,
|
||||
isc_mem_t *mctx) {
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_symvalue_t symvalue;
|
||||
char *symkey;
|
||||
char keydirbuf[DNS_NAME_FORMATSIZE + 128];
|
||||
|
|
@ -4070,7 +4086,7 @@ keydirexist(const cfg_obj_t *zcfg, const char *optname, dns_name_t *zname,
|
|||
}
|
||||
keydir = keydirbuf;
|
||||
|
||||
result = isc_symtab_lookup(symtab, keydir, 0, &symvalue);
|
||||
result = isc_symtab_lookup(symtab, keydir, 1, &symvalue);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
const cfg_obj_t *kasp = NULL;
|
||||
const cfg_obj_t *exist = symvalue.as_cpointer;
|
||||
|
|
@ -4104,7 +4120,7 @@ keydirexist(const cfg_obj_t *zcfg, const char *optname, dns_name_t *zname,
|
|||
*/
|
||||
symkey = isc_mem_strdup(mctx, keydir);
|
||||
symvalue.as_cpointer = zcfg;
|
||||
result = isc_symtab_define(symtab, symkey, 2, symvalue,
|
||||
result = isc_symtab_define(symtab, symkey, 1, symvalue,
|
||||
isc_symexists_reject);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
return result;
|
||||
|
|
@ -4888,8 +4904,8 @@ check_ta_conflicts(const cfg_obj_t *global_ta, const cfg_obj_t *view_ta,
|
|||
const cfg_obj_t *keylist = NULL;
|
||||
isc_symtab_t *statictab = NULL, *dstab = NULL;
|
||||
|
||||
isc_symtab_create(mctx, 100, freekey, mctx, false, &statictab);
|
||||
isc_symtab_create(mctx, 100, freekey, mctx, false, &dstab);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &statictab);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &dstab);
|
||||
|
||||
/*
|
||||
* First we record all the static keys (trust-anchors configured with
|
||||
|
|
@ -4971,7 +4987,7 @@ check_rpz_catz(const char *rpz_catz, const cfg_obj_t *rpz_obj,
|
|||
const char *zonename, *zonetype;
|
||||
const char *forview = " for view ";
|
||||
isc_symvalue_t value;
|
||||
isc_result_t result, tresult;
|
||||
isc_result_t result = ISC_R_SUCCESS, tresult;
|
||||
dns_fixedname_t fixed;
|
||||
dns_name_t *name;
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
|
|
@ -5106,7 +5122,7 @@ check_catz(const cfg_obj_t *catz_obj, const char *viewname, isc_mem_t *mctx) {
|
|||
forview = "";
|
||||
}
|
||||
|
||||
isc_symtab_create(mctx, 100, freekey, mctx, false, &symtab);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &symtab);
|
||||
|
||||
obj = cfg_tuple_get(catz_obj, "zone list");
|
||||
|
||||
|
|
@ -5186,7 +5202,7 @@ check_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
|
|||
void *callback_data) {
|
||||
struct check_one_plugin_data *data = callback_data;
|
||||
char full_path[PATH_MAX];
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
result = ns_plugin_expandpath(plugin_path, full_path,
|
||||
sizeof(full_path));
|
||||
|
|
@ -5287,7 +5303,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
|||
* Check that all zone statements are syntactically correct and
|
||||
* there are no duplicate zones.
|
||||
*/
|
||||
isc_symtab_create(mctx, 1000, freekey, mctx, false, &symtab);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &symtab);
|
||||
|
||||
cfg_aclconfctx_create(mctx, &actx);
|
||||
|
||||
|
|
@ -5400,7 +5416,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
|||
* Check that all key statements are syntactically correct and
|
||||
* there are no duplicate keys.
|
||||
*/
|
||||
isc_symtab_create(mctx, 1000, freekey, mctx, false, &symtab);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &symtab);
|
||||
|
||||
(void)cfg_map_get(config, "key", &keys);
|
||||
tresult = check_keylist(keys, symtab, mctx);
|
||||
|
|
@ -5630,7 +5646,7 @@ check_logging(const cfg_obj_t *config, isc_mem_t *mctx) {
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab);
|
||||
isc_symtab_create(mctx, NULL, NULL, false, &symtab);
|
||||
|
||||
symvalue.as_cpointer = NULL;
|
||||
for (i = 0; default_channels[i] != NULL; i++) {
|
||||
|
|
@ -5764,7 +5780,7 @@ check_controls(const cfg_obj_t *config, isc_mem_t *mctx) {
|
|||
|
||||
cfg_aclconfctx_create(mctx, &actx);
|
||||
|
||||
isc_symtab_create(mctx, 100, freekey, mctx, true, &symtab);
|
||||
isc_symtab_create(mctx, freekey, mctx, true, &symtab);
|
||||
|
||||
/*
|
||||
* INET: Check allow clause.
|
||||
|
|
@ -5839,7 +5855,7 @@ isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags,
|
|||
const cfg_obj_t *acls = NULL;
|
||||
const cfg_listelt_t *velement;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_result_t tresult;
|
||||
isc_result_t tresult = ISC_R_SUCCESS;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
isc_symtab_t *files = NULL;
|
||||
isc_symtab_t *keydirs = NULL;
|
||||
|
|
@ -5900,9 +5916,9 @@ isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags,
|
|||
* case sensitive. This will prevent people using FOO.DB and foo.db
|
||||
* on case sensitive file systems but that shouldn't be a major issue.
|
||||
*/
|
||||
isc_symtab_create(mctx, 100, NULL, NULL, false, &files);
|
||||
isc_symtab_create(mctx, 100, freekey, mctx, false, &keydirs);
|
||||
isc_symtab_create(mctx, 100, freekey, mctx, true, &inview);
|
||||
isc_symtab_create(mctx, NULL, NULL, false, &files);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &keydirs);
|
||||
isc_symtab_create(mctx, freekey, mctx, true, &inview);
|
||||
|
||||
if (views == NULL) {
|
||||
tresult = check_viewconf(config, NULL, NULL, dns_rdataclass_in,
|
||||
|
|
@ -5931,7 +5947,7 @@ isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags,
|
|||
}
|
||||
}
|
||||
|
||||
isc_symtab_create(mctx, 100, NULL, NULL, true, &symtab);
|
||||
isc_symtab_create(mctx, NULL, NULL, true, &symtab);
|
||||
|
||||
for (velement = cfg_list_first(views); velement != NULL;
|
||||
velement = cfg_list_next(velement))
|
||||
|
|
|
|||
|
|
@ -72,7 +72,9 @@
|
|||
#define CAT CFG_LOGCATEGORY_CONFIG
|
||||
#define MOD CFG_LOGMODULE_PARSER
|
||||
|
||||
#define MAP_SYM 1 /* Unique type for isc_symtab */
|
||||
/* isc_symtab_t takes both a string and an int as input, but we don't need
|
||||
* the int, so we define a "dummy" value to use instead. */
|
||||
#define SYMTAB_DUMMY_TYPE 1
|
||||
|
||||
#define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
|
||||
#define TOKEN_REGION(pctx) (pctx->token.value.as_textregion)
|
||||
|
|
@ -2207,7 +2209,6 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
|||
cfg_obj_t *eltobj = NULL;
|
||||
cfg_obj_t *includename = NULL;
|
||||
isc_symvalue_t symval;
|
||||
cfg_list_t *list = NULL;
|
||||
|
||||
REQUIRE(pctx != NULL);
|
||||
REQUIRE(type != NULL);
|
||||
|
|
@ -2358,32 +2359,20 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
|||
}
|
||||
|
||||
/* See if the clause already has a value; if not create one. */
|
||||
result = isc_symtab_lookup(obj->value.map.symtab, clause->name,
|
||||
0, &symval);
|
||||
|
||||
if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
|
||||
/* Multivalued clause */
|
||||
cfg_obj_t *listobj = NULL;
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
CHECK(cfg_create_list(pctx,
|
||||
&cfg_type_implicitlist,
|
||||
&listobj));
|
||||
symval.as_pointer = listobj;
|
||||
result = isc_symtab_define(
|
||||
obj->value.map.symtab, clause->name, 1,
|
||||
symval, isc_symexists_reject);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_parser_error(pctx, CFG_LOG_NEAR,
|
||||
"isc_symtab_define(%s)"
|
||||
" "
|
||||
"failed",
|
||||
clause->name);
|
||||
isc_mem_put(pctx->mctx, list,
|
||||
sizeof(cfg_list_t));
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
CHECK(cfg_create_list(pctx, &cfg_type_implicitlist,
|
||||
&listobj));
|
||||
symval.as_pointer = listobj;
|
||||
result = isc_symtab_define_and_return(
|
||||
obj->value.map.symtab, clause->name,
|
||||
SYMTAB_DUMMY_TYPE, symval, isc_symexists_reject,
|
||||
&symval);
|
||||
|
||||
if (result == ISC_R_EXISTS) {
|
||||
CLEANUP_OBJ(listobj);
|
||||
listobj = symval.as_pointer;
|
||||
}
|
||||
|
||||
|
|
@ -2394,25 +2383,23 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
|||
ISC_LIST_APPEND(listobj->value.list, elt, link);
|
||||
} else {
|
||||
/* Single-valued clause */
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
bool callback = ((clause->flags &
|
||||
CFG_CLAUSEFLAG_CALLBACK) !=
|
||||
0);
|
||||
CHECK(parse_symtab_elt(
|
||||
pctx, clause->name, clause->type,
|
||||
obj->value.map.symtab, callback));
|
||||
CHECK(parse_semicolon(pctx));
|
||||
} else if (result == ISC_R_SUCCESS) {
|
||||
bool callback = ((clause->flags &
|
||||
CFG_CLAUSEFLAG_CALLBACK) != 0);
|
||||
|
||||
result = parse_symtab_elt(
|
||||
pctx, clause->name, clause->type,
|
||||
obj->value.map.symtab, callback);
|
||||
if (result == ISC_R_EXISTS) {
|
||||
cfg_parser_error(pctx, CFG_LOG_NEAR,
|
||||
"'%s' redefined",
|
||||
clause->name);
|
||||
result = ISC_R_EXISTS;
|
||||
goto cleanup;
|
||||
} else {
|
||||
CHECK(result);
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
cfg_parser_error(pctx, CFG_LOG_NEAR,
|
||||
"isc_symtab_define() failed");
|
||||
goto cleanup;
|
||||
CHECK(result);
|
||||
}
|
||||
CHECK(parse_semicolon(pctx));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2441,7 +2428,8 @@ parse_symtab_elt(cfg_parser_t *pctx, const char *name, cfg_type_t *elttype,
|
|||
}
|
||||
|
||||
symval.as_pointer = obj;
|
||||
CHECK(isc_symtab_define(symtab, name, 1, symval, isc_symexists_reject));
|
||||
CHECK(isc_symtab_define(symtab, name, SYMTAB_DUMMY_TYPE, symval,
|
||||
isc_symexists_reject));
|
||||
return ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
|
|
@ -2556,7 +2544,8 @@ cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj) {
|
|||
for (clause = *clauseset; clause->name != NULL; clause++) {
|
||||
isc_result_t result;
|
||||
result = isc_symtab_lookup(obj->value.map.symtab,
|
||||
clause->name, 0, &symval);
|
||||
clause->name,
|
||||
SYMTAB_DUMMY_TYPE, &symval);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
cfg_obj_t *symobj = symval.as_pointer;
|
||||
if (symobj->type == &cfg_type_implicitlist) {
|
||||
|
|
@ -2727,7 +2716,7 @@ cfg_map_get(const cfg_obj_t *mapobj, const char *name, const cfg_obj_t **obj) {
|
|||
|
||||
map = &mapobj->value.map;
|
||||
|
||||
result = isc_symtab_lookup(map->symtab, name, MAP_SYM, &val);
|
||||
result = isc_symtab_lookup(map->symtab, name, SYMTAB_DUMMY_TYPE, &val);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3797,8 +3786,8 @@ create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
|||
cfg_obj_t *obj = NULL;
|
||||
|
||||
CHECK(cfg_create_obj(pctx, type, &obj));
|
||||
isc_symtab_create(pctx->mctx, 5, /* XXX */
|
||||
map_symtabitem_destroy, pctx, false, &symtab);
|
||||
isc_symtab_create(pctx->mctx, map_symtabitem_destroy, pctx, false,
|
||||
&symtab);
|
||||
obj->value.map.symtab = symtab;
|
||||
obj->value.map.id = NULL;
|
||||
|
||||
|
|
@ -3922,7 +3911,8 @@ breakout:
|
|||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
result = isc_symtab_lookup(map->symtab, clausename, 0, &symval);
|
||||
result = isc_symtab_lookup(map->symtab, clausename, SYMTAB_DUMMY_TYPE,
|
||||
&symval);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
|
||||
CHECK(cfg_create_list(pctx, &cfg_type_implicitlist,
|
||||
|
|
@ -3935,8 +3925,10 @@ breakout:
|
|||
symval.as_pointer = obj;
|
||||
}
|
||||
|
||||
CHECK(isc_symtab_define(map->symtab, clausename, 1, symval,
|
||||
isc_symexists_reject));
|
||||
result = isc_symtab_define(map->symtab, clausename,
|
||||
SYMTAB_DUMMY_TYPE, symval,
|
||||
isc_symexists_reject);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
} else {
|
||||
cfg_obj_t *destobj2 = symval.as_pointer;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,105 +28,254 @@
|
|||
|
||||
#include <tests/isc.h>
|
||||
|
||||
static void
|
||||
undefine(char *key, unsigned int type, isc_symvalue_t value, void *arg) {
|
||||
UNUSED(arg);
|
||||
#define TEST_NITEMS 10000
|
||||
|
||||
assert_int_equal(type, 1);
|
||||
static void
|
||||
undefine(char *key, unsigned int type ISC_ATTR_UNUSED, isc_symvalue_t value,
|
||||
void *arg ISC_ATTR_UNUSED) {
|
||||
isc_mem_free(mctx, key);
|
||||
isc_mem_free(mctx, value.as_pointer);
|
||||
}
|
||||
|
||||
/* test symbol table growth */
|
||||
ISC_RUN_TEST_IMPL(symtab_grow) {
|
||||
ISC_RUN_TEST_IMPL(symtab_define) {
|
||||
isc_result_t result;
|
||||
isc_symtab_t *st = NULL;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
isc_symvalue_t value;
|
||||
isc_symvalue_t found;
|
||||
isc_symexists_t policy = isc_symexists_reject;
|
||||
char str[16], *key;
|
||||
snprintf(str, sizeof(str), "%p", "define");
|
||||
key = isc_mem_strdup(mctx, str);
|
||||
|
||||
isc_symtab_create(mctx, undefine, NULL, false, &symtab);
|
||||
assert_non_null(symtab);
|
||||
|
||||
value.as_pointer = isc_mem_strdup(mctx, key);
|
||||
assert_non_null(value.as_pointer);
|
||||
|
||||
result = isc_symtab_define(symtab, key, 1, value, policy);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_symtab_lookup(symtab, key, 1, &found);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_string_equal(value.as_pointer, found.as_pointer);
|
||||
|
||||
result = isc_symtab_lookup(symtab, key, 2, NULL);
|
||||
assert_int_equal(result, ISC_R_NOTFOUND);
|
||||
|
||||
isc_symtab_destroy(&symtab);
|
||||
}
|
||||
|
||||
ISC_RUN_TEST_IMPL(symtab_undefine) {
|
||||
isc_result_t result;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
isc_symvalue_t value;
|
||||
isc_symexists_t policy = isc_symexists_reject;
|
||||
int i;
|
||||
|
||||
UNUSED(state);
|
||||
/* We need a separate copy of the key to prevent an use-after-free */
|
||||
char str[16], *key, *key_after_undefine;
|
||||
snprintf(str, sizeof(str), "%p", "undefine");
|
||||
|
||||
isc_symtab_create(mctx, 3, undefine, NULL, false, &st);
|
||||
assert_non_null(st);
|
||||
key = isc_mem_strdup(mctx, str);
|
||||
key_after_undefine = isc_mem_strdup(mctx, str);
|
||||
|
||||
isc_symtab_create(mctx, undefine, NULL, false, &symtab);
|
||||
assert_non_null(symtab);
|
||||
|
||||
value.as_pointer = isc_mem_strdup(mctx, key);
|
||||
assert_non_null(value.as_pointer);
|
||||
|
||||
result = isc_symtab_define(symtab, key, 1, value, policy);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_symtab_lookup(symtab, key_after_undefine, 1, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_symtab_undefine(symtab, key, 1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_symtab_lookup(symtab, key_after_undefine, 1, NULL);
|
||||
assert_int_equal(result, ISC_R_NOTFOUND);
|
||||
|
||||
isc_symtab_destroy(&symtab);
|
||||
|
||||
/* key will be freed by isc_symtab_undefine, so we don't need to free
|
||||
* it again
|
||||
*/
|
||||
isc_mem_free(mctx, key_after_undefine);
|
||||
}
|
||||
|
||||
ISC_RUN_TEST_IMPL(symtab_replace) {
|
||||
isc_result_t result;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
isc_symvalue_t value1;
|
||||
isc_symvalue_t value2;
|
||||
isc_symvalue_t found;
|
||||
isc_symexists_t policy = isc_symexists_replace;
|
||||
char str[16], *key1, *key2;
|
||||
snprintf(str, sizeof(str), "%p", "replace");
|
||||
key1 = isc_mem_strdup(mctx, str);
|
||||
key2 = isc_mem_strdup(mctx, str);
|
||||
|
||||
isc_symtab_create(mctx, undefine, NULL, false, &symtab);
|
||||
assert_non_null(symtab);
|
||||
|
||||
value1.as_pointer = isc_mem_strdup(mctx, key1);
|
||||
assert_non_null(value1.as_pointer);
|
||||
|
||||
value2.as_pointer = isc_mem_strdup(mctx, key2);
|
||||
assert_non_null(value2.as_pointer);
|
||||
|
||||
result = isc_symtab_define(symtab, key1, 1, value1, policy);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_symtab_lookup(symtab, key1, 1, &found);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_string_equal(value1.as_pointer, found.as_pointer);
|
||||
|
||||
result = isc_symtab_define(symtab, key2, 1, value2, policy);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_symtab_lookup(symtab, key2, 1, &found);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_string_equal(value2.as_pointer, found.as_pointer);
|
||||
|
||||
result = isc_symtab_undefine(symtab, key2, 1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_symtab_destroy(&symtab);
|
||||
}
|
||||
|
||||
ISC_RUN_TEST_IMPL(symtab_reject) {
|
||||
isc_result_t result;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
isc_symvalue_t value1;
|
||||
isc_symvalue_t value2;
|
||||
isc_symvalue_t found;
|
||||
isc_symexists_t policy = isc_symexists_reject;
|
||||
char str[16], *key1, *key2;
|
||||
snprintf(str, sizeof(str), "%p", "reject");
|
||||
key1 = isc_mem_strdup(mctx, str);
|
||||
key2 = isc_mem_strdup(mctx, str);
|
||||
|
||||
isc_symtab_create(mctx, undefine, NULL, false, &symtab);
|
||||
assert_non_null(symtab);
|
||||
|
||||
value1.as_pointer = isc_mem_strdup(mctx, key1);
|
||||
assert_non_null(value1.as_pointer);
|
||||
|
||||
value2.as_pointer = isc_mem_strdup(mctx, key2);
|
||||
assert_non_null(value2.as_pointer);
|
||||
|
||||
result = isc_symtab_define(symtab, key1, 1, value1, policy);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_symtab_lookup(symtab, key1, 1, &found);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_string_equal(value1.as_pointer, found.as_pointer);
|
||||
|
||||
result = isc_symtab_define_and_return(symtab, key2, 1, value2, policy,
|
||||
&found);
|
||||
assert_int_equal(result, ISC_R_EXISTS);
|
||||
assert_string_equal(value1.as_pointer, found.as_pointer);
|
||||
|
||||
result = isc_symtab_lookup(symtab, key2, 1, &found);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_string_equal(value1.as_pointer, found.as_pointer);
|
||||
|
||||
result = isc_symtab_undefine(symtab, key1, 1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
undefine(key2, 1, value2, NULL);
|
||||
|
||||
isc_symtab_destroy(&symtab);
|
||||
}
|
||||
|
||||
static bool
|
||||
peek(char *key ISC_ATTR_UNUSED, unsigned int type,
|
||||
isc_symvalue_t value ISC_ATTR_UNUSED, void *arg) {
|
||||
bool *seen = arg;
|
||||
size_t i = type - 1;
|
||||
|
||||
assert_false(seen[i]);
|
||||
|
||||
seen[i] = true;
|
||||
|
||||
return i % 2;
|
||||
}
|
||||
|
||||
ISC_RUN_TEST_IMPL(symtab_foreach) {
|
||||
isc_result_t result;
|
||||
isc_symtab_t *symtab = NULL;
|
||||
isc_symvalue_t value;
|
||||
isc_symexists_t policy = isc_symexists_reject;
|
||||
bool seen[TEST_NITEMS] = { 0 };
|
||||
|
||||
isc_symtab_create(mctx, undefine, NULL, false, &symtab);
|
||||
|
||||
/* Nothing should be in the table yet */
|
||||
assert_non_null(symtab);
|
||||
|
||||
/*
|
||||
* Put 1024 entries in the table (this should necessate
|
||||
* regrowing the hash table several times
|
||||
* Put TEST_NITEMS entries in the table.
|
||||
*/
|
||||
for (i = 0; i < 1024; i++) {
|
||||
char str[16], *key;
|
||||
for (size_t i = 0; i < TEST_NITEMS; i++) {
|
||||
char str[256] = {}, *key;
|
||||
|
||||
snprintf(str, sizeof(str), "%08zx", i);
|
||||
|
||||
snprintf(str, sizeof(str), "%04x", i);
|
||||
key = isc_mem_strdup(mctx, str);
|
||||
assert_non_null(key);
|
||||
value.as_pointer = isc_mem_strdup(mctx, str);
|
||||
assert_non_null(value.as_pointer);
|
||||
result = isc_symtab_define(st, key, 1, value, policy);
|
||||
result = isc_symtab_define(symtab, key, i + 1, value, policy);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
undefine(key, 1, value, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to put them in again; this should fail
|
||||
*/
|
||||
for (i = 0; i < 1024; i++) {
|
||||
char str[16], *key;
|
||||
|
||||
snprintf(str, sizeof(str), "%04x", i);
|
||||
key = isc_mem_strdup(mctx, str);
|
||||
assert_non_null(key);
|
||||
value.as_pointer = isc_mem_strdup(mctx, str);
|
||||
assert_non_null(value.as_pointer);
|
||||
result = isc_symtab_define(st, key, 1, value, policy);
|
||||
assert_int_equal(result, ISC_R_EXISTS);
|
||||
undefine(key, 1, value, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve them; this should succeed
|
||||
*/
|
||||
for (i = 0; i < 1024; i++) {
|
||||
char str[16];
|
||||
for (size_t i = 0; i < TEST_NITEMS; i++) {
|
||||
char str[256] = {};
|
||||
|
||||
snprintf(str, sizeof(str), "%04x", i);
|
||||
result = isc_symtab_lookup(st, str, 0, &value);
|
||||
snprintf(str, sizeof(str), "%08zx", i);
|
||||
result = isc_symtab_lookup(symtab, str, i + 1, &value);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_string_equal(str, (char *)value.as_pointer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Undefine them
|
||||
* Undefine even items them via foreach
|
||||
*/
|
||||
for (i = 0; i < 1024; i++) {
|
||||
char str[16];
|
||||
isc_symtab_foreach(symtab, peek, seen);
|
||||
|
||||
snprintf(str, sizeof(str), "%04x", i);
|
||||
result = isc_symtab_undefine(st, str, 1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
for (size_t i = 0; i < TEST_NITEMS; i++) {
|
||||
assert_true(seen[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve them again; this should fail
|
||||
* Destroy the even ones by hand.
|
||||
*/
|
||||
for (i = 0; i < 1024; i++) {
|
||||
char str[16];
|
||||
for (size_t i = 0; i < TEST_NITEMS; i++) {
|
||||
if (i % 2 == 0) {
|
||||
char str[256] = {};
|
||||
|
||||
snprintf(str, sizeof(str), "%04x", i);
|
||||
result = isc_symtab_lookup(st, str, 0, &value);
|
||||
assert_int_equal(result, ISC_R_NOTFOUND);
|
||||
snprintf(str, sizeof(str), "%08zx", i);
|
||||
result = isc_symtab_undefine(symtab, str, i + 1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
isc_symtab_destroy(&st);
|
||||
isc_symtab_destroy(&symtab);
|
||||
}
|
||||
|
||||
ISC_TEST_LIST_START
|
||||
|
||||
ISC_TEST_ENTRY(symtab_grow)
|
||||
ISC_TEST_ENTRY(symtab_define)
|
||||
ISC_TEST_ENTRY(symtab_undefine)
|
||||
ISC_TEST_ENTRY(symtab_reject)
|
||||
ISC_TEST_ENTRY(symtab_replace)
|
||||
ISC_TEST_ENTRY(symtab_foreach)
|
||||
|
||||
ISC_TEST_LIST_END
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue