- Added an extended state plugin callback: ca_statedata2 with offset and limit parameters
- Fixed memory errors
This commit is contained in:
parent
28f58fb7d6
commit
aaf9a89183
9 changed files with 121 additions and 114 deletions
|
|
@ -72,6 +72,9 @@
|
||||||
#include "backend_handle.h"
|
#include "backend_handle.h"
|
||||||
#include "backend_get.h"
|
#include "backend_get.h"
|
||||||
|
|
||||||
|
/* List pagination remaining attribute using meta */
|
||||||
|
#undef REMAINING
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Maybe should be in the restconf client instead of backend?
|
* Maybe should be in the restconf client instead of backend?
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
|
@ -184,10 +187,10 @@ client_get_streams(clicon_handle h,
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
client_statedata(clicon_handle h,
|
get_client_statedata(clicon_handle h,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
cxobj **xret)
|
cxobj **xret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
|
@ -257,7 +260,7 @@ client_statedata(clicon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Use plugin state callbacks */
|
/* 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;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -338,8 +341,6 @@ get_list_pagination(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
uint32_t limit = 0;
|
uint32_t limit = 0;
|
||||||
uint32_t total = 0;
|
|
||||||
uint32_t remaining = 0;
|
|
||||||
char *direction = NULL;
|
char *direction = NULL;
|
||||||
char *sort = NULL;
|
char *sort = NULL;
|
||||||
char *where = NULL;
|
char *where = NULL;
|
||||||
|
|
@ -347,7 +348,6 @@ get_list_pagination(clicon_handle h,
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
int list_config;
|
int list_config;
|
||||||
yang_stmt *ylist;
|
yang_stmt *ylist;
|
||||||
cxobj *xcache = NULL;
|
|
||||||
cxobj **xvec = NULL;
|
cxobj **xvec = NULL;
|
||||||
size_t xlen;
|
size_t xlen;
|
||||||
cxobj **xvecnacm = NULL;
|
cxobj **xvecnacm = NULL;
|
||||||
|
|
@ -359,6 +359,11 @@ get_list_pagination(clicon_handle h,
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
cxobj *xnacm = NULL;
|
cxobj *xnacm = NULL;
|
||||||
|
#ifdef REMAINING
|
||||||
|
cxobj *xcache = NULL;
|
||||||
|
uint32_t total = 0;
|
||||||
|
uint32_t remaining = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if list/leaf-list */
|
/* Check if list/leaf-list */
|
||||||
if (yang_path_arg(yspec, xpath, &ylist) < 0)
|
if (yang_path_arg(yspec, xpath, &ylist) < 0)
|
||||||
|
|
@ -380,6 +385,7 @@ get_list_pagination(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
/* Sanity checks on state/config */
|
||||||
if ((list_config = yang_config_ancestor(ylist)) != 0){ /* config list */
|
if ((list_config = yang_config_ancestor(ylist)) != 0){ /* config list */
|
||||||
if (content == CONTENT_NONCONFIG){
|
if (content == CONTENT_NONCONFIG){
|
||||||
if (netconf_invalid_value(cbret, "application", "list-pagination targets a config list but content request is nonconfig") < 0)
|
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 done;
|
||||||
goto ok;
|
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)
|
if (netconf_operation_not_supported(cbret, "protocol", "List pagination for state lists is not yet implemented") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -445,7 +451,11 @@ get_list_pagination(clicon_handle h,
|
||||||
}
|
}
|
||||||
else if (limit)
|
else if (limit)
|
||||||
cprintf(cbpath, "[position() < %u]", limit);
|
cprintf(cbpath, "[position() < %u]", limit);
|
||||||
|
/* Append predicate to original xpath and replace it */
|
||||||
|
xpath2 = cbuf_get(cbpath);
|
||||||
|
#ifdef REMAINING
|
||||||
/* Get total/remaining
|
/* Get total/remaining
|
||||||
|
* XXX: Works only for cache, and only if already populated
|
||||||
* XXX: Maybe together with get config / state data
|
* XXX: Maybe together with get config / state data
|
||||||
*/
|
*/
|
||||||
if (list_config){
|
if (list_config){
|
||||||
|
|
@ -462,11 +472,11 @@ get_list_pagination(clicon_handle h,
|
||||||
* 2. Read all here and count (fallback)
|
* 2. Read all here and count (fallback)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
/* Append predicate to original xpath and replace it */
|
#endif /* REMAINING */
|
||||||
xpath2 = cbuf_get(cbpath);
|
/* Read config */
|
||||||
|
|
||||||
switch (content){
|
switch (content){
|
||||||
case CONTENT_CONFIG: /* config data only */
|
case CONTENT_CONFIG: /* config data only */
|
||||||
|
case CONTENT_ALL: /* both config and state */
|
||||||
/* specific xpath */
|
/* specific xpath */
|
||||||
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath2?xpath2:"/", 1, &xret, NULL, NULL) < 0) {
|
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath2?xpath2:"/", 1, &xret, NULL, NULL) < 0) {
|
||||||
if ((cbmsg = cbuf_new()) == NULL){
|
if ((cbmsg = cbuf_new()) == NULL){
|
||||||
|
|
@ -479,72 +489,17 @@ get_list_pagination(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CONTENT_ALL: /* both config and state */
|
|
||||||
case CONTENT_NONCONFIG: /* state data only */
|
case CONTENT_NONCONFIG: /* state data only */
|
||||||
if (clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
if ((xret = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)/* Only top tree */
|
||||||
/* 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 */
|
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
}/* switch content */
|
}/* switch content */
|
||||||
if (content != CONTENT_CONFIG &&
|
if (!list_config){
|
||||||
clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
/* Look if registered,
|
||||||
/* Check XML by validating it. return internal error with error cause
|
* get all state list and filter using cbpath
|
||||||
* Primarily intended for user-supplied state-data.
|
|
||||||
* The whole config tree must be present in case the state data references config data
|
|
||||||
*/
|
*/
|
||||||
if ((ret = xml_yang_validate_all_top(h, xret, &xerr)) < 0)
|
/* Use plugin state callbacks */
|
||||||
goto done;
|
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, offset, limit, &xret)) < 0)
|
||||||
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)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Code complex to filter out anything that is outside of xpath
|
/* 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)
|
if (xml_default_recurse(xret, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
#ifdef REMAINING
|
||||||
/* Add remaining attribute Sec 3.1.5:
|
/* Add remaining attribute Sec 3.1.5:
|
||||||
Any list or leaf-list that is limited includes, on the first element in the result set,
|
Any list or leaf-list that is limited includes, on the first element in the result set,
|
||||||
a metadata value [RFC7952] called "remaining"*/
|
a metadata value [RFC7952] called "remaining"*/
|
||||||
|
|
@ -604,6 +560,7 @@ get_list_pagination(clicon_handle h,
|
||||||
if (cba)
|
if (cba)
|
||||||
cbuf_free(cba);
|
cbuf_free(cba);
|
||||||
}
|
}
|
||||||
|
#endif /* REMAINING */
|
||||||
/* Pre-NACM access step */
|
/* Pre-NACM access step */
|
||||||
xnacm = clicon_nacm_cache(h);
|
xnacm = clicon_nacm_cache(h);
|
||||||
if (xnacm != NULL){ /* Do NACM validation */
|
if (xnacm != NULL){ /* Do NACM validation */
|
||||||
|
|
@ -673,7 +630,8 @@ get_common(clicon_handle h,
|
||||||
size_t xlennacm;
|
size_t xlennacm;
|
||||||
cxobj *xnacm = NULL;
|
cxobj *xnacm = NULL;
|
||||||
char *username;
|
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;
|
char *attr;
|
||||||
int32_t depth = -1; /* Nr of levels to print, -1 is all, 0 is none */
|
int32_t depth = -1; /* Nr of levels to print, -1 is all, 0 is none */
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
|
@ -683,7 +641,6 @@ get_common(clicon_handle h,
|
||||||
char *reason = NULL;
|
char *reason = NULL;
|
||||||
cbuf *cbmsg = NULL; /* For error msg */
|
cbuf *cbmsg = NULL; /* For error msg */
|
||||||
char *xpath0;
|
char *xpath0;
|
||||||
cvec *nsc1 = NULL;
|
|
||||||
cbuf *cbreason = NULL;
|
cbuf *cbreason = NULL;
|
||||||
#ifdef LIST_PAGINATION
|
#ifdef LIST_PAGINATION
|
||||||
int list_pagination = 0;
|
int list_pagination = 0;
|
||||||
|
|
@ -705,9 +662,9 @@ get_common(clicon_handle h,
|
||||||
* <filter> element.
|
* <filter> element.
|
||||||
*/
|
*/
|
||||||
else
|
else
|
||||||
if (xml_nsctx_node(xfilter, &nsc) < 0)
|
if (xml_nsctx_node(xfilter, &nsc0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = xpath2canonical(xpath0, nsc, yspec, &xpath, &nsc1, &cbreason)) < 0)
|
if ((ret = xpath2canonical(xpath0, nsc0, yspec, &xpath, &nsc, &cbreason)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if (netconf_bad_attribute(cbret, "application",
|
if (netconf_bad_attribute(cbret, "application",
|
||||||
|
|
@ -715,7 +672,6 @@ get_common(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
nsc = nsc1;
|
|
||||||
}
|
}
|
||||||
/* Clixon extensions: depth */
|
/* Clixon extensions: depth */
|
||||||
if ((attr = xml_find_value(xe, "depth")) != NULL){
|
if ((attr = xml_find_value(xe, "depth")) != NULL){
|
||||||
|
|
@ -798,13 +754,13 @@ get_common(clicon_handle h,
|
||||||
/* If not only config,
|
/* If not only config,
|
||||||
* get state data from plugins as defined by plugin_statedata(), if any
|
* 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){
|
switch (content){
|
||||||
case CONTENT_CONFIG: /* config data only */
|
case CONTENT_CONFIG: /* config data only */
|
||||||
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 = client_statedata(h, xpath?xpath:"/", nsc, &xret)) < 0)
|
if ((ret = get_client_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 (clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0)
|
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);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
if (cbreason)
|
if (cbreason)
|
||||||
cbuf_free(cbreason);
|
cbuf_free(cbreason);
|
||||||
|
if (nsc0)
|
||||||
|
xml_nsctx_free(nsc0);
|
||||||
if (nsc)
|
if (nsc)
|
||||||
xml_nsctx_free(nsc);
|
xml_nsctx_free(nsc);
|
||||||
if (cbmsg)
|
if (cbmsg)
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,8 @@ clixon_plugin_daemon_all(clicon_handle h)
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
* @param[in] nsc namespace context for xpath
|
* @param[in] nsc namespace context for xpath
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||||
|
* @param[in] offset Offset, for list pagination
|
||||||
|
* @param[in] limit Limit, for list pagination
|
||||||
* @param[out] xp If retval=1, state tree created and returned: <config>...
|
* @param[out] xp If retval=1, state tree created and returned: <config>...
|
||||||
* @retval -1 Fatal error
|
* @retval -1 Fatal error
|
||||||
* @retval 0 Statedata callback failed. no XML tree returned
|
* @retval 0 Statedata callback failed. no XML tree returned
|
||||||
|
|
@ -249,14 +251,27 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
||||||
clicon_handle h,
|
clicon_handle h,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t limit,
|
||||||
cxobj **xp)
|
cxobj **xp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
plgstatedata_t *fn; /* Plugin statedata fn */
|
plgstatedata_t *fn; /* Plugin statedata fn */
|
||||||
cxobj *x = NULL;
|
plgstatedata2_t *fn2; /* Plugin statedata fn2, try this first */
|
||||||
|
cxobj *x = NULL;
|
||||||
|
|
||||||
clicon_debug(1, "%s %s", __FUNCTION__, clixon_plugin_name_get(cp));
|
clicon_debug(1, "%s %s", __FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
|
if ((fn2 = clixon_plugin_api_get(cp)->ca_statedata2) != NULL){
|
||||||
|
if ((x = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (fn2(h, nsc, xpath, offset, limit, x) < 0){
|
||||||
|
if (clicon_errno < 0)
|
||||||
|
clicon_log(LOG_WARNING, "%s: Internal error: State callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
|
goto fail; /* Dont quit here on user callbacks */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
|
||||||
if ((x = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
if ((x = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (fn(h, nsc, xpath, x) < 0){
|
if (fn(h, nsc, xpath, x) < 0){
|
||||||
|
|
@ -283,6 +298,8 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[in] nsc Namespace context
|
* @param[in] nsc Namespace context
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||||
|
* @param[in] offset Offset, for list pagination
|
||||||
|
* @param[in] limit Limit, for list pagination
|
||||||
* @param[in,out] xret State XML tree is merged with existing tree.
|
* @param[in,out] xret State XML tree is merged with existing tree.
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 Statedata callback failed (xret set with netconf-error)
|
* @retval 0 Statedata callback failed (xret set with netconf-error)
|
||||||
|
|
@ -290,11 +307,13 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
||||||
* @note xret can be replaced in this function
|
* @note xret can be replaced in this function
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clixon_plugin_statedata_all(clicon_handle h,
|
clixon_plugin_statedata_all(clicon_handle h,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cxobj **xret)
|
uint32_t offset,
|
||||||
|
uint32_t limit,
|
||||||
|
cxobj **xret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -305,7 +324,7 @@ clixon_plugin_statedata_all(clicon_handle h,
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
if ((ret = clixon_plugin_statedata_one(cp, h, nsc, xpath, &x)) < 0)
|
if ((ret = clixon_plugin_statedata_one(cp, h, nsc, xpath, offset, limit, &x)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if ((cberr = cbuf_new()) == NULL){
|
if ((cberr = cbuf_new()) == NULL){
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,8 @@ int clixon_plugin_reset_all(clicon_handle h, char *db);
|
||||||
int clixon_plugin_pre_daemon_all(clicon_handle h);
|
int clixon_plugin_pre_daemon_all(clicon_handle h);
|
||||||
int clixon_plugin_daemon_all(clicon_handle h);
|
int clixon_plugin_daemon_all(clicon_handle h);
|
||||||
|
|
||||||
int clixon_plugin_statedata_all(clicon_handle h, yang_stmt *yspec, cvec *nsc, char *xpath, cxobj **xtop);
|
int clixon_plugin_statedata_all(clicon_handle h, yang_stmt *yspec, cvec *nsc, char *xpath,
|
||||||
|
uint32_t offset, uint32_t limit, cxobj **xtop);
|
||||||
transaction_data_t * transaction_new(void);
|
transaction_data_t * transaction_new(void);
|
||||||
int transaction_free(transaction_data_t *);
|
int transaction_free(transaction_data_t *);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -987,6 +987,14 @@ cli_pagination(clicon_handle h,
|
||||||
}
|
}
|
||||||
if (xlen != window) /* Break if fewer elements than requested */
|
if (xlen != window) /* Break if fewer elements than requested */
|
||||||
break;
|
break;
|
||||||
|
if (xret){
|
||||||
|
xml_free(xret);
|
||||||
|
xret = NULL;
|
||||||
|
}
|
||||||
|
if (xvec){
|
||||||
|
free(xvec);
|
||||||
|
xvec = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -994,6 +1002,8 @@ cli_pagination(clicon_handle h,
|
||||||
free(xvec);
|
free(xvec);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
|
if (nsc)
|
||||||
|
cvec_free(nsc);
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -365,19 +365,23 @@ int
|
||||||
example_statedata(clicon_handle h,
|
example_statedata(clicon_handle h,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t limit,
|
||||||
cxobj *xstate)
|
cxobj *xstate)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj **xvec = NULL;
|
cxobj **xvec = NULL;
|
||||||
size_t xlen = 0;
|
size_t xlen = 0;
|
||||||
cbuf *cb = cbuf_new();
|
cbuf *cb = cbuf_new();
|
||||||
int i;
|
int i;
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
char *name;
|
char *name;
|
||||||
cvec *nsc1 = NULL;
|
cvec *nsc1 = NULL;
|
||||||
cvec *nsc2 = NULL;
|
cvec *nsc2 = NULL;
|
||||||
yang_stmt *yspec = NULL;
|
yang_stmt *yspec = NULL;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
cxobj *x1;
|
||||||
|
uint32_t upper;
|
||||||
|
|
||||||
if (!_state)
|
if (!_state)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -401,7 +405,6 @@ example_statedata(clicon_handle h,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
cxobj *x1;
|
|
||||||
if ((fp = fopen(_state_file, "r")) == NULL){
|
if ((fp = fopen(_state_file, "r")) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", _state_file);
|
clicon_err(OE_UNIX, errno, "open(%s)", _state_file);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -413,17 +416,22 @@ example_statedata(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, xpath) < 0)
|
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, xpath) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
for (i=0; i<xlen; i++){
|
if (limit == 0)
|
||||||
x1 = xvec[i];
|
upper = xlen;
|
||||||
|
else{
|
||||||
|
if ((upper = offset+limit)>xlen)
|
||||||
|
upper = xlen;
|
||||||
|
}
|
||||||
|
for (i=offset; i<upper; i++){
|
||||||
|
if ((x1 = xvec[i]) == NULL)
|
||||||
|
break;
|
||||||
xml_flag_set(x1, XML_FLAG_MARK);
|
xml_flag_set(x1, XML_FLAG_MARK);
|
||||||
}
|
}
|
||||||
/* Remove everything that is not marked */
|
/* Remove everything that is not marked */
|
||||||
if (xml_tree_prune_flagged_sub(xt, XML_FLAG_MARK, 1, NULL) < 0)
|
if (xml_tree_prune_flagged_sub(xt, XML_FLAG_MARK, 1, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
for (i=0; i<xlen; i++){
|
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||||
x1 = xvec[i];
|
goto done;
|
||||||
xml_flag_reset(x1, XML_FLAG_MARK);
|
|
||||||
}
|
|
||||||
if (xml_copy(xt, xstate) < 0)
|
if (xml_copy(xt, xstate) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xvec){
|
if (xvec){
|
||||||
|
|
@ -1024,7 +1032,7 @@ static clixon_plugin_api api = {
|
||||||
.ca_extension=example_extension, /* yang extensions */
|
.ca_extension=example_extension, /* yang extensions */
|
||||||
.ca_daemon=example_daemon, /* daemon */
|
.ca_daemon=example_daemon, /* daemon */
|
||||||
.ca_reset=example_reset, /* reset */
|
.ca_reset=example_reset, /* reset */
|
||||||
.ca_statedata=example_statedata, /* statedata */
|
.ca_statedata2=example_statedata, /* statedata2 */
|
||||||
.ca_trans_begin=main_begin, /* trans begin */
|
.ca_trans_begin=main_begin, /* trans begin */
|
||||||
.ca_trans_validate=main_validate, /* trans validate */
|
.ca_trans_validate=main_validate, /* trans validate */
|
||||||
.ca_trans_complete=main_complete, /* trans complete */
|
.ca_trans_complete=main_complete, /* trans complete */
|
||||||
|
|
|
||||||
|
|
@ -200,12 +200,17 @@ typedef int (plgreset_t)(clicon_handle h, const char *db);
|
||||||
* @param[in] Clicon handle
|
* @param[in] Clicon handle
|
||||||
* @param[in] xpath Part of state requested
|
* @param[in] xpath Part of state requested
|
||||||
* @param[in] nsc XPATH namespace context.
|
* @param[in] nsc XPATH namespace context.
|
||||||
* @param[in] xtop XML tree where statedata is added
|
* @param[out] xtop XML tree where statedata is added
|
||||||
* @retval -1 Fatal error
|
* @retval -1 Fatal error
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
*/
|
*/
|
||||||
typedef int (plgstatedata_t)(clicon_handle h, cvec *nsc, char *xpath, cxobj *xtop);
|
typedef int (plgstatedata_t)(clicon_handle h, cvec *nsc, char *xpath, cxobj *xtop);
|
||||||
|
|
||||||
|
/*! Temporary new statedata callback */
|
||||||
|
typedef int (plgstatedata2_t)(clicon_handle h, cvec *nsc, char *xpath,
|
||||||
|
uint32_t offset, uint32_t limit,
|
||||||
|
cxobj *xtop);
|
||||||
|
|
||||||
/* Transaction-data type
|
/* Transaction-data type
|
||||||
* @see clixon_backend_transaction.h for full transaction API
|
* @see clixon_backend_transaction.h for full transaction API
|
||||||
*/
|
*/
|
||||||
|
|
@ -277,6 +282,7 @@ struct clixon_plugin_api{
|
||||||
plgdaemon_t *cb_daemon; /* Plugin daemonized (always called) */
|
plgdaemon_t *cb_daemon; /* Plugin daemonized (always called) */
|
||||||
plgreset_t *cb_reset; /* Reset system status */
|
plgreset_t *cb_reset; /* Reset system status */
|
||||||
plgstatedata_t *cb_statedata; /* Get state data from plugin (backend only) */
|
plgstatedata_t *cb_statedata; /* Get state data from plugin (backend only) */
|
||||||
|
plgstatedata2_t *cb_statedata2; /* Get state data from plugin (backend only) */
|
||||||
trans_cb_t *cb_trans_begin; /* Transaction start */
|
trans_cb_t *cb_trans_begin; /* Transaction start */
|
||||||
trans_cb_t *cb_trans_validate; /* Transaction validation */
|
trans_cb_t *cb_trans_validate; /* Transaction validation */
|
||||||
trans_cb_t *cb_trans_complete; /* Transaction validation complete */
|
trans_cb_t *cb_trans_complete; /* Transaction validation complete */
|
||||||
|
|
@ -298,6 +304,7 @@ struct clixon_plugin_api{
|
||||||
#define ca_daemon u.cau_backend.cb_daemon
|
#define ca_daemon u.cau_backend.cb_daemon
|
||||||
#define ca_reset u.cau_backend.cb_reset
|
#define ca_reset u.cau_backend.cb_reset
|
||||||
#define ca_statedata u.cau_backend.cb_statedata
|
#define ca_statedata u.cau_backend.cb_statedata
|
||||||
|
#define ca_statedata2 u.cau_backend.cb_statedata2
|
||||||
#define ca_trans_begin u.cau_backend.cb_trans_begin
|
#define ca_trans_begin u.cau_backend.cb_trans_begin
|
||||||
#define ca_trans_validate u.cau_backend.cb_trans_validate
|
#define ca_trans_validate u.cau_backend.cb_trans_validate
|
||||||
#define ca_trans_complete u.cau_backend.cb_trans_complete
|
#define ca_trans_complete u.cau_backend.cb_trans_complete
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ fexample=$dir/example-social.yang
|
||||||
: ${validatexml:=false}
|
: ${validatexml:=false}
|
||||||
|
|
||||||
# Number of audit-log entries
|
# Number of audit-log entries
|
||||||
|
# Note mem.sh sets it
|
||||||
#: ${perfnr:=20000}
|
#: ${perfnr:=20000}
|
||||||
: ${perfnr:=200}
|
: ${perfnr:=200}
|
||||||
|
|
||||||
|
|
@ -151,8 +152,6 @@ wait_backend
|
||||||
# XXX How to run without using a terminal?
|
# XXX How to run without using a terminal?
|
||||||
new "cli show"
|
new "cli show"
|
||||||
$clixon_cli -f $cfg -l o -1 show pagination xpath /es:members/es:member[es:member-id=\'bob\']/es:favorites/es:uint64-numbers cli
|
$clixon_cli -f $cfg -l o -1 show pagination xpath /es:members/es:member[es:member-id=\'bob\']/es:favorites/es:uint64-numbers cli
|
||||||
#expectpart "$(echo "show pagination xpath /es:members/es:member[es:member-id=\'bob\']/es:favorites/es:uint64-numbers cli" | $clixon_cli -f $cfg -l o)" 0 foo
|
|
||||||
#expectpart "$($clixon_cli -1 -f $cfg -l o show pagination xpath /es:members/es:member[es:member-id=\'bob\']/es:favorites/es:uint64-numbers cli)" 0 foo
|
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,9 @@ function testlimit()
|
||||||
|
|
||||||
for li in $list; do
|
for li in $list; do
|
||||||
if [ $i = 0 ]; then
|
if [ $i = 0 ]; then
|
||||||
if [ $limit == 0 ]; then
|
# Note: if REMAINING is enabled:
|
||||||
|
# if [ $limit == 0 ]; then
|
||||||
|
if true; then
|
||||||
el="<uint8-numbers>$li</uint8-numbers>"
|
el="<uint8-numbers>$li</uint8-numbers>"
|
||||||
el2="<uint8-numbers xmlns=\"http://example.com/ns/example-social\">$li</uint8-numbers>"
|
el2="<uint8-numbers xmlns=\"http://example.com/ns/example-social\">$li</uint8-numbers>"
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@
|
||||||
# Magic line must be first in script (see README.md)
|
# Magic line must be first in script (see README.md)
|
||||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
|
echo "...skipped: Must run interactvely"
|
||||||
|
if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
|
|
||||||
cfg=$dir/conf.xml
|
cfg=$dir/conf.xml
|
||||||
|
|
@ -127,8 +130,9 @@ fi
|
||||||
new "wait backend"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
|
# XXX How to run without using a terminal?
|
||||||
new "cli show"
|
new "cli show"
|
||||||
expectpart "$($clixon_cli -1 -f $cfg -l o show pagination xpath /es:audit-logs/es:audit-log cli)" 255 "Get configuration: protocol operation-not-supported List pagination for state lists is not yet implemented"
|
$clixon_cli -1 -f $cfg -l o show pagination xpath /es:audit-logs/es:audit-log cli
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue