Clixon 4.4 three compile-time options: MOVE_TRANS_END for changing transaction-end callbacks; STATE_ORDERED_BY_SYSTEM to make state data system ordered; XML_MERGE_TWO_ROUNDS to improve xml_merge performance.

This commit is contained in:
Olof hagsand 2020-04-02 14:28:58 +02:00
parent 5535239363
commit 662d6b0a3f
19 changed files with 483 additions and 61 deletions

View file

@ -1704,6 +1704,14 @@ xml_merge1(cxobj *x0, /* the target */
char *x1bstr; /* mod body string */
yang_stmt *yc; /* yang child */
cbuf *cbr = NULL; /* Reason buffer */
#ifdef XML_MERGE_TWO_ROUNDS
int i;
struct {
cxobj *w_x0c;
cxobj *w_x1c;
yang_stmt *w_yc;
} *second_wave = NULL;
#endif
assert(x1 && xml_type(x1) == CX_ELMNT);
assert(y0);
@ -1739,6 +1747,13 @@ xml_merge1(cxobj *x0, /* the target */
}
if (assign_namespaces(x1, x0, x0p) < 0)
goto done;
#ifdef XML_MERGE_TWO_ROUNDS
if ((second_wave = calloc(xml_child_nr(x1), sizeof(*second_wave))) == NULL){
clicon_err(OE_UNIX, errno, "calloc");
goto done;
}
i = 0;
#endif
/* Loop through children of the modification tree */
x1c = NULL;
while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) {
@ -1762,11 +1777,38 @@ xml_merge1(cxobj *x0, /* the target */
x0c = NULL;
if (yc && match_base_child(x0, x1c, yc, &x0c) < 0)
goto done;
#ifdef XML_MERGE_TWO_ROUNDS
/* Save x0c, x1c, yc and merge in second wave, so that x1c entries "interfer"
* with itself, ie that later searches are among earlier objects already added
* to x0 */
second_wave[i].w_x0c = x0c;
second_wave[i].w_x1c = x1c;
second_wave[i].w_yc = yc;
i++;
#else
if (xml_merge1(x0c, yc, x0, x1c, reason) < 0)
goto done;
if (*reason != NULL)
goto ok;
#endif
} /* while */
#ifdef XML_MERGE_TWO_ROUNDS
/* Second run where actual merging is done
* Loop through children of the modification tree */
x1c = NULL;
i = 0;
while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) {
if (xml_merge1(second_wave[i].w_x0c,
second_wave[i].w_yc,
x0,
second_wave[i].w_x1c,
reason) < 0)
goto done;
if (*reason != NULL)
goto ok;
i++;
}
#endif
if (xml_parent(x0) == NULL &&
xml_insert(x0p, x0, INS_LAST, NULL, NULL) < 0)
goto done;
@ -1774,6 +1816,10 @@ xml_merge1(cxobj *x0, /* the target */
ok:
retval = 0;
done:
#ifdef XML_MERGE_TWO_ROUNDS
if (second_wave)
free(second_wave);
#endif
if (cbr)
cbuf_free(cbr);
return retval;
@ -1838,7 +1884,7 @@ xml_merge(cxobj *x0,
}
break;
}
/* See if there is a corresponding node in the base tree */
/* See if there is a corresponding node (x1c) in the base tree (x0) */
if (match_base_child(x0, x1c, yc, &x0c) < 0)
goto done;
/* There is a case where x0c and x1c are choice nodes, if so,

View file

@ -253,7 +253,11 @@ xml_cmp(cxobj *x1,
* existing list.
*/
if (same &&
(yang_config(y1)==0 || yang_find(y1, Y_ORDERED_BY, "user") != NULL)){
(
#ifndef STATE_ORDERED_BY_SYSTEM
yang_config(y1)==0 ||
#endif
yang_find(y1, Y_ORDERED_BY, "user") != NULL)){
equal = nr1-nr2;
goto done; /* Ordered by user or state data : maintain existing order */
}
@ -385,16 +389,19 @@ xml_cmp_qsort(const void* arg1,
* @retval 0 OK, all nodes traversed (subparts may have been skipped)
* @retval 1 OK, aborted on first fn returned 1
* @see xml_apply - typically called by recursive apply function
* @see xml_sort_verify
*/
int
xml_sort(cxobj *x,
void *arg)
{
#ifndef STATE_ORDERED_BY_SYSTEM
yang_stmt *ys;
/* Abort sort if non-config (=state) data */
if ((ys = xml_spec(x)) != 0 && yang_config(ys)==0)
if ((ys = xml_spec(x)) != 0 && yang_config(ys)==0)
return 1;
#endif
xml_enumerate_children(x);
qsort(xml_childvec_get(x), xml_child_nr(x), sizeof(cxobj *), xml_cmp_qsort);
return 0;
@ -759,10 +766,13 @@ xml_search_yang(cxobj *xp,
for (low=0; low<upper; low++)
if ((xa = xml_child_i(xp, low)) == NULL || xml_type(xa) != CX_ATTR)
break;
#ifndef STATE_ORDERED_BY_SYSTEM
/* Find if non-config and if ordered-by-user */
if (yang_config_ancestor(yc)==0)
sorted = 0;
else if (yang_keyword_get(yc) == Y_LIST || yang_keyword_get(yc) == Y_LEAF_LIST)
else
#endif
if (yang_keyword_get(yc) == Y_LIST || yang_keyword_get(yc) == Y_LEAF_LIST)
sorted = (yang_find(yc, Y_ORDERED_BY, "user") == NULL);
yangi = yang_order(yc);
return xml_search_binary(xp, x1, sorted, yangi, low, upper, skip1, indexvar, xvec);
@ -996,10 +1006,13 @@ xml_insert(cxobj *xp,
if ((xa = xml_child_i(xp, low)) == NULL || xml_type(xa)!=CX_ATTR)
break;
/* Find if non-config and if ordered-by-user */
#ifndef STATE_ORDERED_BY_SYSTEM
if (yang_config_ancestor(y)==0)
userorder = 1;
else if (yang_keyword_get(y) == Y_LIST || yang_keyword_get(y) == Y_LEAF_LIST)
userorder = (yang_find(y, Y_ORDERED_BY, "user") != NULL);
else
#endif
if (yang_keyword_get(y) == Y_LIST || yang_keyword_get(y) == Y_LEAF_LIST)
userorder = (yang_find(y, Y_ORDERED_BY, "user") != NULL);
yi = yang_order(y);
if ((i = xml_insert2(xp, xi, y, yi,
userorder, ins, key_val, nsc_key,
@ -1019,8 +1032,8 @@ xml_insert(cxobj *xp,
/*! Verify all children of XML node are sorted according to xml_sort()
* @param[in] x XML node. Check its children
* @param[in] arg Dummy. Ensures xml_apply can be used with this fn
@ @retval 0 Sorted
@ @retval -1 Not sorted
* @retval 0 Sorted
* @retval -1 Not sorted
* @see xml_apply
*/
int
@ -1030,13 +1043,15 @@ xml_sort_verify(cxobj *x0,
int retval = -1;
cxobj *x = NULL;
cxobj *xprev = NULL;
#ifndef STATE_ORDERED_BY_SYSTEM
yang_stmt *ys;
/* Abort sort if non-config (=state) data */
if ((ys = xml_spec(x0)) != 0 && yang_config_ancestor(ys)==0){
retval = 1;
goto done;
}
#endif
if (xml_type(x0) == CX_ELMNT){
xml_enumerate_children(x0);
while ((x = xml_child_each(x0, x, -1)) != NULL) {
@ -1067,15 +1082,15 @@ match_base_child(cxobj *x0,
yang_stmt *yc,
cxobj **x0cp)
{
int retval = -1;
cvec *cvk = NULL; /* vector of index keys */
cg_var *cvi;
cxobj *xb;
char *keyname;
cxobj *x0c = NULL;
yang_stmt *y0c;
yang_stmt *y0p;
yang_stmt *yp; /* yang parent */
int retval = -1;
cvec *cvk = NULL; /* vector of index keys */
cg_var *cvi;
cxobj *xb;
char *keyname;
cxobj *x0c = NULL;
yang_stmt *y0c;
yang_stmt *y0p;
yang_stmt *yp; /* yang parent */
clixon_xvec *xvec = NULL;
*x0cp = NULL; /* init return value */