Optimized datastore access by ensuring REPORT_ALL in memory and EXPLICIT in file
This commit is contained in:
parent
9989ee4d52
commit
f8de2b7c0a
12 changed files with 183 additions and 217 deletions
|
|
@ -19,6 +19,7 @@ Expected: February 2024
|
||||||
* All clixon applications added command-line option `-V` for printing version
|
* All clixon applications added command-line option `-V` for printing version
|
||||||
* New ca_version callback for customized version output
|
* New ca_version callback for customized version output
|
||||||
* Optimization:
|
* Optimization:
|
||||||
|
* Optimized datastore access by ensuring REPORT_ALL in memory and EXPLICIT in file
|
||||||
* Added mountpoint cache as yang flag `YANG_FLAG_MTPOINT_POTENTIAL`
|
* Added mountpoint cache as yang flag `YANG_FLAG_MTPOINT_POTENTIAL`
|
||||||
* Optimized `yang_find`, especially namespace lookup
|
* Optimized `yang_find`, especially namespace lookup
|
||||||
* Filtered state data if not match xpath
|
* Filtered state data if not match xpath
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,8 @@ restconf_client_get_capabilities(clixon_handle h,
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[in] xpath Xpath selection, not used but may be to filter early
|
* @param[in] xpath XPath selection, not used but may be to filter early
|
||||||
|
* @param[in] nsc Namespace context
|
||||||
* @param[in] module Name of yang module
|
* @param[in] module Name of yang module
|
||||||
* @param[in] top Top symbol, ie netconf or restconf-state
|
* @param[in] top Top symbol, ie netconf or restconf-state
|
||||||
* @param[in,out] xret Existing XML tree, merge x into this
|
* @param[in,out] xret Existing XML tree, merge x into this
|
||||||
|
|
@ -132,15 +133,14 @@ static int
|
||||||
client_get_streams(clixon_handle h,
|
client_get_streams(clixon_handle h,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
|
cvec *nsc,
|
||||||
yang_stmt *ymod,
|
yang_stmt *ymod,
|
||||||
char *top,
|
char *top,
|
||||||
cxobj **xret)
|
cxobj **xret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *yns = NULL; /* yang namespace */
|
yang_stmt *yns = NULL; /* yang namespace */
|
||||||
cxobj *x = NULL;
|
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if ((yns = yang_find(ymod, Y_NAMESPACE, NULL)) == NULL){
|
if ((yns = yang_find(ymod, Y_NAMESPACE, NULL)) == NULL){
|
||||||
clixon_err(OE_YANG, 0, "%s yang namespace not found", yang_argument_get(ymod));
|
clixon_err(OE_YANG, 0, "%s yang namespace not found", yang_argument_get(ymod));
|
||||||
|
|
@ -158,21 +158,15 @@ client_get_streams(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb,"</%s>", top);
|
cprintf(cb,"</%s>", top);
|
||||||
|
|
||||||
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, &x, NULL) < 0){
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0){
|
||||||
if (xret && netconf_operation_failed_xml(xret, "protocol", clixon_err_reason())< 0)
|
if (xret && netconf_operation_failed_xml(xret, "protocol", clixon_err_reason())< 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((ret = netconf_trymerge(x, yspec, xret)) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret == 0)
|
|
||||||
goto fail;
|
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
if (x)
|
|
||||||
xml_free(x);
|
|
||||||
return retval;
|
return retval;
|
||||||
fail:
|
fail:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -184,7 +178,6 @@ client_get_streams(clixon_handle h,
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] xpath XPath selection, may be used to filter early
|
* @param[in] xpath XPath selection, may be used to filter early
|
||||||
* @param[in] nsc XML Namespace context for xpath
|
* @param[in] nsc XML Namespace context for xpath
|
||||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
|
||||||
* @param[in,out] xret Existing XML tree, merge x into this, or rpc-error
|
* @param[in,out] xret Existing XML tree, merge x into this, or rpc-error
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
* @retval 0 Statedata callback failed (error in xret)
|
* @retval 0 Statedata callback failed (error in xret)
|
||||||
|
|
@ -199,14 +192,11 @@ client_get_streams(clixon_handle h,
|
||||||
* Instead, I think there should be a second out argument **xerr with the error message, see code
|
* Instead, I think there should be a second out argument **xerr with the error message, see code
|
||||||
* for CLICON_NETCONF_MONITORING which is transformed in calling function(?) to an internal error
|
* for CLICON_NETCONF_MONITORING which is transformed in calling function(?) to an internal error
|
||||||
* message. But this needs to be explored in all sub-functions
|
* message. But this needs to be explored in all sub-functions
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_statedata(clixon_handle h,
|
get_statedata(clixon_handle h,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
withdefaults_type wdef,
|
|
||||||
cxobj **xret)
|
cxobj **xret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -214,7 +204,6 @@ get_statedata(clixon_handle h,
|
||||||
yang_stmt *ymod;
|
yang_stmt *ymod;
|
||||||
cxobj *x1 = NULL;
|
cxobj *x1 = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
char *namespace;
|
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
|
|
||||||
|
|
@ -232,37 +221,34 @@ get_statedata(clixon_handle h,
|
||||||
clixon_err(OE_YANG, ENOENT, "yang module clixon-rfc5277 not found");
|
clixon_err(OE_YANG, ENOENT, "yang module clixon-rfc5277 not found");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((namespace = yang_find_mynamespace(ymod)) == NULL){
|
if ((ret = client_get_streams(h, yspec, xpath, nsc, ymod, "netconf", &x1)) < 0)
|
||||||
clixon_err(OE_YANG, ENOENT, "clixon-rfc5277 namespace not found");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
cprintf(cb, "<netconf xmlns=\"%s\"/>", namespace);
|
|
||||||
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
if ((ret = client_get_streams(h, yspec, xpath, ymod, "netconf", xret)) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
if (xpath_first(x1, nsc, "%s", xpath) != NULL){
|
||||||
|
if ((ret = netconf_trymerge(x1, yspec, xret)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040")){
|
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040")){
|
||||||
if ((ymod = yang_find_module_by_name(yspec, "ietf-restconf-monitoring")) == NULL){
|
if ((ymod = yang_find_module_by_name(yspec, "ietf-restconf-monitoring")) == NULL){
|
||||||
clixon_err(OE_YANG, ENOENT, "yang module ietf-restconf-monitoring not found");
|
clixon_err(OE_YANG, ENOENT, "yang module ietf-restconf-monitoring not found");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((namespace = yang_find_mynamespace(ymod)) == NULL){
|
if ((ret = client_get_streams(h, yspec, xpath, nsc, ymod, "restconf-state", &x1)) < 0)
|
||||||
clixon_err(OE_YANG, ENOENT, "ietf-restconf-monitoring namespace not found");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
cbuf_reset(cb);
|
|
||||||
cprintf(cb, "<restconf-state xmlns=\"%s\"/>", namespace);
|
|
||||||
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
if ((ret = client_get_streams(h, yspec, xpath, ymod, "restconf-state", xret)) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((ret = restconf_client_get_capabilities(h, yspec, xpath, xret)) < 0)
|
if (restconf_client_get_capabilities(h, yspec, xpath, &x1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (xpath_first(x1, nsc, "%s", xpath) != NULL){
|
||||||
|
if ((ret = netconf_trymerge(x1, yspec, xret)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (clicon_option_bool(h, "CLICON_YANG_LIBRARY")){
|
if (clicon_option_bool(h, "CLICON_YANG_LIBRARY")){
|
||||||
if ((ret = yang_modules_state_get(h, yspec, xpath, nsc, 0, xret)) < 0)
|
if ((ret = yang_modules_state_get(h, yspec, xpath, nsc, 0, xret)) < 0)
|
||||||
|
|
@ -270,7 +256,10 @@ get_statedata(clixon_handle h,
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (clicon_option_bool(h, "CLICON_NETCONF_MONITORING")){
|
if (clicon_option_bool(h, "CLICON_NETCONF_MONITORING"))
|
||||||
|
if (xpath == NULL || /* Raw optimization of xpath filtering */
|
||||||
|
strcmp(xpath, "/") == 0 ||
|
||||||
|
strstr(xpath, "netconf-state") != 0){
|
||||||
if ((ret = netconf_monitoring_state_get(h, yspec, xpath, nsc, xret, &xerr)) < 0)
|
if ((ret = netconf_monitoring_state_get(h, yspec, xpath, nsc, xret, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
|
|
@ -296,11 +285,13 @@ get_statedata(clixon_handle h,
|
||||||
xerr = NULL;
|
xerr = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (xpath_first(x1, nsc, "%s", xpath) != NULL){
|
||||||
if ((ret = netconf_trymerge(x1, yspec, xret)) < 0)
|
if ((ret = netconf_trymerge(x1, yspec, xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){
|
if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){
|
||||||
if ((ret = yang_schema_mount_statedata(h, yspec, xpath, nsc, xret, &xerr)) < 0)
|
if ((ret = yang_schema_mount_statedata(h, yspec, xpath, nsc, xret, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -315,62 +306,10 @@ get_statedata(clixon_handle h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Use plugin state callbacks */
|
/* Use plugin state callbacks */
|
||||||
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, wdef, xret)) < 0)
|
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
switch (wdef){
|
|
||||||
case WITHDEFAULTS_REPORT_ALL:
|
|
||||||
case WITHDEFAULTS_EXPLICIT:
|
|
||||||
/* Add global defaults. */
|
|
||||||
if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Apply default values */
|
|
||||||
if (xml_default_recurse(*xret, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
case WITHDEFAULTS_TRIM:
|
|
||||||
/* Mark and remove nodes having schema default values */
|
|
||||||
if (xml_apply((*xret), CX_ELMNT, (xml_applyfn_t*) xml_flag_state_default_value, (void*) XML_FLAG_MARK) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_tree_prune_flags((*xret), XML_FLAG_MARK, XML_FLAG_MARK)< 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_defaults_nopresence((*xret), 1) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
case WITHDEFAULTS_REPORT_ALL_TAGGED:{
|
|
||||||
cxobj *xc;
|
|
||||||
char *ns;
|
|
||||||
/* Add global defaults. */
|
|
||||||
if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Apply default values */
|
|
||||||
if (xml_default_recurse(*xret, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
xc = NULL;
|
|
||||||
while ((xc = xml_child_each((*xret), xc, CX_ELMNT)) != NULL){
|
|
||||||
/* Check if exists */
|
|
||||||
ns = NULL;
|
|
||||||
if (xml2ns(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ns == NULL){
|
|
||||||
if (xmlns_set(xc, 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(*xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_state_default_value, (void*) XML_FLAG_MARK) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Add tag attributes to default nodes */
|
|
||||||
if (xml_apply(*xret, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} /* switch wdef */
|
|
||||||
retval = 1; /* OK */
|
retval = 1; /* OK */
|
||||||
done:
|
done:
|
||||||
clixon_debug(CLIXON_DBG_CLIENT, "retval:%d", retval);
|
clixon_debug(CLIXON_DBG_CLIENT, "retval:%d", retval);
|
||||||
|
|
@ -464,6 +403,7 @@ get_nacm_and_reply(clixon_handle h,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *username,
|
char *username,
|
||||||
int32_t depth,
|
int32_t depth,
|
||||||
|
withdefaults_type wdef,
|
||||||
cbuf *cbret)
|
cbuf *cbret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -483,7 +423,7 @@ get_nacm_and_reply(clixon_handle h,
|
||||||
if (xml_name_set(xret, NETCONF_OUTPUT_DATA) < 0)
|
if (xml_name_set(xret, NETCONF_OUTPUT_DATA) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Top level is data, so add 1 to depth if significant */
|
/* Top level is data, so add 1 to depth if significant */
|
||||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, depth>0?depth+1:depth, 0) < 0)
|
if (clixon_xml2cbuf1(cbret, xret, 0, 0, NULL, depth>0?depth+1:depth, 0, wdef) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cbret, "</rpc-reply>");
|
cprintf(cbret, "</rpc-reply>");
|
||||||
|
|
@ -804,7 +744,7 @@ get_list_pagination(clixon_handle h,
|
||||||
cbuf_free(cba);
|
cbuf_free(cba);
|
||||||
}
|
}
|
||||||
#endif /* LIST_PAGINATION_REMAINING */
|
#endif /* LIST_PAGINATION_REMAINING */
|
||||||
if (get_nacm_and_reply(h, xret, xvec, xlen, xpath, nsc, username, depth, cbret) < 0)
|
if (get_nacm_and_reply(h, xret, xvec, xlen, xpath, nsc, username, depth, wdef, cbret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -997,13 +937,20 @@ get_common(clixon_handle h,
|
||||||
break;
|
break;
|
||||||
case CONTENT_ALL: /* both config and state */
|
case CONTENT_ALL: /* both config and state */
|
||||||
case CONTENT_NONCONFIG: /* state data only */
|
case CONTENT_NONCONFIG: /* state data only */
|
||||||
if ((ret = get_statedata(h, xpath?xpath:"/", nsc, wdef, &xret)) < 0)
|
if ((ret = get_statedata(h, xpath?xpath:"/", nsc, &xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){ /* Error from callback (error in xret) */
|
if (ret == 0){ /* Error from callback (error in xret) */
|
||||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
|
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
/* Add defaults to state data. This consumes some cycles */
|
||||||
|
/* Ensure all state-data is report-all */
|
||||||
|
if (xml_global_defaults(h, xret, nsc, xpath, yspec, 1) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Apply default values */
|
||||||
|
if (xml_default_recurse(xret, 1) < 0)
|
||||||
|
goto done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (content != CONTENT_CONFIG &&
|
if (content != CONTENT_CONFIG &&
|
||||||
|
|
@ -1028,7 +975,7 @@ get_common(clixon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
} /* CLICON_VALIDATE_STATE_XML */
|
} /* CLICON_VALIDATE_STATE_XML */
|
||||||
|
if (clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML"))
|
||||||
if (content == CONTENT_NONCONFIG){ /* state only, all config should be removed now */
|
if (content == CONTENT_NONCONFIG){ /* state only, all config should be removed now */
|
||||||
/* Keep state data only, remove everything that is config. Note that state data
|
/* Keep state data only, remove everything that is config. Note that state data
|
||||||
* may be a sub-part in a config tree, we need to traverse to find all
|
* may be a sub-part in a config tree, we need to traverse to find all
|
||||||
|
|
@ -1044,7 +991,7 @@ get_common(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (filter_xpath_again(h, yspec, xret, xvec, xlen, xpath, nsc) < 0)
|
if (filter_xpath_again(h, yspec, xret, xvec, xlen, xpath, nsc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (get_nacm_and_reply(h, xret, xvec, xlen, xpath, nsc, username, depth, cbret) < 0)
|
if (get_nacm_and_reply(h, xret, xvec, xlen, xpath, nsc, username, depth, wdef, cbret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -337,7 +337,6 @@ clixon_plugin_statedata_all(clixon_handle h,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
withdefaults_type wdef,
|
|
||||||
cxobj **xret)
|
cxobj **xret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,9 @@ startup_extraxml(clixon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
if (xt==NULL || xml_child_nr(xt)==0)
|
if (xt==NULL || xml_child_nr(xt)==0)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
/* Ensure yang bindings and defaults that were scratched in startup_validate */
|
||||||
|
if (xmldb_populate(h, tmp_db) < 0)
|
||||||
|
goto done;
|
||||||
/* Merge tmp into running (no commit) */
|
/* Merge tmp into running (no commit) */
|
||||||
if ((ret = db_merge(h, tmp_db, "running", cbret)) < 0)
|
if ((ret = db_merge(h, tmp_db, "running", cbret)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,7 @@ int clixon_plugin_reset_all(clixon_handle h, char *db);
|
||||||
int clixon_plugin_pre_daemon_all(clixon_handle h);
|
int clixon_plugin_pre_daemon_all(clixon_handle h);
|
||||||
int clixon_plugin_daemon_all(clixon_handle h);
|
int clixon_plugin_daemon_all(clixon_handle h);
|
||||||
|
|
||||||
int clixon_plugin_statedata_all(clixon_handle h, yang_stmt *yspec, cvec *nsc, char *xpath,
|
int clixon_plugin_statedata_all(clixon_handle h, yang_stmt *yspec, cvec *nsc, char *xpath, cxobj **xtop);
|
||||||
withdefaults_type wdef, cxobj **xtop);
|
|
||||||
int clixon_plugin_lockdb_all(clixon_handle h, char *db, int lock, int id);
|
int clixon_plugin_lockdb_all(clixon_handle h, char *db, int lock, int id);
|
||||||
|
|
||||||
int clixon_pagination_cb_register(clixon_handle h, handler_function fn, char *path, void *arg);
|
int clixon_pagination_cb_register(clixon_handle h, handler_function fn, char *path, void *arg);
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,10 @@ int xmldb_db2file(clixon_handle h, const char *db, char **filename);
|
||||||
int xmldb_connect(clixon_handle h);
|
int xmldb_connect(clixon_handle h);
|
||||||
int xmldb_disconnect(clixon_handle h);
|
int xmldb_disconnect(clixon_handle h);
|
||||||
/* in clixon_datastore_read.[ch] */
|
/* in clixon_datastore_read.[ch] */
|
||||||
int xmldb_get(clixon_handle h, const char *db, cvec *nsc, char *xpath, cxobj **xtop);
|
int xmldb_get(clixon_handle h, const char *db, cvec *nsc, char *xpath, cxobj **xret);
|
||||||
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 **xret, modstate_diff_t *msd, cxobj **xerr);
|
||||||
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);
|
||||||
|
|
@ -75,5 +75,6 @@ int xmldb_empty_get(clixon_handle h, const char *db);
|
||||||
int xmldb_dump(clixon_handle h, FILE *f, cxobj *xt);
|
int xmldb_dump(clixon_handle h, FILE *f, cxobj *xt);
|
||||||
int xmldb_print(clixon_handle h, FILE *f);
|
int xmldb_print(clixon_handle h, FILE *f);
|
||||||
int xmldb_rename(clixon_handle h, const char *db, const char *newdb, const char *suffix);
|
int xmldb_rename(clixon_handle h, const char *db, const char *newdb, const char *suffix);
|
||||||
|
int xmldb_populate(clixon_handle h, const char *db);
|
||||||
|
|
||||||
#endif /* _CLIXON_DATASTORE_H */
|
#endif /* _CLIXON_DATASTORE_H */
|
||||||
|
|
|
||||||
|
|
@ -77,11 +77,12 @@
|
||||||
#include "clixon_options.h"
|
#include "clixon_options.h"
|
||||||
#include "clixon_data.h"
|
#include "clixon_data.h"
|
||||||
#include "clixon_netconf_lib.h"
|
#include "clixon_netconf_lib.h"
|
||||||
|
#include "clixon_xml_bind.h"
|
||||||
|
#include "clixon_xml_default.h"
|
||||||
#include "clixon_datastore.h"
|
#include "clixon_datastore.h"
|
||||||
#include "clixon_datastore_write.h"
|
#include "clixon_datastore_write.h"
|
||||||
#include "clixon_datastore_read.h"
|
#include "clixon_datastore_read.h"
|
||||||
|
|
||||||
|
|
||||||
/*! Translate from symbolic database name to actual filename in file-system
|
/*! Translate from symbolic database name to actual filename in file-system
|
||||||
*
|
*
|
||||||
* @param[in] th text handle handle
|
* @param[in] th text handle handle
|
||||||
|
|
@ -681,3 +682,40 @@ xmldb_rename(clixon_handle h,
|
||||||
free(old);
|
free(old);
|
||||||
return retval;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -701,7 +701,7 @@ xmldb_get_cache(clixon_handle h,
|
||||||
db_elmnt de0 = {0,};
|
db_elmnt de0 = {0,};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "db %s", db);
|
clixon_debug(CLIXON_DBG_DATASTORE, "db %s", db);
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clixon_err(OE_DB, EINVAL, "xret is NULL");
|
clixon_err(OE_DB, EINVAL, "xret is NULL");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -725,22 +725,16 @@ xmldb_get_cache(clixon_handle h,
|
||||||
if (de)
|
if (de)
|
||||||
de0.de_id = de->de_id;
|
de0.de_id = de->de_id;
|
||||||
clicon_db_elmnt_set(h, db, &de0); /* Content is copied */
|
clicon_db_elmnt_set(h, db, &de0); /* Content is copied */
|
||||||
} /* 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) */
|
/* 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)
|
if (xml_global_defaults(h, x0t, nsc, xpath, yspec, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Add default recursive values */
|
/* Add default recursive values */
|
||||||
if (xml_default_recurse(x0t, 0) < 0)
|
if (xml_default_recurse(x0t, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
} /* x0t == NULL */
|
||||||
}
|
else
|
||||||
|
x0t = de->de_xml;
|
||||||
/* Here x0t looks like: <config>...</config> */
|
/* Here x0t looks like: <config>...</config> */
|
||||||
/* Given the xpath, return a vector of matches in xvec
|
/* Given the xpath, return a vector of matches in xvec
|
||||||
* Can we do everything in one go?
|
* 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)
|
if (xpath_vec(x0t, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
// XXX: Remove copying and return x0 eventually
|
||||||
/* Make new tree by copying top-of-tree from x0t to x1t */
|
/* Make new tree by copying top-of-tree from x0t to x1t */
|
||||||
if ((x1t = xml_new(xml_name(x0t), NULL, CX_ELMNT)) == NULL)
|
if ((x1t = xml_new(xml_name(x0t), NULL, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
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)
|
if (xml_apply(x1t, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
|
||||||
goto done;
|
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 empty NACM config, then disable NACM if loaded
|
||||||
*/
|
*/
|
||||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
||||||
|
|
@ -935,5 +884,26 @@ xmldb_get0(clixon_handle h,
|
||||||
modstate_diff_t *msdiff,
|
modstate_diff_t *msdiff,
|
||||||
cxobj **xerr)
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1286,13 +1286,18 @@ xmldb_put(clixon_handle h,
|
||||||
if (xml_apply(x0, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
if (xml_apply(x0, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
|
||||||
(void*)(XML_FLAG_NONE|XML_FLAG_MARK)) < 0)
|
(void*)(XML_FLAG_NONE|XML_FLAG_MARK)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Remove global defaults and empty non-presence containers */
|
/* Remove empty non-presence containers recursively.
|
||||||
if (xml_defaults_nopresence(x0, 2) < 0)
|
* 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;
|
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 */
|
/* Write back to datastore cache if first time */
|
||||||
{
|
{
|
||||||
db_elmnt de0 = {0,};
|
db_elmnt de0 = {0,};
|
||||||
|
|
@ -1331,7 +1336,7 @@ xmldb_put(clixon_handle h,
|
||||||
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
|
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
|
||||||
goto done;
|
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;
|
goto done;
|
||||||
/* Remove modules state after writing to file
|
/* Remove modules state after writing to file
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -885,8 +885,7 @@ nacm_data_read_xrule_xml(cxobj *xn,
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] xn XML node (requested node)
|
* @param[in] xn XML node (requested node)
|
||||||
* @param[in] rulevec Precomputed rules that apply to this user group
|
* @param[in] pv_list Precomputed rules + paths that apply to this user group
|
||||||
* @param[in] xpathvec Precomputed xpath results that apply to this XML tree
|
|
||||||
* @param[in] yspec YANG spec
|
* @param[in] yspec YANG spec
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
|
||||||
|
|
@ -1660,7 +1660,10 @@ xml_copy_marked(cxobj *x0,
|
||||||
char *name;
|
char *name;
|
||||||
char *prefix;
|
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 */
|
yt = xml_spec(x0); /* can be null */
|
||||||
xml_spec_set(x1, yt);
|
xml_spec_set(x1, yt);
|
||||||
/* Copy prefix*/
|
/* Copy prefix*/
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ module nacm-example{
|
||||||
prefix ex2;
|
prefix ex2;
|
||||||
}
|
}
|
||||||
container table{
|
container table{
|
||||||
|
presence "Tests rely on empty table";
|
||||||
container parameters{
|
container parameters{
|
||||||
list parameter{
|
list parameter{
|
||||||
key name;
|
key name;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue