Removed other datastore options than cached
Marked `CLICON_DATASTORE_CACHE` as obsolete
This commit is contained in:
parent
bca315ef9d
commit
9989ee4d52
13 changed files with 75 additions and 530 deletions
|
|
@ -30,6 +30,12 @@ Users may have to change how they access the system
|
||||||
|
|
||||||
* Revert the creators attribute feature introduced in 6.2. It is now obsoleted.
|
* Revert the creators attribute feature introduced in 6.2. It is now obsoleted.
|
||||||
It is replaced with a configured `creators` and user/application semantics
|
It is replaced with a configured `creators` and user/application semantics
|
||||||
|
* New `clixon-lib@2024-01-01.yang` revision
|
||||||
|
* Replaced container creators to grouping/uses
|
||||||
|
* New `clixon-config@2024-01-01.yang` revision
|
||||||
|
* Marked as obsolete:
|
||||||
|
* `CLICON_DATASTORE_CACHE` Replaced with enhanced datastore read API
|
||||||
|
* `CLICON_NETCONF_CREATOR_ATTR` reverting 6.5 functionality
|
||||||
|
|
||||||
### C/CLI-API changes on existing features
|
### C/CLI-API changes on existing features
|
||||||
Developers may need to change their code
|
Developers may need to change their code
|
||||||
|
|
|
||||||
|
|
@ -366,9 +366,6 @@ startup_validate(clixon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
plugin_transaction_end_all(h, td);
|
plugin_transaction_end_all(h, td);
|
||||||
/* Clear cached trees from default values and marking */
|
|
||||||
if (xmldb_get0_clear(h, td->td_target) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xtr){
|
if (xtr){
|
||||||
*xtr = td->td_target;
|
*xtr = td->td_target;
|
||||||
td->td_target = NULL;
|
td->td_target = NULL;
|
||||||
|
|
@ -376,7 +373,6 @@ startup_validate(clixon_handle h,
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (td){
|
if (td){
|
||||||
xmldb_get0_free(h, &td->td_target);
|
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -421,10 +417,9 @@ startup_commit(clixon_handle h,
|
||||||
/* After commit, make a post-commit call (sure that all plugins have committed) */
|
/* After commit, make a post-commit call (sure that all plugins have committed) */
|
||||||
if (plugin_transaction_commit_done_all(h, td) < 0)
|
if (plugin_transaction_commit_done_all(h, td) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Clear cached trees from default values and marking */
|
/* Remove global defaults and empty non-presence containers */
|
||||||
if (xmldb_get0_clear(h, td->td_target) < 0)
|
if (xml_defaults_nopresence(td->td_target, 2) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* [Delete and] create running db */
|
/* [Delete and] create running db */
|
||||||
if (xmldb_exists(h, "running") == 1){
|
if (xmldb_exists(h, "running") == 1){
|
||||||
if (xmldb_delete(h, "running") != 0 && errno != ENOENT)
|
if (xmldb_delete(h, "running") != 0 && errno != ENOENT)
|
||||||
|
|
@ -454,7 +449,6 @@ startup_commit(clixon_handle h,
|
||||||
if (td){
|
if (td){
|
||||||
if (retval < 1)
|
if (retval < 1)
|
||||||
plugin_transaction_abort_all(h, td);
|
plugin_transaction_abort_all(h, td);
|
||||||
xmldb_get0_free(h, &td->td_target);
|
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -622,10 +616,6 @@ candidate_validate(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (xmldb_get0_clear(h, td->td_src) < 0 ||
|
|
||||||
xmldb_get0_clear(h, td->td_target) < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
plugin_transaction_end_all(h, td);
|
plugin_transaction_end_all(h, td);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
|
|
@ -634,8 +624,6 @@ candidate_validate(clixon_handle h,
|
||||||
if (td){
|
if (td){
|
||||||
if (retval < 1)
|
if (retval < 1)
|
||||||
plugin_transaction_abort_all(h, td);
|
plugin_transaction_abort_all(h, td);
|
||||||
xmldb_get0_free(h, &td->td_target);
|
|
||||||
xmldb_get0_free(h, &td->td_src);
|
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -715,13 +703,6 @@ candidate_commit(clixon_handle h,
|
||||||
/* After commit, make a post-commit call (sure that all plugins have committed) */
|
/* After commit, make a post-commit call (sure that all plugins have committed) */
|
||||||
if (plugin_transaction_commit_done_all(h, td) < 0)
|
if (plugin_transaction_commit_done_all(h, td) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Clear cached trees from default values and marking */
|
|
||||||
if (xmldb_get0_clear(h, td->td_target) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xmldb_get0_clear(h, td->td_src) < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* 8. Success: Copy candidate to running
|
/* 8. Success: Copy candidate to running
|
||||||
*/
|
*/
|
||||||
if (xmldb_copy(h, db, "running") < 0)
|
if (xmldb_copy(h, db, "running") < 0)
|
||||||
|
|
@ -746,8 +727,6 @@ candidate_commit(clixon_handle h,
|
||||||
if (td){
|
if (td){
|
||||||
if (retval < 1)
|
if (retval < 1)
|
||||||
plugin_transaction_abort_all(h, td);
|
plugin_transaction_abort_all(h, td);
|
||||||
xmldb_get0_free(h, &td->td_target);
|
|
||||||
xmldb_get0_free(h, &td->td_src);
|
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
if (xret)
|
if (xret)
|
||||||
|
|
@ -1043,7 +1022,6 @@ from_client_restart_one(clixon_handle h,
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (td){
|
if (td){
|
||||||
xmldb_get0_free(h, &td->td_target);
|
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,6 @@ db_merge(clixon_handle h,
|
||||||
/* 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:
|
||||||
xmldb_get0_free(h, &xt);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -334,7 +333,6 @@ startup_extraxml(clixon_handle h,
|
||||||
done:
|
done:
|
||||||
if (xt0)
|
if (xt0)
|
||||||
xml_free(xt0);
|
xml_free(xt0);
|
||||||
xmldb_get0_free(h, &xt);
|
|
||||||
if (xmldb_delete(h, tmp_db) != 0 && errno != ENOENT)
|
if (xmldb_delete(h, tmp_db) != 0 && errno != ENOENT)
|
||||||
return -1;
|
return -1;
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,6 @@ int xmldb_get(clixon_handle h, const char *db, cvec *nsc, char *xpath, cxobj **x
|
||||||
int xmldb_get0(clixon_handle h, const char *db, yang_bind yb,
|
int xmldb_get0(clixon_handle h, const char *db, yang_bind yb,
|
||||||
cvec *nsc, const char *xpath, int copy, withdefaults_type wdef,
|
cvec *nsc, const char *xpath, int copy, withdefaults_type wdef,
|
||||||
cxobj **xtop, modstate_diff_t *msd, cxobj **xerr);
|
cxobj **xtop, modstate_diff_t *msd, cxobj **xerr);
|
||||||
int xmldb_get0_clear(clixon_handle h, cxobj *x);
|
|
||||||
int xmldb_get0_free(clixon_handle h, cxobj **xp);
|
|
||||||
int xmldb_put(clixon_handle h, const char *db, enum operation_type op, cxobj *xt, char *username, cbuf *cbret); /* in clixon_datastore_write.[ch] */
|
int xmldb_put(clixon_handle h, const char *db, enum operation_type op, cxobj *xt, char *username, cbuf *cbret); /* in clixon_datastore_write.[ch] */
|
||||||
int xmldb_copy(clixon_handle h, const char *from, const char *to);
|
int xmldb_copy(clixon_handle h, const char *from, const char *to);
|
||||||
int xmldb_lock(clixon_handle h, const char *db, uint32_t id);
|
int xmldb_lock(clixon_handle h, const char *db, uint32_t id);
|
||||||
|
|
|
||||||
|
|
@ -85,16 +85,6 @@ enum nacm_credentials_t{
|
||||||
NC_EXCEPT /* Exact match except for root and www user */
|
NC_EXCEPT /* Exact match except for root and www user */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! 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
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! yang clixon regexp engine
|
/*! yang clixon regexp engine
|
||||||
*
|
*
|
||||||
* @see regexp_mode in clixon-config.yang
|
* @see regexp_mode in clixon-config.yang
|
||||||
|
|
@ -204,7 +194,6 @@ enum priv_mode_t clicon_backend_privileges_mode(clixon_handle h);
|
||||||
enum priv_mode_t clicon_restconf_privileges_mode(clixon_handle h);
|
enum priv_mode_t clicon_restconf_privileges_mode(clixon_handle h);
|
||||||
enum nacm_credentials_t clicon_nacm_credentials(clixon_handle h);
|
enum nacm_credentials_t clicon_nacm_credentials(clixon_handle h);
|
||||||
|
|
||||||
enum datastore_cache clicon_datastore_cache(clixon_handle h);
|
|
||||||
enum regexp_mode clicon_yang_regexp(clixon_handle h);
|
enum regexp_mode clicon_yang_regexp(clixon_handle h);
|
||||||
/*-- Specific option access functions for non-yang options --*/
|
/*-- Specific option access functions for non-yang options --*/
|
||||||
int clicon_quiet_mode(clixon_handle h);
|
int clicon_quiet_mode(clixon_handle h);
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,6 @@ xmldb_copy(clixon_handle h,
|
||||||
|
|
||||||
clixon_debug(CLIXON_DBG_DATASTORE, "%s %s", from, to);
|
clixon_debug(CLIXON_DBG_DATASTORE, "%s %s", from, to);
|
||||||
/* XXX lock */
|
/* XXX lock */
|
||||||
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)
|
||||||
|
|
@ -225,7 +224,6 @@ xmldb_copy(clixon_handle h,
|
||||||
if (de2)
|
if (de2)
|
||||||
de0 = *de2;
|
de0 = *de2;
|
||||||
de0.de_xml = x2; /* The new tree */
|
de0.de_xml = x2; /* The new tree */
|
||||||
}
|
|
||||||
clicon_db_elmnt_set(h, to, &de0);
|
clicon_db_elmnt_set(h, to, &de0);
|
||||||
|
|
||||||
/* Copy the files themselves (above only in-memory cache) */
|
/* Copy the files themselves (above only in-memory cache) */
|
||||||
|
|
|
||||||
|
|
@ -677,162 +677,6 @@ xmldb_readfile(clixon_handle h,
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
* @retval 0 Parse OK but yang assigment not made (or only partial) and xerr set
|
* @retval 0 Parse OK but yang assigment not made (or only partial) and xerr set
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @note Use of 1 for OK
|
|
||||||
* @see xmldb_get the generic API function
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xmldb_get_nocache(clixon_handle h,
|
|
||||||
const char *db,
|
|
||||||
yang_bind yb,
|
|
||||||
cvec *nsc,
|
|
||||||
const char *xpath,
|
|
||||||
withdefaults_type wdef,
|
|
||||||
cxobj **xtop,
|
|
||||||
modstate_diff_t *msdiff,
|
|
||||||
cxobj **xerr)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
yang_stmt *yspec;
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *x;
|
|
||||||
int fd = -1;
|
|
||||||
cxobj **xvec = NULL;
|
|
||||||
size_t xlen;
|
|
||||||
int i;
|
|
||||||
int ret;
|
|
||||||
db_elmnt de0 = {0,};
|
|
||||||
|
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
|
||||||
clixon_err(OE_YANG, ENOENT, "No yang spec");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* xml looks like: <top><config><x>... where "x" is a top-level symbol in a module */
|
|
||||||
if ((ret = xmldb_readfile(h, db, yb, yspec, &xt, &de0, msdiff, xerr)) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret == 0)
|
|
||||||
goto fail;
|
|
||||||
clicon_db_elmnt_set(h, db, &de0); /* Content is copied */
|
|
||||||
/* Here xt looks like: <config>...</config> */
|
|
||||||
/* Given the xpath, return a vector of matches in xvec */
|
|
||||||
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* If vectors are specified then mark the nodes found with all ancestors
|
|
||||||
* and filter out everything else,
|
|
||||||
* otherwise return complete tree.
|
|
||||||
*/
|
|
||||||
if (xvec != NULL)
|
|
||||||
for (i=0; i<xlen; i++){
|
|
||||||
x = xvec[i];
|
|
||||||
xml_flag_set(x, XML_FLAG_MARK);
|
|
||||||
}
|
|
||||||
/* Remove everything that is not marked */
|
|
||||||
if (!xml_flag(xt, XML_FLAG_MARK))
|
|
||||||
if (xml_tree_prune_flagged_sub(xt, XML_FLAG_MARK, 1, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
/* reset flag */
|
|
||||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (yb != YB_NONE){
|
|
||||||
/* Add global defaults. */
|
|
||||||
if (xml_global_defaults(h, xt, nsc, xpath, yspec, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Add default values (if not set) */
|
|
||||||
if (xml_default_recurse(xt, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
#if 1
|
|
||||||
/* Sub-optimal: first add defaults, then remove them in some cases
|
|
||||||
* Reason is code is primarily test for _cache case and I dont have time to "revert" it here
|
|
||||||
*/
|
|
||||||
switch (wdef){
|
|
||||||
case WITHDEFAULTS_REPORT_ALL:
|
|
||||||
break;
|
|
||||||
case WITHDEFAULTS_TRIM:
|
|
||||||
/* Mark and remove nodes having schema default values */
|
|
||||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_tree_prune_flags(xt, XML_FLAG_MARK, XML_FLAG_MARK)
|
|
||||||
< 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_defaults_nopresence(xt, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
case WITHDEFAULTS_EXPLICIT:
|
|
||||||
if (xml_defaults_nopresence(xt, 2) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
case WITHDEFAULTS_REPORT_ALL_TAGGED:{
|
|
||||||
cxobj *x;
|
|
||||||
char *ns;
|
|
||||||
x = NULL;
|
|
||||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL){
|
|
||||||
ns = NULL;
|
|
||||||
if (xml2ns(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ns == NULL){
|
|
||||||
if (xmlns_set(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else if (strcmp(ns, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) != 0){
|
|
||||||
/* XXX: Assume if namespace is set that it is withdefaults otherwise just ignore? */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Mark nodes having default schema values */
|
|
||||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Add tag attributes to default nodes */
|
|
||||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} /* switch wdef */
|
|
||||||
#endif
|
|
||||||
/* If empty NACM config, then disable NACM if loaded
|
|
||||||
*/
|
|
||||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
|
||||||
if (disable_nacm_on_empty(xt, yspec) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
clixon_debug_xml(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, xt, "");
|
|
||||||
*xtop = xt;
|
|
||||||
xt = NULL;
|
|
||||||
retval = 1;
|
|
||||||
done:
|
|
||||||
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "retval:%d", retval);
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
if (xvec)
|
|
||||||
free(xvec);
|
|
||||||
if (fd != -1)
|
|
||||||
close(fd);
|
|
||||||
return retval;
|
|
||||||
fail:
|
|
||||||
retval = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Get content of database using xpath. return a set of matching sub-trees
|
|
||||||
*
|
|
||||||
* The function returns a minimal tree that includes all sub-trees that match
|
|
||||||
* xpath.
|
|
||||||
* This is a clixon datastore plugin of the the xmldb api
|
|
||||||
* @param[in] h Clixon handle
|
|
||||||
* @param[in] db Name of database to search in (filename including dir path
|
|
||||||
* @param[in] yb How to bind yang to XML top-level when parsing
|
|
||||||
* @param[in] nsc External XML namespace context, or NULL
|
|
||||||
* @param[in] xpath String with XPath syntax. or NULL for all
|
|
||||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
|
||||||
* @param[out] xtop Single return XML tree. Free with xml_free()
|
|
||||||
* @param[out] msdiff If set, return modules-state differences
|
|
||||||
* @param[out] xerr XML error if retval is 0
|
|
||||||
* @retval 1 OK
|
|
||||||
* @retval 0 Parse OK but yang assigment not made (or only partial) and xerr set
|
|
||||||
* @retval -1 Error
|
|
||||||
* @note Use of 1 for OK
|
|
||||||
* @see xmldb_get the generic API function
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xmldb_get_cache(clixon_handle h,
|
xmldb_get_cache(clixon_handle h,
|
||||||
|
|
@ -841,10 +685,9 @@ xmldb_get_cache(clixon_handle h,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
const char *xpath,
|
const char *xpath,
|
||||||
withdefaults_type wdef,
|
withdefaults_type wdef,
|
||||||
cxobj **xtop,
|
cxobj **xret,
|
||||||
modstate_diff_t *msdiff,
|
modstate_diff_t *msdiff,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
|
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
|
@ -859,7 +702,10 @@ xmldb_get_cache(clixon_handle h,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "db %s", db);
|
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "db %s", db);
|
||||||
|
if (xret == NULL){
|
||||||
|
clixon_err(OE_DB, EINVAL, "xret is NULL");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||||
clixon_err(OE_YANG, ENOENT, "No yang spec");
|
clixon_err(OE_YANG, ENOENT, "No yang spec");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -992,155 +838,7 @@ xmldb_get_cache(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
clixon_debug_xml(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, x1t, "");
|
clixon_debug_xml(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, x1t, "");
|
||||||
*xtop = x1t;
|
*xret = x1t;
|
||||||
retval = 1;
|
|
||||||
done:
|
|
||||||
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "retval:%d", retval);
|
|
||||||
if (xvec)
|
|
||||||
free(xvec);
|
|
||||||
return retval;
|
|
||||||
fail:
|
|
||||||
retval = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Get the raw cache of whole tree
|
|
||||||
*
|
|
||||||
* Useful for some higer level usecases for optimized access
|
|
||||||
* This is a clixon datastore plugin of the the xmldb api
|
|
||||||
* @param[in] h Clixon handle
|
|
||||||
* @param[in] db Name of database to search in (filename including dir path
|
|
||||||
* @param[in] yb How to bind yang to XML top-level when parsing
|
|
||||||
* @param[in] nsc External XML namespace context, or NULL
|
|
||||||
* @param[in] xpath String with XPath syntax. or NULL for all
|
|
||||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
|
||||||
* @param[out] xret Single return XML tree. Free with xml_free()
|
|
||||||
* @param[out] msdiff If set, return modules-state differences
|
|
||||||
* @param[out] xerr XML error if retval is 0
|
|
||||||
* @retval 1 OK
|
|
||||||
* @retval 0 Parse OK but yang assigment not made (or only partial) and xerr set
|
|
||||||
* @retval -1 Error
|
|
||||||
* @note Use of 1 for OK
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xmldb_get_zerocopy(clixon_handle h,
|
|
||||||
const char *db,
|
|
||||||
yang_bind yb,
|
|
||||||
cvec *nsc,
|
|
||||||
const char *xpath,
|
|
||||||
withdefaults_type wdef,
|
|
||||||
cxobj **xtop,
|
|
||||||
modstate_diff_t *msdiff,
|
|
||||||
cxobj **xerr)
|
|
||||||
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
yang_stmt *yspec;
|
|
||||||
cxobj *x0t = NULL; /* (cached) top of tree */
|
|
||||||
cxobj **xvec = NULL;
|
|
||||||
size_t xlen;
|
|
||||||
int i;
|
|
||||||
db_elmnt *de = NULL;
|
|
||||||
db_elmnt de0 = {0,};
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
|
||||||
clixon_err(OE_YANG, ENOENT, "No yang spec");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
de = clicon_db_elmnt_get(h, db);
|
|
||||||
if (de == NULL || de->de_xml == NULL){ /* Cache miss, read XML from file */
|
|
||||||
/* If there is no xml x0 tree (in cache), then read it from file */
|
|
||||||
/* xml looks like: <top><config><x>... where "x" is a top-level symbol in a module */
|
|
||||||
if ((ret = xmldb_readfile(h, db, yb, yspec, &x0t, &de0, msdiff, xerr)) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret == 0)
|
|
||||||
goto fail;
|
|
||||||
/* Should we validate file if read from disk?
|
|
||||||
* No, argument against: we may want to have a semantically wrong file and wish to edit?
|
|
||||||
*/
|
|
||||||
de0.de_xml = x0t;
|
|
||||||
if (de)
|
|
||||||
de0.de_id = de->de_id;
|
|
||||||
clicon_db_elmnt_set(h, db, &de0);
|
|
||||||
} /* x0t == NULL */
|
|
||||||
else
|
|
||||||
x0t = de->de_xml;
|
|
||||||
|
|
||||||
/* Here xt looks like: <config>...</config> */
|
|
||||||
if (xpath_vec(x0t, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
|
||||||
goto done;
|
|
||||||
/* Iterate through the match vector
|
|
||||||
* For every node found in x0, mark the tree up to t1
|
|
||||||
*/
|
|
||||||
for (i=0; i<xlen; i++){
|
|
||||||
cxobj *x0 = xvec[i];
|
|
||||||
xml_flag_set(x0, XML_FLAG_MARK);
|
|
||||||
xml_apply_ancestor(x0, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE);
|
|
||||||
}
|
|
||||||
if (yb != YB_NONE){
|
|
||||||
/* Add global defaults. */
|
|
||||||
if (xml_global_defaults(h, x0t, nsc, xpath, yspec, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Apply default values (removed in clear function) */
|
|
||||||
if (xml_default_recurse(x0t, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
#if 1
|
|
||||||
/* Sub-optimal: first add defaults, then remove them in some cases
|
|
||||||
* Reason is code is primarily test for _cache case and I dont have time to "revert" it here
|
|
||||||
*/
|
|
||||||
switch (wdef){
|
|
||||||
case WITHDEFAULTS_REPORT_ALL:
|
|
||||||
break;
|
|
||||||
case WITHDEFAULTS_TRIM:
|
|
||||||
/* Mark and remove nodes having schema default values */
|
|
||||||
if (xml_apply(x0t, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_tree_prune_flags(x0t, XML_FLAG_MARK, XML_FLAG_MARK) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_defaults_nopresence(x0t, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
case WITHDEFAULTS_EXPLICIT:
|
|
||||||
if (xml_defaults_nopresence(x0t, 2) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
case WITHDEFAULTS_REPORT_ALL_TAGGED:{
|
|
||||||
cxobj *x;
|
|
||||||
char *ns;
|
|
||||||
x = NULL;
|
|
||||||
while ((x = xml_child_each(x0t, x, CX_ELMNT)) != NULL){
|
|
||||||
ns = NULL;
|
|
||||||
if (xml2ns(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ns == NULL){
|
|
||||||
if (xmlns_set(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else if (strcmp(ns, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) != 0){
|
|
||||||
/* XXX: Assume if namespace is set that it is withdefaults otherwise just ignore? */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Mark nodes having default schema values */
|
|
||||||
if (xml_apply(x0t, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Add tag attributes to default nodes */
|
|
||||||
if (xml_apply(x0t, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} /* switch wdef */
|
|
||||||
#endif
|
|
||||||
/* If empty NACM config, then disable NACM if loaded
|
|
||||||
*/
|
|
||||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
|
||||||
if (disable_nacm_on_empty(x0t, yspec) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
clixon_debug_xml(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, x0t, "");
|
|
||||||
*xtop = x0t;
|
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "retval:%d", retval);
|
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "retval:%d", retval);
|
||||||
|
|
@ -1180,14 +878,10 @@ xmldb_get(clixon_handle h,
|
||||||
return xmldb_get0(h, db, YB_MODULE, nsc, xpath, 1, 0, xret, NULL, NULL);
|
return xmldb_get0(h, db, YB_MODULE, nsc, xpath, 1, 0, xret, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Zero-copy variant of get content of database
|
/*! Get content of datastore, use cache if present
|
||||||
*
|
*
|
||||||
* The function returns a minimal tree that includes all sub-trees that match
|
* The function returns a minimal tree that includes all sub-trees that match
|
||||||
* xpath.
|
* xpath.
|
||||||
* It can be used for zero-copying if CLICON_DATASTORE_CACHE is set
|
|
||||||
* appropriately.
|
|
||||||
* The tree returned may be the actual cache, therefore calls for cleaning and
|
|
||||||
* freeing tree must be made after use.
|
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] db Name of datastore, eg "running"
|
* @param[in] db Name of datastore, eg "running"
|
||||||
* @param[in] yb How to bind yang to XML top-level when parsing (if YB_NONE, no defaults)
|
* @param[in] yb How to bind yang to XML top-level when parsing (if YB_NONE, no defaults)
|
||||||
|
|
@ -1211,8 +905,6 @@ xmldb_get(clixon_handle h,
|
||||||
* # Error handling
|
* # Error handling
|
||||||
* }
|
* }
|
||||||
* ...
|
* ...
|
||||||
* xmldb_get0_clear(h, xt); # Clear tree from default values and flags
|
|
||||||
* xmldb_get0_free(h, &xt); # Free tree
|
|
||||||
* xml_free(xerr);
|
* xml_free(xerr);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see xml_nsctx_node to get a XML namespace context from XML tree
|
* @see xml_nsctx_node to get a XML namespace context from XML tree
|
||||||
|
|
@ -1243,92 +935,5 @@ xmldb_get0(clixon_handle h,
|
||||||
modstate_diff_t *msdiff,
|
modstate_diff_t *msdiff,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
return xmldb_get_cache(h, db, yb, nsc, xpath, wdef, xret, msdiff, xerr);
|
||||||
|
|
||||||
if (xret == NULL){
|
|
||||||
clixon_err(OE_DB, EINVAL, "xret is NULL");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
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, yb, nsc, xpath, wdef, xret, msdiff, xerr);
|
|
||||||
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, yb, nsc, xpath, wdef, xret, msdiff, xerr);
|
|
||||||
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, yb, nsc, xpath, wdef, xret, msdiff, xerr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Clear cached xml tree obtained with xmldb_get0, if zerocopy
|
|
||||||
*
|
|
||||||
* @param[in] h Clixon handle
|
|
||||||
* @param[in] db Name of datastore
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
* @note "Clear" an xml tree means removing default values and resetting all flags.
|
|
||||||
* @see xmldb_get0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xmldb_get0_clear(clixon_handle h,
|
|
||||||
cxobj *x)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (x == NULL)
|
|
||||||
goto ok;
|
|
||||||
/* Remove global defaults and empty non-presence containers */
|
|
||||||
if (xml_defaults_nopresence(x, 2) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Clear XML tree of defaults */
|
|
||||||
if (xml_tree_prune_flagged(x, XML_FLAG_TRANSIENT, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
/* clear mark and change */
|
|
||||||
xml_apply0(x, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
|
||||||
(void*)(XML_FLAG_MARK|XML_FLAG_ADD|XML_FLAG_CHANGE));
|
|
||||||
ok:
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Free xml tree obtained with xmldb_get0
|
|
||||||
*
|
|
||||||
* @param[in] h Clixon handle
|
|
||||||
* @param[in,out] xp Pointer to XML cache.
|
|
||||||
* @retval 0 Always.
|
|
||||||
* @see xmldb_get0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xmldb_get0_free(clixon_handle h,
|
|
||||||
cxobj **xp)
|
|
||||||
{
|
|
||||||
if (*xp == NULL)
|
|
||||||
return 0;
|
|
||||||
/* Note that if clicon_datastore_cache(h) fails (returns -1), the following
|
|
||||||
* xml_free can fail (if **xp not obtained using xmldb_get0) */
|
|
||||||
if (clicon_datastore_cache(h) != DATASTORE_CACHE_ZEROCOPY)
|
|
||||||
xml_free(*xp);
|
|
||||||
*xp = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1213,6 +1213,7 @@ xmldb_put(clixon_handle h,
|
||||||
int pretty;
|
int pretty;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
|
|
||||||
|
clixon_debug(CLIXON_DBG_DATASTORE|CLIXON_DBG_DETAIL, "db %s", db);
|
||||||
if (cbret == NULL){
|
if (cbret == NULL){
|
||||||
clixon_err(OE_XML, EINVAL, "cbret is NULL");
|
clixon_err(OE_XML, EINVAL, "cbret is NULL");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1227,7 +1228,6 @@ xmldb_put(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
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; /* XXX flag is not XML_FLAG_TOP */
|
x0 = de->de_xml; /* XXX flag is not XML_FLAG_TOP */
|
||||||
}
|
}
|
||||||
/* 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 */
|
||||||
|
|
@ -1294,7 +1294,7 @@ xmldb_put(clixon_handle h,
|
||||||
clixon_log(h, LOG_NOTICE, "%s: verify failed #3", __FUNCTION__);
|
clixon_log(h, 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_datastore_cache(h) != DATASTORE_NOCACHE){
|
{
|
||||||
db_elmnt de0 = {0,};
|
db_elmnt de0 = {0,};
|
||||||
if (de != NULL)
|
if (de != NULL)
|
||||||
de0 = *de;
|
de0 = *de;
|
||||||
|
|
@ -1327,7 +1327,7 @@ xmldb_put(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
pretty = clicon_option_bool(h, "CLICON_XMLDB_PRETTY");
|
pretty = clicon_option_bool(h, "CLICON_XMLDB_PRETTY");
|
||||||
if (strcmp(format,"json")==0){
|
if (strcmp(format, "json")==0){
|
||||||
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
|
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -1339,6 +1339,7 @@ xmldb_put(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
|
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "retval:%d", retval);
|
||||||
if (f != NULL)
|
if (f != NULL)
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (xerr)
|
if (xerr)
|
||||||
|
|
@ -1347,8 +1348,6 @@ xmldb_put(clixon_handle h,
|
||||||
xml_nsctx_free(nsc);
|
xml_nsctx_free(nsc);
|
||||||
if (dbfile)
|
if (dbfile)
|
||||||
free(dbfile);
|
free(dbfile);
|
||||||
if (x0 && clicon_datastore_cache(h) == DATASTORE_NOCACHE)
|
|
||||||
xml_free(x0);
|
|
||||||
return retval;
|
return retval;
|
||||||
fail:
|
fail:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -117,15 +117,6 @@ static const map_str2int nacm_credentials_map[] = {
|
||||||
{NULL, -1}
|
{NULL, -1}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Mapping between datastore cache string <--> constants,
|
|
||||||
* see clixon-config.yang type datastore_cache */
|
|
||||||
static const map_str2int datastore_cache_map[] = {
|
|
||||||
{"nocache", DATASTORE_NOCACHE},
|
|
||||||
{"cache", DATASTORE_CACHE},
|
|
||||||
{"cache-zerocopy", DATASTORE_CACHE_ZEROCOPY},
|
|
||||||
{NULL, -1}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Mapping between regular expression type string <--> constants,
|
/* Mapping between regular expression type string <--> constants,
|
||||||
* see clixon-config.yang type regexp_mode */
|
* see clixon-config.yang type regexp_mode */
|
||||||
static const map_str2int yang_regexp_map[] = {
|
static const map_str2int yang_regexp_map[] = {
|
||||||
|
|
@ -997,23 +988,6 @@ clicon_nacm_credentials(clixon_handle h)
|
||||||
return clicon_str2int(nacm_credentials_map, mode);
|
return clicon_str2int(nacm_credentials_map, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Which datastore cache method to use
|
|
||||||
*
|
|
||||||
* @param[in] h Clixon handle
|
|
||||||
* @retval method Datastore cache method
|
|
||||||
* @see clixon-config@<date>.yang CLICON_DATASTORE_CACHE
|
|
||||||
*/
|
|
||||||
enum datastore_cache
|
|
||||||
clicon_datastore_cache(clixon_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Which Yang regexp/pattern engine to use
|
/*! Which Yang regexp/pattern engine to use
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
|
|
|
||||||
|
|
@ -315,11 +315,11 @@ xml_default(yang_stmt *yt,
|
||||||
/* If config parameter and local is config false */
|
/* If config parameter and local is config false */
|
||||||
if (!state && !yang_config(yc))
|
if (!state && !yang_config(yc))
|
||||||
continue;
|
continue;
|
||||||
switch (yang_keyword_get(yc)){
|
|
||||||
case Y_LEAF:
|
|
||||||
/* Want to add state defaults, but this is config */
|
/* Want to add state defaults, but this is config */
|
||||||
if (state && yang_config_ancestor(yc))
|
if (state && yang_config_ancestor(yc))
|
||||||
break;
|
continue;
|
||||||
|
switch (yang_keyword_get(yc)){
|
||||||
|
case Y_LEAF:
|
||||||
if ((cv = yang_cv_get(yc)) == NULL){
|
if ((cv = yang_cv_get(yc)) == NULL){
|
||||||
clixon_err(OE_YANG,0, "Internal error: yang leaf %s not populated with cv as it should",
|
clixon_err(OE_YANG,0, "Internal error: yang leaf %s not populated with cv as it should",
|
||||||
yang_argument_get(yc));
|
yang_argument_get(yc));
|
||||||
|
|
@ -402,9 +402,10 @@ xml_default_recurse(cxobj *xn,
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
yang_stmt *y;
|
yang_stmt *y;
|
||||||
|
|
||||||
if ((yn = (yang_stmt*)xml_spec(xn)) != NULL)
|
if ((yn = (yang_stmt*)xml_spec(xn)) != NULL){
|
||||||
if (xml_default(yn, xn, state) < 0)
|
if (xml_default(yn, xn, state) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
x = NULL;
|
x = NULL;
|
||||||
while ((x = xml_child_each(xn, x, CX_ELMNT)) != NULL) {
|
while ((x = xml_child_each(xn, x, CX_ELMNT)) != NULL) {
|
||||||
if ((y = (yang_stmt*)xml_spec(x)) != NULL){
|
if ((y = (yang_stmt*)xml_spec(x)) != NULL){
|
||||||
|
|
@ -536,6 +537,7 @@ xml_global_defaults(clixon_handle h,
|
||||||
* @param[in] purge 0: Dont remove any nodes
|
* @param[in] purge 0: Dont remove any nodes
|
||||||
* 1: Remove config sub-nodes that are empty non-presence container or default leaf
|
* 1: Remove config sub-nodes that are empty non-presence container or default leaf
|
||||||
* 2: Remove all sub-nodes that are empty non-presence container or default leaf
|
* 2: Remove all sub-nodes that are empty non-presence container or default leaf
|
||||||
|
* 3: Remove all sub-nodes that are empty non-presence containers
|
||||||
* @retval 1 Node is an (recursive) empty non-presence container or default leaf
|
* @retval 1 Node is an (recursive) empty non-presence container or default leaf
|
||||||
* @retval 0 Other node
|
* @retval 0 Other node
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
@ -562,7 +564,8 @@ xml_defaults_nopresence(cxobj *xn,
|
||||||
yang_find(yn, Y_PRESENCE, NULL) == NULL)
|
yang_find(yn, Y_PRESENCE, NULL) == NULL)
|
||||||
rmx = 1;
|
rmx = 1;
|
||||||
else if (keyw == Y_LEAF &&
|
else if (keyw == Y_LEAF &&
|
||||||
xml_flag(xn, XML_FLAG_DEFAULT))
|
xml_flag(xn, XML_FLAG_DEFAULT) &&
|
||||||
|
purge != 3)
|
||||||
rmx = 1;
|
rmx = 1;
|
||||||
config = yang_config_ancestor(yn);
|
config = yang_config_ancestor(yn);
|
||||||
}
|
}
|
||||||
|
|
@ -570,6 +573,7 @@ xml_defaults_nopresence(cxobj *xn,
|
||||||
x = NULL;
|
x = NULL;
|
||||||
xprev = NULL;
|
xprev = NULL;
|
||||||
while ((x = xml_child_each(xn, x, CX_ELMNT)) != NULL) {
|
while ((x = xml_child_each(xn, x, CX_ELMNT)) != NULL) {
|
||||||
|
/* 1: node is empty non-presence or default leaf (eg rmx) */
|
||||||
if ((ret = xml_defaults_nopresence(x, purge)) < 0)
|
if ((ret = xml_defaults_nopresence(x, purge)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 1){
|
if (ret == 1){
|
||||||
|
|
@ -582,6 +586,7 @@ xml_defaults_nopresence(cxobj *xn,
|
||||||
break;
|
break;
|
||||||
/* fall thru */
|
/* fall thru */
|
||||||
case 2: /* purge all nodes */
|
case 2: /* purge all nodes */
|
||||||
|
case 3:
|
||||||
if (xml_purge(x) < 0)
|
if (xml_purge(x) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
x = xprev;
|
x = xprev;
|
||||||
|
|
@ -649,8 +654,6 @@ xml_flag_state_default_value(cxobj *x,
|
||||||
goto done;
|
goto done;
|
||||||
if ((cv = yang_cv_get(y)) == NULL)
|
if ((cv = yang_cv_get(y)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cv = yang_cv_get(y)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (cv_name_get(cv) == NULL)
|
if (cv_name_get(cv) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if ((yv = cv2str_dup(cv)) == NULL)
|
if ((yv = cv2str_dup(cv)) == NULL)
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,11 @@ find_schema_mounts(cxobj *x,
|
||||||
* "ietf-yang-schema-mount" modules in the mounted schema and specifying
|
* "ietf-yang-schema-mount" modules in the mounted schema and specifying
|
||||||
* the schemas in exactly the same way as the top-level schema.
|
* the schemas in exactly the same way as the top-level schema.
|
||||||
* Alt: see snmp_yang2xml to get instances instead of brute force traverse of whole tree
|
* Alt: see snmp_yang2xml to get instances instead of brute force traverse of whole tree
|
||||||
* @note: Mountpoints must exist in xret on entry
|
* XXX Mountpoints must exist in xret on entry, which is problematic:
|
||||||
|
* XXX A get state may have an xpath not including their config, ie:
|
||||||
|
* XXX xpath=/top/mymount/yang-library does not include /top/mymount and therefore
|
||||||
|
* XXX the mountpoint will not be present in xret
|
||||||
|
* XXX see: https://github.com/clicon/clixon/issues/485
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
yang_schema_mount_statedata_yanglib(clixon_handle h,
|
yang_schema_mount_statedata_yanglib(clixon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -225,10 +225,7 @@ EOF
|
||||||
|
|
||||||
# Type tests.
|
# Type tests.
|
||||||
# Parameters:
|
# Parameters:
|
||||||
# 1: dbcache: cache, nocache, cache-zerocopy
|
|
||||||
function testrun(){
|
function testrun(){
|
||||||
dbcache=$1
|
|
||||||
new "test params: -f $cfg # dbcache: $dbcache"
|
|
||||||
|
|
||||||
cat <<EOF > $cfg
|
cat <<EOF > $cfg
|
||||||
<clixon-config xmlns="http://clicon.org/config">
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
|
@ -242,7 +239,6 @@ function testrun(){
|
||||||
<CLICON_SOCK>/usr/local/var/run/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/run/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/run/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/run/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
<CLICON_DATASTORE_CACHE>$dbcache</CLICON_DATASTORE_CACHE>
|
|
||||||
<CLICON_XMLDB_FORMAT>$format</CLICON_XMLDB_FORMAT>
|
<CLICON_XMLDB_FORMAT>$format</CLICON_XMLDB_FORMAT>
|
||||||
${AUTOCLI}
|
${AUTOCLI}
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
|
|
@ -698,14 +694,8 @@ EOF
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run without db cache
|
# Run test
|
||||||
testrun nocache
|
testrun
|
||||||
|
|
||||||
# Run with db cache
|
|
||||||
testrun cache
|
|
||||||
|
|
||||||
# Run with zero-copy
|
|
||||||
testrun cache-zerocopy
|
|
||||||
|
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ module clixon-config {
|
||||||
revision 2024-01-01 {
|
revision 2024-01-01 {
|
||||||
description
|
description
|
||||||
"Makred as obsolete:
|
"Makred as obsolete:
|
||||||
|
CLICON_DATASTORE_CACHE
|
||||||
CLICON_NETCONF_CREATOR_ATTR
|
CLICON_NETCONF_CREATOR_ATTR
|
||||||
Released in Clixon 6.6";
|
Released in Clixon 6.6";
|
||||||
}
|
}
|
||||||
|
|
@ -960,7 +961,9 @@ module clixon-config {
|
||||||
"Clixon datastore cache behaviour. There are three values: no cache,
|
"Clixon datastore cache behaviour. There are three values: no cache,
|
||||||
cache with copy, or cache without copy.
|
cache with copy, or cache without copy.
|
||||||
Note: 'cache' is default value and supported with regressions etc.
|
Note: 'cache' is default value and supported with regressions etc.
|
||||||
Others are experimental (in Clixon 5.5)";
|
Others are experimental (in Clixon 5.5)
|
||||||
|
Note that from 6.6 this is OBSOLETED, only datastore_cache is supported";
|
||||||
|
status obsolete;
|
||||||
}
|
}
|
||||||
leaf CLICON_XMLDB_FORMAT {
|
leaf CLICON_XMLDB_FORMAT {
|
||||||
type cl:datastore_format;
|
type cl:datastore_format;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue