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:
Olof hagsand 2021-10-07 09:17:25 +02:00
commit ce06f25be7
19 changed files with 996 additions and 123 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -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_ */