work in progress: Removal of nextlcause/newclause and list

newclause/nextclause API are removed as well as IDs in paths
list are removed
renaming clause->node for clarity.
This commit is contained in:
Colin Vidal
2025-02-24 10:35:39 +01:00
parent 34f9de111a
commit 80f5981de0
3 changed files with 983 additions and 1939 deletions
+195 -666
View File
File diff suppressed because it is too large Load Diff
+59 -142
View File
@@ -25,18 +25,38 @@
*
* The materialization of the running mode is based on the following rules:
*
* - the "options" clause gets all the values from the builtin
* "option" clause, then all the values from the user "options" clause
* - the "options" node gets all the values from the builtin
* "options" node, then all the values from the user "options" node
* (potentially overriding those from the builtin mode)
*
* - the "view" clauses gets all the values of the running "options"
* clause, then can override those. It also means that an update in the
* running "options" clause automatically applies to all "view" clauses as
* - the "views" sub-nodes gets all the values of the running "options"
* node, then can override those. It also means that an update in the
* running "options" node automatically applies to all "views" sub-nodes as
* well.
*
* - the "zone" clauses gets all the values of its parent running "view" clause,
* - the "zones" sub-nodes gets all the values of its parent view,
* then can override those. It also means that an update in the running parent
* "view" clause propagates to all its zones.
* view propagates to all its zones.
*
* To clarify what "views sub-nodes" or "parent view" means, here is a tree
* representation how things are represented in cfgmgr:
*
* /
* ├── options/
* │ ├── allow-query
* │ └── listen-on
* └── views/
* ├── zones/
* │ └── isc.org
* │ └── allow-query
* ├── allow-query
* └── another-prop
*
* Of course, other node than "options", "views" and "zones" (as well as the
* zone sub-nodes named after a domain name) can be used as there is no
* restriction on the node names or properties names. However the
* materialization logic will apply only on running version of "options" and
* "zones" sub-nodes.
*/
typedef enum isc_cfgmgr_mode isc_cfgmgr_mode_t;
enum isc_cfgmgr_mode {
@@ -58,31 +78,6 @@ typedef enum isc_cfgmgr_type {
ISC_CFGMGR_UINT32
} __attribute__((__packed__)) isc_cfgmgr_type_t;
/*
* Configuration validation and printing. The validator is able to verify that
* mandatory properties (or subclauses) of a clause are present, as well as
* their respective types, as well as a non-repeatable clause is not repeated or
* a mandatory clause is not present. However it won't verify if a non-expected
* clause does exists. (This actually might handy if non-user configurable data
* needs to be stored in cfgmgr.)
*/
typedef struct isc_cfgmgr_clause isc_cfgmgr_clause_t;
typedef struct isc_cfgmgr_property isc_cfgmgr_prop_t;
struct isc_cfgmgr_clause {
const char *name;
bool optional;
bool repeat;
const isc_cfgmgr_clause_t **clauses;
const isc_cfgmgr_prop_t **props;
};
struct isc_cfgmgr_property {
const char *name;
bool optional;
isc_cfgmgr_type_t type;
};
/*
* Generic value holding the actual value and type value for
* read/write from/to cfgmgr.
@@ -107,96 +102,62 @@ void
isc_cfgmgr_setmode(isc_cfgmgr_mode_t mode);
/*
* Get the property "name" in the opened clause into the caller
* Get the property "name" in the opened node into the caller
* allocated "value" and returns ISC_R_SUCCESS. Returns ISC_R_NOTFOUND
* and "*value" is not mutated if "name" is not found. If "name" is a list
* property, get its head.
* and "*value" is not mutated if "name" is not found. Must be called under a
* transaction.
*/
isc_result_t
isc_cfgmgr_getval(const char *name, isc_cfgmgr_val_t *value);
/*
* Write "value" into the property "name" in the opened clause and
* Write "value" into the property "name" in the opened node and
* returns ISC_R_SUCCESS. If the property already exists, it is
* overridden and even if the type is different. If "value" is NULL
* and the property exists, it will be deleted (applies for list
* properties as well), otherwise, it returns ISC_R_NOTFOUND.
* and the property exists, it will be deleted, otherwise it returns
* ISC_R_NOTFOUND. Must be called under a write transaction.
*/
isc_result_t
isc_cfgmgr_setval(const char *name, const isc_cfgmgr_val_t *value);
/*
* Same as isc_cfgmgr_getval but applies for elements after the head
* of a list property. The head is read using isc_cfgmgr_getval as any
* other value, then subsequents calls to isc_cfgmgr_getnextlistval
* will get the next elements in the list. When the end of the list is
* reached, ISC_R_NOMORE is returned. Calls to
* isc_cfgmgr_getnextlistval name has to be made in immediate sequence
* (without intermediate isc_cfgmgr_{set,get}val calls) to retrieve
* each list element.
*/
isc_result_t
isc_cfgmgr_getnextlistval(isc_cfgmgr_val_t *value);
/*
* Same as isc_cfgmgr_setval but applies for a list property. Writes
* by appending "*value" at the end of the list property "name" in the
* opened clause and returns ISC_R_SUCCESS. If "name" property wasn't
* existing before (or wasn't a list) it's overriden. It is not
* possible to delete individual list element, only the whole list can
* be removed using isc_cfgmgr_setval.
*/
isc_result_t
isc_cfgmgr_setnextlistval(const char *name, const isc_cfgmgr_val_t *value);
/*
* If the opened clause is a repeatable clause (i.e. view, acl, etc.),
* internally closes the opened clause and open the next clause of the
* same type and returns ISC_R_SUCCESS. When there is no next clause
* of the same type, ISC_R_NOMORE is returned.
*/
isc_result_t
isc_cfgmgr_nextclause(void);
/*
* Create and open a new clause. If not clause is currently opened, the newly
* created clause is a top-level one. Otherwise, it is nested in the clause
* opened when this function is called. Note that in order to have the new
* clause actually written in cfgmgr, at least one property needs to be set to
* that clause.
* Close and delete the opened node. (And thus all its properties,
* including nested nodes). If the node was nested, the currently
* opened node is now the parent node. Can't be called from the root
* node. Must be called under a write transaction.
*/
void
isc_cfgmgr_newclause(const char *name);
isc_cfgmgr_delnode(void);
/*
* Delete and close the opened clause. (And thus all its properties,
* including nested clauses). If the clause was nested, the currently
* opened clause is now the parent clause. Otherwise, no clause is
* opened.
* Open the node "name". Must be called under a transaction.
*/
void
isc_cfgmgr_delclause(void);
/*
* Open the clause "name" and returns ISC_R_SUCCES or ISC_R_NOTFOUND
* is the clause is not found. Must be called under a transaction.
*/
isc_result_t
isc_cfgmgr_open(const char *name);
/*
* Close the currently opened clause and returns ISC_R_SUCCESS. If the
* closed clause was nested, the currently opened clause is now the
* parent clause. Must be called under a transaction.
* Close the currently opened node. If the closed node was nested, the currently
* opened node is now the parent node. Can't be called from the root node. Must
* be called under a transaction.
*/
void
isc_cfgmgr_close(void);
/*
* Calls function "action" for each direct sub-nodes of the currently opened
* node. The caller is free to do whatever needed inside "action", in
* particular, opening "name" (and its sub-nodes) to read or write properties
* inside. Must be called under a transaction.
*/
void
isc_cfgmgr_foreachnodes(void(*action)(void *state, const char *name),
void *state);
/*
* Starts a read-only transaction and returns ISC_R_SUCCESS. If there is an
* issue creating a transaction, ISC_R_FAILURE is returned. Prior callimg this
* issue creating a transaction, ISC_R_FAILURE is returned. Prior calling this
* function, there must be no currently transaction started from the current
* thread.
* thread. By default, the root node is opened.
*/
isc_result_t
isc_cfgmgr_transaction(void);
@@ -206,7 +167,8 @@ isc_cfgmgr_transaction(void);
* issue creating a transaction, ISC_R_FAILURE is returned. Prior callimg this
* function, there must be no currently transaction started from the current
* thread. If another thread already started a read-write transaction,
* this call will block until the other transaction is terminated.
* this call will block until the other transaction is terminated. By default,
* the root node is opened.
*/
isc_result_t
isc_cfgmgr_rwtransaction(void);
@@ -216,8 +178,7 @@ isc_cfgmgr_rwtransaction(void);
* transaction visible to all transaction started after this call returns. If
* something goes wrong while applying the changes, ISC_R_FAILURE is returned
* and the changes made during the transaction are discareded. ISC_R_SUCCESS is
* returned otherwise. If a clause is opened when this function is called, it is
* automatically closed.
* returned otherwise.
*
* If the validation of the new configuration fails, the transaction is
* rolled-backed and all the changes are discarded. It is possible to get
@@ -237,47 +198,9 @@ isc_cfgmgr_commit(void);
const char *
isc_cfgmgr_lasterror(void);
/*
* Configuration of the dump provided by the user. The three function pointers
* are provided by the user which is responsible of implementing the dump output
* format. "clausestarts" and "clauseends" functions are called at the entry and
* exit of each clause, "property" is called whenever a property is reached, and
* "indent" is the number of spaces that cfgmgr must calculate each time it
* enters a clause. (The actual indentation level is provided to each of those 3
* functions).
*
* The "state" pointer to each user provided function can be anything and is
* simply passed from the isc_cfgmgr_dumpcfg to each function when they are
* called.
*
* isc_cfgmgr_dump must be called outside of any transaction (it internally uses
* a read-only transaction).
*
* The dump mode indicates if only the builtin configuration, or only the user
* provided configuration, or the actual running configuration (builtin + user
* overriding builtin data) should be dumped. It can't be unknown.
*
* A configuration format must be provided to cfgmgr (when isc_cfgmgr_init is
* called) in order to build a dump, otherwise, ISC_R_FAILURE will be returned.
*/
typedef struct isc_cfgmgr_dumpcfg isc_cfgmgr_dumpcfg_t;
struct isc_cfgmgr_dumpcfg {
void (*clausestarts)(void *state, const char *name, size_t indent);
void (*clauseends)(void *state, const char *name, size_t indent);
void (*property)(void *state, const char *name,
const isc_cfgmgr_val_t *val, size_t indent);
void *state;
size_t indent;
isc_cfgmgr_mode_t dumpmode;
};
isc_result_t
isc_cfgmgr_dump(const isc_cfgmgr_dumpcfg_t *cfg);
/*
* Discard all the changes made during transaction and terminate the
* transaction. If a clause is opened when this function is called, it is
* automatically closed.
* transaction.
*/
void
isc_cfgmgr_rollback(void);
@@ -288,15 +211,9 @@ isc_cfgmgr_rollback(void);
* isc_cfgmgr_deinit (this drops all the data written in
* cfgmgr). Returns ISC_R_SUCCESS or ISC_R_FAILURE if there is an
* issue initializing the internal database.
*
* "configformat" is a NULL-terminated array and its life-cycle must outlive
* cfgmgr (it is not copied). It is used to validate and to dump the
* configuration. NULL can be passed, in which case the validation is bypassed
* and the dump functions won't return anything.
*/
isc_result_t
isc_cfgmgr_init(isc_mem_t *mctx, const char *dbpath,
const isc_cfgmgr_clause_t **configformat);
isc_cfgmgr_init(isc_mem_t *mctx, const char *dbpath);
/*
* Destroy all cfgmgr data and free memory. Must be called only after
+729 -1131
View File
File diff suppressed because it is too large Load Diff