Clixon config option CLICON_XMLDB_CACHE renamed to CLICON_DATASTORE_CACHE and changed type from boolean to datastore_cache
This commit is contained in:
parent
70221742f7
commit
99b7a1fe5b
13 changed files with 207 additions and 150 deletions
|
|
@ -53,6 +53,10 @@
|
||||||
|
|
||||||
### API changes on existing features (you may need to change your code)
|
### API changes on existing features (you may need to change your code)
|
||||||
|
|
||||||
|
* Clixon config option `CLICON_XMLDB_CACHE` renamed to `CLICON_DATASTORE_CACHE` and changed type from `boolean` to `datastore_cache`
|
||||||
|
* Change code from: `clicon_option_bool(h, "CLICON_XMLDB_CACHE")` to `clicon_datastore_cache(h) == DATASTORE_CACHE`
|
||||||
|
* Type `datastore_cache` have values: nocache, cache, or cache-zerocopy
|
||||||
|
* `xmldb_get1` removed (functionality merged with `xmldb_get`)
|
||||||
* Non-key list now not accepted in edit-config (before only on validation)
|
* Non-key list now not accepted in edit-config (before only on validation)
|
||||||
* Changed return values in internal functions
|
* Changed return values in internal functions
|
||||||
* These functions are affected: `netconf_trymerge`, `startup_module_state`, `yang_modules_state_get`
|
* These functions are affected: `netconf_trymerge`, `startup_module_state`, `yang_modules_state_get`
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,10 @@ from_client_get_config(clicon_handle h,
|
||||||
if ((xfilter = xml_find(xe, "filter")) != NULL)
|
if ((xfilter = xml_find(xe, "filter")) != NULL)
|
||||||
if ((xpath = xml_find_value(xfilter, "select"))==NULL)
|
if ((xpath = xml_find_value(xfilter, "select"))==NULL)
|
||||||
xpath="/";
|
xpath="/";
|
||||||
if (xmldb_get(h, db, xpath, &xret, NULL) < 0){
|
/* Note xret can be pruned by nacm below (and change name),
|
||||||
|
* so zero-copy cant be used
|
||||||
|
*/
|
||||||
|
if (xmldb_get(h, db, xpath, 1, &xret, NULL) < 0){
|
||||||
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -800,14 +803,16 @@ from_client_get(clicon_handle h,
|
||||||
if ((xfilter = xml_find(xe, "filter")) != NULL)
|
if ((xfilter = xml_find(xe, "filter")) != NULL)
|
||||||
if ((xpath = xml_find_value(xfilter, "select"))==NULL)
|
if ((xpath = xml_find_value(xfilter, "select"))==NULL)
|
||||||
xpath="/";
|
xpath="/";
|
||||||
/* Get config */
|
/* Get config
|
||||||
if (xmldb_get(h, "running", xpath, &xret, NULL) < 0){
|
* Note xret can be pruned by nacm below and change name and
|
||||||
|
* metrged with state data, so zero-copy cant be used
|
||||||
|
*/
|
||||||
|
if (xmldb_get(h, "running", xpath, 1, &xret, NULL) < 0){
|
||||||
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
/* Get state data from plugins as defined by plugin_statedata(), if any */
|
/* Get state data from plugins as defined by plugin_statedata(), if any */
|
||||||
assert(xret);
|
|
||||||
clicon_err_reset();
|
clicon_err_reset();
|
||||||
if ((ret = client_statedata(h, xpath, &xret)) < 0)
|
if ((ret = client_statedata(h, xpath, &xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ startup_common(clicon_handle h,
|
||||||
if ((msd = modstate_diff_new()) == NULL)
|
if ((msd = modstate_diff_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_debug(1, "Reading startup config from %s", db);
|
clicon_debug(1, "Reading startup config from %s", db);
|
||||||
if (xmldb_get1(h, db, "/", &xt, msd) < 0)
|
if (xmldb_get(h, db, "/", 0, &xt, msd) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Clear flags xpath for get */
|
/* Clear flags xpath for get */
|
||||||
xml_apply0(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
xml_apply0(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
||||||
|
|
@ -276,7 +276,7 @@ startup_validate(clicon_handle h,
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
/* Clear cached trees from default values and marking */
|
/* Clear cached trees from default values and marking */
|
||||||
if (xmldb_get1_clear(h, db) < 0)
|
if (xmldb_get_clear(h, td->td_target) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xtr){
|
if (xtr){
|
||||||
*xtr = td->td_target;
|
*xtr = td->td_target;
|
||||||
|
|
@ -285,11 +285,7 @@ startup_validate(clicon_handle h,
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (td){
|
if (td){
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
|
xmldb_get_free(h, &td->td_target);
|
||||||
/* xmldb_get1 requires free only if not cache */
|
|
||||||
td->td_target = NULL;
|
|
||||||
td->td_src = NULL;
|
|
||||||
}
|
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -332,7 +328,7 @@ startup_commit(clicon_handle h,
|
||||||
if (plugin_transaction_commit(h, td) < 0)
|
if (plugin_transaction_commit(h, td) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Clear cached trees from default values and marking */
|
/* Clear cached trees from default values and marking */
|
||||||
if (xmldb_get1_clear(h, db) < 0)
|
if (xmldb_get_clear(h, td->td_target) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* [Delete and] create running db */
|
/* [Delete and] create running db */
|
||||||
|
|
@ -356,11 +352,7 @@ startup_commit(clicon_handle h,
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (td){
|
if (td){
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
|
xmldb_get_free(h, &td->td_target);
|
||||||
/* xmldb_get1 requires free only if not cache */
|
|
||||||
td->td_target = NULL;
|
|
||||||
td->td_src = NULL;
|
|
||||||
}
|
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -398,7 +390,7 @@ from_validate_common(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* This is the state we are going to */
|
/* This is the state we are going to */
|
||||||
if (xmldb_get1(h, candidate, "/", &td->td_target, NULL) < 0)
|
if (xmldb_get(h, candidate, "/", 0, &td->td_target, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Clear flags xpath for get */
|
/* Clear flags xpath for get */
|
||||||
|
|
@ -416,7 +408,7 @@ from_validate_common(clicon_handle h,
|
||||||
|
|
||||||
/* 2. Parse xml trees
|
/* 2. Parse xml trees
|
||||||
* This is the state we are going from */
|
* This is the state we are going from */
|
||||||
if (xmldb_get1(h, "running", "/", &td->td_src, NULL) < 0)
|
if (xmldb_get(h, "running", "/", 0, &td->td_src, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Clear flags xpath for get */
|
/* Clear flags xpath for get */
|
||||||
xml_apply0(td->td_src, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
xml_apply0(td->td_src, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
||||||
|
|
@ -521,9 +513,9 @@ candidate_commit(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Clear cached trees from default values and marking */
|
/* Clear cached trees from default values and marking */
|
||||||
if (xmldb_get1_clear(h, candidate) < 0)
|
if (xmldb_get_clear(h, td->td_target) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xmldb_get1_clear(h, "running") < 0)
|
if (xmldb_get_clear(h, td->td_src) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Optionally write (potentially modified) tree back to candidate
|
/* Optionally write (potentially modified) tree back to candidate
|
||||||
|
|
@ -559,11 +551,8 @@ candidate_commit(clicon_handle h,
|
||||||
if (retval < 1 && td)
|
if (retval < 1 && td)
|
||||||
plugin_transaction_abort(h, td);
|
plugin_transaction_abort(h, td);
|
||||||
if (td){
|
if (td){
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
|
xmldb_get_free(h, &td->td_target);
|
||||||
/* xmldb_get1 requires free only if not cache */
|
xmldb_get_free(h, &td->td_src);
|
||||||
td->td_target = NULL;
|
|
||||||
td->td_src = NULL;
|
|
||||||
}
|
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -749,9 +738,9 @@ from_client_validate(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
/* Clear cached trees from default values and marking */
|
/* Clear cached trees from default values and marking */
|
||||||
if (xmldb_get1_clear(h, db) < 0)
|
if (xmldb_get_clear(h, td->td_target) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xmldb_get1_clear(h, "running") < 0)
|
if (xmldb_get_clear(h, td->td_src) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Optionally write (potentially modified) tree back to candidate */
|
/* Optionally write (potentially modified) tree back to candidate */
|
||||||
|
|
@ -768,12 +757,9 @@ from_client_validate(clicon_handle h,
|
||||||
if (retval < 0 && td)
|
if (retval < 0 && td)
|
||||||
plugin_transaction_abort(h, td);
|
plugin_transaction_abort(h, td);
|
||||||
if (td){
|
if (td){
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
|
xmldb_get_free(h, &td->td_target);
|
||||||
/* xmldb_get1 requires free only if not cache */
|
xmldb_get_free(h, &td->td_src);
|
||||||
td->td_target = NULL;
|
transaction_free(td);
|
||||||
td->td_src = NULL;
|
|
||||||
}
|
|
||||||
transaction_free(td);
|
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
} /* from_client_validate */
|
} /* from_client_validate */
|
||||||
|
|
|
||||||
|
|
@ -102,13 +102,12 @@ db_merge(clicon_handle h,
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
|
|
||||||
/* Get data as xml from db1 */
|
/* Get data as xml from db1 */
|
||||||
if (xmldb_get(h, (char*)db1, NULL, &xt, NULL) < 0)
|
if (xmldb_get(h, (char*)db1, NULL, 0, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Merge xml into db2. Without commit */
|
/* Merge xml into db2. Without commit */
|
||||||
retval = xmldb_put(h, (char*)db2, OP_MERGE, xt, clicon_username_get(h), cbret);
|
retval = xmldb_put(h, (char*)db2, OP_MERGE, xt, clicon_username_get(h), cbret);
|
||||||
done:
|
done:
|
||||||
if (xt)
|
xmldb_get_free(h, &xt);
|
||||||
xml_free(xt);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,8 +269,7 @@ startup_extraxml(clicon_handle h,
|
||||||
ok:
|
ok:
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (xt && !clicon_option_bool(h, "CLICON_XMLDB_CACHE"))
|
xmldb_get_free(h, &xt);
|
||||||
xml_free(xt);
|
|
||||||
if (xmldb_delete(h, db) != 0 && errno != ENOENT)
|
if (xmldb_delete(h, db) != 0 && errno != ENOENT)
|
||||||
return -1;
|
return -1;
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,9 @@ int xmldb_db2file(clicon_handle h, const char *db, char **filename);
|
||||||
int xmldb_validate_db(const char *db);
|
int xmldb_validate_db(const char *db);
|
||||||
int xmldb_connect(clicon_handle h);
|
int xmldb_connect(clicon_handle h);
|
||||||
int xmldb_disconnect(clicon_handle h);
|
int xmldb_disconnect(clicon_handle h);
|
||||||
int xmldb_get(clicon_handle h, const char *db, char *xpath, cxobj **xtop, modstate_diff_t *msd); /* in clixon_datastore_read.[ch] */
|
int xmldb_get(clicon_handle h, const char *db, char *xpath, int copy, cxobj **xtop, modstate_diff_t *msd); /* in clixon_datastore_read.[ch] */
|
||||||
int xmldb_get1(clicon_handle h, const char *db, char *xpath, cxobj **xtop, modstate_diff_t *msd); /* in clixon_datastore_read.[ch] */
|
int xmldb_get_clear(clicon_handle h, cxobj *x);
|
||||||
int xmldb_get1_clear(clicon_handle h, const char *db);
|
int xmldb_get_free(clicon_handle h, cxobj **xp);
|
||||||
int xmldb_put(clicon_handle h, const char *db, enum operation_type op, cxobj *xt, char *username, cbuf *cbret); /* in clixon_datastore_write.[ch] */
|
int xmldb_put(clicon_handle h, const char *db, enum operation_type op, cxobj *xt, char *username, cbuf *cbret); /* in clixon_datastore_write.[ch] */
|
||||||
int xmldb_copy(clicon_handle h, const char *from, const char *to);
|
int xmldb_copy(clicon_handle h, const char *from, const char *to);
|
||||||
int xmldb_lock(clicon_handle h, const char *db, int pid);
|
int xmldb_lock(clicon_handle h, const char *db, int pid);
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,15 @@ enum startup_mode_t{
|
||||||
SM_INIT
|
SM_INIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! Datastore cache behaviour, see clixon_datastore.[ch]
|
||||||
|
* See config option type datastore_cache in clixon-config.yang
|
||||||
|
*/
|
||||||
|
enum datastore_cache{
|
||||||
|
DATASTORE_NOCACHE,
|
||||||
|
DATASTORE_CACHE,
|
||||||
|
DATASTORE_CACHE_ZEROCOPY
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
|
@ -163,6 +172,7 @@ int clicon_sock_family(clicon_handle h);
|
||||||
int clicon_sock_port(clicon_handle h);
|
int clicon_sock_port(clicon_handle h);
|
||||||
int clicon_autocommit(clicon_handle h);
|
int clicon_autocommit(clicon_handle h);
|
||||||
int clicon_startup_mode(clicon_handle h);
|
int clicon_startup_mode(clicon_handle h);
|
||||||
|
enum datastore_cache clicon_datastore_cache(clicon_handle h);
|
||||||
|
|
||||||
/*-- Specific option access functions for non-yang options --*/
|
/*-- Specific option access functions for non-yang options --*/
|
||||||
int clicon_quiet_mode(clicon_handle h);
|
int clicon_quiet_mode(clicon_handle h);
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,6 @@ xmldb_disconnect(clicon_handle h)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Copy database from db1 to db2
|
/*! Copy database from db1 to db2
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] from Source database
|
* @param[in] from Source database
|
||||||
|
|
@ -199,7 +198,7 @@ xmldb_copy(clicon_handle h,
|
||||||
cxobj *x2 = NULL; /* to */
|
cxobj *x2 = NULL; /* to */
|
||||||
|
|
||||||
/* XXX lock */
|
/* XXX lock */
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
|
if (clicon_datastore_cache(h) != DATASTORE_NOCACHE){
|
||||||
/* Copy in-memory cache */
|
/* Copy in-memory cache */
|
||||||
/* 1. "to" xml tree in x1 */
|
/* 1. "to" xml tree in x1 */
|
||||||
if ((de1 = clicon_db_elmnt_get(h, from)) != NULL)
|
if ((de1 = clicon_db_elmnt_get(h, from)) != NULL)
|
||||||
|
|
@ -387,7 +386,7 @@ xmldb_delete(clicon_handle h,
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
|
if (clicon_datastore_cache(h) != DATASTORE_NOCACHE){
|
||||||
if ((de = clicon_db_elmnt_get(h, db)) != NULL){
|
if ((de = clicon_db_elmnt_get(h, db)) != NULL){
|
||||||
if ((xt = de->de_xml) != NULL){
|
if ((xt = de->de_xml) != NULL){
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
|
|
@ -425,7 +424,7 @@ xmldb_create(clicon_handle h,
|
||||||
db_elmnt *de = NULL;
|
db_elmnt *de = NULL;
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
|
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){ /* XXX This should not really happen? */
|
if (clicon_datastore_cache(h) != DATASTORE_NOCACHE){
|
||||||
if ((de = clicon_db_elmnt_get(h, db)) != NULL){
|
if ((de = clicon_db_elmnt_get(h, db)) != NULL){
|
||||||
if ((xt = de->de_xml) != NULL){
|
if ((xt = de->de_xml) != NULL){
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
|
|
|
||||||
|
|
@ -572,11 +572,11 @@ xmldb_get_cache(clicon_handle h,
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xmldb_get1_cache(clicon_handle h,
|
xmldb_get_zerocopy(clicon_handle h,
|
||||||
const char *db,
|
const char *db,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cxobj **xtop,
|
cxobj **xtop,
|
||||||
modstate_diff_t *msd)
|
modstate_diff_t *msd)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
|
@ -641,16 +641,29 @@ xmldb_get1_cache(clicon_handle h,
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] db Name of database to search in (filename including dir path
|
* @param[in] db Name of database to search in (filename including dir path
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||||
|
* @param[in] copy Force copy. Overrides cache_zerocopy -> cache
|
||||||
* @param[out] xret Single return XML tree. Free with xml_free()
|
* @param[out] xret Single return XML tree. Free with xml_free()
|
||||||
* @param[out] msd If set, return modules-state differences
|
* @param[out] msd If set, return modules-state differences
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
* There are two variants of the call:
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt;
|
* cxobj *xt;
|
||||||
* if (xmldb_get(xh, "running", "/interfaces/interface[name="eth"]", &xt, NULL) < 0)
|
* if (xmldb_get(xh, "running", "/interfaces/interface[name="eth"]", 0, &xt, NULL) < 0)
|
||||||
|
* err;
|
||||||
|
* # Code accessing and setting XML flags on xt, sorting, populate w yang spec,...
|
||||||
|
* xmldb_get_clear(h, xt); # Clear tree from default values and flags
|
||||||
|
* # (only if cache+zerocopy
|
||||||
|
* xmldb_get_free(h, &xt); # Free tree (only if not zero-copy)
|
||||||
|
* @endcode
|
||||||
|
* The second variant only applies to zerocopy cases where you want to force a copy
|
||||||
|
* since it may be too difficult to handle marked subtrees.
|
||||||
|
* @code
|
||||||
|
* if (xmldb_get(xh, "running", "/interfaces/interface[name="eth"]", 1, &xt, NULL) < 0)
|
||||||
* err;
|
* err;
|
||||||
* xml_free(xt);
|
* xml_free(xt);
|
||||||
* @endcode
|
* @endcode
|
||||||
|
*
|
||||||
* @note if xvec is given, then purge tree, if not return whole tree.
|
* @note if xvec is given, then purge tree, if not return whole tree.
|
||||||
* @see xpath_vec
|
* @see xpath_vec
|
||||||
*/
|
*/
|
||||||
|
|
@ -658,84 +671,83 @@ int
|
||||||
xmldb_get(clicon_handle h,
|
xmldb_get(clicon_handle h,
|
||||||
const char *db,
|
const char *db,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
|
int copy,
|
||||||
cxobj **xret,
|
cxobj **xret,
|
||||||
modstate_diff_t *msd)
|
modstate_diff_t *msd)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE"))
|
switch (clicon_datastore_cache(h)){
|
||||||
|
case DATASTORE_NOCACHE:
|
||||||
|
/* Read from file into created/copy tree, prune non-matching xpath
|
||||||
|
* Add default values in copy
|
||||||
|
* Copy deleted by xmldb_free
|
||||||
|
*/
|
||||||
|
retval = xmldb_get_nocache(h, db, xpath, xret, msd);
|
||||||
|
break;
|
||||||
|
case DATASTORE_CACHE_ZEROCOPY:
|
||||||
|
/* Get cache (file if empty) mark xpath match in original tree
|
||||||
|
* add default values in original tree and return that.
|
||||||
|
* Default values and markings removed in xmldb_clear
|
||||||
|
*/
|
||||||
|
if (!copy){
|
||||||
|
retval = xmldb_get_zerocopy(h, db, xpath, xret, msd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
case DATASTORE_CACHE:
|
||||||
|
/* Get cache (file if empty) mark xpath match and copy marked into copy
|
||||||
|
* Add default values in copy, return copy
|
||||||
|
* Copy deleted by xmldb_free
|
||||||
|
*/
|
||||||
retval = xmldb_get_cache(h, db, xpath, xret, msd);
|
retval = xmldb_get_cache(h, db, xpath, xret, msd);
|
||||||
else
|
break;
|
||||||
retval = xmldb_get_nocache(h, db, xpath, xret, msd);
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Get content of database using xpath. return a set of matching sub-trees
|
/*! Clear cached xml tree obtained with xmldb_get, if zerocopy
|
||||||
* The function returns a minimal tree that includes all sub-trees that match
|
|
||||||
* xpath.
|
|
||||||
* @param[in] h Clicon handle
|
|
||||||
* @param[in] db Name of database to search in (filename including dir path
|
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
|
||||||
* @param[out] xret Single return XML tree. see note
|
|
||||||
* @param[out] msd If set, return modules-state differences
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
* @code
|
|
||||||
* cxobj *xt;
|
|
||||||
* if (xmldb_get(xh, "running", "/interfaces/interface[name="eth"]", &xt, NULL) < 0)
|
|
||||||
* err;
|
|
||||||
* xml_free(xt);
|
|
||||||
* @endcode
|
|
||||||
* @note if xvec is given, then purge tree, if not return whole tree.
|
|
||||||
* @see xmldb_get This version uses direct cache access and needs to be
|
|
||||||
* cleanued up after use
|
|
||||||
* @see xmldb_get1_clear Must call after use
|
|
||||||
* @note If !CLICON_XMLDB_CACHE you need to free xret after use
|
|
||||||
* @note If CLICON_XMLDB_CACHE mark|change flags set, need to clear after call
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xmldb_get1(clicon_handle h,
|
|
||||||
const char *db,
|
|
||||||
char *xpath,
|
|
||||||
cxobj **xret,
|
|
||||||
modstate_diff_t *msd)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE"))
|
|
||||||
retval = xmldb_get1_cache(h, db, xpath, xret, msd);
|
|
||||||
else
|
|
||||||
retval = xmldb_get_nocache(h, db, xpath, xret, msd);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Clear cached tree after accessed by xmldb_get1
|
|
||||||
*
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] dbname Name of database to search in (filename including dir path
|
* @param[in] db Name of datastore
|
||||||
* @see xmldb_get1
|
* "Clear" an xml tree means removing default values and resetting all flags.
|
||||||
|
* @see xmldb_get
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xmldb_get1_clear(clicon_handle h,
|
xmldb_get_clear(clicon_handle h,
|
||||||
const char *db)
|
cxobj *x)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
db_elmnt *de = NULL;
|
|
||||||
|
|
||||||
if (!clicon_option_bool(h, "CLICON_XMLDB_CACHE"))
|
if (clicon_datastore_cache(h) != DATASTORE_CACHE_ZEROCOPY)
|
||||||
goto ok; /* dont bother, tree is a copy */
|
goto ok;
|
||||||
de = clicon_db_elmnt_get(h, db);
|
if (x == NULL)
|
||||||
if (de != NULL && de->de_xml != NULL){
|
goto ok;
|
||||||
/* clear XML tree of defaults */
|
/* clear XML tree of defaults */
|
||||||
if (xml_tree_prune_flagged(de->de_xml, XML_FLAG_DEFAULT, 1) < 0)
|
if (xml_tree_prune_flagged(x, XML_FLAG_DEFAULT, 1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* clear mark and change */
|
/* clear mark and change */
|
||||||
xml_apply0(de->de_xml, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
xml_apply0(x, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
||||||
(void*)(0xff));
|
(void*)(0xff));
|
||||||
}
|
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Free xml tree obtained with xmldb_get, unless zerocopy
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in,out] xp Pointer to XML cache.
|
||||||
|
* @see xmldb_get
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmldb_get_free(clicon_handle h,
|
||||||
|
cxobj **xp)
|
||||||
|
{
|
||||||
|
if (*xp == NULL ||
|
||||||
|
clicon_datastore_cache(h) == DATASTORE_CACHE_ZEROCOPY)
|
||||||
|
return 0;
|
||||||
|
xml_free(*xp);
|
||||||
|
*xp = NULL;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -652,8 +652,9 @@ xmldb_put(clicon_handle h,
|
||||||
xml_name(x1));
|
xml_name(x1));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
|
|
||||||
if ((de = clicon_db_elmnt_get(h, db)) != NULL)
|
if ((de = clicon_db_elmnt_get(h, db)) != NULL){
|
||||||
|
if (clicon_datastore_cache(h) != DATASTORE_NOCACHE)
|
||||||
x0 = de->de_xml;
|
x0 = de->de_xml;
|
||||||
}
|
}
|
||||||
/* If there is no xml x0 tree (in cache), then read it from file */
|
/* If there is no xml x0 tree (in cache), then read it from file */
|
||||||
|
|
@ -713,8 +714,9 @@ xmldb_put(clicon_handle h,
|
||||||
if (xml_apply0(x0, -1, xml_sort_verify, NULL) < 0)
|
if (xml_apply0(x0, -1, xml_sort_verify, NULL) < 0)
|
||||||
clicon_log(LOG_NOTICE, "%s: verify failed #3", __FUNCTION__);
|
clicon_log(LOG_NOTICE, "%s: verify failed #3", __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Write back to datastore cache if first time */
|
/* Write back to datastore cache if first time */
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
|
if (clicon_datastore_cache(h) != DATASTORE_NOCACHE){
|
||||||
db_elmnt de0 = {0,};
|
db_elmnt de0 = {0,};
|
||||||
if (de != NULL)
|
if (de != NULL)
|
||||||
de0 = *de;
|
de0 = *de;
|
||||||
|
|
@ -770,7 +772,7 @@ xmldb_put(clicon_handle h,
|
||||||
free(dbfile);
|
free(dbfile);
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
if (!clicon_option_bool(h, "CLICON_XMLDB_CACHE") && x0)
|
if (x0 && clicon_datastore_cache(h) == DATASTORE_NOCACHE)
|
||||||
xml_free(x0);
|
xml_free(x0);
|
||||||
return retval;
|
return retval;
|
||||||
fail:
|
fail:
|
||||||
|
|
|
||||||
|
|
@ -890,7 +890,7 @@ nacm_access_pre(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if (strcmp(mode, "internal")==0){
|
else if (strcmp(mode, "internal")==0){
|
||||||
if (xmldb_get(h, "running", "nacm", &xnacm0, NULL) < 0)
|
if (xmldb_get(h, "running", "nacm", 1, &xnacm0, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -543,30 +543,25 @@ clicon_cli_genmodel_completion(clicon_handle h)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const map_str2int cli_genmodel_map[] = {
|
||||||
|
{"NONE", GT_NONE},
|
||||||
|
{"VARS", GT_VARS},
|
||||||
|
{"ALL", GT_ALL},
|
||||||
|
{NULL, -1}
|
||||||
|
};
|
||||||
|
|
||||||
/*! How to generate and show CLI syntax: VARS|ALL
|
/*! How to generate and show CLI syntax: VARS|ALL
|
||||||
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL_TYPE
|
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL_TYPE
|
||||||
*/
|
*/
|
||||||
enum genmodel_type
|
enum genmodel_type
|
||||||
clicon_cli_genmodel_type(clicon_handle h)
|
clicon_cli_genmodel_type(clicon_handle h)
|
||||||
{
|
{
|
||||||
char *s;
|
char *str;
|
||||||
enum genmodel_type gt = GT_ERR;
|
|
||||||
|
|
||||||
if (!clicon_option_exists(h, "CLICON_CLI_GENMODEL_TYPE")){
|
if ((str = clicon_option_str(h, "CLICON_CLI_GENMODEL_TYPE")) == NULL)
|
||||||
gt = GT_VARS;
|
return GT_VARS;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
s = clicon_option_str(h, "CLICON_CLI_GENMODEL_TYPE");
|
|
||||||
if (strcmp(s, "NONE")==0)
|
|
||||||
gt = GT_NONE;
|
|
||||||
else
|
else
|
||||||
if (strcmp(s, "VARS")==0)
|
return clicon_str2int(cli_genmodel_map, str);
|
||||||
gt = GT_VARS;
|
|
||||||
else
|
|
||||||
if (strcmp(s, "ALL")==0)
|
|
||||||
gt = GT_ALL;
|
|
||||||
done:
|
|
||||||
return gt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Get Dont include keys in cvec in cli vars callbacks
|
/*! Get Dont include keys in cvec in cli vars callbacks
|
||||||
|
|
@ -638,6 +633,28 @@ clicon_startup_mode(clicon_handle h)
|
||||||
return clicon_str2int(startup_mode_map, mode);
|
return clicon_str2int(startup_mode_map, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const map_str2int datastore_cache_map[] = {
|
||||||
|
{"nocache", DATASTORE_NOCACHE},
|
||||||
|
{"cache", DATASTORE_CACHE},
|
||||||
|
{"cache-zerocopy", DATASTORE_CACHE_ZEROCOPY},
|
||||||
|
{NULL, -1}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! How to generate and show CLI syntax: VARS|ALL
|
||||||
|
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL_TYPE
|
||||||
|
*/
|
||||||
|
enum datastore_cache
|
||||||
|
clicon_datastore_cache(clicon_handle h)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
if ((str = clicon_option_str(h, "CLICON_DATASTORE_CACHE")) == NULL)
|
||||||
|
return DATASTORE_CACHE;
|
||||||
|
else
|
||||||
|
return clicon_str2int(datastore_cache_map, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
/*---------------------------------------------------------------------
|
||||||
* Specific option access functions for non-yang options
|
* Specific option access functions for non-yang options
|
||||||
* Typically dynamic values and more complex datatypes,
|
* Typically dynamic values and more complex datatypes,
|
||||||
|
|
|
||||||
|
|
@ -198,11 +198,14 @@ main(int argc, char **argv)
|
||||||
xpath = argv[1];
|
xpath = argv[1];
|
||||||
else
|
else
|
||||||
xpath = "/";
|
xpath = "/";
|
||||||
if (xmldb_get(h, db, xpath, &xt, NULL) < 0)
|
if (xmldb_get(h, db, xpath, 1, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_xml2file(stdout, xt, 0, 0);
|
clicon_xml2file(stdout, xt, 0, 0);
|
||||||
|
|
||||||
fprintf(stdout, "\n");
|
fprintf(stdout, "\n");
|
||||||
|
if (xt){
|
||||||
|
xml_free(xt);
|
||||||
|
xt = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "mget")==0){
|
else if (strcmp(cmd, "mget")==0){
|
||||||
int nr;
|
int nr;
|
||||||
|
|
@ -214,15 +217,17 @@ main(int argc, char **argv)
|
||||||
else
|
else
|
||||||
xpath = "/";
|
xpath = "/";
|
||||||
for (i=0;i<nr;i++){
|
for (i=0;i<nr;i++){
|
||||||
if (xmldb_get(h, db, xpath, &xt, NULL) < 0)
|
if (xmldb_get(h, db, xpath, 1, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xt == NULL){
|
if (xt == NULL){
|
||||||
clicon_err(OE_DB, 0, "xt is NULL");
|
clicon_err(OE_DB, 0, "xt is NULL");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
clicon_xml2file(stdout, xt, 0, 0);
|
clicon_xml2file(stdout, xt, 0, 0);
|
||||||
xml_free(xt);
|
if (xt){
|
||||||
xt = NULL;
|
xml_free(xt);
|
||||||
|
xt = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fprintf(stdout, "\n");
|
fprintf(stdout, "\n");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,9 @@ module clixon-config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typedef xmldb_format{
|
typedef datastore_format{
|
||||||
description
|
description
|
||||||
"Format of TEXT xml database format.";
|
"Datastore format.";
|
||||||
type enumeration{
|
type enumeration{
|
||||||
enum xml{
|
enum xml{
|
||||||
description "Save and load xmldb as XML";
|
description "Save and load xmldb as XML";
|
||||||
|
|
@ -96,6 +96,24 @@ module clixon-config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
typedef datastore_cache{
|
||||||
|
description
|
||||||
|
"XML configuration, ie running/candididate/ datastore cache behaviour.";
|
||||||
|
type enumeration{
|
||||||
|
enum nocache{
|
||||||
|
description "No cache always work directly with file";
|
||||||
|
}
|
||||||
|
enum cache{
|
||||||
|
description "Use in-memory cache.
|
||||||
|
Make copies when accessing internally.";
|
||||||
|
}
|
||||||
|
enum cache-zerocopy{
|
||||||
|
description "Use in-memory cache and dont copy.
|
||||||
|
Fastest but opens up for callbacks changing cache.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef cli_genmodel_type{
|
typedef cli_genmodel_type{
|
||||||
description
|
description
|
||||||
"How to generate CLI from YANG model,
|
"How to generate CLI from YANG model,
|
||||||
|
|
@ -258,7 +276,8 @@ module clixon-config {
|
||||||
"If set, generate CLI specification for CLI completion of
|
"If set, generate CLI specification for CLI completion of
|
||||||
loaded Yang modules. This CLI tree can be accessed in CLI
|
loaded Yang modules. This CLI tree can be accessed in CLI
|
||||||
spec files using the tree reference syntax (eg @datamodel).
|
spec files using the tree reference syntax (eg @datamodel).
|
||||||
See also CLICON_CLI_MODEL_TREENAME.";
|
See also CLICON_CLI_MODEL_TREENAME.
|
||||||
|
(Consider boolean)";
|
||||||
}
|
}
|
||||||
leaf CLICON_CLI_MODEL_TREENAME {
|
leaf CLICON_CLI_MODEL_TREENAME {
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -271,7 +290,8 @@ module clixon-config {
|
||||||
leaf CLICON_CLI_GENMODEL_COMPLETION {
|
leaf CLICON_CLI_GENMODEL_COMPLETION {
|
||||||
type int32;
|
type int32;
|
||||||
default 1;
|
default 1;
|
||||||
description "Generate code for CLI completion of existing db symbols";
|
description "Generate code for CLI completion of existing db symbols.
|
||||||
|
Consider boolean type";
|
||||||
}
|
}
|
||||||
leaf CLICON_CLI_GENMODEL_TYPE {
|
leaf CLICON_CLI_GENMODEL_TYPE {
|
||||||
type cli_genmodel_type;
|
type cli_genmodel_type;
|
||||||
|
|
@ -368,16 +388,15 @@ module clixon-config {
|
||||||
(see datastore/ and clixon_xml_db.[ch])
|
(see datastore/ and clixon_xml_db.[ch])
|
||||||
Obsolete: Merged with libclixon in 3.10";
|
Obsolete: Merged with libclixon in 3.10";
|
||||||
}
|
}
|
||||||
leaf CLICON_XMLDB_CACHE {
|
leaf CLICON_DATASTORE_CACHE {
|
||||||
type boolean;
|
type datastore_cache;
|
||||||
default true;
|
default cache;
|
||||||
description
|
description
|
||||||
"XMLDB datatsore cache.
|
"Clixon datastore cache behaviour. There are three values: no cache,
|
||||||
If set, XML candidate/running parsed tree is stored in memory
|
cache with copy, or cache without copy.";
|
||||||
If not set, candidate/running is always accessed via disk.";
|
|
||||||
}
|
}
|
||||||
leaf CLICON_XMLDB_FORMAT {
|
leaf CLICON_XMLDB_FORMAT {
|
||||||
type xmldb_format;
|
type datastore_format;
|
||||||
default xml;
|
default xml;
|
||||||
description "XMLDB datastore format.";
|
description "XMLDB datastore format.";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue