xmldb api cleanup
This commit is contained in:
parent
caccfe8f2d
commit
cf3cf351c8
16 changed files with 177 additions and 361 deletions
58
lib/src/clixon_qdb.h
Normal file
58
lib/src/clixon_qdb.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
CLIXON is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLIXON is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with CLIXON; see the file LICENSE. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CLIXON_QDB_H_
|
||||
#define _CLIXON_QDB_H_
|
||||
|
||||
|
||||
/*
|
||||
* Low level API
|
||||
*/
|
||||
|
||||
struct db_pair {
|
||||
char *dp_key; /* database key */
|
||||
char *dp_matched; /* Matched component of key */
|
||||
char *dp_val; /* pointer to vector of lvalues */
|
||||
int dp_vlen; /* length of vector of lvalues */
|
||||
};
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int db_init(char *file);
|
||||
|
||||
int db_set(char *file, char *key, void *data, size_t datalen);
|
||||
|
||||
int db_get(char *file, char *key, void *data, size_t *datalen);
|
||||
|
||||
int db_get_alloc(char *file, char *key, void **data, size_t *datalen);
|
||||
|
||||
int db_del(char *file, char *key);
|
||||
|
||||
int db_exists(char *file, char *key);
|
||||
|
||||
int db_regexp(char *file, char *regexp, const char *label,
|
||||
struct db_pair **pairs, int noval);
|
||||
|
||||
char *db_sanitize(char *rx, const char *label);
|
||||
|
||||
#endif /* _CLIXON_QDB_H_ */
|
||||
|
|
@ -165,6 +165,7 @@ yang2xmlkeyfmt(yang_stmt *ys, char **xkfmt)
|
|||
}
|
||||
|
||||
/*! Transform an xml key format and a vector of values to an XML key
|
||||
* Used for actual key, eg in clicon_rpc_change(), xmldb_put_xkey()
|
||||
* Example:
|
||||
* xmlkeyfmt: /aaa/%s
|
||||
* cvv: key=17
|
||||
|
|
@ -188,6 +189,7 @@ xmlkeyfmt2key(char *xkfmt,
|
|||
char *str;
|
||||
|
||||
/* Sanity check */
|
||||
#if 1
|
||||
j = 0; /* Count % */
|
||||
for (i=0; i<strlen(xkfmt); i++)
|
||||
if (xkfmt[i] == '%')
|
||||
|
|
@ -200,6 +202,7 @@ xmlkeyfmt2key(char *xkfmt,
|
|||
cv_string_get(cvec_i(cvv, 0)));
|
||||
// goto done;
|
||||
}
|
||||
#endif
|
||||
if ((cb = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
j = 1; /* j==0 is cli string */
|
||||
|
|
@ -233,20 +236,33 @@ xmlkeyfmt2key(char *xkfmt,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Transform an xml key format and a vector of values to an XML key
|
||||
* Used to input xmldb_get() or xmldb_get_vec
|
||||
* Add .* in last %s position.
|
||||
* Example:
|
||||
* xmlkeyfmt: /interface/%s/address/%s
|
||||
* cvv: name=eth0
|
||||
* xmlkey: /interface/[name=eth0]/address
|
||||
* @param[in] xkfmt XML key format
|
||||
* @param[in] cvv cligen variable vector, one for every wildchar in xkfmt
|
||||
* @param[out] xk XPATH
|
||||
*/
|
||||
int
|
||||
xmlkeyfmt2key2(char *xkfmt,
|
||||
cvec *cvv,
|
||||
char **xk)
|
||||
xmlkeyfmt2xpath(char *xkfmt,
|
||||
cvec *cvv,
|
||||
char **xk)
|
||||
{
|
||||
int retval = -1;
|
||||
char c;
|
||||
int esc=0;
|
||||
cbuf *cb = NULL;
|
||||
int i;
|
||||
int j;
|
||||
char *str;
|
||||
int retval = -1;
|
||||
char c;
|
||||
int esc=0;
|
||||
cbuf *cb = NULL;
|
||||
int i;
|
||||
int j;
|
||||
char *str;
|
||||
cg_var *cv;
|
||||
int skip = 0;
|
||||
|
||||
/* Sanity check */
|
||||
/* Sanity check: count '%' */
|
||||
#if 1
|
||||
j = 0; /* Count % */
|
||||
for (i=0; i<strlen(xkfmt); i++)
|
||||
|
|
@ -263,7 +279,6 @@ xmlkeyfmt2key2(char *xkfmt,
|
|||
#endif
|
||||
if ((cb = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
cprintf(cb, "^");
|
||||
j = 1; /* j==0 is cli string */
|
||||
for (i=0; i<strlen(xkfmt); i++){
|
||||
c = xkfmt[i];
|
||||
|
|
@ -271,27 +286,40 @@ xmlkeyfmt2key2(char *xkfmt,
|
|||
esc = 0;
|
||||
if (c!='s')
|
||||
continue;
|
||||
if (j == cvec_len(cvv)){
|
||||
if ((str = strdup(".*")) == NULL){
|
||||
if (j == cvec_len(cvv)){ /* last element */
|
||||
skip++;
|
||||
}
|
||||
else{
|
||||
/* XXX: remove preceding '/' :
|
||||
a/[x=y] -> a[x=y] */
|
||||
if ((str = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((str = cv2str_dup(cvec_i(cvv, j++))) == NULL){
|
||||
str[strlen(str)-1] = '\0';
|
||||
cbuf_reset(cb);
|
||||
cprintf(cb, "%s", str);
|
||||
free(str);
|
||||
|
||||
cv = cvec_i(cvv, j++);
|
||||
if ((str = cv2str_dup(cv)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "%s", str);
|
||||
free(str);
|
||||
cprintf(cb, "[%s=%s]", cv_name_get(cv), str);
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
else
|
||||
else /* regular char */
|
||||
if (c == '%')
|
||||
esc++;
|
||||
else
|
||||
cprintf(cb, "%c", c);
|
||||
else{
|
||||
if (skip)
|
||||
skip=0;
|
||||
else
|
||||
cprintf(cb, "%c", c);
|
||||
}
|
||||
}
|
||||
cprintf(cb, "$");
|
||||
if ((*xk = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
|
|
@ -435,6 +463,7 @@ xml_tree_prune_unmarked(cxobj *xt,
|
|||
/*!
|
||||
* @param[in] xkey xmlkey
|
||||
* @param[out] xt XML tree as result
|
||||
* XXX cannot handle top-level list
|
||||
*/
|
||||
static int
|
||||
get(char *dbname,
|
||||
|
|
@ -637,7 +666,6 @@ xml_default(cxobj *x,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Get content of database using xpath. return a single tree
|
||||
* The function returns a minimal tree that includes all sub-trees that match
|
||||
* xpath.
|
||||
|
|
@ -691,7 +719,9 @@ xmldb_get(char *dbname,
|
|||
* 2. only read necessary parts,...?
|
||||
*/
|
||||
if (xpath){
|
||||
if ((xvec = xpath_vec(xt, xpath, &len)) != NULL){
|
||||
if (xpath_vec(xt, xpath, &xvec, &len) < 0)
|
||||
goto done;
|
||||
if (xvec != NULL){
|
||||
/* Prune everything except nodes in xvec and how to get there
|
||||
* Alt: Create a new subtree from xt with that property,...(no)
|
||||
*/
|
||||
|
|
@ -737,7 +767,7 @@ xmldb_get(char *dbname,
|
|||
* cxobj **xvec;
|
||||
* size_t xlen;
|
||||
* yang_spec *yspec = clicon_dbspec_yang(h);
|
||||
* if (xmldb_get_vec(dbname, "/interfaces/interface[name="eth*"]", yspec,
|
||||
* if (xmldb_get_vec(dbname, "/interfaces/interface[name="eth"]", yspec,
|
||||
* &xt, &xvec, &xlen) < 0)
|
||||
* err;
|
||||
* for (i=0; i<xlen; i++){
|
||||
|
|
@ -781,7 +811,7 @@ xmldb_get_vec(char *dbname,
|
|||
xt) < 0)
|
||||
goto done;
|
||||
}
|
||||
if ((*xvec = xpath_vec(xt, xpath, xlen)) == NULL)
|
||||
if (xpath_vec(xt, xpath, xvec, xlen) < 0)
|
||||
goto done;
|
||||
if (xml_apply(xt, CX_ELMNT, xml_default, NULL) < 0)
|
||||
goto done;
|
||||
|
|
@ -797,6 +827,8 @@ xmldb_get_vec(char *dbname,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! Get value of the "operation" attribute and change op if given
|
||||
* @param[in] xn XML node
|
||||
* @param[out] op "operation" attribute may change operation
|
||||
|
|
@ -1126,7 +1158,6 @@ xmldb_put_xkey(char *dbname,
|
|||
if (db_del(dbname, pairs[i].dp_key) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -1143,6 +1174,41 @@ xmldb_put_xkey(char *dbname,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Raw dump of database, just keys and values, no xml interpretation
|
||||
* param[in] f File
|
||||
* param[in] dbname Name of database
|
||||
* param[in] rxkey Key regexp, eg "^.*$"
|
||||
*/
|
||||
int
|
||||
xmldb_dump(FILE *f,
|
||||
char *dbname,
|
||||
char *rxkey)
|
||||
{
|
||||
int retval = 0;
|
||||
int npairs;
|
||||
struct db_pair *pairs;
|
||||
|
||||
/* Default is match all */
|
||||
if (rxkey == NULL)
|
||||
rxkey = "^.*$";
|
||||
|
||||
/* Get all keys/values for vector */
|
||||
if ((npairs = db_regexp(dbname, rxkey, __FUNCTION__, &pairs, 0)) < 0)
|
||||
return -1;
|
||||
|
||||
for (npairs--; npairs >= 0; npairs--)
|
||||
fprintf(f, "%s %s\n", pairs[npairs].dp_key,
|
||||
pairs[npairs].dp_val?pairs[npairs].dp_val:"");
|
||||
unchunk_group(__FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
xmldb_init(char *file)
|
||||
{
|
||||
return db_init(file);
|
||||
}
|
||||
|
||||
#if 1 /* Test program */
|
||||
/*
|
||||
* Turn this on to get an xpath test program
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@
|
|||
#include "clixon_yang.h"
|
||||
#include "clixon_yang_type.h"
|
||||
#include "clixon_options.h"
|
||||
#include "clixon_qdb.h"
|
||||
#include "clixon_xml.h"
|
||||
#include "clixon_xsl.h"
|
||||
#include "clixon_log.h"
|
||||
|
|
|
|||
|
|
@ -149,8 +149,9 @@ xpath_print(FILE *f, struct xpath_element *xplist)
|
|||
struct xpath_element *xe;
|
||||
|
||||
for (xe=xplist; xe; xe=xe->xe_next)
|
||||
fprintf(f, "\t:%s %s\n", axis_type2str(xe->xe_type),
|
||||
xe->xe_str?xe->xe_str:"");
|
||||
fprintf(f, "\t:%s %s %s\n", axis_type2str(xe->xe_type),
|
||||
xe->xe_str?xe->xe_str:"",
|
||||
xe->xe_predicate?xe->xe_predicate:"");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +335,7 @@ recursive_find(cxobj *xn,
|
|||
}
|
||||
|
||||
static int
|
||||
xpath_expr(char *e,
|
||||
xpath_expr(char *e00,
|
||||
uint16_t flags,
|
||||
cxobj ***vec0,
|
||||
size_t *vec0len)
|
||||
|
|
@ -350,7 +351,14 @@ xpath_expr(char *e,
|
|||
int oplen;
|
||||
char *tag;
|
||||
char *val;
|
||||
char *e0;
|
||||
char *e;
|
||||
|
||||
if ((e0 = strdup(e00)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
e = e0;
|
||||
if (*e == '@'){ /* @ attribute */
|
||||
e++;
|
||||
e_v=e;
|
||||
|
|
@ -418,6 +426,8 @@ xpath_expr(char *e,
|
|||
*vec0len = veclen;
|
||||
retval = 0;
|
||||
done:
|
||||
if (e0)
|
||||
free(e0);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +613,7 @@ xpath_exec(char *xpath,
|
|||
goto done;
|
||||
if (xpath_parse(xpath, &xplist) < 0)
|
||||
goto done;
|
||||
if (0)
|
||||
if (debug > 1)
|
||||
xpath_print(stderr, xplist);
|
||||
if (xpath_find(xplist, 0, vec1, vec1len, flags, vec2, vec2len) < 0)
|
||||
goto done;
|
||||
|
|
@ -767,9 +777,10 @@ xpath_each(cxobj *cxtop,
|
|||
* See xpath1() on details for subset.
|
||||
* @param[in] cxtop xml-tree where to search
|
||||
* @param[in] xpath string with XPATH syntax
|
||||
* @param[out] vec vector of xml-trees. Vector must be free():d after use
|
||||
* @param[out] xv_len returns length of vector in return value
|
||||
* @retval vec vector of xml-trees. Vector must be free():d after use
|
||||
* @retval NULL NULL on error.
|
||||
* @retval 0 OK
|
||||
* @retval -1 error.
|
||||
*
|
||||
* @code
|
||||
* cxobj **xv;
|
||||
|
|
@ -786,34 +797,30 @@ xpath_each(cxobj *cxtop,
|
|||
* trees need not be.
|
||||
* @see also xpath_first, xpath_each.
|
||||
*/
|
||||
cxobj **
|
||||
xpath_vec(cxobj *cxtop,
|
||||
char *xpath,
|
||||
size_t *veclen)
|
||||
int
|
||||
xpath_vec(cxobj *cxtop,
|
||||
char *xpath,
|
||||
cxobj ***vec,
|
||||
size_t *veclen)
|
||||
{
|
||||
cxobj **vec=NULL;
|
||||
|
||||
*vec = NULL;
|
||||
*veclen = 0;
|
||||
if (xpath_choice(cxtop, xpath, 0, &vec, (size_t*)veclen) < 0)
|
||||
return NULL;
|
||||
return vec;
|
||||
return xpath_choice(cxtop, xpath, 0, vec, veclen);
|
||||
}
|
||||
|
||||
/* A restricted xpath that returns a vector of matches (only nodes marked with flags)
|
||||
* @param[in] flags Set of flags that return nodes must match (0 if all)
|
||||
*/
|
||||
cxobj **
|
||||
int
|
||||
xpath_vec_flag(cxobj *cxtop,
|
||||
char *xpath,
|
||||
uint16_t flags,
|
||||
cxobj ***vec,
|
||||
size_t *veclen)
|
||||
{
|
||||
cxobj **vec=NULL;
|
||||
|
||||
*vec=NULL;
|
||||
*veclen = 0;
|
||||
if (xpath_choice(cxtop, xpath, flags, &vec, (size_t*)veclen) < 0)
|
||||
return NULL;
|
||||
return vec;
|
||||
return xpath_choice(cxtop, xpath, flags, vec, veclen);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -852,7 +859,9 @@ main(int argc, char **argv)
|
|||
}
|
||||
printf("\n");
|
||||
|
||||
if ((xv = xpath_vec(x, argv[1], &xlen)) != NULL) {
|
||||
if (xpath_vec(x, argv[1], &xv, &xlen) < 0)
|
||||
goto done;
|
||||
if (xv)
|
||||
for (i=0; i<xlen; i++){
|
||||
xn = xv[i];
|
||||
fprintf(stdout, "[%d]:\n", i);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue