Merge branch dispatcher and broke out pagination callbacks to use it
* Merge branch 'dcornejo-master' * Broke out pagination callback API from state data callbacks * New pagination callback API uses new dispatcher from netgate, thanks @dcornejo * Register callback with: `clixon_pagination_cb_register()` * Use accessor functions `pagination_offset()`, `pagination_limit()`, etc * Reverted state data callback API to pre-5.3 (see C/CLI API changes below)
This commit is contained in:
commit
ce06f25be7
19 changed files with 996 additions and 123 deletions
|
|
@ -212,7 +212,6 @@ get_client_statedata(clicon_handle h,
|
|||
/* Add default global state */
|
||||
if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0)
|
||||
goto done;
|
||||
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277")){
|
||||
if ((ymod = yang_find_module_by_name(yspec, "clixon-rfc5277")) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "yang module clixon-rfc5277 not found");
|
||||
|
|
@ -258,7 +257,7 @@ get_client_statedata(clicon_handle h,
|
|||
goto fail;
|
||||
}
|
||||
/* Use plugin state callbacks */
|
||||
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, PAGINATION_NONE, 0, 0, NULL, xret)) < 0)
|
||||
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
|
|
@ -490,7 +489,7 @@ get_list_pagination(clicon_handle h,
|
|||
}
|
||||
if (yang_keyword_get(ylist) != Y_LIST &&
|
||||
yang_keyword_get(ylist) != Y_LEAF_LIST){
|
||||
if (netconf_invalid_value(cbret, "application", "list-pagination is enabled but target is not leaf or leaf-list") < 0)
|
||||
if (netconf_invalid_value(cbret, "application", "list-pagination is enabled but target is not list or leaf-list") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
|
|
@ -539,35 +538,37 @@ get_list_pagination(clicon_handle h,
|
|||
/* where */
|
||||
if (ret && (x = xml_find_type(xe, NULL, "where", CX_ELMNT)) != NULL)
|
||||
where = xml_body(x);
|
||||
/* Build a "predicate" cbuf
|
||||
* This solution uses xpath predicates to translate "limit" and "offset" to
|
||||
* relational operators <>.
|
||||
*/
|
||||
if ((cbpath = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
/* This uses xpath. Maybe limit should use parameters */
|
||||
if (xpath)
|
||||
cprintf(cbpath, "%s", xpath);
|
||||
else
|
||||
cprintf(cbpath, "/");
|
||||
if (where)
|
||||
cprintf(cbpath, "[%s]", where);
|
||||
if (offset){
|
||||
cprintf(cbpath, "[%u <= position()", offset);
|
||||
if (limit)
|
||||
cprintf(cbpath, " and position() < %u", limit+offset);
|
||||
cprintf(cbpath, "]");
|
||||
}
|
||||
else if (limit)
|
||||
cprintf(cbpath, "[position() < %u]", limit);
|
||||
/* Append predicate to original xpath and replace it */
|
||||
xpath2 = cbuf_get(cbpath);
|
||||
|
||||
/* Read config */
|
||||
switch (content){
|
||||
case CONTENT_CONFIG: /* config data only */
|
||||
case CONTENT_ALL: /* both config and state */
|
||||
/* Build a "predicate" cbuf
|
||||
* This solution uses xpath predicates to translate "limit" and "offset" to
|
||||
* relational operators <>.
|
||||
*/
|
||||
if ((cbpath = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
/* This uses xpath. Maybe limit should use parameters */
|
||||
if (xpath)
|
||||
cprintf(cbpath, "%s", xpath);
|
||||
else
|
||||
cprintf(cbpath, "/");
|
||||
if (where)
|
||||
cprintf(cbpath, "[%s]", where);
|
||||
if (offset){
|
||||
cprintf(cbpath, "[%u <= position()", offset);
|
||||
if (limit)
|
||||
cprintf(cbpath, " and position() < %u", limit+offset);
|
||||
cprintf(cbpath, "]");
|
||||
}
|
||||
else if (limit)
|
||||
cprintf(cbpath, "[position() < %u]", limit);
|
||||
|
||||
/* Append predicate to original xpath and replace it */
|
||||
xpath2 = cbuf_get(cbpath);
|
||||
/* specific xpath */
|
||||
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath2?xpath2:"/", 1, &xret, NULL, NULL) < 0) {
|
||||
if ((cbmsg = cbuf_new()) == NULL){
|
||||
|
|
@ -603,11 +604,12 @@ get_list_pagination(clicon_handle h,
|
|||
pagmode = PAGINATION_LOCK;
|
||||
else
|
||||
pagmode = PAGINATION_STATELESS;
|
||||
/* Use plugin state callbacks */
|
||||
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath,
|
||||
pagmode,
|
||||
offset, limit, &remaining, &xret)) < 0)
|
||||
if ((ret = clixon_pagination_cb_call(h, xpath, pagmode,
|
||||
offset, limit, &remaining,
|
||||
xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto ok;
|
||||
}
|
||||
/* Help function to filter out anything that is outside of xpath */
|
||||
if (filter_xpath_again(h, yspec, xret, xpath, nsc, &x1) < 0)
|
||||
|
|
|
|||
|
|
@ -253,10 +253,6 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
|||
clicon_handle h,
|
||||
cvec *nsc,
|
||||
char *xpath,
|
||||
pagination_mode_t pagmode,
|
||||
uint32_t offset,
|
||||
uint32_t limit,
|
||||
uint32_t *remaining,
|
||||
cxobj **xp)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -267,7 +263,7 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
|||
if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
|
||||
if ((x = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
if (fn(h, nsc, xpath, pagmode, offset, limit, remaining, x) < 0){
|
||||
if (fn(h, nsc, xpath, 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));
|
||||
|
|
@ -306,10 +302,6 @@ clixon_plugin_statedata_all(clicon_handle h,
|
|||
yang_stmt *yspec,
|
||||
cvec *nsc,
|
||||
char *xpath,
|
||||
pagination_mode_t pagmode,
|
||||
uint32_t offset,
|
||||
uint32_t limit,
|
||||
uint32_t *remaining,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -321,8 +313,7 @@ clixon_plugin_statedata_all(clicon_handle h,
|
|||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||
if ((ret = clixon_plugin_statedata_one(cp, h, nsc, xpath, pagmode,
|
||||
offset, limit, remaining, &x)) < 0)
|
||||
if ((ret = clixon_plugin_statedata_one(cp, h, nsc, xpath, &x)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
if ((cberr = cbuf_new()) == NULL){
|
||||
|
|
@ -455,6 +446,63 @@ clixon_plugin_lockdb_all(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Traverse state data callbacks
|
||||
*
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] xpath Registered XPath using canonical prefixes
|
||||
*/
|
||||
int
|
||||
clixon_pagination_cb_call(clicon_handle h,
|
||||
char *xpath,
|
||||
pagination_mode_t pagmode,
|
||||
uint32_t offset,
|
||||
uint32_t limit,
|
||||
uint32_t *remaining,
|
||||
cxobj *xstate)
|
||||
{
|
||||
int retval = -1;
|
||||
pagination_data_t pd = {pagmode, offset, limit, 0, xstate};
|
||||
dispatcher_entry_t *htable = NULL;
|
||||
|
||||
clicon_ptr_get(h, "pagination-entries", (void**)&htable);
|
||||
if (htable && dispatcher_call_handlers(htable, h, xpath, &pd) < 0)
|
||||
goto done;
|
||||
if (remaining)
|
||||
*remaining = pd.pd_remaining;
|
||||
retval = 1;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Register a state data callback
|
||||
*
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] fn Callback
|
||||
* @param[in] xpath Registered XPath using canonical prefixes
|
||||
* @param[in] arg Domain-specific argument to send to callback
|
||||
*/
|
||||
int
|
||||
clixon_pagination_cb_register(clicon_handle h,
|
||||
handler_function fn,
|
||||
char *xpath,
|
||||
void *arg)
|
||||
{
|
||||
int retval = -1;
|
||||
dispatcher_definition x = {xpath, fn};
|
||||
dispatcher_entry_t *htable = NULL;
|
||||
|
||||
clicon_ptr_get(h, "pagination-entries", (void**)&htable);
|
||||
if (dispatcher_register_handler(&htable, &x) < 0){
|
||||
clicon_err(OE_PLUGIN, errno, "dispatcher");
|
||||
goto done;
|
||||
}
|
||||
if (clicon_ptr_set(h, "pagination-entries", htable) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Create and initialize a validate/commit transaction
|
||||
* @retval td New alloced transaction,
|
||||
* @retval NULL Error
|
||||
|
|
@ -885,4 +933,3 @@ plugin_transaction_abort_all(clicon_handle h,
|
|||
retval = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
* It is up to the validate callbacks to ensure that these changes are OK
|
||||
* It is up to the commit callbacks to enforce these changes in the "state" of
|
||||
* the system.
|
||||
* see also transaction_data in clixon_plugin.h
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t td_id; /* Transaction id */
|
||||
|
|
@ -66,6 +67,21 @@ typedef struct {
|
|||
int td_clen; /* Changed xml vector length */
|
||||
} transaction_data_t;
|
||||
|
||||
/*! Pagination userdata
|
||||
* @param[in] pagmode List pagination mode
|
||||
* @param[in] offset Offset, for list pagination
|
||||
* @param[in] limit Limit, for list pagination
|
||||
* @param[out] remaining Remaining elements (if limit is non-zero)
|
||||
* see also pagination_data in clixon_plugin.h
|
||||
*/
|
||||
typedef struct {
|
||||
pagination_mode_t pd_pagmode; /* Pagination mode, stateless or locked */
|
||||
uint32_t pd_offset; /* Start of pagination interval */
|
||||
uint32_t pd_limit; /* Number of elemenents (limit) */
|
||||
uint32_t pd_remaining; /* If limit, then remaining nr of elements */
|
||||
cxobj *pd_xstate; /* Returned xml state tree */
|
||||
} pagination_data_t;
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
|
|
@ -76,11 +92,14 @@ int clixon_plugin_pre_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,
|
||||
pagination_mode_t pagmode,
|
||||
uint32_t offset, uint32_t limit, uint32_t *remaining,
|
||||
cxobj **xtop);
|
||||
int clixon_plugin_lockdb_all(clicon_handle h, char *db, int lock, int id);
|
||||
|
||||
int clixon_pagination_cb_register(clicon_handle h, handler_function fn, char *path, void *arg);
|
||||
int clixon_pagination_cb_call(clicon_handle h, char *xpath, pagination_mode_t pagmode,
|
||||
uint32_t offset, uint32_t limit, uint32_t *remaining,
|
||||
cxobj *xstate);
|
||||
|
||||
transaction_data_t * transaction_new(void);
|
||||
int transaction_free(transaction_data_t *);
|
||||
|
||||
|
|
|
|||
|
|
@ -284,3 +284,59 @@ transaction_log(clicon_handle h,
|
|||
cbuf_free(cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Get pagination data: mode parameter
|
||||
*
|
||||
* @param[in] pd Pagination userdata
|
||||
* @retval mode Pagination mode, stateless or locked
|
||||
*/
|
||||
pagination_mode_t
|
||||
pagination_pagmode(pagination_data pd)
|
||||
{
|
||||
return ((pagination_data_t *)pd)->pd_pagmode;
|
||||
}
|
||||
|
||||
/*! Get pagination data: offset parameter
|
||||
*
|
||||
* @param[in] pd Pagination userdata
|
||||
* @retval offset Start of pagination interval
|
||||
*/
|
||||
uint32_t
|
||||
pagination_offset(pagination_data pd)
|
||||
{
|
||||
return ((pagination_data_t *)pd)->pd_offset;
|
||||
}
|
||||
|
||||
/*! Get pagination data: limit parameter
|
||||
*
|
||||
* @param[in] pd Pagination userdata
|
||||
* @retval limit Number of elemenents (limit)
|
||||
*/
|
||||
uint32_t
|
||||
pagination_limit(pagination_data pd)
|
||||
{
|
||||
return ((pagination_data_t *)pd)->pd_limit;
|
||||
}
|
||||
|
||||
/*! Set pagination data: remaining nr of elements
|
||||
*
|
||||
* @param[in] pd Pagination userdata
|
||||
* @param[in] remaining If limit, then remaining nr of elements
|
||||
*/
|
||||
int
|
||||
pagination_remaining_set(pagination_data pd,
|
||||
uint32_t remaining)
|
||||
{
|
||||
return ((pagination_data_t *)pd)->pd_remaining = remaining;
|
||||
}
|
||||
|
||||
/*! Get pagination data: Returned xml state tree
|
||||
*
|
||||
* @param[in] pd Pagination userdata
|
||||
* @retval xstate Returned xml state tree
|
||||
*/
|
||||
cxobj*
|
||||
pagination_xstate(pagination_data pd)
|
||||
{
|
||||
return ((pagination_data_t *)pd)->pd_xstate;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@
|
|||
* Prototypes
|
||||
*/
|
||||
/* Transaction callback data accessors for client plugins
|
||||
* (defined in config_dbdep.c)
|
||||
* @see transaction_data_t internal structure
|
||||
*/
|
||||
uint64_t transaction_id(transaction_data td);
|
||||
|
|
@ -65,4 +64,13 @@ size_t transaction_clen(transaction_data td);
|
|||
int transaction_print(FILE *f, transaction_data th);
|
||||
int transaction_log(clicon_handle h, transaction_data th, int level, const char *id);
|
||||
|
||||
/* Pagination callbacks
|
||||
* @see pagination_data_t internal structure
|
||||
*/
|
||||
pagination_mode_t pagination_pagmode(pagination_data pd);
|
||||
uint32_t pagination_offset(pagination_data pd);
|
||||
uint32_t pagination_limit(pagination_data pd);
|
||||
int pagination_remaining_set(pagination_data pd, uint32_t remaining);
|
||||
cxobj *pagination_xstate(pagination_data pd);
|
||||
|
||||
#endif /* _CLIXON_BACKEND_TRANSACTION_H_ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue