diff --git a/lib/clixon/clixon_path.h b/lib/clixon/clixon_path.h index ff0c392e..496e4a12 100644 --- a/lib/clixon/clixon_path.h +++ b/lib/clixon/clixon_path.h @@ -86,13 +86,13 @@ int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop, cxobj **xpathp, yang_stmt **ypathp, cxobj **xerr); int xml2api_path_1(cxobj *x, cbuf *cb); #if defined(__GNUC__) && __GNUC__ >= 3 -int clixon_xml_find_api_path(cxobj *xt, yang_stmt *yt, cxobj ***xvec, size_t *xlen, char *format, - ...) __attribute__ ((format (printf, 5, 6)));; -int clixon_xml_find_instance_id(cxobj *xt, yang_stmt *yt, cxobj ***xvec, size_t *xlen, char *format, - ...) __attribute__ ((format (printf, 5, 6)));; +int clixon_xml_find_api_path(cxobj *xt, yang_stmt *yt, clixon_xvec **xvec, char *format, + ...) __attribute__ ((format (printf, 4, 5)));; +int clixon_xml_find_instance_id(cxobj *xt, yang_stmt *yt, clixon_xvec **xvec, char *format, + ...) __attribute__ ((format (printf, 4, 5)));; #else -int clixon_xml_find_api_path(cxobj *xt, yang_stmt *yt, cxobj ***xvec, size_t *xlen, char *format, ...); -int clixon_xml_find_instance_id(cxobj *xt, yang_stmt *yt, cxobj ***xvec, size_t *xlen, char *format, ...); +int clixon_xml_find_api_path(cxobj *xt, yang_stmt *yt, clixon_xvec **xvec, char *format, ...); +int clixon_xml_find_instance_id(cxobj *xt, yang_stmt *yt, clixon_xvec **xvec, char *format, ...); #endif #endif /* _CLIXON_PATH_H_ */ diff --git a/lib/clixon/clixon_xml_sort.h b/lib/clixon/clixon_xml_sort.h index 0b75da5b..9daff2f9 100644 --- a/lib/clixon/clixon_xml_sort.h +++ b/lib/clixon/clixon_xml_sort.h @@ -50,7 +50,7 @@ int xml_search_indexvar_binary_pos(cxobj *xp, char *indexvar, clixon_xvec *xvec, #endif int match_base_child(cxobj *x0, cxobj *x1c, yang_stmt *yc, cxobj **x0cp); int clixon_xml_find_index(cxobj *xp, yang_stmt *yp, char *namespace, char *name, - cvec *cvk, cxobj ***xvec, size_t *xlen); -int clixon_xml_find_pos(cxobj *xp, yang_stmt *yc, uint32_t pos, cxobj ***xvec, size_t *xlen); + cvec *cvk, clixon_xvec **xvec); +int clixon_xml_find_pos(cxobj *xp, yang_stmt *yc, uint32_t pos, clixon_xvec **xvec); #endif /* _CLIXON_XML_SORT_H */ diff --git a/lib/clixon/clixon_xml_vec.h b/lib/clixon/clixon_xml_vec.h index 79e3a268..4b6d25d4 100644 --- a/lib/clixon/clixon_xml_vec.h +++ b/lib/clixon/clixon_xml_vec.h @@ -51,6 +51,7 @@ clixon_xvec *clixon_xvec_dup(clixon_xvec *xv0); int clixon_xvec_free(clixon_xvec *xv); int clixon_xvec_len(clixon_xvec *xv); cxobj *clixon_xvec_i(clixon_xvec *xv, int i); +int clixon_xvec_vec(clixon_xvec *xv, cxobj ***xvec, size_t *xlen); int clixon_xvec_append(clixon_xvec *xv, cxobj *x); int clixon_xvec_prepend(clixon_xvec *xv, cxobj *x); int clixon_xvec_insert_pos(clixon_xvec *xv, cxobj *x, int i); diff --git a/lib/clixon/clixon_xpath_optimize.h b/lib/clixon/clixon_xpath_optimize.h index c91eebab..dc492905 100644 --- a/lib/clixon/clixon_xpath_optimize.h +++ b/lib/clixon/clixon_xpath_optimize.h @@ -38,9 +38,10 @@ #define _CLIXON_XPATH_OPTIMIZE_H -int xpath_list_optimize_stats(int *hits); -int xpath_list_optimize_set(int enable); +int xpath_list_optimize_stats(int *hits); +int xpath_list_optimize_set(int enable); void xpath_optimize_exit(void); -int xpath_optimize_check(); +//int xpath_optimize_check(xpath_tree *xs, cxobj *xv, cxobj ***xvec0, size_t *xlen0); +int xpath_optimize_check(); #endif /* _CLIXON_XPATH_OPTIMIZE_H */ diff --git a/lib/src/clixon_path.c b/lib/src/clixon_path.c index f4e29f95..65bf1412 100644 --- a/lib/src/clixon_path.c +++ b/lib/src/clixon_path.c @@ -89,6 +89,7 @@ #include "clixon_yang.h" #include "clixon_xml.h" #include "clixon_xml_nsctx.h" +#include "clixon_xml_vec.h" #include "clixon_xml_sort.h" #include "clixon_netconf_lib.h" #include "clixon_xml_map.h" @@ -1401,7 +1402,6 @@ instance_id_resolve(clixon_path *cplist, * @param[in] yt Yang statement of top symbol (can be yang-spec if top-level) * @param[in] cplist Lisp of clixon-path * @param[out] xvec Vector of xml-trees. Vector must be free():d after use - * @param[out] xlen Returns length of vector in return value * @retval -1 Error * @retval 0 Fail fail: eg no yang * @retval 1 OK with found xml nodes in xvec (if any) @@ -1410,61 +1410,61 @@ static int clixon_path_search(cxobj *xt, yang_stmt *yt, clixon_path *cplist, - cxobj ***xvec0, - size_t *xlen0) + clixon_xvec **xvec0) { int retval = -1; char *modns; /* Module namespace of api-path */ clixon_path *cp; - cxobj **xvecp = NULL; /* parent set */ - size_t xlenp = 0; - cxobj **xvecc = NULL; /* child set */ - size_t xlenc = 0; + clixon_xvec *xvecp = NULL; + clixon_xvec *xvecc = NULL; yang_stmt *yc; cxobj *xp; int i; cg_var *cv; + if ((xvecp = clixon_xvec_new()) == NULL) + goto done; modns = NULL; if ((cp = cplist) != NULL){ - cxvec_append(xt, &xvecp, &xlenp); /* Initialize parent xml set */ + if (clixon_xvec_append(xvecp, xt) < 0) + goto done; do { yc = cp->cp_yang; if ((modns = yang_find_mynamespace(yc)) == NULL) goto fail; - for (i=0; icp_cvk && /* cornercase for instance-id [] special case */ (yang_keyword_get(yc) == Y_LIST || yang_keyword_get(yc) == Y_LEAF_LIST) && cvec_len(cp->cp_cvk) == 1 && (cv = cvec_i(cp->cp_cvk,0)) && (cv_type_get(cv) == CGV_UINT32)){ - if (clixon_xml_find_pos(xp, yc, cv_uint32_get(cv), &xvecc, &xlenc) < 0) + if (clixon_xml_find_pos(xp, yc, cv_uint32_get(cv), &xvecc) < 0) goto done; } else if (clixon_xml_find_index(xp, yang_parent_get(yc), modns, yang_argument_get(yc), - cp->cp_cvk, &xvecc, &xlenc) < 0) + cp->cp_cvk, &xvecc) < 0) goto done; - } + } /* for */ if (xvecp) - free(xvecp); - xvecp = xvecc; xlenp = xlenc; - xvecc = NULL, xlenc = 0; + clixon_xvec_free(xvecp); + xvecp = xvecc; + xvecc = NULL; cp = NEXTQ(clixon_path *, cp); } while (cp && cp != cplist); - *xvec0 = xvecp; xvecp = NULL; - *xlen0 = xlenp; - } + *xvec0 = xvecp; + xvecp = NULL; + } /* if */ retval = 1; done: if (xvecp) - free(xvecp); + clixon_xvec_free(xvecp); if (xvecc) - free(xvecc); + clixon_xvec_free(xvecc); return retval; fail: /* eg no yang for api-path, no match */ *xvec0 = NULL; - *xlen0 = 0; retval = 0; goto done; } @@ -1474,7 +1474,6 @@ clixon_path_search(cxobj *xt, * @param[in] xt Top xml-tree where to search * @param[in] yt Yang statement of top symbol (can be yang-spec if top-level) * @param[out] xvec Vector of xml-trees. Vector must be free():d after use - * @param[out] xlen Returns length of vector in return value * @param[in] format Format string for api-path syntax * @retval -1 Error * @retval 0 Nomatch @@ -1484,24 +1483,23 @@ clixon_path_search(cxobj *xt, * - Modulename not defined for top-level id. * - Number of keys in key-value list does not match Yang list * @code - * cxobj **xvec = NULL; - * size_t xlen; - * if (clixon_xml_find_api_path(x, yspec, &xvec, &xlen, "/symbol/%s", "foo") < 0) - * err; - * for (i=0; i0 means search upper interval, <0 lower interval, = 0 is equal */ cmp = xml_cmp(x1, xc, 0, skip1, NULL); if (cmp && !sorted){ /* Ordered by user (if not equal) */ - retval = xml_find_keys_notsorted(xp, x1, yangi, mid, skip1, xvec, xlen); + retval = xml_find_keys_notsorted(xp, x1, yangi, mid, skip1, xvec); goto done; } } if (cmp == 0){ - if (cxvec_append(xc, xvec, xlen) < 0) + if (clixon_xvec_append(xvec, xc) < 0) goto done; /* there may be more? */ if (search_multi_equals(xml_childvec_get(xp), xml_child_nr(xp), - x1, yangi, mid, - skip1, xvec, xlen) < 0) + x1, yangi, mid, skip1, xvec) < 0) goto done; } else if (cmp < 0) - xml_search_binary(xp, x1, sorted, yangi, low, mid-1, skip1, indexvar, xvec, xlen); + xml_search_binary(xp, x1, sorted, yangi, low, mid-1, skip1, indexvar, xvec); else - xml_search_binary(xp, x1, sorted, yangi, mid+1, upper, skip1, indexvar, xvec, xlen); + xml_search_binary(xp, x1, sorted, yangi, mid+1, upper, skip1, indexvar, xvec); ok: retval = 0; done: @@ -740,7 +731,6 @@ xml_search_binary(cxobj *xp, * @param[in] skip1 Key matching skipped for keys not in x1 * @param[in] indexvar Override list key value search with explicit search index var of x1 * @param[out] xvec Vector of matching XML return objects (can be empty) - * @param[out] xlen Length of xvec * @retval 0 OK, see xvec (may be empty) * @retval -1 Error * @see xml_find_index for a generic search function @@ -751,8 +741,7 @@ xml_search_yang(cxobj *xp, yang_stmt *yc, int skip1, char *indexvar, - cxobj ***xvec, - size_t *xlen) + clixon_xvec *xvec) { cxobj *xa; int low = 0; @@ -771,7 +760,7 @@ xml_search_yang(cxobj *xp, else 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, xlen); + return xml_search_binary(xp, x1, sorted, yangi, low, upper, skip1, indexvar, xvec); } /*! Insert xn in xp:s sorted child list (special case of ordered-by user) @@ -1080,8 +1069,7 @@ match_base_child(cxobj *x0, yang_stmt *y0c; yang_stmt *y0p; yang_stmt *yp; /* yang parent */ - cxobj **xvec = NULL; - size_t xlen = 0; + clixon_xvec *xvec = NULL; *x0cp = NULL; /* init return value */ /* Special case is if yc parent (yp) is choice/case @@ -1118,27 +1106,28 @@ match_base_child(cxobj *x0, default: break; } - /* Get match. */ - if (xml_search_yang(x0, x1c, yc, 0, 0, &xvec, &xlen) < 0) + if ((xvec = clixon_xvec_new()) == NULL) goto done; - if (xlen) - *x0cp = xvec[0]; + /* Get match. */ + if (xml_search_yang(x0, x1c, yc, 0, 0, xvec) < 0) + goto done; + if (clixon_xvec_len(xvec)) + *x0cp = clixon_xvec_i(xvec, 0); ok: retval = 0; done: if (xvec) - free(xvec); + clixon_xvec_free(xvec); return retval; } /*! API for search in XML child list with non-indexed variables */ static int -xml_find_noyang_cvk(char *ns0, - cxobj *xc, - cvec *cvk, - cxobj ***xvec, - size_t *xlen) +xml_find_noyang_cvk(char *ns0, + cxobj *xc, + cvec *cvk, + clixon_xvec *xvec) { int retval = -1; cg_var *cvi; @@ -1182,7 +1171,7 @@ xml_find_noyang_cvk(char *ns0, } } if (cvi == NULL) /* means we iterated through all indexes without breaks */ - if (cxvec_append(xc, xvec, xlen) < 0) + if (clixon_xvec_append(xvec, xc) < 0) goto done; retval = 0; done: @@ -1193,12 +1182,12 @@ xml_find_noyang_cvk(char *ns0, * Fallback if no yang available. Only linear search for matching name, and eventual index match */ static int -xml_find_noyang_name(cxobj *xp, - char *ns0, - char *name, - cvec *cvk, - cxobj ***xvec, - size_t *xlen) +xml_find_noyang_name(cxobj *xp, + char *ns0, + char *name, + cvec *cvk, + clixon_xvec *xvec) + { int retval = -1; cxobj *xc; @@ -1221,11 +1210,11 @@ xml_find_noyang_name(cxobj *xp, if (strcmp(name, xml_name(xc)) != 0) /* Namespace does not match, skip */ continue; if (cvk){ /* Check indexes */ - if (xml_find_noyang_cvk(ns0, xc, cvk, xvec, xlen) < 0) + if (xml_find_noyang_cvk(ns0, xc, cvk, xvec) < 0) goto done; } else /* No index variables: just add node to found list */ - if (cxvec_append(xc, xvec, xlen) < 0) + if (clixon_xvec_append(xvec, xc) < 0) goto done; } retval = 0; @@ -1246,17 +1235,15 @@ xml_find_noyang_name(cxobj *xp, * @param[in] yc Yang spec of list child (preferred) See rule (2) above * @param[in] cvk List of keys and values as CLIgen vector on the form k1=foo, k2=bar * @param[out] xvec Array of found nodes - * @param[out] xlen Len of xvec * @retval 1 OK * @retval 0 Revert, try again with no-yang search * @retval -1 Error */ static int -xml_find_index_yang(cxobj *xp, - yang_stmt *yc, - cvec *cvk, - cxobj ***xvec, - size_t *xlen) +xml_find_index_yang(cxobj *xp, + yang_stmt *yc, + cvec *cvk, + clixon_xvec *xvec) { int retval = -1; cxobj *xc = NULL; @@ -1348,7 +1335,7 @@ xml_find_index_yang(cxobj *xp, if (xml_spec_set(xk, yk) < 0) goto done; } - if (xml_search_yang(xp, xc, yc, 1, indexvar, xvec, xlen) < 0) + if (xml_search_yang(xp, xc, yc, 1, indexvar, xvec) < 0) goto done; retval = 1; /* OK */ done: @@ -1393,16 +1380,20 @@ xml_find_index_yang(cxobj *xp, * @param[in] name Name of child (not required if yc given) * @param[in] cvk List of keys and values as CLIgen vector on the form k1=foo, k2=bar * @param[out] xvec Array of found nodes - * @param[out] xlen Len of xvec * @retval 0 OK, see xret * @retval -1 Error * @code - * cxobj **xvec = NULL; - * size_t xlen = 0; - * cvec *cvk = NULL; vector of index keys + * clixon_xvec *xv = NULL; + * cvec *cvk = NULL; vector of index keys + * cxobj *x; * ... Populate cvk with key/values eg a:5 b:6 - * if (clixon_xml_find_index(xp, yp, NULL, "a", ns, cvk, &xvec, &xlen) < 0) + * if (clixon_xml_find_index(xp, yp, NULL, "a", ns, cvk, &xv) < 0) * err; + * for (i=0; ixv_len++; if (xv->xv_len > xv->xv_max){ - if (xv->xv_max == 0) + if (xv->xv_max < XVEC_MAX_DEFAULT) xv->xv_max = XVEC_MAX_DEFAULT; - if (xv->xv_max < XVEC_MAX_THRESHOLD) + else if (xv->xv_max < XVEC_MAX_THRESHOLD) xv->xv_max *= 2; else xv->xv_max += XVEC_MAX_THRESHOLD; @@ -197,6 +197,37 @@ clixon_xvec_i(clixon_xvec *xv, return NULL; } +/*! Return whole XML object vector + * + * Used in glue code between clixon_xvec code and cxobj **, size_t code, may go AWAY? + * @param[in] xv XML tree vector + * @param[out] xvec XML object vector + * @retval 0 + * @retval -1 + */ +int +clixon_xvec_vec(clixon_xvec *xv, + cxobj ***xvec, + size_t *xlen) +{ + size_t sz; + + if (xv->xv_len == 0){ + *xvec = NULL; + *xlen = 0; + } + else { + sz = xv->xv_len * sizeof(cxobj*); + if ((*xvec = malloc(sz)) == NULL){ + clicon_err(OE_UNIX, errno, "memcpy"); + return -1; + } + memcpy(*xvec, xv->xv_vec, sz); + *xlen = xv->xv_len; + } + return 0; +} + /*! Append a new xml tree to an existing xml vector last in the list * * @param[in] xv XML tree vector @@ -218,7 +249,7 @@ clixon_xvec_append(clixon_xvec *xv, if (clixon_xvec_inc(xv) < 0) goto done; - xv->xv_vec[xv->xv_len] = x; + xv->xv_vec[xv->xv_len-1] = x; retval = 0; done: return retval; diff --git a/lib/src/clixon_xpath_optimize.c b/lib/src/clixon_xpath_optimize.c index 05551137..9b664e17 100644 --- a/lib/src/clixon_xpath_optimize.c +++ b/lib/src/clixon_xpath_optimize.c @@ -63,6 +63,7 @@ #include "clixon_handle.h" #include "clixon_yang.h" #include "clixon_xml.h" +#include "clixon_xml_vec.h" #include "clixon_xml_sort.h" #include "clixon_xpath_ctx.h" #include "clixon_xpath.h" @@ -227,8 +228,7 @@ loop_preds(xpath_tree *xt, static int xpath_list_optimize_fn(xpath_tree *xt, cxobj *xv, - cxobj ***xvec, - size_t *xlen) + clixon_xvec **xvec) { int retval = -1; xpath_tree *xm = NULL; @@ -294,7 +294,7 @@ xpath_list_optimize_fn(xpath_tree *xt, i++; } /* Use 2a form since yc allready given to compute cvk */ - if (clixon_xml_find_index(xv, yp, NULL, name, cvk, xvec, xlen) < 0) + if (clixon_xml_find_index(xv, yp, NULL, name, cvk, xvec) < 0) goto done; retval = 1; /* match */ done: @@ -314,22 +314,27 @@ xpath_list_optimize_fn(xpath_tree *xt, * @retval -1 Error * @retval 0 Dont optimize: not special case, do normal processing * @retval 1 Optimization made, special case, use x (found if != NULL) + * XXX Contains glue code between cxobj ** and clixon_xvec code */ int xpath_optimize_check(xpath_tree *xs, cxobj *xv, - cxobj ***xvec, - size_t *xlen) - + cxobj ***xvec0, + size_t *xlen0) { #ifdef XPATH_LIST_OPTIMIZE - int ret; + int ret; + clixon_xvec *xvec = NULL; if (!_optimize_enable) return 0; /* use regular code */ - if ((ret = xpath_list_optimize_fn(xs, xv, xvec, xlen)) < 0) + /* Glue code since xpath code uses (old) cxobj ** and search code uses (new) clixon_xvec */ + if ((ret = xpath_list_optimize_fn(xs, xv, &xvec)) < 0) return -1; if (ret == 1){ + if (clixon_xvec_vec(xvec, xvec0, xlen0) < 0) + return -1; + clixon_xvec_free(xvec); _optimize_hits++; return 1; /* Optimized */ } diff --git a/test/test_api.sh b/test/test_api.sh index a6c9fe27..762bb9ba 100755 --- a/test/test_api.sh +++ b/test/test_api.sh @@ -117,8 +117,7 @@ trigger_rpc(clicon_handle h, /* Clicon handle */ char *val; cvec *cvk = NULL; cg_var *cv; - cxobj **xvec = NULL; - size_t xlen = 0; + clixon_xvec *xvec = NULL; if (xmldb_get(h, "running", NULL, "/c", &xret) < 0) goto done; @@ -158,10 +157,10 @@ trigger_rpc(clicon_handle h, /* Clicon handle */ cv_name_set(cv, "k"); cv_string_set(cv, "5"); /* Use form 2c use spec of xc + name */ - if (clixon_xml_find_index(xc, NULL, NULL, "y3", cvk, &xvec, &xlen) < 0) + if (clixon_xml_find_index(xc, NULL, NULL, "y3", cvk, &xvec) < 0) goto done; - if (xlen) - val = xml_find_body(xvec[0], "val"); + if (clixon_xvec_len(xvec)) + val = xml_find_body(clixon_xvec_i(xvec,0), "val"); else val = NULL; clicon_debug(1, "%s Method 3: val:%s", __FUNCTION__, val?val:"null"); diff --git a/util/clixon_util_path.c b/util/clixon_util_path.c index 6b935dda..60da8484 100644 --- a/util/clixon_util_path.c +++ b/util/clixon_util_path.c @@ -90,8 +90,8 @@ main(int argc, char *argv0 = argv[0]; int i; cxobj *x = NULL; - cxobj **xvec = NULL; - size_t xlen = 0; + cxobj *xc; + clixon_xvec *xvec = NULL; int c; int len; char *buf = NULL; @@ -244,13 +244,14 @@ main(int argc, clicon_log(LOG_NOTICE, "%s: sort verify failed", __FUNCTION__); } /* Repeat for profiling (default is nr = 1) */ + xvec = NULL; for (i=0; i