fixed datastore cache
This commit is contained in:
parent
e169485985
commit
14faf93eec
7 changed files with 173 additions and 173 deletions
|
|
@ -312,64 +312,75 @@ singleconfigroot(cxobj *xt,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Given XML tree x0 with marked nodes, copy marked nodes to new tree x1
|
||||||
|
* Two marks are used: XML_FLAG_MARK and XML_FLAG_CHANGE
|
||||||
|
*
|
||||||
|
* The algorithm works as following:
|
||||||
|
* (1) Copy individual nodes marked with XML_FLAG_CHANGE
|
||||||
|
* until nodes marked with XML_FLAG_MARK are reached, where
|
||||||
|
* (2) the complete subtree of that node is copied.
|
||||||
|
* (3) Special case: key nodes in lists are copied if any node in list is marked
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
xml_copy_marked(cxobj *x0,
|
xml_copy_marked(cxobj *x0,
|
||||||
cxobj *x1,
|
cxobj *x1)
|
||||||
int flag,
|
|
||||||
int test,
|
|
||||||
int *upmark)
|
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int submark;
|
|
||||||
int mark;
|
int mark;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
cxobj *xcopy;
|
cxobj *xcopy;
|
||||||
int iskey;
|
int iskey;
|
||||||
yang_node *yt;
|
yang_stmt *yt;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
assert(x0 && x1);
|
||||||
|
yt = xml_spec(x0); /* can be null */
|
||||||
|
/* Go through children to detect any marked nodes:
|
||||||
|
* (3) Special case: key nodes in lists are copied if any
|
||||||
|
* node in list is marked
|
||||||
|
*/
|
||||||
mark = 0;
|
mark = 0;
|
||||||
yt = xml_spec(x0); /* xan be null */
|
x = NULL;
|
||||||
|
while ((x = xml_child_each(x0, x, CX_ELMNT)) != NULL) {
|
||||||
|
if (xml_flag(x, XML_FLAG_MARK|XML_FLAG_CHANGE)){
|
||||||
|
mark++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
x = NULL;
|
x = NULL;
|
||||||
while ((x = xml_child_each(x0, x, CX_ELMNT)) != NULL) {
|
while ((x = xml_child_each(x0, x, CX_ELMNT)) != NULL) {
|
||||||
name = xml_name(x);
|
name = xml_name(x);
|
||||||
if (xml_flag(x, flag) == test?flag:0){
|
if (xml_flag(x, XML_FLAG_MARK)){
|
||||||
/* Pass test */
|
/* (2) the complete subtree of that node is copied. */
|
||||||
mark++;
|
if ((xcopy = xml_new(name, x1, xml_spec(x))) == NULL)
|
||||||
if (x1){
|
goto done;
|
||||||
|
if (xml_copy(x, xcopy) < 0)
|
||||||
|
goto done;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (xml_flag(x, XML_FLAG_CHANGE)){
|
||||||
|
/* Copy individual nodes marked with XML_FLAG_CHANGE */
|
||||||
|
if ((xcopy = xml_new(name, x1, xml_spec(x))) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (xml_copy_marked(x, xcopy) < 0) /* */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* (3) Special case: key nodes in lists are copied if any
|
||||||
|
* node in list is marked */
|
||||||
|
if (mark && yt && yt->ys_keyword == Y_LIST){
|
||||||
|
/* XXX: I think yang_key_match is suboptimal here */
|
||||||
|
if ((iskey = yang_key_match((yang_node*)yt, name)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (iskey){
|
||||||
if ((xcopy = xml_new(name, x1, xml_spec(x))) == NULL)
|
if ((xcopy = xml_new(name, x1, xml_spec(x))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_copy(x, xcopy) < 0)
|
if (xml_copy(x, xcopy) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
continue; /* mark and stop here */
|
|
||||||
}
|
|
||||||
/* If it is key dont remove it yet (see second round) */
|
|
||||||
if (yt){
|
|
||||||
if ((iskey = yang_key_match(yt, name)) < 0)
|
|
||||||
goto done;
|
|
||||||
if (iskey)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (xml_copy_marked(x, NULL, flag, test, &submark) < 0)
|
|
||||||
goto done;
|
|
||||||
/* if x0 is list and submark anywhere, then key subs are also marked
|
|
||||||
*/
|
|
||||||
if (submark){
|
|
||||||
mark++; /* copy */
|
|
||||||
if (x1){
|
|
||||||
if ((xcopy = xml_new(name, x1, xml_spec(x))) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (xml_copy_marked(x, xcopy, flag, test, &submark) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (upmark)
|
|
||||||
*upmark = mark;
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -458,20 +469,29 @@ text_get(xmldb_handle xh,
|
||||||
* otherwise return complete tree.
|
* otherwise return complete tree.
|
||||||
*/
|
*/
|
||||||
if (xvec != NULL)
|
if (xvec != NULL)
|
||||||
for (i=0; i<xlen; i++)
|
for (i=0; i<xlen; i++){
|
||||||
xml_flag_set(xvec[i], XML_FLAG_MARK);
|
xml_flag_set(xvec[i], XML_FLAG_MARK);
|
||||||
/* Write back to datastore cache if first time */
|
if (datastore_cache)
|
||||||
|
xml_apply_ancestor(xvec[i], (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
if (datastore_cache){
|
if (datastore_cache){
|
||||||
|
/* Copy the matching parts of the (relevant) XML tree.
|
||||||
|
* If cache was NULL, also write to datastore cache
|
||||||
|
*/
|
||||||
cxobj *x1;
|
cxobj *x1;
|
||||||
struct db_element de0 = {0,};
|
struct db_element de0 = {0,};
|
||||||
|
|
||||||
if (de != NULL)
|
if (de != NULL)
|
||||||
de0 = *de;
|
de0 = *de;
|
||||||
|
|
||||||
x1 = xml_new(xml_name(xt), NULL, xml_spec(xt));
|
x1 = xml_new(xml_name(xt), NULL, xml_spec(xt));
|
||||||
/* Copy everything that is marked */
|
/* Copy everything that is marked */
|
||||||
if (xml_copy_marked(xt, x1, XML_FLAG_MARK, 1, NULL) < 0)
|
if (xml_copy_marked(xt, x1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_apply(x1, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (de0.de_xml == NULL){
|
if (de0.de_xml == NULL){
|
||||||
de0.de_xml = xt;
|
de0.de_xml = xt;
|
||||||
|
|
@ -501,12 +521,6 @@ text_get(xmldb_handle xh,
|
||||||
/* Order XML children according to YANG */
|
/* Order XML children according to YANG */
|
||||||
if (xml_apply(xt, CX_ELMNT, xml_order, NULL) < 0)
|
if (xml_apply(xt, CX_ELMNT, xml_order, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
#ifdef XXX
|
|
||||||
/// (XML_CHILD_HASH==1)
|
|
||||||
/* Add hash */
|
|
||||||
if (xml_apply0(xt, CX_ELMNT, xml_hash_op, (void*)1) < 0)
|
|
||||||
goto done;
|
|
||||||
#endif
|
|
||||||
if (debug>1)
|
if (debug>1)
|
||||||
clicon_xml2file(stderr, xt, 0, 1);
|
clicon_xml2file(stderr, xt, 0, 1);
|
||||||
*xtop = xt;
|
*xtop = xt;
|
||||||
|
|
@ -572,7 +586,7 @@ text_modify(cxobj *x0,
|
||||||
case OP_REPLACE:
|
case OP_REPLACE:
|
||||||
if (x0==NULL){
|
if (x0==NULL){
|
||||||
// int iamkey=0;
|
// int iamkey=0;
|
||||||
if ((x0 = xml_new(x1name, x0p, y0)) == NULL)
|
if ((x0 = xml_new(x1name, x0p, (yang_stmt*)y0)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
#if 0
|
#if 0
|
||||||
/* If it is key I dont want to mark it */
|
/* If it is key I dont want to mark it */
|
||||||
|
|
@ -601,6 +615,7 @@ text_modify(cxobj *x0,
|
||||||
if (xml_child_hash &&
|
if (xml_child_hash &&
|
||||||
xml_apply0(x0, CX_ELMNT, xml_hash_op, (void*)1) < 0)
|
xml_apply0(x0, CX_ELMNT, xml_hash_op, (void*)1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case OP_DELETE:
|
case OP_DELETE:
|
||||||
if (x0==NULL){
|
if (x0==NULL){
|
||||||
|
|
@ -638,17 +653,18 @@ text_modify(cxobj *x0,
|
||||||
if (x0){
|
if (x0){
|
||||||
xml_purge(x0);
|
xml_purge(x0);
|
||||||
}
|
}
|
||||||
if ((x0 = xml_new(x1name, x0p, y0)) == NULL)
|
if ((x0 = xml_new(x1name, x0p, (yang_stmt*)y0)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_copy(x1, x0) < 0)
|
if (xml_copy(x1, x0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (x0==NULL){
|
if (x0==NULL){
|
||||||
if ((x0 = xml_new(x1name, x0p, y0)) == NULL)
|
if ((x0 = xml_new(x1name, x0p, (yang_stmt*)y0)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (op==OP_NONE)
|
if (op==OP_NONE)
|
||||||
xml_flag_set(x0, XML_FLAG_NONE); /* Mark for potential deletion */
|
xml_flag_set(x0, XML_FLAG_NONE); /* Mark for potential deletion */
|
||||||
|
|
||||||
}
|
}
|
||||||
if (xml_child_hash &&
|
if (xml_child_hash &&
|
||||||
xml_apply0(x0, CX_ELMNT, xml_hash_op, (void*)1) < 0)
|
xml_apply0(x0, CX_ELMNT, xml_hash_op, (void*)1) < 0)
|
||||||
|
|
@ -880,10 +896,11 @@ text_put(xmldb_handle xh,
|
||||||
if (xml_apply(x1, CX_ELMNT, xml_spec_populate, yspec) < 0)
|
if (xml_apply(x1, CX_ELMNT, xml_spec_populate, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Add hash */
|
/* Add hash */
|
||||||
|
#if 0
|
||||||
if (xml_child_hash &&
|
if (xml_child_hash &&
|
||||||
xml_apply0(x0, CX_ELMNT, xml_hash_op, (void*)1) < 0)
|
xml_apply0(x0, CX_ELMNT, xml_hash_op, (void*)1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Modify base tree x with modification x1
|
* Modify base tree x with modification x1
|
||||||
*/
|
*/
|
||||||
|
|
@ -1133,7 +1150,17 @@ text_delete(xmldb_handle xh,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
struct text_handle *th = handle(xh);
|
struct text_handle *th = handle(xh);
|
||||||
|
struct db_element *de = NULL;
|
||||||
|
cxobj *xt = NULL;
|
||||||
|
|
||||||
|
if (datastore_cache){
|
||||||
|
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL){
|
||||||
|
if ((xt = de->de_xml) != NULL){
|
||||||
|
xml_free(xt);
|
||||||
|
de->de_xml = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (text_db2file(th, db, &filename) < 0)
|
if (text_db2file(th, db, &filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (unlink(filename) < 0){
|
if (unlink(filename) < 0){
|
||||||
|
|
@ -1162,7 +1189,18 @@ text_create(xmldb_handle xh,
|
||||||
struct text_handle *th = handle(xh);
|
struct text_handle *th = handle(xh);
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
struct db_element *de = NULL;
|
||||||
|
cxobj *xt = NULL;
|
||||||
|
|
||||||
|
if (datastore_cache){ /* XXX This should nt really happen? */
|
||||||
|
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL){
|
||||||
|
if ((xt = de->de_xml) != NULL){
|
||||||
|
assert(xt==NULL); /* XXX */
|
||||||
|
xml_free(xt);
|
||||||
|
de->de_xml = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (text_db2file(th, db, &filename) < 0)
|
if (text_db2file(th, db, &filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((fd = open(filename, O_CREAT|O_WRONLY, S_IRWXU)) == -1) {
|
if ((fd = open(filename, O_CREAT|O_WRONLY, S_IRWXU)) == -1) {
|
||||||
|
|
|
||||||
|
|
@ -113,9 +113,9 @@ cxobj *xml_child_each(cxobj *xparent, cxobj *xprev, enum cxobj_type type);
|
||||||
|
|
||||||
cxobj **xml_childvec_get(cxobj *x);
|
cxobj **xml_childvec_get(cxobj *x);
|
||||||
int xml_childvec_set(cxobj *x, int len);
|
int xml_childvec_set(cxobj *x, int len);
|
||||||
cxobj *xml_new(char *name, cxobj *xn_parent, void *spec);
|
cxobj *xml_new(char *name, cxobj *xn_parent, yang_stmt *spec);
|
||||||
void *xml_spec(cxobj *x);
|
yang_stmt *xml_spec(cxobj *x);
|
||||||
void *xml_spec_set(cxobj *x, void *spec);
|
int xml_spec_set(cxobj *x, yang_stmt *spec);
|
||||||
cxobj *xml_find(cxobj *xn_parent, char *name);
|
cxobj *xml_find(cxobj *xn_parent, char *name);
|
||||||
|
|
||||||
int xml_addsub(cxobj *xp, cxobj *xc);
|
int xml_addsub(cxobj *xp, cxobj *xc);
|
||||||
|
|
|
||||||
|
|
@ -515,7 +515,7 @@ xml_childvec_get(cxobj *x)
|
||||||
cxobj *
|
cxobj *
|
||||||
xml_new(char *name,
|
xml_new(char *name,
|
||||||
cxobj *xp,
|
cxobj *xp,
|
||||||
void *spec)
|
yang_stmt *spec)
|
||||||
{
|
{
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
|
||||||
|
|
@ -531,7 +531,7 @@ xml_new(char *name,
|
||||||
if (xp && xml_child_append(xp, x) < 0)
|
if (xp && xml_child_append(xp, x) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
x->x_spec = spec; /* Can be NULL */
|
x->x_spec = spec; /* Can be NULL */
|
||||||
if (xml_child_hash && xml_hash_add(x) < 0)
|
if (xml_child_hash && spec && xml_hash_add(x) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -539,15 +539,15 @@ xml_new(char *name,
|
||||||
/*! Return yang spec of node.
|
/*! Return yang spec of node.
|
||||||
* Not necessarily set. Either has not been set yet (by xml_spec_set( or anyxml.
|
* Not necessarily set. Either has not been set yet (by xml_spec_set( or anyxml.
|
||||||
*/
|
*/
|
||||||
void *
|
yang_stmt *
|
||||||
xml_spec(cxobj *x)
|
xml_spec(cxobj *x)
|
||||||
{
|
{
|
||||||
return x->x_spec;
|
return x->x_spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
int
|
||||||
xml_spec_set(cxobj *x,
|
xml_spec_set(cxobj *x,
|
||||||
void *spec)
|
yang_stmt *spec)
|
||||||
{
|
{
|
||||||
x->x_spec = spec;
|
x->x_spec = spec;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1459,6 +1459,7 @@ cxvec_append(cxobj *x,
|
||||||
* @note do not delete or move around any children during this function
|
* @note do not delete or move around any children during this function
|
||||||
* @note return value > 0 aborts the traversal
|
* @note return value > 0 aborts the traversal
|
||||||
* @see xml_apply0 including top object
|
* @see xml_apply0 including top object
|
||||||
|
* @see xml_apply_ancestor for marking all parents recursively
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_apply(cxobj *xn,
|
xml_apply(cxobj *xn,
|
||||||
|
|
@ -1847,25 +1848,33 @@ xml_hash_key(cxobj *x,
|
||||||
|
|
||||||
/*! XML hash add. Create hash and add key/value to parent
|
/*! XML hash add. Create hash and add key/value to parent
|
||||||
*
|
*
|
||||||
* @param[in] arg 0: rm entry, 1: add
|
* @param[in] arg add flag. If 1, else if 0 remove.
|
||||||
* Typically called for a whole tree.
|
* Typically called for a whole tree.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_hash_op(cxobj *x,
|
xml_hash_op(cxobj *x,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
|
int add = (intptr_t)arg;
|
||||||
|
#if 1
|
||||||
|
if (add)
|
||||||
|
return xml_hash_add(x);
|
||||||
|
else
|
||||||
|
return xml_hash_rm_entry(x);
|
||||||
|
#else
|
||||||
|
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xp;
|
cxobj *xp;
|
||||||
clicon_hash_t *ph;
|
clicon_hash_t *ph;
|
||||||
yang_stmt *y;
|
yang_stmt *y;
|
||||||
cbuf *key = NULL; /* cligen buffer hash key */
|
cbuf *key = NULL; /* cligen buffer hash key */
|
||||||
int op = (intptr_t)arg;
|
|
||||||
|
|
||||||
if (xml_hash(x)==NULL){
|
if (xml_hash(x)==NULL){
|
||||||
if (op==1)
|
if (add)
|
||||||
xml_hash_init(x);
|
xml_hash_init(x);
|
||||||
}
|
}
|
||||||
else if (op==0)
|
else if (!add)
|
||||||
xml_hash_rm_only(x);
|
xml_hash_rm_only(x);
|
||||||
if ((xp = xml_parent(x)) == NULL)
|
if ((xp = xml_parent(x)) == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -1881,7 +1890,7 @@ xml_hash_op(cxobj *x,
|
||||||
goto done;
|
goto done;
|
||||||
if (cbuf_len(key)){
|
if (cbuf_len(key)){
|
||||||
// fprintf(stderr, "%s add %s = 0x%x\n", __FUNCTION__, cbuf_get(key), (unsigned int)x);
|
// fprintf(stderr, "%s add %s = 0x%x\n", __FUNCTION__, cbuf_get(key), (unsigned int)x);
|
||||||
if (op == 1){
|
if (add){
|
||||||
if (hash_add(ph, cbuf_get(key), &x, sizeof(x)) == NULL)
|
if (hash_add(ph, cbuf_get(key), &x, sizeof(x)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -1895,6 +1904,7 @@ xml_hash_op(cxobj *x,
|
||||||
if (key)
|
if (key)
|
||||||
cbuf_free(key);
|
cbuf_free(key);
|
||||||
return retval;
|
return retval;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! XML hash add. Create hash and add key/value to parent
|
/*! XML hash add. Create hash and add key/value to parent
|
||||||
|
|
@ -1909,6 +1919,7 @@ xml_hash_add(cxobj *x)
|
||||||
cxobj *xp;
|
cxobj *xp;
|
||||||
clicon_hash_t *ph;
|
clicon_hash_t *ph;
|
||||||
yang_stmt *y;
|
yang_stmt *y;
|
||||||
|
yang_stmt *yp;
|
||||||
cbuf *key = NULL; /* cligen buffer hash key */
|
cbuf *key = NULL; /* cligen buffer hash key */
|
||||||
|
|
||||||
if ((ph = xml_hash(x))==NULL){
|
if ((ph = xml_hash(x))==NULL){
|
||||||
|
|
@ -1917,6 +1928,9 @@ xml_hash_add(cxobj *x)
|
||||||
}
|
}
|
||||||
if ((xp = xml_parent(x)) == NULL)
|
if ((xp = xml_parent(x)) == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
yp = xml_spec(xp);
|
||||||
|
if (yp && yp->ys_keyword != Y_LIST)
|
||||||
|
goto ok;
|
||||||
if ((y = xml_spec(x)) == NULL)
|
if ((y = xml_spec(x)) == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
if ((key = cbuf_new()) == NULL){
|
if ((key = cbuf_new()) == NULL){
|
||||||
|
|
|
||||||
|
|
@ -1204,7 +1204,7 @@ xml_tree_prune_flagged_sub(cxobj *xt,
|
||||||
cxobj *xprev;
|
cxobj *xprev;
|
||||||
int iskey;
|
int iskey;
|
||||||
int anykey=0;
|
int anykey=0;
|
||||||
yang_node *yt;
|
yang_stmt *yt;
|
||||||
|
|
||||||
mark = 0;
|
mark = 0;
|
||||||
yt = xml_spec(xt); /* xan be null */
|
yt = xml_spec(xt); /* xan be null */
|
||||||
|
|
@ -1219,7 +1219,7 @@ xml_tree_prune_flagged_sub(cxobj *xt,
|
||||||
}
|
}
|
||||||
/* If it is key dont remove it yet (see second round) */
|
/* If it is key dont remove it yet (see second round) */
|
||||||
if (yt){
|
if (yt){
|
||||||
if ((iskey = yang_key_match(yt, xml_name(x))) < 0)
|
if ((iskey = yang_key_match((yang_node*)yt, xml_name(x))) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (iskey){
|
if (iskey){
|
||||||
anykey++;
|
anykey++;
|
||||||
|
|
@ -1247,7 +1247,7 @@ xml_tree_prune_flagged_sub(cxobj *xt,
|
||||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) {
|
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) {
|
||||||
/* If it is key remove it here */
|
/* If it is key remove it here */
|
||||||
if (yt){
|
if (yt){
|
||||||
if ((iskey = yang_key_match(yt, xml_name(x))) < 0)
|
if ((iskey = yang_key_match((yang_node*)yt, xml_name(x))) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (iskey && xml_purge(x) < 0)
|
if (iskey && xml_purge(x) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1858,7 +1858,7 @@ xml_merge1(cxobj *x0,
|
||||||
if (y0->yn_keyword == Y_LEAF_LIST || y0->yn_keyword == Y_LEAF){
|
if (y0->yn_keyword == Y_LEAF_LIST || y0->yn_keyword == Y_LEAF){
|
||||||
x1bstr = xml_body(x1);
|
x1bstr = xml_body(x1);
|
||||||
if (x0==NULL){
|
if (x0==NULL){
|
||||||
if ((x0 = xml_new(x1name, x0p, y0)) == NULL)
|
if ((x0 = xml_new(x1name, x0p, (yang_stmt*)y0)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (x1bstr){ /* empty type does not have body */
|
if (x1bstr){ /* empty type does not have body */
|
||||||
if ((x0b = xml_new("body", x0, NULL)) == NULL)
|
if ((x0b = xml_new("body", x0, NULL)) == NULL)
|
||||||
|
|
@ -1879,7 +1879,7 @@ xml_merge1(cxobj *x0,
|
||||||
} /* if LEAF|LEAF_LIST */
|
} /* if LEAF|LEAF_LIST */
|
||||||
else { /* eg Y_CONTAINER, Y_LIST */
|
else { /* eg Y_CONTAINER, Y_LIST */
|
||||||
if (x0==NULL){
|
if (x0==NULL){
|
||||||
if ((x0 = xml_new(x1name, x0p, y0)) == NULL)
|
if ((x0 = xml_new(x1name, x0p, (yang_stmt*)y0)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Loop through children of the modification tree */
|
/* Loop through children of the modification tree */
|
||||||
|
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Scaling test
|
|
||||||
|
|
||||||
if [ $# = 0 ]; then
|
|
||||||
number=1000
|
|
||||||
req=10
|
|
||||||
elif [ $# = 1 ]; then
|
|
||||||
number=$1
|
|
||||||
req=10
|
|
||||||
elif [ $# = 2 ]; then
|
|
||||||
number=$1
|
|
||||||
req=$2
|
|
||||||
else
|
|
||||||
echo "Usage: $0 [<number> [<requests>]]"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
rnd=$(( ( RANDOM % $number ) ))
|
|
||||||
|
|
||||||
fyang=/tmp/scaling.yang
|
|
||||||
db=/tmp/text/candidate_db
|
|
||||||
name=text
|
|
||||||
dir=/tmp/text
|
|
||||||
conf="-d candidate -b $dir -p ../datastore/$name/$name.so -y /tmp -m ietf-ip"
|
|
||||||
|
|
||||||
# include err() and new() functions
|
|
||||||
. ./lib.sh
|
|
||||||
clixon_cf=/tmp/scaling-conf.xml
|
|
||||||
|
|
||||||
|
|
||||||
# For memcheck
|
|
||||||
# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf"
|
|
||||||
# clixon_netconf="valgrind --tool=callgrind clixon_netconf
|
|
||||||
clixon_netconf=clixon_netconf
|
|
||||||
|
|
||||||
|
|
||||||
cat <<EOF > $fyang
|
|
||||||
module example{
|
|
||||||
container x {
|
|
||||||
list y {
|
|
||||||
key "a";
|
|
||||||
leaf a {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
leaf b {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
leaf-list c {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat <<EOF > $clixon_cf
|
|
||||||
<config>
|
|
||||||
<CLICON_CONFIGFILE>/tmp/test_yang.xml</CLICON_CONFIGFILE>
|
|
||||||
<CLICON_YANG_DIR>/usr/local/share/routing/yang</CLICON_YANG_DIR>
|
|
||||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
|
||||||
<CLICON_SOCK>/usr/local/var/routing/routing.sock</CLICON_SOCK>
|
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/routing/routing.pidfile</CLICON_BACKEND_PIDFILE>
|
|
||||||
<CLICON_XMLDB_DIR>/usr/local/var/routing</CLICON_XMLDB_DIR>
|
|
||||||
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
|
|
||||||
</config>
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ ! -d $dir ]; then
|
|
||||||
mkdir $dir
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "datastore_client $conf mget $req /x/y[a=$rnd][b=$rnd]"
|
|
||||||
|
|
||||||
new "generate large list config"
|
|
||||||
echo -n "<config><x>" > $db
|
|
||||||
for (( i=0; i<$number; i++ )); do
|
|
||||||
echo -n "<y><a>$i</a><b>$i</b></y>" >> $db
|
|
||||||
done
|
|
||||||
echo "</x></config>" >> $db
|
|
||||||
|
|
||||||
new "datastore_client $name init"
|
|
||||||
expectfn "datastore_client $conf init" ""
|
|
||||||
|
|
||||||
new "datastore $name mget"
|
|
||||||
expectfn "datastore_client $conf mget 1 /x/y[a=$rnd][b=$rnd]" "^<config><x><y><a>$rnd</a><b>$rnd</b></y></x></config>$"
|
|
||||||
|
|
||||||
new "make $req gets"
|
|
||||||
time datastore_client $conf mget $req "/x/y[a=$rnd][b=$rnd]" > /dev/null
|
|
||||||
|
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Scaling test
|
# Scaling test
|
||||||
|
|
||||||
|
number=1000
|
||||||
|
req=100
|
||||||
if [ $# = 0 ]; then
|
if [ $# = 0 ]; then
|
||||||
number=1000
|
number=1000
|
||||||
elif [ $# = 1 ]; then
|
elif [ $# = 1 ]; then
|
||||||
number=$1
|
number=$1
|
||||||
|
elif [ $# = 2 ]; then
|
||||||
|
number=$1
|
||||||
|
req=$2
|
||||||
else
|
else
|
||||||
echo "Usage: $0 [<number>]"
|
echo "Usage: $0 [<number> [<requests>]]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -15,6 +20,7 @@ fconfig=/tmp/config
|
||||||
|
|
||||||
# include err() and new() functions
|
# include err() and new() functions
|
||||||
. ./lib.sh
|
. ./lib.sh
|
||||||
|
clixon_cf=/tmp/scaling-conf.xml
|
||||||
|
|
||||||
# For memcheck
|
# For memcheck
|
||||||
# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf"
|
# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf"
|
||||||
|
|
@ -40,6 +46,19 @@ module ietf-ip{
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF > $clixon_cf
|
||||||
|
<config>
|
||||||
|
<CLICON_CONFIGFILE>$clixon_cf</CLICON_CONFIGFILE>
|
||||||
|
<CLICON_YANG_DIR>$fyang</CLICON_YANG_DIR>
|
||||||
|
<CLICON_YANG_MODULE_MAIN>ietf-ip</CLICON_YANG_MODULE_MAIN>
|
||||||
|
<CLICON_SOCK>/usr/local/var/routing/routing.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/routing/routing.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_XMLDB_DIR>/usr/local/var/routing</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
|
||||||
|
</config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
# kill old backend (if any)
|
# kill old backend (if any)
|
||||||
new "kill old backend"
|
new "kill old backend"
|
||||||
sudo clixon_backend -zf $clixon_cf -y $fyang
|
sudo clixon_backend -zf $clixon_cf -y $fyang
|
||||||
|
|
@ -61,26 +80,44 @@ for (( i=0; i<$number; i++ )); do
|
||||||
done
|
done
|
||||||
echo "</x></config></edit-config></rpc>]]>]]>" >> $fconfig
|
echo "</x></config></edit-config></rpc>]]>]]>" >> $fconfig
|
||||||
|
|
||||||
|
# Just for manual dbg
|
||||||
|
echo "$clixon_netconf -qf $clixon_cf -y $fyang"
|
||||||
|
|
||||||
new "netconf edit large config"
|
new "netconf edit large config"
|
||||||
expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang
|
||||||
|
|
||||||
new "netconf edit large config again"
|
new "netconf edit large config again"
|
||||||
expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang
|
||||||
|
|
||||||
rm $fconfig
|
rm $fconfig
|
||||||
|
|
||||||
new "netconf commit large config"
|
new "netconf commit large config"
|
||||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf add small config"
|
new "netconf add one small config"
|
||||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>x</a><b>y</b></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>x</a><b>y</b></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf add $req small config"
|
||||||
|
time -p for (( i=0; i<$req; i++ )); do
|
||||||
|
rnd=$(( ( RANDOM % $number ) ))
|
||||||
|
echo "<rpc><edit-config><target><candidate/></target><config><x><y><a>$rnd</a><b>$rnd</b></y></x></config></edit-config></rpc>]]>]]>"
|
||||||
|
done | $clixon_netconf -qf $clixon_cf -y $fyang > /dev/null
|
||||||
|
|
||||||
new "netconf commit small config"
|
new "netconf commit small config"
|
||||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf get large config"
|
new "netconf get large config"
|
||||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b>"
|
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b>"
|
||||||
|
|
||||||
|
new "netconf get $req small config"
|
||||||
|
time -p for (( i=0; i<$req; i++ )); do
|
||||||
|
rnd=$(( ( RANDOM % $number ) ))
|
||||||
|
echo "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/y[a=$rnd][b=$rnd]\" /></get-config></rpc>]]>]]>"
|
||||||
|
done | $clixon_netconf -qf $clixon_cf -y $fyang > /dev/null
|
||||||
|
|
||||||
new "generate large leaf-list config"
|
new "generate large leaf-list config"
|
||||||
echo -n "<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><x>" > $fconfig
|
echo -n "<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><x>" > $fconfig
|
||||||
|
|
|
||||||
|
|
@ -128,13 +128,12 @@ expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test.yang" "<rpc><edit-config>
|
||||||
new "netconf set presence and not present"
|
new "netconf set presence and not present"
|
||||||
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test.yang" "<rpc><edit-config><target><candidate/></target><config><x><nopresence/><presence/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test.yang" "<rpc><edit-config><target><candidate/></target><config><x><nopresence/><presence/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf get"
|
new "netconf get presence only"
|
||||||
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test.yang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/*presence\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><presence/></x></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test.yang" '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/x/*presence"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><x><presence/></x></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf discard-changes"
|
new "netconf discard-changes"
|
||||||
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
|
||||||
new "netconf anyxml"
|
new "netconf anyxml"
|
||||||
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test.yang" "<rpc><edit-config><target><candidate/></target><config><x><any><foo><bar a=\"nisse\"/></foo></any></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test.yang" "<rpc><edit-config><target><candidate/></target><config><x><any><foo><bar a=\"nisse\"/></foo></any></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue