- Added an extended state plugin callback: ca_statedata2 with offset and limit parameters

- Fixed memory errors
This commit is contained in:
Olof hagsand 2021-09-02 12:35:48 +02:00
parent 28f58fb7d6
commit aaf9a89183
9 changed files with 121 additions and 114 deletions

View file

@ -72,6 +72,9 @@
#include "backend_handle.h"
#include "backend_get.h"
/* List pagination remaining attribute using meta */
#undef REMAINING
/*!
* Maybe should be in the restconf client instead of backend?
* @param[in] h Clicon handle
@ -184,10 +187,10 @@ client_get_streams(clicon_handle h,
* @retval 1 OK
*/
static int
client_statedata(clicon_handle h,
char *xpath,
cvec *nsc,
cxobj **xret)
get_client_statedata(clicon_handle h,
char *xpath,
cvec *nsc,
cxobj **xret)
{
int retval = -1;
yang_stmt *yspec;
@ -257,7 +260,7 @@ client_statedata(clicon_handle h,
goto fail;
}
/* Use plugin state callbacks */
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, xret)) < 0)
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, 0, 0, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
@ -338,8 +341,6 @@ get_list_pagination(clicon_handle h,
int retval = -1;
uint32_t offset = 0;
uint32_t limit = 0;
uint32_t total = 0;
uint32_t remaining = 0;
char *direction = NULL;
char *sort = NULL;
char *where = NULL;
@ -347,7 +348,6 @@ get_list_pagination(clicon_handle h,
cxobj *x;
int list_config;
yang_stmt *ylist;
cxobj *xcache = NULL;
cxobj **xvec = NULL;
size_t xlen;
cxobj **xvecnacm = NULL;
@ -359,6 +359,11 @@ get_list_pagination(clicon_handle h,
int ret;
int i;
cxobj *xnacm = NULL;
#ifdef REMAINING
cxobj *xcache = NULL;
uint32_t total = 0;
uint32_t remaining = 0;
#endif
/* Check if list/leaf-list */
if (yang_path_arg(yspec, xpath, &ylist) < 0)
@ -380,6 +385,7 @@ get_list_pagination(clicon_handle h,
goto done;
goto ok;
}
/* Sanity checks on state/config */
if ((list_config = yang_config_ancestor(ylist)) != 0){ /* config list */
if (content == CONTENT_NONCONFIG){
if (netconf_invalid_value(cbret, "application", "list-pagination targets a config list but content request is nonconfig") < 0)
@ -393,7 +399,7 @@ get_list_pagination(clicon_handle h,
goto done;
goto ok;
}
#if 1 /* XXX For now state lists are not implemenetd */
#if 0 /* XXX For now state lists are not implemenetd */
if (netconf_operation_not_supported(cbret, "protocol", "List pagination for state lists is not yet implemented") < 0)
goto done;
goto ok;
@ -445,7 +451,11 @@ get_list_pagination(clicon_handle h,
}
else if (limit)
cprintf(cbpath, "[position() < %u]", limit);
/* Append predicate to original xpath and replace it */
xpath2 = cbuf_get(cbpath);
#ifdef REMAINING
/* Get total/remaining
* XXX: Works only for cache, and only if already populated
* XXX: Maybe together with get config / state data
*/
if (list_config){
@ -462,11 +472,11 @@ get_list_pagination(clicon_handle h,
* 2. Read all here and count (fallback)
*/
}
/* Append predicate to original xpath and replace it */
xpath2 = cbuf_get(cbpath);
#endif /* REMAINING */
/* Read config */
switch (content){
case CONTENT_CONFIG: /* config data only */
case CONTENT_ALL: /* both config and state */
/* specific xpath */
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath2?xpath2:"/", 1, &xret, NULL, NULL) < 0) {
if ((cbmsg = cbuf_new()) == NULL){
@ -479,72 +489,17 @@ get_list_pagination(clicon_handle h,
goto ok;
}
break;
case CONTENT_ALL: /* both config and state */
case CONTENT_NONCONFIG: /* state data only */
if (clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
/* Whole config tree, for validate debug */
if (xmldb_get0(h, "running", YB_MODULE, nsc, NULL, 1, &xret, NULL, NULL) < 0) {
if ((cbmsg = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cbmsg, "Get %s datastore: %s", db, clicon_err_reason);
if (netconf_operation_failed(cbret, "application", cbuf_get(cbmsg)) < 0)
goto done;
goto ok;
}
}
else if (content == CONTENT_ALL){
/* specific xpath */
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath2?xpath2:"/", 1, &xret, NULL, NULL) < 0) {
if ((cbmsg = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cbmsg, "Get %s datastore: %s", db, clicon_err_reason);
if (netconf_operation_failed(cbret, "application", cbuf_get(cbmsg)) < 0)
goto done;
goto ok;
}
}
/* CONTENT_NONCONFIG */
else if ((xret = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)/* Only top tree */
if ((xret = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)/* Only top tree */
goto done;
break;
}/* switch content */
if (content != CONTENT_CONFIG &&
clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
/* Check XML by validating it. return internal error with error cause
* Primarily intended for user-supplied state-data.
* The whole config tree must be present in case the state data references config data
if (!list_config){
/* Look if registered,
* get all state list and filter using cbpath
*/
if ((ret = xml_yang_validate_all_top(h, xret, &xerr)) < 0)
goto done;
if (ret > 0 &&
(ret = xml_yang_validate_add(h, xret, &xerr)) < 0)
goto done;
if (ret == 0){
if (clicon_debug_get())
clicon_log_xml(LOG_DEBUG, xret, "VALIDATE_STATE");
if (clixon_netconf_internal_error(xerr,
". Internal error, state callback returned invalid XML",
NULL) < 0)
goto done;
if (clicon_xml2cbuf(cbret, xerr, 0, 0, -1) < 0)
goto done;
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)
/* Use plugin state callbacks */
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, offset, limit, &xret)) < 0)
goto done;
}
/* Code complex to filter out anything that is outside of xpath
@ -579,6 +534,7 @@ get_list_pagination(clicon_handle h,
if (xml_default_recurse(xret, 0) < 0)
goto done;
#ifdef REMAINING
/* Add remaining attribute Sec 3.1.5:
Any list or leaf-list that is limited includes, on the first element in the result set,
a metadata value [RFC7952] called "remaining"*/
@ -604,6 +560,7 @@ get_list_pagination(clicon_handle h,
if (cba)
cbuf_free(cba);
}
#endif /* REMAINING */
/* Pre-NACM access step */
xnacm = clicon_nacm_cache(h);
if (xnacm != NULL){ /* Do NACM validation */
@ -673,7 +630,8 @@ get_common(clicon_handle h,
size_t xlennacm;
cxobj *xnacm = NULL;
char *username;
cvec *nsc = NULL; /* Create a netconf namespace context from filter */
cvec *nsc0 = NULL; /* Create a netconf namespace context from filter */
cvec *nsc = NULL;
char *attr;
int32_t depth = -1; /* Nr of levels to print, -1 is all, 0 is none */
yang_stmt *yspec;
@ -683,7 +641,6 @@ get_common(clicon_handle h,
char *reason = NULL;
cbuf *cbmsg = NULL; /* For error msg */
char *xpath0;
cvec *nsc1 = NULL;
cbuf *cbreason = NULL;
#ifdef LIST_PAGINATION
int list_pagination = 0;
@ -705,9 +662,9 @@ get_common(clicon_handle h,
* <filter> element.
*/
else
if (xml_nsctx_node(xfilter, &nsc) < 0)
if (xml_nsctx_node(xfilter, &nsc0) < 0)
goto done;
if ((ret = xpath2canonical(xpath0, nsc, yspec, &xpath, &nsc1, &cbreason)) < 0)
if ((ret = xpath2canonical(xpath0, nsc0, yspec, &xpath, &nsc, &cbreason)) < 0)
goto done;
if (ret == 0){
if (netconf_bad_attribute(cbret, "application",
@ -715,7 +672,6 @@ get_common(clicon_handle h,
goto done;
goto ok;
}
nsc = nsc1;
}
/* Clixon extensions: depth */
if ((attr = xml_find_value(xe, "depth")) != NULL){
@ -798,13 +754,13 @@ get_common(clicon_handle h,
/* If not only config,
* get state data from plugins as defined by plugin_statedata(), if any
*/
/* Read state XXX can we do this first and create an operational db? */
/* Read state */
switch (content){
case CONTENT_CONFIG: /* config data only */
break;
case CONTENT_ALL: /* both config and state */
case CONTENT_NONCONFIG: /* state data only */
if ((ret = client_statedata(h, xpath?xpath:"/", nsc, &xret)) < 0)
if ((ret = get_client_statedata(h, xpath?xpath:"/", nsc, &xret)) < 0)
goto done;
if (ret == 0){ /* Error from callback (error in xret) */
if (clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0)
@ -906,6 +862,8 @@ get_common(clicon_handle h,
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
if (cbreason)
cbuf_free(cbreason);
if (nsc0)
xml_nsctx_free(nsc0);
if (nsc)
xml_nsctx_free(nsc);
if (cbmsg)