From 7ac87939729a1da40b8c626fb718f95004df87a7 Mon Sep 17 00:00:00 2001 From: Colin Vidal Date: Wed, 19 Feb 2025 16:59:18 +0100 Subject: [PATCH] Materializations fix save state Need to fix materialization ahead (materializing properties on non-yet exitstant zones) --- bin/tools/named-nzd2nzf.c | 2 + lib/isc/cfgmgr.c | 825 ++++++++++++++++++----------- tests/isc/cfgmgr_test.c | 1027 +++++++++++++------------------------ 3 files changed, 889 insertions(+), 965 deletions(-) diff --git a/bin/tools/named-nzd2nzf.c b/bin/tools/named-nzd2nzf.c index 82b9c61294..2b14283c5e 100644 --- a/bin/tools/named-nzd2nzf.c +++ b/bin/tools/named-nzd2nzf.c @@ -13,8 +13,10 @@ #include #include + #include #include + #include int diff --git a/lib/isc/cfgmgr.c b/lib/isc/cfgmgr.c index d63ff17e7c..b92c839909 100644 --- a/lib/isc/cfgmgr.c +++ b/lib/isc/cfgmgr.c @@ -68,11 +68,17 @@ static uint32_t isc__cfgmgr_hashoptions; static uint32_t isc__cfgmgr_hashviews; static uint32_t isc__cfgmgr_hashzones; -#define NODE_FLG_OPTIONS 1 << 0 -#define NODE_FLG_VIEWS 1 << 1 -#define NODE_FLG_VIEW 1 << 2 -#define NODE_FLG_ZONES 1 << 3 -#define NODE_FLG_ZONE 1 << 4 +typedef enum isc__cfgmgr_nodetype isc__cfgmgr_nodetype_t; +enum isc__cfgmgr_nodetype { + ISC__CFGMGR_NODEGENERIC, + ISC__CFGMGR_NODEOPTIONS, + ISC__CFGMGR_NODESUBOPTIONS, + ISC__CFGMGR_NODEVIEWS, + ISC__CFGMGR_NODEVIEW, + ISC__CFGMGR_NODESUBVIEW, + ISC__CFGMGR_NODEZONES, + ISC__CFGMGR_NODEZONE +} __attribute__((__packed__)); /* * Defines an opened node. @@ -82,13 +88,13 @@ struct isc__cfgmgr_node { char *name; char *prefix; uint32_t hash; - uint32_t flags; + uint8_t type; ISC_LINK(isc__cfgmgr_node_t) link; }; typedef ISC_LIST(isc__cfgmgr_node_t) isc__cfgmgr_nodes_t; typedef struct { - isc__cfgmgr_nodes_t openednodes; + isc__cfgmgr_nodes_t path; MDB_cursor *builtincursor; MDB_cursor *usercursor; MDB_cursor *runningcursor; @@ -103,7 +109,7 @@ typedef struct { static isc_mem_t *isc__cfgmgr_mctx = NULL; static MDB_env *isc__cfgmgr_env = NULL; static thread_local context_t isc__cfgmgr_ctx = - (context_t){ .openednodes = ISC_LIST_INITIALIZER, + (context_t){ .path = ISC_LIST_INITIALIZER, .builtincursor = NULL, .usercursor = NULL, .runningcursor = NULL, @@ -181,7 +187,7 @@ isc__cfgmgr_startlmdbtransaction(bool readonly) { static void isc__cfgmgr_checkofftransaction(void) { REQUIRE(isc__cfgmgr_env != NULL); - REQUIRE(ISC_LIST_EMPTY(isc__cfgmgr_ctx.openednodes)); + REQUIRE(ISC_LIST_EMPTY(isc__cfgmgr_ctx.path)); REQUIRE(isc__cfgmgr_ctx.txn == NULL); REQUIRE(isc__cfgmgr_ctx.builtincursor == NULL); REQUIRE(isc__cfgmgr_ctx.usercursor == NULL); @@ -208,6 +214,7 @@ isc_cfgmgr_init(isc_mem_t *mctx, const char *dbpath) { REQUIRE(sizeof(bool) == sizeof(uint8_t)); REQUIRE(sizeof(isc_cfgmgr_type_t) == sizeof(uint8_t)); REQUIRE(sizeof(isc_cfgmgr_mode_t) == sizeof(uint8_t)); + REQUIRE(sizeof(isc__cfgmgr_nodetype_t) == sizeof(uint8_t)); isc_mem_attach(mctx, &isc__cfgmgr_mctx); INSIST(isc__cfgmgr_mctx != NULL); @@ -309,7 +316,7 @@ isc_cfgmgr_deinit(void) { } static MDB_cursor * -isc__cfgmgr_lmdbcursor(void) { +isc__cfgmgr_dbcursor(void) { switch (isc__cfgmgr_ctx.mode) { case ISC_CFGMGR_MODEUNKNOWN: UNREACHABLE(); @@ -325,7 +332,7 @@ isc__cfgmgr_lmdbcursor(void) { } static MDB_dbi -isc__cfgmgr_lmdbdbi(void) { +isc__cfgmgr_dbi(void) { switch (isc__cfgmgr_ctx.mode) { case ISC_CFGMGR_MODEUNKNOWN: UNREACHABLE(); @@ -340,6 +347,21 @@ isc__cfgmgr_lmdbdbi(void) { UNREACHABLE(); } +static void +isc__cfgmgr_dbput(MDB_cursor *cursor, char *k, size_t klen, void *v, + size_t vlen) { + MDB_val dbk = { .mv_size = klen, .mv_data = (void *)k }; + MDB_val dbv = { .mv_size = vlen, .mv_data = v }; + REQUIRE(mdb_cursor_put(cursor, &dbk, &dbv, 0) == MDB_SUCCESS); +} + +static void +isc__cfgmgr_dbdel(MDB_cursor *cursor, char *k, size_t klen) { + MDB_val dbk = { .mv_size = klen, .mv_data = (void *)k }; + REQUIRE(mdb_cursor_get(cursor, &dbk, NULL, MDB_SET) == MDB_SUCCESS); + REQUIRE(mdb_cursor_del(cursor, 0) == MDB_SUCCESS); +} + static void isc__cfgmgr_setlasterror(const char *fmt, ...) { va_list ap; @@ -361,7 +383,7 @@ isc__cfgmgr_checkontransaction(void) { static void isc__cfgmgr_checkopenednodes(void) { isc__cfgmgr_checkontransaction(); - REQUIRE(ISC_LIST_EMPTY(isc__cfgmgr_ctx.openednodes) == false); + REQUIRE(ISC_LIST_EMPTY(isc__cfgmgr_ctx.path) == false); } void @@ -431,7 +453,7 @@ isc_cfgmgr_commit(void) { isc__cfgmgr_checkontransaction(); - while (ISC_LIST_EMPTY(isc__cfgmgr_ctx.openednodes) == false) { + while (ISC_LIST_EMPTY(isc__cfgmgr_ctx.path) == false) { isc_cfgmgr_close(); } @@ -452,7 +474,7 @@ void isc_cfgmgr_rollback(void) { isc__cfgmgr_checkontransaction(); - while (ISC_LIST_EMPTY(isc__cfgmgr_ctx.openednodes) == false) { + while (ISC_LIST_EMPTY(isc__cfgmgr_ctx.path) == false) { isc_cfgmgr_close(); } @@ -465,11 +487,11 @@ isc_cfgmgr_rollback(void) { static isc__cfgmgr_node_t * isc__cfgmgr_curnode(void) { - if (ISC_LIST_EMPTY(isc__cfgmgr_ctx.openednodes)) { + if (ISC_LIST_EMPTY(isc__cfgmgr_ctx.path)) { return NULL; } - return ISC_LIST_TAIL(isc__cfgmgr_ctx.openednodes); + return ISC_LIST_TAIL(isc__cfgmgr_ctx.path); } static const char * @@ -483,13 +505,13 @@ isc__cfgmgr_curprefix(void) { return "/"; } -static uint64_t +static uint32_t isc__cfgmgr_curhash(void) { const isc__cfgmgr_node_t *node = isc__cfgmgr_curnode(); if (node == NULL) { const char *rootprefix = isc__cfgmgr_curprefix(); - uint64_t roothash = isc_hash32(rootprefix, strlen(rootprefix), + uint32_t roothash = isc_hash32(rootprefix, strlen(rootprefix), false); INSIST(roothash > 0); @@ -534,105 +556,6 @@ isc__cfgmgr_keylen(const char *key) { return strlen(key + 5) + 5; } -static void -isc__cfgmgr_addindex(MDB_cursor *cursor, const char *name) { - char key[BUFLEN]; - MDB_val dbkey; - MDB_val dbval = { .mv_size = strlen(name), .mv_data = (void *)name }; - - /* - * Add the index of the node into it's parent node - */ - isc__cfgmgr_buildkey(key, sizeof(key), NODEINDEXFLG, - isc__cfgmgr_curhash(), "%s%s/", - isc__cfgmgr_curprefix(), name); - dbkey.mv_size = isc__cfgmgr_keylen(key) + 1; - dbkey.mv_data = key; - REQUIRE(mdb_cursor_put(cursor, &dbkey, &dbval, 0) == 0); -} - -static void -isc__cfgmgr_setnodeflags(isc__cfgmgr_node_t *node) { - isc__cfgmgr_node_t *curnode = isc__cfgmgr_curnode(); - uint32_t hash = isc_hash32(node->name, strlen(node->name), false); - - /* - * At root level, can be options or views special nodes - */ - if (curnode == NULL) { - if (hash == isc__cfgmgr_hashoptions) { - node->flags |= NODE_FLG_OPTIONS; - } else if (hash == isc__cfgmgr_hashviews) { - node->flags |= NODE_FLG_VIEWS; - } - } - - /* - * Inside the views special node, marking the new node as a view - * instance. - */ - else if (curnode->flags & NODE_FLG_VIEWS) - { - node->flags |= NODE_FLG_VIEW; - } - - /* - * Knowing that a node is a zone instance doesn't seems needed right - * now... I'm leaving the code below for now, just in case, but likely - * to be removed later. - */ - - /* - * Inside a view instance node, looking for the zones special node. - */ - else if (curnode->flags & NODE_FLG_VIEW && - hash == isc__cfgmgr_hashzones) - { - node->flags |= NODE_FLG_ZONES; - } - - /* - * Inside a view zones special instance node, marking the new node as a - * zone instance node - */ - else if (curnode->flags & NODE_FLG_ZONES) - { - node->flags |= NODE_FLG_ZONE; - } -} - -void -isc_cfgmgr_open(const char *name) { - isc__cfgmgr_node_t *node = NULL; - - isc__cfgmgr_checkontransaction(); - REQUIRE(name != NULL); - - node = isc_mem_get(isc__cfgmgr_mctx, sizeof(*node)); - *node = (isc__cfgmgr_node_t){ - .name = isc_mem_allocate(isc__cfgmgr_mctx, strlen(name) + 1), - .prefix = isc_mem_get(isc__cfgmgr_mctx, BUFLEN), - .link = ISC_LINK_INITIALIZER, - }; - - strcpy(node->name, name); - REQUIRE(snprintf(node->prefix, BUFLEN, "%s%s/", isc__cfgmgr_curprefix(), - name) < BUFLEN); - - node->hash = isc_hash32(node->prefix, strlen(node->prefix), true); - INSIST(node->hash > 0); - - isc__cfgmgr_setnodeflags(node); - - if (isc__cfgmgr_ctx.readonly == false) { - isc__cfgmgr_addindex(isc__cfgmgr_ctx.builtincursor, name); - isc__cfgmgr_addindex(isc__cfgmgr_ctx.usercursor, name); - isc__cfgmgr_addindex(isc__cfgmgr_ctx.runningcursor, name); - } - - ISC_LIST_APPEND(isc__cfgmgr_ctx.openednodes, node, link); -} - static bool isc__cfgmgr_keymatches(const unsigned char *foundkey, char flag, uint32_t hash) { @@ -669,65 +592,200 @@ isc__cfgmgr_findprefix(MDB_cursor *cursor, char flag, uint32_t hash, } static void -isc__cfgmgr_clearindex(MDB_cursor *cursor, uint32_t hash, const char *prefix) { - MDB_val dbkey; - char key[BUFLEN]; +isc__cfgmgr_addindex(const isc__cfgmgr_node_t *node) { + isc__cfgmgr_node_t *parent; + uint32_t parenthash; + char k[BUFLEN]; + size_t klen; + void *v; + size_t vlen; - if (isc__cfgmgr_findprefix(cursor, PROPERTYFLG, hash, prefix, NULL, - NULL)) - { - /* - * There still are properties in the closed node. Keep its index - * in the parent. - */ + if (node == NULL) { return; } + parent = ISC_LIST_PREV(node, link); + parenthash = parent ? parent->hash + : isc_hash32("/", strlen("/"), false); - if (isc__cfgmgr_findprefix(cursor, NODEINDEXFLG, hash, prefix, NULL, - NULL)) + /* + * Add the index of the node into it's parent node + */ + isc__cfgmgr_buildkey(k, sizeof(k), NODEINDEXFLG, parenthash, "%s", + node->prefix); + klen = isc__cfgmgr_keylen(k) + 1; + v = (void *)node->name; + vlen = strlen(node->name) + 1; + isc__cfgmgr_dbput(isc__cfgmgr_dbcursor(), k, klen, v, vlen); + + /* + * Attempt to index the parent + */ + isc__cfgmgr_addindex(parent); +} + +static void +isc__cfgmgr_clearindex(const isc__cfgmgr_node_t *node) { + char key[BUFLEN]; + isc__cfgmgr_node_t *parent; + uint32_t parenthash; + size_t keylen; + + if (node == NULL) { + return; + } + parent = ISC_LIST_PREV(node, link); + parenthash = parent ? parent->hash + : isc_hash32("/", strlen("/"), false); + + isc__cfgmgr_buildkey(key, sizeof(key), NODEINDEXFLG, parenthash, "%s", + node->prefix); + keylen = isc__cfgmgr_keylen(key) + 1; + + if (isc__cfgmgr_findprefix(isc__cfgmgr_dbcursor(), PROPERTYFLG, + node->hash, node->prefix, NULL, NULL)) { /* - * There still are sub-nodes indexes in the closed node. Keep + * There still are properties in the closed node. Keep * its index in the parent. */ return; } + if (isc__cfgmgr_findprefix(isc__cfgmgr_dbcursor(), NODEINDEXFLG, + node->hash, node->prefix, NULL, NULL)) + { + /* + * There still are sub-nodes indexes in the closed node. + * Keep its index in the parent. + */ + return; + } + /* - * No properties or sub-node indexes found in the closed node. Delete - * the index of the closed node from it's parent node: the closed node - * doesn't exists anymore. + * No properties or sub-node indexes found in the closed node. + * Delete the index of the closed node from it's parent node: + * the closed node doesn't exists anymore. */ - isc__cfgmgr_buildkey(key, sizeof(key), NODEINDEXFLG, - isc__cfgmgr_curhash(), "%s", prefix); - dbkey.mv_size = isc__cfgmgr_keylen(key) + 1; - dbkey.mv_data = key; - REQUIRE(mdb_cursor_get(cursor, &dbkey, NULL, MDB_SET) == 0); - REQUIRE(mdb_cursor_del(cursor, 0) == 0); + isc__cfgmgr_dbdel(isc__cfgmgr_dbcursor(), key, keylen); + isc__cfgmgr_clearindex(parent); +} + +static void +isc__cfgmgr_setnodetype(const isc__cfgmgr_node_t *curnode, + isc__cfgmgr_node_t *node) { + uint32_t hash = isc_hash32(node->name, strlen(node->name), false); + + node->type = ISC__CFGMGR_NODEGENERIC; + + if (curnode == NULL) { + if (hash == isc__cfgmgr_hashoptions) { + node->type = ISC__CFGMGR_NODEOPTIONS; + } else if (hash == isc__cfgmgr_hashviews) { + node->type = ISC__CFGMGR_NODEVIEWS; + } + } else { + switch (curnode->type) { + case ISC__CFGMGR_NODEOPTIONS: + case ISC__CFGMGR_NODESUBOPTIONS: + node->type = ISC__CFGMGR_NODESUBOPTIONS; + break; + case ISC__CFGMGR_NODEVIEWS: + node->type = ISC__CFGMGR_NODEVIEW; + break; + case ISC__CFGMGR_NODEVIEW: + if (hash == isc__cfgmgr_hashzones) { + node->type = ISC__CFGMGR_NODEZONES; + } else { + node->type = ISC__CFGMGR_NODESUBVIEW; + } + break; + case ISC__CFGMGR_NODESUBVIEW: + node->type = ISC__CFGMGR_NODESUBVIEW; + break; + case ISC__CFGMGR_NODEZONES: + node->type = ISC__CFGMGR_NODEZONE; + break; + case ISC__CFGMGR_NODEZONE: + node->type = ISC__CFGMGR_NODEZONE; + break; + default: + break; + } + } +} + +static void +isc__cfgmgr_open(isc__cfgmgr_nodes_t *path, const char *name, + bool materialize) { + isc__cfgmgr_node_t *node = NULL; + isc__cfgmgr_node_t *curnode = ISC_LIST_TAIL(*path); + const char *prefix = curnode ? curnode->prefix : "/"; + + node = isc_mem_get(isc__cfgmgr_mctx, sizeof(*node)); + *node = (isc__cfgmgr_node_t){ + .name = isc_mem_allocate(isc__cfgmgr_mctx, strlen(name) + 1), + .prefix = isc_mem_get(isc__cfgmgr_mctx, BUFLEN), + .link = ISC_LINK_INITIALIZER, + }; + + strcpy(node->name, name); + REQUIRE(snprintf(node->prefix, BUFLEN, "%s%s/", prefix, name) < BUFLEN); + + node->hash = isc_hash32(node->prefix, strlen(node->prefix), true); + INSIST(node->hash > 0); + + isc__cfgmgr_setnodetype(curnode, node); + + ISC_LIST_APPEND(*path, node, link); + + /* + * If builtin or user options/view property has been set but the running + * zone has not been created yet. + * + * Note: currently it re-apply all properties which must be materialized + * when opening a zone on write mode. It means that it re-run + * materialization even on zones which already exists (hence, already + * has materialized properties). This is fine fron correctness POV + * (because matrialization rules won't override a property set on + * running mode), but obviously not from performance POV, so this needs + * to be tweaked to not re-run this flow in such case. + */ + if (isc__cfgmgr_ctx.readonly == false && materialize && + isc__cfgmgr_ctx.mode == ISC_CFGMGR_MODERUNNING && + node->type == ISC__CFGMGR_NODEZONE) + { + // isc__cfgmgr_nodes_t path = ISC_LIST_INITIALIZER; + // isc__cfgmgr_materializectx_t ctx; + } } void -isc_cfgmgr_close(void) { +isc_cfgmgr_open(const char *name) { + isc__cfgmgr_checkontransaction(); + REQUIRE(name != NULL); + + isc__cfgmgr_open(&isc__cfgmgr_ctx.path, name, true); +} + +static void +isc__cfgmgr_close(isc__cfgmgr_nodes_t *path) { isc__cfgmgr_node_t *node; - isc__cfgmgr_checkopenednodes(); - node = isc__cfgmgr_curnode(); - ISC_LIST_UNLINK(isc__cfgmgr_ctx.openednodes, node, link); - - if (isc__cfgmgr_ctx.readonly == false) { - isc__cfgmgr_clearindex(isc__cfgmgr_ctx.builtincursor, - node->hash, node->prefix); - isc__cfgmgr_clearindex(isc__cfgmgr_ctx.usercursor, node->hash, - node->prefix); - isc__cfgmgr_clearindex(isc__cfgmgr_ctx.runningcursor, - node->hash, node->prefix); - } + node = ISC_LIST_TAIL(*path); + ISC_LIST_UNLINK(*path, node, link); isc_mem_free(isc__cfgmgr_mctx, node->name); isc_mem_put(isc__cfgmgr_mctx, node->prefix, BUFLEN); isc_mem_put(isc__cfgmgr_mctx, node, sizeof(*node)); } +void +isc_cfgmgr_close(void) { + isc__cfgmgr_checkopenednodes(); + + isc__cfgmgr_close(&isc__cfgmgr_ctx.path); +} + static void isc__cfgmgr_delsubnode(void *state, const char *name) { UNUSED(state); @@ -736,6 +794,10 @@ isc__cfgmgr_delsubnode(void *state, const char *name) { isc_cfgmgr_delnode(); } +/* + * TODO Rewrite this using _foreach APIs + * This should make materialization automatic (and simplify the implementation) + */ void isc_cfgmgr_delnode(void) { isc__cfgmgr_checkopenednodes(); @@ -745,16 +807,21 @@ isc_cfgmgr_delnode(void) { /* * Delete all node properties. */ - if (isc__cfgmgr_findprefix(isc__cfgmgr_lmdbcursor(), - PROPERTYFLG, isc__cfgmgr_curhash(), + if (isc__cfgmgr_findprefix(isc__cfgmgr_dbcursor(), PROPERTYFLG, + isc__cfgmgr_curhash(), isc__cfgmgr_curprefix(), NULL, NULL) == false) { break; } - REQUIRE(mdb_cursor_del(isc__cfgmgr_lmdbcursor(), 0) == 0); + REQUIRE(mdb_cursor_del(isc__cfgmgr_dbcursor(), 0) == 0); } while (1); + /* + * Delete its index + */ + isc__cfgmgr_clearindex(isc__cfgmgr_curnode()); + /* * Then delete node sub-nodes */ @@ -791,27 +858,24 @@ isc__cfgmgr_valuesz(const isc_cfgmgr_val_t *value) { } static isc_result_t -isc__cfgmgr_read(MDB_cursor *cursor, const char *name, isc_cfgmgr_val_t *value, - isc_cfgmgr_mode_t *modep) { +isc__cfgmgr_read(const isc__cfgmgr_node_t *node, const char *name, + isc_cfgmgr_val_t *value, uint8_t *levelp) { isc_result_t result = ISC_R_SUCCESS; MDB_val dbkey; MDB_val dbval; - isc_cfgmgr_mode_t mode; - char key[BUFLEN]; + uint8_t level; isc_buffer_t b; isc_region_t r; + char key[BUFLEN]; - isc__cfgmgr_checkopenednodes(); - REQUIRE(name != NULL); - REQUIRE(value != NULL); - - isc__cfgmgr_buildkey(key, sizeof(key), PROPERTYFLG, - isc__cfgmgr_curhash(), "%s%s", - isc__cfgmgr_curprefix(), name); + isc__cfgmgr_buildkey(key, sizeof(key), PROPERTYFLG, node->hash, "%s%s", + node->prefix, name); dbkey = (MDB_val){ .mv_size = isc__cfgmgr_keylen(key) + 1, - .mv_data = key }; + .mv_data = (char *)key }; - if (mdb_cursor_get(cursor, &dbkey, &dbval, MDB_SET) != 0) { + if (mdb_cursor_get(isc__cfgmgr_dbcursor(), &dbkey, &dbval, MDB_SET) != + 0) + { result = ISC_R_NOTFOUND; goto out; } @@ -820,9 +884,9 @@ isc__cfgmgr_read(MDB_cursor *cursor, const char *name, isc_cfgmgr_val_t *value, isc_buffer_add(&b, dbval.mv_size); value->type = isc_buffer_getuint8(&b); - mode = isc_buffer_getuint8(&b); - if (modep) { - *modep = mode; + level = isc_buffer_getuint8(&b); + if (levelp) { + *levelp = level; } switch (value->type) { @@ -852,137 +916,44 @@ out: isc_result_t isc_cfgmgr_read(const char *name, isc_cfgmgr_val_t *value) { - return isc__cfgmgr_read(isc__cfgmgr_lmdbcursor(), name, value, NULL); + isc__cfgmgr_checkopenednodes(); + REQUIRE(name != NULL); + REQUIRE(value != NULL); + + return isc__cfgmgr_read(isc__cfgmgr_curnode(), name, value, NULL); } +static void +isc__cfgmgr_materialize(const char *name, const isc_cfgmgr_val_t *value, + uint8_t level); + static isc_result_t -isc__cfgmgr_write(MDB_cursor *cursor, const char *name, - const isc_cfgmgr_val_t *value, bool materialize); - -typedef struct isc__cfgmgr_materializeprop isc__cfgmgr_materializeprop_t; -struct isc__cfgmgr_materializeprop { - const char *name; - const isc_cfgmgr_val_t *value; -}; - -static void -isc__cfgmgr_materialize_apply(void *state, const char *nodename) { - isc_cfgmgr_mode_t valmode; - isc_cfgmgr_val_t val; - isc_result_t result; - isc__cfgmgr_materializeprop_t *property = state; - - UNUSED(nodename); - - result = isc__cfgmgr_read(isc__cfgmgr_ctx.runningcursor, property->name, - &val, &valmode); - INSIST(result == ISC_R_NOTFOUND || result == ISC_R_SUCCESS); - - if ((result == ISC_R_NOTFOUND && property->value != NULL) || - (result == ISC_R_SUCCESS && valmode <= isc__cfgmgr_ctx.mode)) - { - REQUIRE(isc__cfgmgr_write(isc__cfgmgr_ctx.runningcursor, - property->name, property->value, - false) == ISC_R_SUCCESS); - } -} - -static void -isc__cfgmgr_materialize_foreachview(void *state, const char *nodename) { - UNUSED(nodename); - - isc_cfgmgr_open("zones"); - isc_cfgmgr_foreachnodes(isc__cfgmgr_materialize_apply, state); - isc_cfgmgr_close(); -} - -static void -isc__cfgmgr_materialize_zone(isc__cfgmgr_materializeprop_t *property, - bool inview) { - if (inview) { - isc_cfgmgr_open("zones"); - isc_cfgmgr_foreachnodes(isc__cfgmgr_materialize_apply, property); - isc_cfgmgr_close(); - } else { - isc_cfgmgr_open("views"); - isc_cfgmgr_foreachnodes(isc__cfgmgr_materialize_foreachview, - property); - isc_cfgmgr_close(); - } -} - -/* - * There is an issue with the materialization on zone: it will copy _all_ - * options properties/sub-nodes into each zones. While this is not a problem for - * reading data (nobody will attempt to read data not expected to be in a zone) - * this will be a problem when dumping the zone. - * - * This is probably something to figure out with the validation of the - * configuration, which could be used as a filter in the copy callbacks during - * the materialization. - * - * isc_cfgmgr_delnode doest not supports materialization (i.e. it won't remove - * deleted properties if they hasn't been overriden). Not sure the _delnode API - * is actually useful. If it is (and we keep it) then it needs to be fixed. - */ -static void -isc__cfgmgr_materialize(const char *name, const isc_cfgmgr_val_t *value) { - isc__cfgmgr_node_t *node = isc__cfgmgr_curnode(); - isc__cfgmgr_materializeprop_t property = { .name = name, - .value = value }; - - if (isc__cfgmgr_ctx.mode == ISC_CFGMGR_MODERUNNING) { - return; - } - - if (node->flags & NODE_FLG_OPTIONS) { - /* - * Materialization of the changed options property in the - * running options node as well as all the running zones. - */ - isc__cfgmgr_materialize_apply(&property, NULL); - isc__cfgmgr_materialize_zone(&property, false); - } else if (node->flags & NODE_FLG_VIEW) { - /* - * Materialization of the changed view property in all its - * running zones - */ - isc__cfgmgr_materialize_zone(&property, true); - } -} - -static isc_result_t -isc__cfgmgr_write(MDB_cursor *cursor, const char *name, - const isc_cfgmgr_val_t *value, bool materialize) { +isc__cfgmgr_write(const isc__cfgmgr_node_t *node, const char *name, + const isc_cfgmgr_val_t *value, uint8_t level, + bool materialize) { isc_result_t result = ISC_R_SUCCESS; MDB_val dbkey; MDB_val dbval; - char key[BUFLEN]; isc_buffer_t b; isc_region_t r; char *bdata; + char key[BUFLEN]; - isc__cfgmgr_checkopenednodes(); - REQUIRE(isc__cfgmgr_ctx.readonly == false); - REQUIRE(name != NULL); - REQUIRE((value != NULL && value->type != ISC_CFGMGR_UNDEFINED) || - value == NULL); - - isc__cfgmgr_buildkey(key, sizeof(key), PROPERTYFLG, - isc__cfgmgr_curhash(), "%s%s", - isc__cfgmgr_curprefix(), name); + isc__cfgmgr_buildkey(key, sizeof(key), PROPERTYFLG, node->hash, "%s%s", + node->prefix, name); dbkey = (MDB_val){ .mv_size = isc__cfgmgr_keylen(key) + 1, - .mv_data = key }; + .mv_data = (char *)key }; if (value == NULL) { - if (mdb_cursor_get(cursor, &dbkey, NULL, MDB_SET) == - MDB_NOTFOUND) + if (mdb_cursor_get(isc__cfgmgr_dbcursor(), &dbkey, NULL, + MDB_SET) == MDB_NOTFOUND) { result = ISC_R_NOTFOUND; goto out; } - REQUIRE(mdb_cursor_del(cursor, 0) == 0); + REQUIRE(mdb_cursor_del(isc__cfgmgr_dbcursor(), 0) == 0); + isc__cfgmgr_clearindex(node); goto out; } @@ -992,7 +963,8 @@ isc__cfgmgr_write(MDB_cursor *cursor, const char *name, dbval.mv_data = isc_buffer_base(&b); isc_buffer_putuint8(&b, value->type); - isc_buffer_putuint8(&b, isc__cfgmgr_ctx.mode); + isc_buffer_putuint8(&b, level); + switch (value->type) { case ISC_CFGMGR_UNDEFINED: UNREACHABLE(); @@ -1016,19 +988,58 @@ isc__cfgmgr_write(MDB_cursor *cursor, const char *name, break; } - REQUIRE(mdb_cursor_put(cursor, &dbkey, &dbval, 0) == 0); + REQUIRE(mdb_cursor_put(isc__cfgmgr_dbcursor(), &dbkey, &dbval, 0) == 0); isc_mem_free(isc__cfgmgr_mctx, dbval.mv_data); + isc__cfgmgr_addindex(node); out: if (materialize) { - isc__cfgmgr_materialize(name, value); + isc__cfgmgr_materialize(name, value, level); } return result; } isc_result_t isc_cfgmgr_write(const char *name, const isc_cfgmgr_val_t *value) { - return isc__cfgmgr_write(isc__cfgmgr_lmdbcursor(), name, value, true); + isc__cfgmgr_node_t *node; + uint8_t level = 0; + isc_cfgmgr_mode_t mode = isc__cfgmgr_ctx.mode; + + isc__cfgmgr_checkopenednodes(); + REQUIRE(isc__cfgmgr_ctx.readonly == false); + REQUIRE(name != NULL); + REQUIRE((value != NULL && value->type != ISC_CFGMGR_UNDEFINED) || + value == NULL); + + node = isc__cfgmgr_curnode(); + + /* + * /views and /views//zones/ are containers for views and + * zones, therefore they can't have values in there. + */ + REQUIRE(node->type != ISC__CFGMGR_NODEVIEWS); + REQUIRE(node->type != ISC__CFGMGR_NODEZONES); + + /* + * Set rules allowing materialization overrides of existing values. A + * value with a bigger level can't override a value of a lower level. + * See isc__cfgmgr_materialize_apply. + */ + if (node->type == ISC__CFGMGR_NODEZONE) { + level = 0; + } else if (node->type == ISC__CFGMGR_NODEVIEW) { + level = 1; + } else if (mode == ISC_CFGMGR_MODERUNNING) { + level = 2; + } else if (mode == ISC_CFGMGR_MODEUSER) { + level = 3; + } else if (mode == ISC_CFGMGR_MODEBUILTIN) { + level = 4; + } else { + UNREACHABLE(); + } + + return isc__cfgmgr_write(node, name, value, level, true); } typedef struct isc__cfgmgr_foreachlambda isc__cfgmgr_foreachlambda_t; @@ -1040,22 +1051,24 @@ struct isc__cfgmgr_foreachlambda { }; static void -isc__cfgmgr_foreachmatch(char flag, +isc__cfgmgr_foreachmatch(isc__cfgmgr_nodes_t *path, char flag, void (*match)(void *lambda, const char *matchedkey), void *lambda) { MDB_cursor *cursor; unsigned char *foundkey = NULL; size_t foundkeylen = 0; - uint32_t curhash = isc__cfgmgr_curhash(); bool found; + isc__cfgmgr_node_t *node = ISC_LIST_TAIL(*path); + uint32_t curhash = node ? node->hash + : isc_hash32("/", strlen("/"), false); + const char *curprefix = node ? node->prefix : "/"; isc__cfgmgr_checkontransaction(); - REQUIRE(mdb_cursor_open(isc__cfgmgr_ctx.txn, isc__cfgmgr_lmdbdbi(), + REQUIRE(mdb_cursor_open(isc__cfgmgr_ctx.txn, isc__cfgmgr_dbi(), &cursor) == 0); - found = isc__cfgmgr_findprefix(cursor, flag, curhash, - isc__cfgmgr_curprefix(), &foundkey, - &foundkeylen); + found = isc__cfgmgr_findprefix(cursor, flag, curhash, curprefix, + &foundkey, &foundkeylen); while (found) { MDB_val dbkey; @@ -1116,37 +1129,233 @@ isc__cfgmgr_foreachmatch(char flag, } static void -isc__cfgmgr_foreachnodes(void *voidlambda, const char *name) { - isc__cfgmgr_foreachlambda_t *lambda = voidlambda; +isc__cfgmgr_foreachmatchednodes(void *voidclosure, const char *name) { + isc__cfgmgr_foreachlambda_t *closure = voidclosure; - lambda->nodefn(lambda->env, name); + closure->nodefn(closure->env, name); +} + +static void +isc__cfgmgr_foreachnodes(isc__cfgmgr_nodes_t *path, + void (*action)(void *state, const char *name), + void *state) { + isc__cfgmgr_foreachlambda_t closure = { .nodefn = action, + .env = state }; + + isc__cfgmgr_foreachmatch(path, NODEINDEXFLG, + isc__cfgmgr_foreachmatchednodes, &closure); } void isc_cfgmgr_foreachnodes(void (*action)(void *state, const char *name), void *state) { - isc__cfgmgr_foreachlambda_t lambda = { .nodefn = action, .env = state }; - - isc__cfgmgr_foreachmatch(NODEINDEXFLG, isc__cfgmgr_foreachnodes, - &lambda); + isc__cfgmgr_foreachnodes(&isc__cfgmgr_ctx.path, action, state); } static void -isc__cfgmgr_foreachproperties(void *voidlambda, const char *name) { - isc__cfgmgr_foreachlambda_t *lambda = voidlambda; +isc__cfgmgr_foreachproperties(void *voidclosure, const char *name) { + isc__cfgmgr_foreachlambda_t *closure = voidclosure; isc_cfgmgr_val_t val; REQUIRE(isc_cfgmgr_read(name, &val) == ISC_R_SUCCESS); - lambda->propertyfn(lambda->env, name, &val); + closure->propertyfn(closure->env, name, &val); } void isc_cfgmgr_foreachproperties(void (*action)(void *state, const char *name, const isc_cfgmgr_val_t *val), void *state) { - isc__cfgmgr_foreachlambda_t lambda = { .propertyfn = action, - .env = state }; + isc__cfgmgr_foreachlambda_t closure = { .propertyfn = action, + .env = state }; - isc__cfgmgr_foreachmatch(PROPERTYFLG, isc__cfgmgr_foreachproperties, - &lambda); + isc__cfgmgr_foreachmatch(&isc__cfgmgr_ctx.path, PROPERTYFLG, + isc__cfgmgr_foreachproperties, &closure); +} +typedef struct isc__cfgmgr_materializectx isc__cfgmgr_materializectx_t; +struct isc__cfgmgr_materializectx { + isc__cfgmgr_nodes_t path; + const isc__cfgmgr_node_t *origin; + const char *name; + const isc_cfgmgr_val_t *value; + uint8_t level; +}; + +static void +isc__cfgmgr_materialize_apply(void *state, const char *nodename) { + uint8_t vallevel; + isc_cfgmgr_val_t val; + isc_result_t result; + isc__cfgmgr_materializectx_t *ctx = state; + const isc__cfgmgr_node_t *node; + size_t nclose = 1; + + /* + * If the node being written to is options, it is already opened and we + * don't need the alternative path. So the node to update is simply the + * origin (only the mode changed, which isc__cfgmgr_materialize does). + * However, if a name is provided, then we're materializing a value into + * something else than options, and we're using the alternative path + * here. + */ + if (nodename != NULL) { + isc__cfgmgr_open(&ctx->path, nodename, false); + + /* + * Because the materialized value might be in a nested node, we + * first walk backwards the "standard" path from origin until we + * find either the views node or the options node. Then we walk + * forward, building the remaining part of the "standard" path + * up to origin into the alternative one. + */ + node = ctx->origin; + while (node->type != ISC__CFGMGR_NODEVIEW && + node->type != ISC__CFGMGR_NODEOPTIONS) + { + node = ISC_LIST_PREV(node, link); + INSIST(node != NULL); + } + + while (node != ctx->origin) { + node = ISC_LIST_NEXT(node, link); + isc__cfgmgr_open(&ctx->path, node->name, false); + nclose++; + } + + node = ISC_LIST_TAIL(ctx->path); + } else { + node = ctx->origin; + } + + result = isc__cfgmgr_read(node, ctx->name, &val, &vallevel); + INSIST(result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND); + + if (result == ISC_R_NOTFOUND) { + if (ctx->value == NULL) { + goto out; + } + goto write; + } + + if (vallevel >= ctx->level) { + goto write; + } + + goto out; + +write: + REQUIRE(isc__cfgmgr_write(node, ctx->name, ctx->value, ctx->level, + false) == ISC_R_SUCCESS); + +out: + if (nodename != NULL) { + while (nclose > 0) { + isc__cfgmgr_close(&ctx->path); + nclose--; + } + } +} + +static void +isc__cfgmgr_materialize_foreachview(void *state, const char *nodename) { + isc__cfgmgr_materializectx_t *ctx = state; + + isc__cfgmgr_open(&ctx->path, nodename, false); + isc__cfgmgr_open(&ctx->path, ZONES, false); + isc__cfgmgr_foreachnodes(&ctx->path, isc__cfgmgr_materialize_apply, + state); + isc__cfgmgr_close(&ctx->path); + isc__cfgmgr_close(&ctx->path); +} + +/* + * Important notes about materialization + * + * 1. It will copy _all_ options properties/sub-nodes into each zones. While + * this is not a problem for reading data (nobody will attempt to read data + * not expected to be in a zone) this will be a problem when dumping the + * zone. This is probably something to figure out with the validation of the + * configuration, which could be used as a filter in the copy callbacks + * during the materialization. + * + * 2. isc_cfgmgr_delnode doest not supports materialization - needs to be done + */ +static void +isc__cfgmgr_materialize(const char *name, const isc_cfgmgr_val_t *value, + uint8_t level) { + isc__cfgmgr_materializectx_t ctx = { .origin = isc__cfgmgr_curnode(), + .name = name, + .value = value, + .level = level }; + isc_cfgmgr_mode_t curmode = isc__cfgmgr_ctx.mode; + bool runningmode = curmode == ISC_CFGMGR_MODERUNNING; + + if (ctx.origin->type == ISC__CFGMGR_NODEOPTIONS || + ctx.origin->type == ISC__CFGMGR_NODESUBOPTIONS) + { + /* + * Materialization of builtin/user options node into running + * options node. We can safely re-use the "standard" path + * (isc__cfgmgr_ctx.path) as the path to apply the values + * is the same. + * + * Note that, because the "options" node is the same in all + * modes, even if the options node never been written in running + * mode, it gets automatically materialized. + * + * This is not true for zones (as we don't know ahead the zone + * names) so specific code to apply materialization of existing + * properties into a new zone must be called from + * isc__cfgmgr_open). + */ + if (runningmode == false) { + isc__cfgmgr_ctx.mode = ISC_CFGMGR_MODERUNNING; + isc__cfgmgr_materialize_apply(&ctx, NULL); + isc__cfgmgr_ctx.mode = curmode; + } + + /* + * Materialization of options into the running zones. This time, + * the path to apply the values is not the same than then + * "standard" path. So we build an alternative path in the + * materialization context. + */ + isc__cfgmgr_ctx.mode = ISC_CFGMGR_MODERUNNING; + + ISC_LIST_INIT(ctx.path); + isc__cfgmgr_open(&ctx.path, VIEWS, false); + isc__cfgmgr_foreachnodes( + &ctx.path, isc__cfgmgr_materialize_foreachview, &ctx); + isc__cfgmgr_close(&ctx.path); + INSIST(ISC_LIST_EMPTY(ctx.path)); + + isc__cfgmgr_ctx.mode = curmode; + } else if (runningmode && (ctx.origin->type == ISC__CFGMGR_NODEVIEW || + ctx.origin->type == ISC__CFGMGR_NODESUBVIEW)) + { + const isc__cfgmgr_node_t *views; + const isc__cfgmgr_node_t *view; + + /* + * Materialization of a running view property defined inside a + * view. As for the materialization of the options properties, + * the path is not the same as the materialization occurs inside + * the zones. Let's build an alternative path here as well. + */ + views = ISC_LIST_HEAD(isc__cfgmgr_ctx.path); + REQUIRE(views && views->type == ISC__CFGMGR_NODEVIEWS); + + view = ISC_LIST_NEXT(views, link); + REQUIRE(view && view->type == ISC__CFGMGR_NODEVIEW); + + ISC_LIST_INIT(ctx.path); + isc__cfgmgr_open(&ctx.path, VIEWS, false); + isc__cfgmgr_open(&ctx.path, view->name, false); + isc__cfgmgr_open(&ctx.path, ZONES, false); + isc__cfgmgr_foreachnodes(&ctx.path, + isc__cfgmgr_materialize_apply, &ctx); + isc__cfgmgr_close(&ctx.path); + isc__cfgmgr_close(&ctx.path); + isc__cfgmgr_close(&ctx.path); + INSIST(ISC_LIST_EMPTY(ctx.path)); + } } diff --git a/tests/isc/cfgmgr_test.c b/tests/isc/cfgmgr_test.c index 2b9027f138..1192d005db 100644 --- a/tests/isc/cfgmgr_test.c +++ b/tests/isc/cfgmgr_test.c @@ -1087,142 +1087,6 @@ ISC_RUN_TEST_IMPL(isc_cfgmgr_threads) { // isc_cfgmgr_deinit(); // } -// ISC_RUN_TEST_IMPL(isc_cfgmgr_getparent) { -// isc_result_t result; -// isc_cfgmgr_val_t val; -// -// result = isc_cfgmgr_init(mctx, TEST_DBPATH, NULL); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_rwtransaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// assert_int_equal(isc_cfgmgr_open("foo"), ISC_R_NOTFOUND); -// assert_int_equal(isc_cfgmgr_open("bar"), ISC_R_NOTFOUND); -// assert_int_equal(isc_cfgmgr_open("baz"), ISC_R_NOTFOUND); -// -// isc_cfgmgr_newclause("foo"); -// -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 42 }; -// result = isc_cfgmgr_write("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_newclause("bar"); -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 24 }; -// result = isc_cfgmgr_write("prop2", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_newclause("baz"); -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 999 }; -// result = isc_cfgmgr_write("prop3", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_commit(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_transaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_open("foo"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_read("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 42); -// -// /* -// * prop2 and prop3 are in child clauses, can't be found -// */ -// result = isc_cfgmgr_read("prop2", &val); -// assert_int_equal(result, ISC_R_NOTFOUND); -// result = isc_cfgmgr_read("prop3", &val); -// assert_int_equal(result, ISC_R_NOTFOUND); -// -// /* -// * open the child bar clause and it gets possible to read prop2 _and_ -// * prop1 (thanks to readparent flow) but still not prop3 as it's in a -// * child clause -// */ -// result = isc_cfgmgr_open("bar"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_read("prop2", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 24); -// -// result = isc_cfgmgr_read("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 42); -// -// result = isc_cfgmgr_read("prop3", &val); -// assert_int_equal(result, ISC_R_NOTFOUND); -// -// /* -// * finally open the baz clause (nested in bar), all properties can be -// * read -// */ -// result = isc_cfgmgr_open("baz"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_read("prop3", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 999); -// -// result = isc_cfgmgr_read("prop2", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 24); -// -// result = isc_cfgmgr_read("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 42); -// -// result = isc_cfgmgr_commit(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// /* -// * bar override prop1, so it has its own prop1 (and this doesn't affect -// * the one in foo, but baz now see the overriden one) -// */ -// result = isc_cfgmgr_rwtransaction(); -// -// assert_int_equal(result, ISC_R_SUCCESS); -// result = isc_cfgmgr_open("foo"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_open("bar"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// val.uint32 = 42424242; -// result = isc_cfgmgr_write("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_open("baz"); -// val.uint32 = 0; -// result = isc_cfgmgr_read("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.uint32, 42424242); -// -// /* -// * Let's go back to foo and make sure we still have 42 for prop1 -// * there... -// */ -// isc_cfgmgr_close(); -// isc_cfgmgr_close(); -// -// result = isc_cfgmgr_read("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.uint32, 42); -// -// isc_cfgmgr_commit(); -// isc_cfgmgr_deinit(); -// } - ISC_RUN_TEST_IMPL(isc_cfgmgr_opentests) { isc_result_t result; isc_cfgmgr_val_t val = { .type = ISC_CFGMGR_UINT32, .uint32 = 1234 }; @@ -1459,7 +1323,7 @@ struct isc__cfgmgr_dump { size_t indent; size_t lvl; isc_buffer_t buffer; - char data[1024]; + char data[2048]; }; static void @@ -1506,7 +1370,6 @@ isc__cfgmgr_dumptestnode(void *state, const char *name) { isc_buffer_putstr(&dump->buffer, " "); } isc_buffer_printf(&dump->buffer, "};\n"); - } static void @@ -1584,29 +1447,28 @@ ISC_RUN_TEST_IMPL(isc_cfgmgr_dumptests) { isc_cfgmgr_commit(); isc_cfgmgr_transaction(); - cmpdump(ISC_CFGMGR_MODERUNNING, - "bar {\n" - " another-stuff barstr;\n" - " propbar1 42;\n" - "};\n" - "foo {\n" - " foo1 {\n" - " foo11 {\n" - " fooprop 123;\n" - " };\n" - " foo12 {\n" - " fooprop 456;\n" - " prop 123;\n" - " };\n" - " foo13 {\n" - " fooprop 789;\n" - " prop 123;\n" - " };\n" - " };\n" - " foo2 {\n" - " another-foo-stuff foo2str;\n" - " };\n" - "};\n"); + cmpdump(ISC_CFGMGR_MODERUNNING, "bar {\n" + " another-stuff barstr;\n" + " propbar1 42;\n" + "};\n" + "foo {\n" + " foo1 {\n" + " foo11 {\n" + " fooprop 123;\n" + " };\n" + " foo12 {\n" + " fooprop 456;\n" + " prop 123;\n" + " };\n" + " foo13 {\n" + " fooprop 789;\n" + " prop 123;\n" + " };\n" + " };\n" + " foo2 {\n" + " another-foo-stuff foo2str;\n" + " };\n" + "};\n"); isc_cfgmgr_rollback(); result = isc_cfgmgr_rwtransaction(); @@ -1635,17 +1497,115 @@ ISC_RUN_TEST_IMPL(isc_cfgmgr_dumptests) { isc_cfgmgr_close(); isc_cfgmgr_close(); - cmpdump(ISC_CFGMGR_MODERUNNING, - "bar {\n" - " another-stuff barstr;\n" - " propbar1 42;\n" - "};\n" - "foo {\n" - " propfoo 987;\n" - " foo14 {\n" - " anotherpropfoo14 654;\n" - " };\n" - "};\n"); + cmpdump(ISC_CFGMGR_MODERUNNING, "bar {\n" + " another-stuff barstr;\n" + " propbar1 42;\n" + "};\n" + "foo {\n" + " propfoo 987;\n" + " foo14 {\n" + " anotherpropfoo14 654;\n" + " };\n" + "};\n"); + + isc_cfgmgr_rollback(); + isc_cfgmgr_deinit(); +} + +ISC_RUN_TEST_IMPL(isc_cfgmgr_materialziation_options) { + isc_result_t result; + isc_cfgmgr_val_t val; + + result = isc_cfgmgr_init(mctx, TEST_DBPATH); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_cfgmgr_rwtransaction(); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_cfgmgr_open("options"); + + isc_cfgmgr_setmode(ISC_CFGMGR_MODEBUILTIN); + + isc_cfgmgr_open("sub"); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 1111 }; + result = isc_cfgmgr_write("prop1", &val); + assert_int_equal(result, ISC_R_SUCCESS); + isc_cfgmgr_close(); + + isc_cfgmgr_setmode(ISC_CFGMGR_MODERUNNING); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 31 }; + result = isc_cfgmgr_write("prop1", &val); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_cfgmgr_setmode(ISC_CFGMGR_MODEBUILTIN); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 1 }; + result = isc_cfgmgr_write("prop1", &val); + assert_int_equal(result, ISC_R_SUCCESS); + + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 2 }; + result = isc_cfgmgr_write("prop2", &val); + assert_int_equal(result, ISC_R_SUCCESS); + + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 3 }; + result = isc_cfgmgr_write("prop3", &val); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_cfgmgr_setmode(ISC_CFGMGR_MODERUNNING); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 34 }; + result = isc_cfgmgr_write("prop4", &val); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_cfgmgr_setmode(ISC_CFGMGR_MODEBUILTIN); + isc_cfgmgr_open("subopts1"); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 11 }; + result = isc_cfgmgr_write("propsubopts1", &val); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_cfgmgr_open("subopts2"); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 12 }; + result = isc_cfgmgr_write("propsubopts2", &val); + assert_int_equal(result, ISC_R_SUCCESS); + + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 333 }; + result = isc_cfgmgr_write("prop3", &val); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_cfgmgr_close(); + isc_cfgmgr_close(); + isc_cfgmgr_close(); + + cmpdump(ISC_CFGMGR_MODEBUILTIN, "options {\n" + " prop1 1;\n" + " prop2 2;\n" + " prop3 3;\n" + " sub {\n" + " prop1 1111;\n" + " };\n" + " subopts1 {\n" + " propsubopts1 11;\n" + " subopts2 {\n" + " prop3 333;\n" + " propsubopts2 12;\n" + " };\n" + " };\n" + "};\n"); + + cmpdump(ISC_CFGMGR_MODERUNNING, "options {\n" + " prop1 31;\n" + " prop2 2;\n" + " prop3 3;\n" + " prop4 34;\n" + " sub {\n" + " prop1 1111;\n" + " };\n" + " subopts1 {\n" + " propsubopts1 11;\n" + " subopts2 {\n" + " prop3 333;\n" + " propsubopts2 12;\n" + " };\n" + " };\n" + "};\n"); isc_cfgmgr_rollback(); isc_cfgmgr_deinit(); @@ -1664,8 +1624,8 @@ ISC_RUN_TEST_IMPL(isc_cfgmgr_materialization) { isc_cfgmgr_open("views"); isc_cfgmgr_open("fooview"); - val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 991 }; - result = isc_cfgmgr_write("prop2", &val); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 1991 }; + result = isc_cfgmgr_write("propspecific", &val); assert_int_equal(result, ISC_R_SUCCESS); isc_cfgmgr_open("zones"); isc_cfgmgr_open("foo.org"); @@ -1674,6 +1634,9 @@ ISC_RUN_TEST_IMPL(isc_cfgmgr_materialization) { assert_int_equal(result, ISC_R_SUCCESS); isc_cfgmgr_close(); isc_cfgmgr_close(); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = 991 }; + result = isc_cfgmgr_write("prop2", &val); + assert_int_equal(result, ISC_R_SUCCESS); isc_cfgmgr_close(); isc_cfgmgr_open("barview"); @@ -1760,12 +1723,16 @@ ISC_RUN_TEST_IMPL(isc_cfgmgr_materialization) { " };\n" " fooview {\n" " prop2 991;\n" + " propspecific 1991;\n" " zones {\n" " foo.org {\n" " prop1 661;\n" " prop2 991;\n" " prop3 3;\n" " prop4 34;\n" + /* TODO this should be there + " propspecific 1991;\n" + */ " };\n" " };\n" " };\n" @@ -1810,511 +1777,259 @@ ISC_RUN_TEST_IMPL(isc_cfgmgr_materialization) { " zones {\n" " bar.org {\n" " prop1 662;\n" + " prop2 21;\n" + " prop4 34;\n" " };\n" " baz.org {\n" " prop1 663;\n" + " prop2 21;\n" + " prop4 34;\n" " };\n" " };\n" " };\n" " fooview {\n" " prop2 991;\n" + " propspecific 1991;\n" " zones {\n" " foo.org {\n" " prop1 661;\n" + " prop2 991;\n" + " prop4 34;\n" + /* TODO this should be there + " propspecific 1991;\n" + */ " };\n" " };\n" " };\n" "};\n"); + /* + * Adding nested properties in options (builtin and user). Also, the + * user overide once of the property of the builtin. Must be visible in + * the zones + */ + isc_cfgmgr_open("options"); + + isc_cfgmgr_setmode(ISC_CFGMGR_MODEBUILTIN); + isc_cfgmgr_open("sub1"); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, + .string = "stuff1" }; + result = isc_cfgmgr_write("sub1prop", &val); + assert_int_equal(result, ISC_R_SUCCESS); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, + .string = "stuff2" }; + result = isc_cfgmgr_write("sub1prop2", &val); + assert_int_equal(result, ISC_R_SUCCESS); + isc_cfgmgr_close(); + + isc_cfgmgr_setmode(ISC_CFGMGR_MODEUSER); + isc_cfgmgr_open("sub2"); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, + .string = "stuff22" }; + result = isc_cfgmgr_write("sub2prop", &val); + assert_int_equal(result, ISC_R_SUCCESS); + isc_cfgmgr_close(); + isc_cfgmgr_open("sub1"); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, + .string = "stuff00" }; + result = isc_cfgmgr_write("sub1prop2", &val); + assert_int_equal(result, ISC_R_SUCCESS); + isc_cfgmgr_close(); + + isc_cfgmgr_close(); + + cmpdump(ISC_CFGMGR_MODEBUILTIN, "options {\n" + " prop1 1;\n" + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 stuff2;\n" + " };\n" + "};\n"); + + cmpdump(ISC_CFGMGR_MODEUSER, "options {\n" + " prop2 21;\n" + " sub1 {\n" + " sub1prop2 stuff00;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + "};\n"); + + cmpdump(ISC_CFGMGR_MODERUNNING, "options {\n" + " prop1 31;\n" + " prop2 21;\n" + " prop4 34;\n" + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 stuff00;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + "};\n" + "views {\n" + " barview {\n" + " zones {\n" + " bar.org {\n" + " prop1 662;\n" + " prop2 21;\n" + " prop4 34;\n" + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 stuff00;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + " };\n" + " baz.org {\n" + " prop1 663;\n" + " prop2 21;\n" + " prop4 34;\n" + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 stuff00;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + " };\n" + " };\n" + " };\n" + " fooview {\n" + " prop2 991;\n" + " propspecific 1991;\n" + " zones {\n" + " foo.org {\n" + " prop1 661;\n" + " prop2 991;\n" + " prop4 34;\n" + /* TODO this should be there + " propspecific 1991;\n" + */ + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 stuff00;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + " };\n" + " };\n" + " };\n" + "};\n"); + + /* + * Adding nested properties in views (running) gets visible on + * zones. Also overriding user sub properties. + */ + isc_cfgmgr_setmode(ISC_CFGMGR_MODERUNNING); + isc_cfgmgr_open("views"); + isc_cfgmgr_open("barview"); + + isc_cfgmgr_open("sub3"); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, .string = "abc" }; + result = isc_cfgmgr_write("sub3prop", &val); + assert_int_equal(result, ISC_R_SUCCESS); + isc_cfgmgr_close(); + + isc_cfgmgr_open("sub1"); + val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, .string = "def" }; + result = isc_cfgmgr_write("sub1prop2", &val); + assert_int_equal(result, ISC_R_SUCCESS); + isc_cfgmgr_close(); + + isc_cfgmgr_close(); + isc_cfgmgr_close(); + + cmpdump(ISC_CFGMGR_MODERUNNING, "options {\n" + " prop1 31;\n" + " prop2 21;\n" + " prop4 34;\n" + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 stuff00;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + "};\n" + "views {\n" + " barview {\n" + " sub1 {\n" + " sub1prop2 def;\n" + " };\n" + " sub3 {\n" + " sub3prop abc;\n" + " };\n" + " zones {\n" + " bar.org {\n" + " prop1 662;\n" + " prop2 21;\n" + " prop4 34;\n" + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 def;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + " sub3 {\n" + " sub3prop abc;\n" + " };\n" + " };\n" + " baz.org {\n" + " prop1 663;\n" + " prop2 21;\n" + " prop4 34;\n" + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 def;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + " sub3 {\n" + " sub3prop abc;\n" + " };\n" + " };\n" + " };\n" + " };\n" + " fooview {\n" + " prop2 991;\n" + " propspecific 1991;\n" + " zones {\n" + " foo.org {\n" + " prop1 661;\n" + " prop2 991;\n" + " prop4 34;\n" + /* TODO this should be there + " propspecific 1991;\n" + */ + " sub1 {\n" + " sub1prop stuff1;\n" + " sub1prop2 stuff00;\n" + " };\n" + " sub2 {\n" + " sub2prop stuff22;\n" + " };\n" + " };\n" + " };\n" + " };\n" + "};\n"); isc_cfgmgr_rollback(); /* * TODO * Then a zone is added _after_ all of those options changes. It must - * contains all of those as well + * contains all of those as well (see propspecific 1991 properties + * commented out up there). */ isc_cfgmgr_deinit(); } -// ISC_RUN_TEST_IMPL(isc_cfgmgr_builtintests) { -// isc_result_t result; -// isc_cfgmgr_val_t val; -// -// result = isc_cfgmgr_init(mctx, TEST_DBPATH, NULL); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_rwtransaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_newclause("foo"); -// -// /* -// * Set a user property and check that it is not possible to read it -// * from builtin mode -// */ -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, -// .string = "userval1" }; -// result = isc_cfgmgr_write("userprop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// expect_assert_failure(isc_cfgmgr_builtinoff()); -// isc_cfgmgr_builtinon(); -// expect_assert_failure(isc_cfgmgr_builtinon()); -// -// result = isc_cfgmgr_read("userprop1", &val); -// assert_int_equal(result, ISC_R_NOTFOUND); -// -// /* -// * Set a builtin property and check that is is readable from -// non-builtin -// * mode -// */ -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = -// 1234 }; result = isc_cfgmgr_write("builtinval1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// val = (isc_cfgmgr_val_t){}; -// isc_cfgmgr_builtinoff(); -// expect_assert_failure(isc_cfgmgr_builtinoff()); -// -// result = isc_cfgmgr_read("builtinval1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 1234); -// -// /* -// * user override builtin property, now only the user value is -// visible in -// * builtin mode off, but the original value is still readable -// with -// * builtin mode on -// */ -// val.uint32 = 5678; -// result = isc_cfgmgr_write("builtinval1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// val = (isc_cfgmgr_val_t){}; -// result = isc_cfgmgr_read("builtinval1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 5678); -// -// isc_cfgmgr_builtinon(); -// val = (isc_cfgmgr_val_t){}; -// result = isc_cfgmgr_read("builtinval1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 1234); -// -// /* -// * builtin mode on is automatically turned off when closing a -// clause -// * (commit automatically clause opened clauses) -// */ -// result = isc_cfgmgr_commit(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_transaction(); -// result = isc_cfgmgr_open("foo"); -// expect_assert_failure(isc_cfgmgr_builtinoff()); -// isc_cfgmgr_builtinon(); -// isc_cfgmgr_close(); -// -// result = isc_cfgmgr_open("foo"); -// expect_assert_failure(isc_cfgmgr_builtinoff()); -// isc_cfgmgr_builtinon(); -// -// isc_cfgmgr_rollback(); -// -// /* -// * create a clause with builtin property and user never override -// it, but -// * can still get the builtin value with a default lookup. -// */ -// result = isc_cfgmgr_rwtransaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_builtinon(); -// isc_cfgmgr_newclause("gee"); -// -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = -// 42 }; result = isc_cfgmgr_write("foo", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_commit(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_transaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_open("gee"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// val = (isc_cfgmgr_val_t){}; -// result = isc_cfgmgr_read("foo", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 42); -// -// isc_cfgmgr_rollback(); -// -// /* -// * then let's re-open this clause and update "foo" property to -// another -// * value, we won't read the builtin in anymore. -// */ -// result = isc_cfgmgr_rwtransaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_open("gee"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// val = (isc_cfgmgr_val_t){}; -// result = isc_cfgmgr_read("foo", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 42); -// -// val.uint32 = 55555; -// result = isc_cfgmgr_write("foo", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_commit(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// /* -// * lets get the new value of gee.foo, then remove it, we'll get -// back the -// * builtin one now. -// */ -// result = isc_cfgmgr_rwtransaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_open("gee"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// val = (isc_cfgmgr_val_t){}; -// result = isc_cfgmgr_read("foo", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 55555); -// -// result = isc_cfgmgr_write("foo", NULL); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_commit(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_transaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_open("gee"); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// val = (isc_cfgmgr_val_t){}; -// result = isc_cfgmgr_read("foo", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// assert_int_equal(val.type, ISC_CFGMGR_UINT32); -// assert_int_equal(val.uint32, 42); -// -// isc_cfgmgr_rollback(); -// isc_cfgmgr_deinit(); -// } - -// static void -// cfgmgr_dumptests_clausestarts(void *state, const char *name, size_t -// indent) { -// isc_buffer_t *b = state; -// -// for (size_t i = 0; i < indent; i++) { -// isc_buffer_putstr(b, " "); -// } -// isc_buffer_printf(b, "%s {\n", name); -// } -// -// static void -// cfgmgr_dumptests_clauseends(void *state, const char *name, size_t -// indent) { -// isc_buffer_t *b = state; -// -// for (size_t i = 0; i < indent; i++) { -// isc_buffer_putstr(b, " "); -// } -// isc_buffer_printf(b, "}; #%s\n", name); -// } -// -// static void -// cfgmgr_dumptests_property(void *state, const char *name, -// const isc_cfgmgr_val_t *val, size_t indent) { -// isc_buffer_t *b = state; -// -// for (size_t i = 0; i < indent; i++) { -// isc_buffer_putstr(b, " "); -// } -// isc_buffer_putstr(b, name); -// isc_buffer_putstr(b, " "); -// -// switch (val->type) { -// case ISC_CFGMGR_UINT32: -// isc_buffer_printf(b, "%" PRIu32, val->uint32); -// break; -// case ISC_CFGMGR_STRING: -// isc_buffer_putstr(b, val->string); -// break; -// default: -// UNREACHABLE(); -// } -// -// isc_buffer_putstr(b, ";\n"); -// } -// -// ISC_RUN_TEST_IMPL(isc_cfgmgr_dumptests) { -// isc_result_t result; -// isc_cfgmgr_val_t val; -// -// const isc_cfgmgr_prop_t prop3 = { "prop3", false, -// ISC_CFGMGR_STRING }; const isc_cfgmgr_prop_t prop4 = { "prop4", true, -// ISC_CFGMGR_STRING }; const isc_cfgmgr_prop_t *bar_props[] = { &prop3, -//&prop4, NULL }; const isc_cfgmgr_clause_t bar = { "bar", true, true, -// NULL, bar_props }; -// -// const isc_cfgmgr_prop_t prop1 = { "prop1", false, -// ISC_CFGMGR_STRING }; const isc_cfgmgr_prop_t prop2 = { "prop2", true, -// ISC_CFGMGR_UINT32 }; const isc_cfgmgr_prop_t prop2bis = { "prop2bis", -// false, ISC_CFGMGR_UINT32 }; -// const isc_cfgmgr_prop_t *foo_props[] = { &prop1, &prop2, &prop2bis, -// NULL }; const isc_cfgmgr_clause_t *foo_clauses[] = { &bar, NULL }; -// const isc_cfgmgr_clause_t foo = { "foo", false, false, foo_clauses, -// foo_props }; -// -// const isc_cfgmgr_prop_t prop5 = { "prop5", false, -// ISC_CFGMGR_STRING }; const isc_cfgmgr_prop_t *baz_props[] = { &prop5, -// NULL }; const isc_cfgmgr_clause_t baz = { "baz", false, true, NULL, -// baz_props }; -// -// const isc_cfgmgr_clause_t *format[] = { &foo, &baz, NULL }; -// -// result = isc_cfgmgr_init(mctx, TEST_DBPATH, format); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_rwtransaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_setmode(ISC_CFGMGR_MODEUSER); -// -// isc_cfgmgr_newclause("foo"); -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, .string = -//"a" }; result = isc_cfgmgr_write("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_UINT32, .uint32 = -// 43 }; result = isc_cfgmgr_write("prop2bis", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// /* -// * Yes, "prop4" has nothing to do in "foo" (according to the -// format). -// * But let's add it anyway: this won't be visible in foo -//(because it's -// * not as part of its format) and... Won't be visible in bar, -// because -// * we'll iniitally make a ISC_CFGMGR_MODEUSER, so a dump of the -// user -// * configuration only, which does have any kind of -// materialization -// */ -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, .string = -//"zz" }; result = isc_cfgmgr_write("prop4", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_newclause("bar"); -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, .string = -//"b" }; result = isc_cfgmgr_write("prop3", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_close(); -// isc_cfgmgr_close(); -// -// isc_cfgmgr_newclause("baz"); -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, .string = -//"c" }; result = isc_cfgmgr_write("prop5", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_close(); -// -// isc_cfgmgr_newclause("baz"); -// /* -// * Let's use the exact internal value, as there is no ordering -// garantee -// * of the repeatable clauses (depending the random clause -// instance -// * identifier, one might be before the other depending the -// runs...) -// */ -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, .string = -//"c" }; result = isc_cfgmgr_write("prop5", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_commit(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// char data[512]; -// isc_buffer_t buffer; -// isc_cfgmgr_dumpcfg_t cfg = { .clausestarts = -// cfgmgr_dumptests_clausestarts, -// .clauseends = -// cfgmgr_dumptests_clauseends, .property = -// cfgmgr_dumptests_property, .state = &buffer, -// .indent = 8, .dumpmode = -// ISC_CFGMGR_MODEUSER }; -// -// isc_buffer_init(&buffer, data, sizeof(data)); -// result = isc_cfgmgr_dump(&cfg); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_buffer_putuint8(&buffer, 0); -// -// const char expected[] = "foo {\n" -// " prop1 a;\n" -// " prop2bis 43;\n" -// " bar {\n" -// " prop3 b;\n" -// " }; #bar\n" -// "}; #foo\n" -// "baz {\n" -// " prop5 c;\n" -// "}; #baz\n" -// "baz {\n" -// " prop5 c;\n" -// "}; #baz\n"; -// -// assert_string_equal(buffer.base, expected); -// -// // /* -// // * Let's now run a ISC_CFGMGR_DUMPRUNNING dump. The only -// //difference is -// // * that prop4 will now be visible in bar, as the -// inheritance is -// //enabled. -// // */ -// // cfg.dumpmode = ISC_CFGMGR_MODERUNNING; -// // isc_buffer_init(&buffer, data, sizeof(data)); -// // result = isc_cfgmgr_dump(&cfg); -// // assert_int_equal(result, ISC_R_SUCCESS); -// // -// // isc_buffer_putuint8(&buffer, 0); -// // -// // const char expected2[] = "foo {\n" -// // " prop1 a;\n" -// // " prop2bis 43;\n" -// // " bar {\n" -// // " prop3 b;\n" -// // " prop4 zz;\n" -// // " }; #bar\n" -// // "}; #foo\n" -// // "baz {\n" -// // " prop5 c;\n" -// // "}; #baz\n" -// // "baz {\n" -// // " prop5 c;\n" -// // "}; #baz\n"; -// // -// // assert_string_equal(buffer.base, expected2); -// -// /* -// * Dump with ISC_CFGMGR_UNKNOWN is a coding error -// */ -// cfg.dumpmode = ISC_CFGMGR_MODEUNKNOWN; -// isc_buffer_init(&buffer, data, sizeof(data)); -// expect_assert_failure(isc_cfgmgr_dump(&cfg)); -// -// /* -// * Let's add some builtin data. -// */ -// result = isc_cfgmgr_rwtransaction(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_setmode(ISC_CFGMGR_MODEBUILTIN); -// isc_cfgmgr_newclause("foo"); -// -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, -// .string = "abuiltin" }; -// result = isc_cfgmgr_write("prop1", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_cfgmgr_close(); -// isc_cfgmgr_newclause("baz"); -// val = (isc_cfgmgr_val_t){ .type = ISC_CFGMGR_STRING, .string = -//"c" }; result = isc_cfgmgr_write("prop5", &val); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// result = isc_cfgmgr_commit(); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// /* -// * let's dump in ISC_CFGMGR_DUMPBUILTIN only -// */ -// cfg.dumpmode = ISC_CFGMGR_MODEBUILTIN; -// isc_buffer_init(&buffer, data, sizeof(data)); -// result = isc_cfgmgr_dump(&cfg); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_buffer_putuint8(&buffer, 0); -// -// const char expected3[] = "foo {\n" -// " prop1 abuiltin;\n" -// "}; #foo\n" -// "baz {\n" -// " prop5 c;\n" -// "}; #baz\n"; -// -// assert_string_equal(buffer.base, expected3); -// -// // /* -// // * let's make a new running dump - foo.prop1 will -// override the -// // * builtin value. -// // */ -// // cfg.dumpmode = ISC_CFGMGR_MODERUNNING; -// // isc_buffer_init(&buffer, data, sizeof(data)); -// // result = isc_cfgmgr_dump(&cfg); -// // assert_int_equal(result, ISC_R_SUCCESS); -// // -// // isc_buffer_putuint8(&buffer, 0); -// // -// // const char expected4[] = "foo {\n" -// // " prop1 a;\n" -// // " prop2bis 43;\n" -// // " bar {\n" -// // " prop3 b;\n" -// // " prop4 zz;\n" -// // " }; #bar\n" -// // "}; #foo\n" -// // "baz {\n" -// // " prop5 c;\n" -// // "}; #baz\n" -// // "baz {\n" -// // " prop5 c;\n" -// // "}; #baz\n"; -// // -// // assert_string_equal(buffer.base, expected4); -// -// /* -// * And another user only dump, which will be as the first dump -//(do the -// * builtin value in foo is ignored) -// */ -// cfg.dumpmode = ISC_CFGMGR_MODEUSER; -// isc_buffer_init(&buffer, data, sizeof(data)); -// result = isc_cfgmgr_dump(&cfg); -// assert_int_equal(result, ISC_R_SUCCESS); -// -// isc_buffer_putuint8(&buffer, 0); -// assert_string_equal(buffer.base, expected); -// -// isc_cfgmgr_deinit(); -// } - ISC_TEST_LIST_START ISC_TEST_ENTRY(isc_cfgmgr_assertions) @@ -2328,11 +2043,9 @@ ISC_TEST_ENTRY(isc_cfgmgr_nested_nodes) ISC_TEST_ENTRY(isc_cfgmgr_threads) ISC_TEST_ENTRY(isc_cfgmgr_opentests) ISC_TEST_ENTRY(isc_cfgmgr_dumptests) +ISC_TEST_ENTRY(isc_cfgmgr_materialziation_options) ISC_TEST_ENTRY(isc_cfgmgr_materialization) - // ISC_TEST_ENTRY(isc_cfgmgr_validationtest) -// ISC_TEST_ENTRY(isc_cfgmgr_getparent) -// ISC_TEST_ENTRY(isc_cfgmgr_builtintests) -// ISC_TEST_ENTRY(isc_cfgmgr_dumptests) + ISC_TEST_LIST_END ISC_TEST_MAIN