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
|
|
@ -120,7 +120,8 @@ restconf_client_get_capabilities(clixon_handle h,
|
|||
*
|
||||
* @param[in] h Clixon handle
|
||||
* @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] top Top symbol, ie netconf or restconf-state
|
||||
* @param[in,out] xret Existing XML tree, merge x into this
|
||||
|
|
@ -132,15 +133,14 @@ static int
|
|||
client_get_streams(clixon_handle h,
|
||||
yang_stmt *yspec,
|
||||
char *xpath,
|
||||
cvec *nsc,
|
||||
yang_stmt *ymod,
|
||||
char *top,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *yns = NULL; /* yang namespace */
|
||||
cxobj *x = NULL;
|
||||
cbuf *cb = NULL;
|
||||
int ret;
|
||||
|
||||
if ((yns = yang_find(ymod, Y_NAMESPACE, NULL)) == NULL){
|
||||
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;
|
||||
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)
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
if ((ret = netconf_trymerge(x, yspec, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
retval = 1;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (x)
|
||||
xml_free(x);
|
||||
return retval;
|
||||
fail:
|
||||
retval = 0;
|
||||
|
|
@ -184,7 +178,6 @@ client_get_streams(clixon_handle h,
|
|||
* @param[in] h Clixon handle
|
||||
* @param[in] xpath XPath selection, may be used to filter early
|
||||
* @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
|
||||
* @retval 1 OK
|
||||
* @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
|
||||
* 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
get_statedata(clixon_handle h,
|
||||
char *xpath,
|
||||
cvec *nsc,
|
||||
withdefaults_type wdef,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -214,7 +204,6 @@ get_statedata(clixon_handle h,
|
|||
yang_stmt *ymod;
|
||||
cxobj *x1 = NULL;
|
||||
int ret;
|
||||
char *namespace;
|
||||
cbuf *cb = NULL;
|
||||
cxobj *xerr = NULL;
|
||||
|
||||
|
|
@ -232,37 +221,34 @@ get_statedata(clixon_handle h,
|
|||
clixon_err(OE_YANG, ENOENT, "yang module clixon-rfc5277 not found");
|
||||
goto done;
|
||||
}
|
||||
if ((namespace = yang_find_mynamespace(ymod)) == NULL){
|
||||
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)
|
||||
if ((ret = client_get_streams(h, yspec, xpath, nsc, ymod, "netconf", &x1)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
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 ((ymod = yang_find_module_by_name(yspec, "ietf-restconf-monitoring")) == NULL){
|
||||
clixon_err(OE_YANG, ENOENT, "yang module ietf-restconf-monitoring not found");
|
||||
goto done;
|
||||
}
|
||||
if ((namespace = yang_find_mynamespace(ymod)) == NULL){
|
||||
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)
|
||||
if ((ret = client_get_streams(h, yspec, xpath, nsc, ymod, "restconf-state", &x1)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
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;
|
||||
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 ((ret = yang_modules_state_get(h, yspec, xpath, nsc, 0, xret)) < 0)
|
||||
|
|
@ -270,37 +256,42 @@ get_statedata(clixon_handle h,
|
|||
if (ret == 0)
|
||||
goto fail;
|
||||
}
|
||||
if (clicon_option_bool(h, "CLICON_NETCONF_MONITORING")){
|
||||
if ((ret = netconf_monitoring_state_get(h, yspec, xpath, nsc, xret, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
if (clixon_netconf_internal_error(xerr, " . Internal error, netconf_monitoring_state returned invalid XML", NULL) < 0)
|
||||
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)
|
||||
goto done;
|
||||
if (*xret)
|
||||
xml_free(*xret);
|
||||
*xret = xerr;
|
||||
xerr = NULL;
|
||||
goto fail;
|
||||
}
|
||||
/* Some state, client state, is avaliable in backend only, not in lib
|
||||
* Needs merge since same subtree as previous lib state
|
||||
*/
|
||||
if ((ret = backend_monitoring_state_get(h, yspec, xpath, nsc, &x1, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
if (clixon_netconf_internal_error(xerr, " . Internal error, baenckend_monitoring_state_get returned invalid XML", NULL) < 0)
|
||||
if (ret == 0){
|
||||
if (clixon_netconf_internal_error(xerr, " . Internal error, netconf_monitoring_state returned invalid XML", NULL) < 0)
|
||||
goto done;
|
||||
if (*xret)
|
||||
xml_free(*xret);
|
||||
*xret = xerr;
|
||||
xerr = NULL;
|
||||
goto fail;
|
||||
}
|
||||
/* Some state, client state, is avaliable in backend only, not in lib
|
||||
* Needs merge since same subtree as previous lib state
|
||||
*/
|
||||
if ((ret = backend_monitoring_state_get(h, yspec, xpath, nsc, &x1, &xerr)) < 0)
|
||||
goto done;
|
||||
if (*xret)
|
||||
xml_free(*xret);
|
||||
*xret = xerr;
|
||||
xerr = NULL;
|
||||
goto fail;
|
||||
if (ret == 0){
|
||||
if (clixon_netconf_internal_error(xerr, " . Internal error, baenckend_monitoring_state_get returned invalid XML", NULL) < 0)
|
||||
goto done;
|
||||
if (*xret)
|
||||
xml_free(*xret);
|
||||
*xret = xerr;
|
||||
xerr = NULL;
|
||||
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 ((ret = netconf_trymerge(x1, yspec, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
}
|
||||
if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){
|
||||
if ((ret = yang_schema_mount_statedata(h, yspec, xpath, nsc, xret, &xerr)) < 0)
|
||||
goto done;
|
||||
|
|
@ -315,62 +306,10 @@ get_statedata(clixon_handle h,
|
|||
}
|
||||
}
|
||||
/* 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;
|
||||
if (ret == 0)
|
||||
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 */
|
||||
done:
|
||||
clixon_debug(CLIXON_DBG_CLIENT, "retval:%d", retval);
|
||||
|
|
@ -456,15 +395,16 @@ filter_xpath_again(clixon_handle h,
|
|||
* @retval -1 Error
|
||||
*/
|
||||
static int
|
||||
get_nacm_and_reply(clixon_handle h,
|
||||
cxobj *xret,
|
||||
cxobj **xvec,
|
||||
size_t xlen,
|
||||
char *xpath,
|
||||
cvec *nsc,
|
||||
char *username,
|
||||
int32_t depth,
|
||||
cbuf *cbret)
|
||||
get_nacm_and_reply(clixon_handle h,
|
||||
cxobj *xret,
|
||||
cxobj **xvec,
|
||||
size_t xlen,
|
||||
char *xpath,
|
||||
cvec *nsc,
|
||||
char *username,
|
||||
int32_t depth,
|
||||
withdefaults_type wdef,
|
||||
cbuf *cbret)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xnacm = NULL;
|
||||
|
|
@ -483,7 +423,7 @@ get_nacm_and_reply(clixon_handle h,
|
|||
if (xml_name_set(xret, NETCONF_OUTPUT_DATA) < 0)
|
||||
goto done;
|
||||
/* 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;
|
||||
}
|
||||
cprintf(cbret, "</rpc-reply>");
|
||||
|
|
@ -567,7 +507,7 @@ list_pagination_hdr(clixon_handle h,
|
|||
* @param[in] xpath XPath point to object to get
|
||||
* @param[in] nsc Namespace context of xpath
|
||||
* @param[in] username
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
|
|
@ -804,7 +744,7 @@ get_list_pagination(clixon_handle h,
|
|||
cbuf_free(cba);
|
||||
}
|
||||
#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;
|
||||
ok:
|
||||
retval = 0;
|
||||
|
|
@ -997,13 +937,20 @@ get_common(clixon_handle h,
|
|||
break;
|
||||
case CONTENT_ALL: /* both config and state */
|
||||
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;
|
||||
if (ret == 0){ /* Error from callback (error in xret) */
|
||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
|
||||
goto done;
|
||||
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;
|
||||
}
|
||||
if (content != CONTENT_CONFIG &&
|
||||
|
|
@ -1028,23 +975,23 @@ get_common(clixon_handle h,
|
|||
goto ok;
|
||||
}
|
||||
} /* CLICON_VALIDATE_STATE_XML */
|
||||
|
||||
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
|
||||
* may be a sub-part in a config tree, we need to traverse to find all
|
||||
*/
|
||||
if (xml_non_config_data(xret, NULL) < 0)
|
||||
goto done;
|
||||
if (xml_tree_prune_flagged_sub(xret, XML_FLAG_MARK, 1, NULL) < 0)
|
||||
goto done;
|
||||
if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML"))
|
||||
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
|
||||
* may be a sub-part in a config tree, we need to traverse to find all
|
||||
*/
|
||||
if (xml_non_config_data(xret, NULL) < 0)
|
||||
goto done;
|
||||
if (xml_tree_prune_flagged_sub(xret, XML_FLAG_MARK, 1, NULL) < 0)
|
||||
goto done;
|
||||
if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||
goto done;
|
||||
if (filter_xpath_again(h, yspec, xret, xvec, xlen, xpath, nsc) < 0)
|
||||
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;
|
||||
ok:
|
||||
retval = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue