Optimized datastore access by ensuring REPORT_ALL in memory and EXPLICIT in file

This commit is contained in:
Olof hagsand 2024-02-01 20:14:10 +01:00
parent 9989ee4d52
commit f8de2b7c0a
12 changed files with 183 additions and 217 deletions

View file

@ -77,11 +77,12 @@
#include "clixon_options.h"
#include "clixon_data.h"
#include "clixon_netconf_lib.h"
#include "clixon_xml_bind.h"
#include "clixon_xml_default.h"
#include "clixon_datastore.h"
#include "clixon_datastore_write.h"
#include "clixon_datastore_read.h"
/*! Translate from symbolic database name to actual filename in file-system
*
* @param[in] th text handle handle
@ -681,3 +682,40 @@ xmldb_rename(clixon_handle h,
free(old);
return retval;
}
/*! Given a datastore, populate its cache with yang binding and default values
*
* @param[in] h Clixon handle
* @param[in] db Name of database to search in (filename including dir path
* @retval 1 OK
* @retval 0 YANG assigment and default assignment not made
* @retval -1 General error, check specific clicon_errno, clicon_suberrno
*/
int
xmldb_populate(clixon_handle h,
const char *db)
{
int retval = -1;
cxobj *x;
yang_stmt *yspec;
int ret;
if ((x = xmldb_cache_get(h, db)) == NULL){
clixon_err(OE_XML, 0, "XML cache not found");
goto done;
}
yspec = clicon_dbspec_yang(h);
if ((ret = xml_bind_yang(h, x, YB_MODULE, yspec, NULL)) < 0)
goto done;
if (ret == 1){
/* Add default global values (to make xpath below include defaults) */
if (xml_global_defaults(h, x, NULL, "/", yspec, 0) < 0)
goto done;
/* Add default recursive values */
if (xml_default_recurse(x, 0) < 0)
goto done;
}
retval = ret;
done:
return retval;
}

View file

@ -701,7 +701,7 @@ xmldb_get_cache(clixon_handle h,
db_elmnt de0 = {0,};
int ret;
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "db %s", db);
clixon_debug(CLIXON_DBG_DATASTORE, "db %s", db);
if (xret == NULL){
clixon_err(OE_DB, EINVAL, "xret is NULL");
return -1;
@ -725,22 +725,16 @@ xmldb_get_cache(clixon_handle h,
if (de)
de0.de_id = de->de_id;
clicon_db_elmnt_set(h, db, &de0); /* Content is copied */
/* Add default global values (to make xpath below include defaults) */
// Alt: xmldb_populate(h, db)
if (xml_global_defaults(h, x0t, nsc, xpath, yspec, 0) < 0)
goto done;
/* Add default recursive values */
if (xml_default_recurse(x0t, 0) < 0)
goto done;
} /* x0t == NULL */
else
x0t = de->de_xml;
if (yb == YB_MODULE && !xml_spec(x0t)){
/* Seems unneccesary to always do this, but breaks test_plugin_reset.sh if removed */
if ((ret = xml_bind_yang(h, x0t, YB_MODULE, yspec, xerr)) < 0)
goto done;
if (ret == 1) {
/* Add default global values (to make xpath below include defaults) */
if (xml_global_defaults(h, x0t, nsc, xpath, yspec, 0) < 0)
goto done;
/* Add default recursive values */
if (xml_default_recurse(x0t, 0) < 0)
goto done;
}
}
/* Here x0t looks like: <config>...</config> */
/* Given the xpath, return a vector of matches in xvec
* Can we do everything in one go?
@ -752,7 +746,7 @@ xmldb_get_cache(clixon_handle h,
*/
if (xpath_vec(x0t, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
goto done;
// XXX: Remove copying and return x0 eventually
/* Make new tree by copying top-of-tree from x0t to x1t */
if ((x1t = xml_new(xml_name(x0t), NULL, CX_ELMNT)) == NULL)
goto done;
@ -786,51 +780,6 @@ xmldb_get_cache(clixon_handle h,
if (xml_apply(x1t, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
goto done;
}
/* Original tree: Remove global defaults and empty non-presence containers */
if (xml_defaults_nopresence(x0t, 2) < 0)
goto done;
switch (wdef){
case WITHDEFAULTS_REPORT_ALL:
break;
case WITHDEFAULTS_TRIM:
/* Mark and remove nodes having schema default values */
if (xml_apply(x1t, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
goto done;
if (xml_tree_prune_flags(x1t, XML_FLAG_MARK, XML_FLAG_MARK) < 0)
goto done;
if (xml_defaults_nopresence(x1t, 1) < 0)
goto done;
break;
case WITHDEFAULTS_EXPLICIT:
if (xml_defaults_nopresence(x1t, 2) < 0)
goto done;
break;
case WITHDEFAULTS_REPORT_ALL_TAGGED:{
cxobj *x;
char *ns;
x = NULL;
while ((x = xml_child_each(x1t, 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(x1t, 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(x1t, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
goto done;
break;
}
} /* switch wdef */
/* If empty NACM config, then disable NACM if loaded
*/
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
@ -935,5 +884,26 @@ xmldb_get0(clixon_handle h,
modstate_diff_t *msdiff,
cxobj **xerr)
{
return xmldb_get_cache(h, db, yb, nsc, xpath, wdef, xret, msdiff, xerr);
int retval = -1;
int ret;
cxobj *x = NULL;
if (wdef != WITHDEFAULTS_EXPLICIT)
return xmldb_get_cache(h, db, yb, nsc, xpath, 0, xret, msdiff, xerr);
if ((ret = xmldb_get_cache(h, db, yb, nsc, xpath, 0, &x, msdiff, xerr)) < 0)
goto done;
if (ret == 0)
goto fail;
if (xml_defaults_nopresence(x, 2) < 0)
goto done;
*xret = x;
x = NULL;
retval = 1;
done:
if (x)
xml_free(x);
return retval;
fail:
retval = 0;
goto done;
}

View file

@ -1286,13 +1286,18 @@ xmldb_put(clixon_handle h,
if (xml_apply(x0, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
(void*)(XML_FLAG_NONE|XML_FLAG_MARK)) < 0)
goto done;
/* Remove global defaults and empty non-presence containers */
if (xml_defaults_nopresence(x0, 2) < 0)
/* Remove empty non-presence containers recursively.
* XXX should really be done for only new data in text_modify
*/
if (xml_defaults_nopresence(x0, 3) < 0)
goto done;
/* Complete defaults in incoming x1
*/
if (xml_global_defaults(h, x0, nsc, "/", yspec, 0) < 0)
goto done;
/* Add default recursive values */
if (xml_default_recurse(x0, 0) < 0)
goto done;
#if 0 /* debug */
if (xml_apply0(x0, -1, xml_sort_verify, NULL) < 0)
clixon_log(h, LOG_NOTICE, "%s: verify failed #3", __FUNCTION__);
#endif
/* Write back to datastore cache if first time */
{
db_elmnt de0 = {0,};
@ -1331,7 +1336,7 @@ xmldb_put(clixon_handle h,
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
goto done;
}
else if (clixon_xml2file(f, x0, 0, pretty, NULL, fprintf, 0, 0) < 0)
else if (clixon_xml2file1(f, x0, 0, pretty, NULL, fprintf, 0, 0, WITHDEFAULTS_EXPLICIT) < 0)
goto done;
/* Remove modules state after writing to file
*/

View file

@ -885,8 +885,7 @@ nacm_data_read_xrule_xml(cxobj *xn,
*
* @param[in] h Clixon handle
* @param[in] xn XML node (requested node)
* @param[in] rulevec Precomputed rules that apply to this user group
* @param[in] xpathvec Precomputed xpath results that apply to this XML tree
* @param[in] pv_list Precomputed rules + paths that apply to this user group
* @param[in] yspec YANG spec
* @retval 0 OK
* @retval -1 Error

View file

@ -1660,7 +1660,10 @@ xml_copy_marked(cxobj *x0,
char *name;
char *prefix;
assert(x0 && x1);
if (x0 == NULL || x1 == NULL){
clixon_err(OE_UNIX, EINVAL, "x0 or x1 is NULL");
goto done;
}
yt = xml_spec(x0); /* can be null */
xml_spec_set(x1, yt);
/* Copy prefix*/