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:
+195
-666
File diff suppressed because it is too large
Load Diff
+59
-142
@@ -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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user