- 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_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,7 +187,7 @@ 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)
@ -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)

View file

@ -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 */
plgstatedata2_t *fn2; /* Plugin statedata fn2, try this first */
cxobj *x = NULL; 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)
@ -294,6 +311,8 @@ clixon_plugin_statedata_all(clicon_handle h,
yang_stmt *yspec, yang_stmt *yspec,
cvec *nsc, cvec *nsc,
char *xpath, char *xpath,
uint32_t offset,
uint32_t limit,
cxobj **xret) cxobj **xret)
{ {
int retval = -1; int retval = -1;
@ -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){

View file

@ -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 *);

View file

@ -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;

View file

@ -365,6 +365,8 @@ 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;
@ -378,6 +380,8 @@ example_statedata(clicon_handle h,
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 */

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"