experimental xml hash for better performance
This commit is contained in:
parent
687641e944
commit
7a7bfc48a4
18 changed files with 612 additions and 481 deletions
|
|
@ -587,271 +587,262 @@ cvec2xml_1(cvec *cvv,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Return 1 if value is a body of one of the named children of xt */
|
||||
static int
|
||||
xml_is_body(cxobj *xt,
|
||||
char *name,
|
||||
char *val)
|
||||
{
|
||||
cxobj *x;
|
||||
char *bx;
|
||||
|
||||
x = NULL;
|
||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) {
|
||||
if (strcmp(name, xml_name(x)))
|
||||
continue;
|
||||
if ((bx = xml_body(x)) == NULL)
|
||||
continue;
|
||||
if (strcmp(xml_body(x), val) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Recursive help function to compute differences between two xml trees
|
||||
* @see dbdiff_vector.
|
||||
*/
|
||||
static int
|
||||
xml_diff1(yang_stmt *ys,
|
||||
cxobj *xt1,
|
||||
cxobj *xt2,
|
||||
cxobj ***first,
|
||||
size_t *firstlen,
|
||||
cxobj ***second,
|
||||
size_t *secondlen,
|
||||
cxobj ***changed1,
|
||||
cxobj ***changed2,
|
||||
size_t *changedlen)
|
||||
/*! Given child tree x1c, find matching child in base tree x0
|
||||
* param[in] x0 Base tree node
|
||||
* param[in] x1c Modification tree child
|
||||
* param[in] yc Yang spec of tree child
|
||||
* param[out] x0cp Matching base tree child (if any)
|
||||
* @note XXX: room for optimization? on 1K calls we have 1M body calls and
|
||||
500K xml_child_each/cvec_each calls.
|
||||
The outer loop is large for large lists
|
||||
The inner loop is small
|
||||
Major time in xml_find_body()
|
||||
Can one do a binary search in the x0 list?
|
||||
*/
|
||||
int
|
||||
match_base_child(cxobj *x0,
|
||||
cxobj *x1c,
|
||||
cxobj **x0cp,
|
||||
yang_stmt *yc)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x1 = NULL;
|
||||
cxobj *x2 = NULL;
|
||||
yang_stmt *y;
|
||||
yang_stmt *ykey;
|
||||
char *name;
|
||||
cg_var *cvi;
|
||||
char *x1cname;
|
||||
cxobj *x0c = NULL; /* x0 child */
|
||||
cvec *cvk = NULL; /* vector of index keys */
|
||||
cg_var *cvi;
|
||||
char *b0;
|
||||
char *b1;
|
||||
yang_stmt *ykey;
|
||||
char *keyname;
|
||||
int equal;
|
||||
char *body1;
|
||||
char *body2;
|
||||
char **b1vec = NULL;
|
||||
int i;
|
||||
#if (XML_CHILD_HASH==1)
|
||||
cxobj **p;
|
||||
cbuf *key = NULL; /* cligen buffer hash key */
|
||||
size_t vlen;
|
||||
|
||||
clicon_debug(2, "%s: %s", __FUNCTION__, ys->ys_argument?ys->ys_argument:"yspec");
|
||||
/* Check nodes present in xt1 and xt2 + nodes only in xt1
|
||||
* Loop over xt1
|
||||
*/
|
||||
x1 = NULL;
|
||||
while ((x1 = xml_child_each(xt1, x1, CX_ELMNT)) != NULL){
|
||||
name = xml_name(x1);
|
||||
if (ys->ys_keyword == Y_SPEC)
|
||||
y = yang_find_topnode((yang_spec*)ys, name, 0);
|
||||
else
|
||||
y = yang_find_datanode((yang_node*)ys, name);
|
||||
if (y == NULL){
|
||||
clicon_err(OE_UNIX, errno, "No yang node found: %s", name);
|
||||
*x0cp = NULL; /* return value */
|
||||
if (xml_hash(x0) == NULL)
|
||||
goto nohash;
|
||||
if ((key = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done1;
|
||||
}
|
||||
if (xml_hash_key(x1c, yc, key) < 0)
|
||||
goto done;
|
||||
x0c = NULL;
|
||||
if (cbuf_len(key))
|
||||
if ((p = hash_value(xml_hash(x0), cbuf_get(key), &vlen)) != NULL){
|
||||
assert(vlen == sizeof(x0c));
|
||||
x0c = *p;
|
||||
}
|
||||
// fprintf(stderr, "%s get %s = 0x%x\n", __FUNCTION__, cbuf_get(key), (unsigned int)x0c);
|
||||
*x0cp = x0c;
|
||||
retval = 0;
|
||||
done1:
|
||||
if (key)
|
||||
cbuf_free(key);
|
||||
return retval;
|
||||
nohash:
|
||||
#endif /* XML_CHILD_HASH */
|
||||
*x0cp = NULL; /* return value */
|
||||
x1cname = xml_name(x1c);
|
||||
switch (yc->ys_keyword){
|
||||
case Y_CONTAINER: /* Equal regardless */
|
||||
case Y_LEAF: /* Equal regardless */
|
||||
x0c = xml_find(x0, x1cname);
|
||||
break;
|
||||
case Y_LEAF_LIST: /* Match with name and value */
|
||||
if ((b1 = xml_body(x1c)) == NULL)
|
||||
goto ok;
|
||||
x0c = xml_find_body_obj(x0, x1cname, b1);
|
||||
break;
|
||||
case Y_LIST: /* Match with key values */
|
||||
if ((ykey = yang_find((yang_node*)yc, Y_KEY, NULL)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key",
|
||||
__FUNCTION__, yc->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
switch (y->ys_keyword){
|
||||
case Y_LIST:
|
||||
if ((ykey = yang_find((yang_node*)y, Y_KEY, NULL)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key",
|
||||
__FUNCTION__, y->ys_argument);
|
||||
/* The value is a list of keys: <key>[ <key>]* */
|
||||
if ((cvk = yang_arg2cvec(ykey, " ")) == NULL)
|
||||
goto done;
|
||||
cvi = NULL; i = 0;
|
||||
while ((cvi = cvec_each(cvk, cvi)) != NULL)
|
||||
i++;
|
||||
if ((b1vec = calloc(i, sizeof(b1))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "calloc");
|
||||
goto done;
|
||||
}
|
||||
cvi = NULL; i = 0;
|
||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||
keyname = cv_string_get(cvi);
|
||||
if ((b1 = xml_find_body(x1c, keyname)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "key %s not found", keyname);
|
||||
goto done;
|
||||
}
|
||||
/* The value is a list of keys: <key>[ <key>]* */
|
||||
if ((cvk = yang_arg2cvec(ykey, " ")) == NULL)
|
||||
goto done;
|
||||
/* Iterate over xt2 tree to (1) find a child that matches name
|
||||
(2) that have keys that matches */
|
||||
b1vec[i++] = b1;
|
||||
}
|
||||
/* Iterate over x0 tree to (1) find a child that matches name
|
||||
(2) that have keys that matches */
|
||||
x0c = NULL;
|
||||
while ((x0c = xml_child_each(x0, x0c, CX_ELMNT)) != NULL){
|
||||
equal = 0;
|
||||
x2 = NULL;
|
||||
while ((x2 = xml_child_each(xt2, x2, CX_ELMNT)) != NULL){
|
||||
if (strcmp(xml_name(x2), name))
|
||||
continue;
|
||||
cvi = NULL;
|
||||
equal = 0;
|
||||
/* (2) Match keys between x1 and x2 */
|
||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||
keyname = cv_string_get(cvi);
|
||||
if ((body1 = xml_find_body(x1, keyname)) == NULL)
|
||||
continue; /* may be error */
|
||||
if ((body2 = xml_find_body(x2, keyname)) == NULL)
|
||||
continue; /* may be error */
|
||||
if (strcmp(body1, body2)==0)
|
||||
equal=1;
|
||||
else{
|
||||
equal=0; /* stop as soon as inequal key found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (equal) /* found x1 and x2 equal, otherwise look
|
||||
for other x2 */
|
||||
break;
|
||||
}
|
||||
if (cvk){
|
||||
cvec_free(cvk);
|
||||
cvk = NULL;
|
||||
}
|
||||
if (equal){
|
||||
if (xml_diff1(y, x1, x2,
|
||||
first, firstlen,
|
||||
second, secondlen,
|
||||
changed1, changed2, changedlen)< 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (cxvec_append(x1, first, firstlen) < 0)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
case Y_CONTAINER:
|
||||
/* Equal regardless */
|
||||
if ((x2 = xml_find(xt2, name)) == NULL){
|
||||
if (cxvec_append(x1, first, firstlen) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
if (xml_diff1(y, x1, x2,
|
||||
first, firstlen,
|
||||
second, secondlen,
|
||||
changed1, changed2, changedlen)< 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_LEAF:
|
||||
if ((x2 = xml_find(xt2, name)) == NULL){
|
||||
if (cxvec_append(x1, first, firstlen) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
body1 = xml_body(x1);
|
||||
body2 = xml_body(x2);
|
||||
if (body1 == NULL || body2 == NULL) /* empty type */
|
||||
break;
|
||||
if (strcmp(xml_body(x1), xml_body(x2))){
|
||||
if (cxvec_append(x1, changed1, changedlen) < 0)
|
||||
goto done;
|
||||
(*changedlen)--; /* append two vectors */
|
||||
if (cxvec_append(x2, changed2, changedlen) < 0)
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case Y_LEAF_LIST:
|
||||
if ((body1 = xml_body(x1)) == NULL)
|
||||
if (strcmp(xml_name(x0c), x1cname))
|
||||
continue;
|
||||
if (!xml_is_body(xt2, name, body1)) /* where body is */
|
||||
if (cxvec_append(x1, first, firstlen) < 0)
|
||||
goto done;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} /* while xt1 */
|
||||
/* Check nodes present only in xt2
|
||||
* Loop over xt2
|
||||
*/
|
||||
x2 = NULL;
|
||||
while ((x2 = xml_child_each(xt2, x2, CX_ELMNT)) != NULL){
|
||||
name = xml_name(x2);
|
||||
if (ys->ys_keyword == Y_SPEC)
|
||||
y = yang_find_topnode((yang_spec*)ys, name, 0);
|
||||
else
|
||||
y = yang_find_datanode((yang_node*)ys, name);
|
||||
if (y == NULL){
|
||||
clicon_err(OE_UNIX, errno, "No yang node found: %s", name);
|
||||
goto done;
|
||||
}
|
||||
switch (y->ys_keyword){
|
||||
case Y_LIST:
|
||||
if ((ykey = yang_find((yang_node*)y, Y_KEY, NULL)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key",
|
||||
__FUNCTION__, y->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
/* The value is a list of keys: <key>[ <key>]* */
|
||||
if ((cvk = yang_arg2cvec(ykey, " ")) == NULL)
|
||||
goto done;
|
||||
/* Iterate over xt1 tree to (1) find a child that matches name
|
||||
(2) that have keys that matches */
|
||||
equal = 0;
|
||||
x1 = NULL;
|
||||
while ((x1 = xml_child_each(xt1, x1, CX_ELMNT)) != NULL){
|
||||
if (strcmp(xml_name(x1), name))
|
||||
continue;
|
||||
cvi = NULL;
|
||||
/* Must be inner loop */
|
||||
cvi = NULL; i = 0;
|
||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||
b1 = b1vec[i++];
|
||||
equal = 0;
|
||||
/* (2) Match keys between x2 and x1 */
|
||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||
keyname = cv_string_get(cvi);
|
||||
if ((body2 = xml_find_body(x2, keyname)) == NULL)
|
||||
continue; /* may be error */
|
||||
if ((body1 = xml_find_body(x1, keyname)) == NULL)
|
||||
continue; /* may be error */
|
||||
if (strcmp(body2, body1)==0)
|
||||
equal=1;
|
||||
else{
|
||||
equal=0; /* stop as soon as inequal key found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (equal) /* found x1 and x2 equal, otherwise look
|
||||
for other x2 */
|
||||
break;
|
||||
keyname = cv_string_get(cvi);
|
||||
if ((b0 = xml_find_body(x0c, keyname)) == NULL)
|
||||
break; /* error case */
|
||||
if (strcmp(b0, b1))
|
||||
break; /* stop as soon as inequal key found */
|
||||
equal=1; /* reaches here for all keynames, x0c is found. */
|
||||
}
|
||||
if (cvk){
|
||||
cvec_free(cvk);
|
||||
cvk = NULL;
|
||||
}
|
||||
if (!equal)
|
||||
if (cxvec_append(x2, second, secondlen) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_CONTAINER:
|
||||
/* Equal regardless */
|
||||
if ((x1 = xml_find(xt1, name)) == NULL)
|
||||
if (cxvec_append(x2, second, secondlen) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_LEAF:
|
||||
if ((x1 = xml_find(xt1, name)) == NULL)
|
||||
if (cxvec_append(x2, second, secondlen) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_LEAF_LIST:
|
||||
body2 = xml_body(x2);
|
||||
if (!xml_is_body(xt1, name, body2)) /* where body is */
|
||||
if (cxvec_append(x2, second, secondlen) < 0)
|
||||
goto done;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} /* while xt1 */
|
||||
if (equal) /* x0c and x1c equal, otherwise look for other */
|
||||
break;
|
||||
} /* while x0c */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ok:
|
||||
*x0cp = x0c;
|
||||
retval = 0;
|
||||
done:
|
||||
if (b1vec)
|
||||
free(b1vec);
|
||||
if (cvk)
|
||||
cvec_free(cvk);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Find next yang node, either start from yang_spec or some yang-node
|
||||
* @param[in] y Node spec or sny yang-node
|
||||
* @param[in] name Name of childnode to find
|
||||
* @retval ys yang statement
|
||||
* @retval NULL Error: no node found
|
||||
*/
|
||||
static yang_stmt *
|
||||
yang_next(yang_node *y,
|
||||
char *name)
|
||||
{
|
||||
yang_stmt *ys;
|
||||
|
||||
if (y->yn_keyword == Y_SPEC)
|
||||
ys = yang_find_topnode((yang_spec*)y, name, 0);
|
||||
else
|
||||
ys = yang_find_datanode(y, name);
|
||||
if (ys == NULL)
|
||||
clicon_err(OE_UNIX, errno, "No yang node found: %s", name);
|
||||
return ys;
|
||||
}
|
||||
|
||||
/*! Recursive help function to compute differences between two xml trees
|
||||
* @param[in] x1 First XML tree
|
||||
* @param[in] x2 Second XML tree
|
||||
* @param[out] x1vec Pointervector to XML nodes existing in only first tree
|
||||
* @param[out] x1veclen Length of first vector
|
||||
* @param[out] x2vec Pointervector to XML nodes existing in only second tree
|
||||
* @param[out] x2veclen Length of x2vec vector
|
||||
* @param[out] changed_x1 Pointervector to XML nodes changed orig value
|
||||
* @param[out] changed_x2 Pointervector to XML nodes changed wanted value
|
||||
* @param[out] changedlen Length of changed vector
|
||||
*/
|
||||
static int
|
||||
xml_diff1(yang_stmt *ys,
|
||||
cxobj *x1,
|
||||
cxobj *x2,
|
||||
cxobj ***x1vec,
|
||||
size_t *x1veclen,
|
||||
cxobj ***x2vec,
|
||||
size_t *x2veclen,
|
||||
cxobj ***changed_x1,
|
||||
cxobj ***changed_x2,
|
||||
size_t *changedlen)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x1c = NULL; /* x1 child */
|
||||
cxobj *x2c = NULL; /* x2 child */
|
||||
yang_stmt *yc;
|
||||
char *b1;
|
||||
char *b2;
|
||||
|
||||
clicon_debug(2, "%s: %s", __FUNCTION__, ys->ys_argument?ys->ys_argument:"yspec");
|
||||
/* Check nodes present in x1 and x2 + nodes only in x1
|
||||
* Loop over x1
|
||||
* XXX: room for improvement. Compare with match_base_child()
|
||||
*/
|
||||
x1c = NULL;
|
||||
while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL){
|
||||
if ((yc = yang_next((yang_node*)ys, xml_name(x1c))) == NULL)
|
||||
goto done;
|
||||
if (match_base_child(x2, x1c, &x2c, yc) < 0)
|
||||
goto done;
|
||||
if (x2c == NULL){
|
||||
if (cxvec_append(x1c, x1vec, x1veclen) < 0)
|
||||
goto done;
|
||||
}
|
||||
else{
|
||||
if (yc->ys_keyword == Y_LEAF){
|
||||
if ((b1 = xml_body(x1c)) == NULL) /* empty type */
|
||||
break;
|
||||
if ((b2 = xml_body(x2c)) == NULL) /* empty type */
|
||||
break;
|
||||
if (strcmp(b1, b2)){
|
||||
if (cxvec_append(x1c, changed_x1, changedlen) < 0)
|
||||
goto done;
|
||||
(*changedlen)--; /* append two vectors */
|
||||
if (cxvec_append(x2c, changed_x2, changedlen) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (xml_diff1(yc, x1c, x2c,
|
||||
x1vec, x1veclen,
|
||||
x2vec, x2veclen,
|
||||
changed_x1, changed_x2, changedlen)< 0)
|
||||
goto done;
|
||||
}
|
||||
} /* while x1 */
|
||||
/* Check nodes present only in x2
|
||||
* Loop over x2
|
||||
*/
|
||||
x2c = NULL;
|
||||
while ((x2c = xml_child_each(x2, x2c, CX_ELMNT)) != NULL){
|
||||
if ((yc = yang_next((yang_node*)ys, xml_name(x2c))) == NULL)
|
||||
goto done;
|
||||
if (match_base_child(x1, x2c, &x1c, yc) < 0)
|
||||
goto done;
|
||||
if (x1c == NULL)
|
||||
if (cxvec_append(x2c, x2vec, x2veclen) < 0)
|
||||
goto done;
|
||||
} /* while x1 */
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Compute differences between two xml trees
|
||||
* @param[in] yspec Yang specification
|
||||
* @param[in] xt1 First XML tree
|
||||
* @param[in] xt2 Second XML tree
|
||||
* @param[in] x1 First XML tree
|
||||
* @param[in] x2 Second XML tree
|
||||
* @param[out] first Pointervector to XML nodes existing in only first tree
|
||||
* @param[out] firstlen Length of first vector
|
||||
* @param[out] second Pointervector to XML nodes existing in only second tree
|
||||
* @param[out] secondlen Length of second vector
|
||||
* @param[out] changed1 Pointervector to XML nodes changed value
|
||||
* @param[out] changed2 Pointervector to XML nodes changed value
|
||||
* @param[out] changed1 Pointervector to XML nodes changed orig value
|
||||
* @param[out] changed2 Pointervector to XML nodes changed wanted value
|
||||
* @param[out] changedlen Length of changed vector
|
||||
* All xml vectors should be freed after use.
|
||||
* Bot xml trees should be freed with xml_free()
|
||||
*/
|
||||
int
|
||||
xml_diff(yang_spec *yspec,
|
||||
cxobj *xt1,
|
||||
cxobj *xt2,
|
||||
cxobj *x1,
|
||||
cxobj *x2,
|
||||
cxobj ***first,
|
||||
size_t *firstlen,
|
||||
cxobj ***second,
|
||||
|
|
@ -865,19 +856,19 @@ xml_diff(yang_spec *yspec,
|
|||
*firstlen = 0;
|
||||
*secondlen = 0;
|
||||
*changedlen = 0;
|
||||
if (xt1 == NULL && xt2 == NULL)
|
||||
if (x1 == NULL && x2 == NULL)
|
||||
return 0;
|
||||
if (xt2 == NULL){
|
||||
if (cxvec_append(xt1, first, firstlen) < 0)
|
||||
if (x2 == NULL){
|
||||
if (cxvec_append(x1, first, firstlen) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (xt1 == NULL){
|
||||
if (cxvec_append(xt1, second, secondlen) < 0)
|
||||
if (x1 == NULL){
|
||||
if (cxvec_append(x1, second, secondlen) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (xml_diff1((yang_stmt*)yspec, xt1, xt2,
|
||||
if (xml_diff1((yang_stmt*)yspec, x1, x2,
|
||||
first, firstlen,
|
||||
second, secondlen,
|
||||
changed1, changed2, changedlen) < 0)
|
||||
|
|
@ -1833,82 +1824,6 @@ api_path2xml(char *api_path,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Given a modification tree, check existing matching child in the base tree
|
||||
* param[in] x0 Base tree node
|
||||
* param[in] x1c Modification tree child
|
||||
* param[in] yc Yang spec of tree child
|
||||
* param[out] x0cp Matching base tree child (if any)
|
||||
*/
|
||||
static int
|
||||
match_base_child(cxobj *x0,
|
||||
cxobj *x1c,
|
||||
yang_stmt *yc,
|
||||
cxobj **x0cp)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x0c = NULL;
|
||||
char *keyname;
|
||||
cvec *cvk = NULL;
|
||||
cg_var *cvi;
|
||||
char *b0;
|
||||
char *b1;
|
||||
yang_stmt *ykey;
|
||||
char *cname;
|
||||
int ok;
|
||||
char *x1bstr; /* body string */
|
||||
|
||||
cname = xml_name(x1c);
|
||||
switch (yc->ys_keyword){
|
||||
case Y_LEAF_LIST: /* Match with name and value */
|
||||
x1bstr = xml_body(x1c);
|
||||
x0c = NULL;
|
||||
while ((x0c = xml_child_each(x0, x0c, CX_ELMNT)) != NULL) {
|
||||
if (strcmp(cname, xml_name(x0c)) == 0 &&
|
||||
strcmp(xml_body(x0c), x1bstr)==0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Y_LIST: /* Match with key values */
|
||||
if ((ykey = yang_find((yang_node*)yc, Y_KEY, NULL)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key",
|
||||
__FUNCTION__, yc->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
/* The value is a list of keys: <key>[ <key>]* */
|
||||
if ((cvk = yang_arg2cvec(ykey, " ")) == NULL)
|
||||
goto done;
|
||||
x0c = NULL;
|
||||
while ((x0c = xml_child_each(x0, x0c, CX_ELMNT)) != NULL) {
|
||||
if (strcmp(xml_name(x0c), cname))
|
||||
continue;
|
||||
cvi = NULL;
|
||||
ok = 0;
|
||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||
keyname = cv_string_get(cvi);
|
||||
ok = 1; /* if we come here */
|
||||
if ((b0 = xml_find_body(x0c, keyname)) == NULL)
|
||||
break; /* error case */
|
||||
if ((b1 = xml_find_body(x1c, keyname)) == NULL)
|
||||
break; /* error case */
|
||||
if (strcmp(b0, b1))
|
||||
break;
|
||||
ok = 2; /* and reaches here for all keynames, x0c is found. */
|
||||
}
|
||||
if (ok == 2)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: /* Just match with name */
|
||||
x0c = xml_find(x0, cname);
|
||||
break;
|
||||
}
|
||||
*x0cp = x0c;
|
||||
retval = 0;
|
||||
done:
|
||||
if (cvk)
|
||||
cvec_free(cvk);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Merge a base tree x0 with x1 with yang spec y
|
||||
* @param[in] x0 Base xml tree (can be NULL in add scenarios)
|
||||
|
|
@ -1975,7 +1890,7 @@ xml_merge1(cxobj *x0,
|
|||
}
|
||||
/* See if there is a corresponding node in the base tree */
|
||||
x0c = NULL;
|
||||
if (yc && match_base_child(x0, x1c, yc, &x0c) < 0)
|
||||
if (yc && match_base_child(x0, x1c, &x0c, yc) < 0)
|
||||
goto done;
|
||||
if (xml_merge1(x0c, (yang_node*)yc, x0, x1c) < 0)
|
||||
goto done;
|
||||
|
|
@ -2012,7 +1927,7 @@ xml_merge(cxobj *x0,
|
|||
goto done;
|
||||
}
|
||||
/* See if there is a corresponding node in the base tree */
|
||||
if (match_base_child(x0, x1c, yc, &x0c) < 0)
|
||||
if (match_base_child(x0, x1c, &x0c, yc) < 0)
|
||||
goto done;
|
||||
if (xml_merge1(x0c, (yang_node*)yc, x0, x1c) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue