diff --git a/CHANGELOG.md b/CHANGELOG.md index 618c2ccc..7d267958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Expected: February 2024 * All clixon applications added command-line option `-V` for printing version * New ca_version callback for customized version output * Optimization: + * Improved performance of GET and PUT operations * Optimized datastore access by ensuring REPORT_ALL in memory and EXPLICIT in file * Added mountpoint cache as yang flag `YANG_FLAG_MTPOINT_POTENTIAL` * Optimized `yang_find`, especially namespace lookup @@ -46,6 +47,10 @@ Users may have to change how they access the system ### C/CLI-API changes on existing features Developers may need to change their code +* Added flags parameter to default functions: + * `xml_default_recurse(...)` -> `xml_default_recurse(..., 0)` + * `xml_defaults_nopresence(...)` -> `xml_default_nopresence(..., 0)` + * Also renamed (_defaults_ -> _default_) * Changed function name: `choice_case_get()` -> `yang_choice_case_get()` * New `clixon-lib@2024-01-01.yang` revision * Removed container creators, reverted from 6.5 diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index 12a3b51d..d3eb06de 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -285,7 +285,7 @@ startup_common(clixon_handle h, if (xml_global_defaults(h, xt, NULL, NULL, yspec, 0) < 0) goto done; /* Apply default values (removed in clear function) */ - if (xml_default_recurse(xt, 0) < 0) + if (xml_default_recurse(xt, 0, 0) < 0) goto done; /* Handcraft transition with with only add tree */ @@ -421,7 +421,7 @@ startup_commit(clixon_handle h, if (plugin_transaction_commit_done_all(h, td) < 0) goto done; /* Remove global defaults and empty non-presence containers */ - if (xml_defaults_nopresence(td->td_target, 2) < 0) + if (xml_default_nopresence(td->td_target, 2, 0) < 0) goto done; /* [Delete and] create running db */ if (xmldb_exists(h, "running") == 1){ diff --git a/apps/backend/backend_get.c b/apps/backend/backend_get.c index 462721ed..bd583497 100644 --- a/apps/backend/backend_get.c +++ b/apps/backend/backend_get.c @@ -950,7 +950,7 @@ get_common(clixon_handle h, if (xml_global_defaults(h, xret, nsc, xpath, yspec, 1) < 0) goto done; /* Apply default values */ - if (xml_default_recurse(xret, 1) < 0) + if (xml_default_recurse(xret, 1, 0) < 0) goto done; break; } diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c index 4627fab3..b22d1fa5 100644 --- a/apps/backend/backend_plugin.c +++ b/apps/backend/backend_plugin.c @@ -389,7 +389,7 @@ clixon_plugin_statedata_all(clixon_handle h, goto done; /* Remove global defaults and empty non-presence containers */ /* XXX: only for state data and according to with-defaults setting */ - if (xml_defaults_nopresence(x, 2) < 0) + if (xml_default_nopresence(x, 2, 0) < 0) goto done; if (xpath_first(x, nsc, "%s", xpath) != NULL){ if ((ret = netconf_trymerge(x, yspec, xret)) < 0) diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 8f7286ab..3e420344 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -613,7 +613,7 @@ cli_show_common(clixon_handle h, ) < 0) goto done; /* Remove empty containers */ - if (xml_defaults_nopresence(xt, 2) < 0) + if (xml_default_nopresence(xt, 2, 0) < 0) goto done; } if (fromroot) diff --git a/apps/restconf/restconf_lib.c b/apps/restconf/restconf_lib.c index 18ea2dcb..c8ad5fe4 100644 --- a/apps/restconf/restconf_lib.c +++ b/apps/restconf/restconf_lib.c @@ -763,7 +763,7 @@ restconf_config_init(clixon_handle h, goto done; } /* Apply default values (removed in clear function) */ - if (xml_default_recurse(xrestconf, 0) < 0) + if (xml_default_recurse(xrestconf, 0, 0) < 0) goto done; if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL && (enable = xml_body(x)) != NULL){ diff --git a/lib/clixon/clixon_datastore.h b/lib/clixon/clixon_datastore.h index 920745f5..1f5cf94c 100644 --- a/lib/clixon/clixon_datastore.h +++ b/lib/clixon/clixon_datastore.h @@ -66,9 +66,7 @@ int xmldb_delete(clixon_handle h, const char *db); int xmldb_create(clixon_handle h, const char *db); /* utility functions */ int xmldb_db_reset(clixon_handle h, const char *db); - cxobj *xmldb_cache_get(clixon_handle h, const char *db); - int xmldb_modified_get(clixon_handle h, const char *db); int xmldb_modified_set(clixon_handle h, const char *db, int value); int xmldb_empty_get(clixon_handle h, const char *db); diff --git a/lib/clixon/clixon_xml_default.h b/lib/clixon/clixon_xml_default.h index 85a7e4d9..02d85239 100644 --- a/lib/clixon/clixon_xml_default.h +++ b/lib/clixon/clixon_xml_default.h @@ -49,10 +49,9 @@ typedef enum yang_class yang_class; /* * Prototypes */ -int xml_default_recurse(cxobj *xn, int state); -int xml_default_recurse_flag(cxobj *xn, int state, int flag); +int xml_default_recurse(cxobj *xn, int state, int flag); int xml_global_defaults(clixon_handle h, cxobj *xn, cvec *nsc, const char *xpath, yang_stmt *yspec, int state); -int xml_defaults_nopresence(cxobj *xn, int purge); +int xml_default_nopresence(cxobj *xn, int mode, int flag); int xml_add_default_tag(cxobj *x, uint16_t flags); int xml_flag_state_default_value(cxobj *x, uint16_t flag); int xml_flag_default_value(cxobj *x, uint16_t flag); diff --git a/lib/src/clixon_datastore.c b/lib/src/clixon_datastore.c index 5e135502..a3e57429 100644 --- a/lib/src/clixon_datastore.c +++ b/lib/src/clixon_datastore.c @@ -713,7 +713,7 @@ xmldb_populate(clixon_handle h, if (xml_global_defaults(h, x, NULL, "/", yspec, 0) < 0) goto done; /* Add default recursive values */ - if (xml_default_recurse(x, 0) < 0) + if (xml_default_recurse(x, 0, 0) < 0) goto done; } retval = ret; diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c index 06d0fd6c..f0fd04a6 100644 --- a/lib/src/clixon_datastore_read.c +++ b/lib/src/clixon_datastore_read.c @@ -729,7 +729,7 @@ xmldb_get_cache(clixon_handle h, if (xml_global_defaults(h, x0t, nsc, xpath, yspec, 0) < 0) goto done; /* Add default recursive values */ - if (xml_default_recurse(x0t, 0) < 0) + if (xml_default_recurse(x0t, 0, 0) < 0) goto done; } /* x0t == NULL */ else @@ -893,7 +893,7 @@ xmldb_get0(clixon_handle h, goto done; if (ret == 0) goto fail; - if (xml_defaults_nopresence(x, 2) < 0) + if (xml_default_nopresence(x, 2, 0) < 0) goto done; *xret = x; x = NULL; diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 6efb182e..ff9a5bbe 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -517,7 +517,7 @@ text_modify(clixon_handle h, goto fail; if (createstr != NULL && (op == OP_REPLACE || op == OP_MERGE || op == OP_CREATE)){ - if (x0 == NULL || xml_defaults_nopresence(x0, 0)){ /* does not exist or is default */ + if (x0 == NULL || xml_default_nopresence(x0, 0, 0)){ /* does not exist or is default */ if (strcmp(createstr, "false")==0){ /* RFC 8040 4.6 PATCH: * If the target resource instance does not exist, the server MUST NOT create it. @@ -774,7 +774,7 @@ text_modify(clixon_handle h, switch(op){ case OP_CREATE: if (x0 && xml_flag(x0, XML_FLAG_DEFAULT)==0){ - if (xml_defaults_nopresence(x0, 0) == 0){ + if (xml_default_nopresence(x0, 0, 0) == 0){ if (netconf_data_exists(cbret, "Data already exists; cannot create new resource") < 0) goto done; goto fail; @@ -1267,15 +1267,6 @@ xmldb_put(clixon_handle h, xml_name(x0), DATASTORE_TOP_SYMBOL); goto done; } - /* XXX Ad-hoc: - * In yang mounts yang specs may not be available - * in initial parsing, but may be at a later stage. - * But it should be possible to find a more precise triggering - */ - if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ - if ((ret = xml_bind_yang(h, x0, YB_MODULE, yspec, NULL)) < 0) - goto done; - } /* Here x0 looks like: ... */ xnacm = clicon_nacm_cache(h); permit = (xnacm==NULL); @@ -1302,16 +1293,15 @@ xmldb_put(clixon_handle h, if (xml_apply(x0, CX_ELMNT, xml_mark_added_ancestors, (void*)(XML_FLAG_ADD|XML_FLAG_DEL)) < 0) goto done; /* Remove empty non-presence containers recursively. - * XXX should use xml_Mark_added_ancestors algorithm that xml_default_recurse uses for only */ - if (xml_defaults_nopresence(x0, 3) < 0) + if (xml_default_nopresence(x0, 3, XML_FLAG_ADD|XML_FLAG_DEL) < 0) goto done; /* Complete defaults in incoming x1 */ if (xml_global_defaults(h, x0, nsc, "/", yspec, 0) < 0) goto done; /* Add default recursive values */ - if (xml_default_recurse_flag(x0, 0, XML_FLAG_ADD|XML_FLAG_DEL) < 0) + if (xml_default_recurse(x0, 0, XML_FLAG_ADD|XML_FLAG_DEL) < 0) goto done; /* Clear flags from previous steps */ if (xml_apply(x0, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index ee001a94..72410d58 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -450,7 +450,7 @@ parse_configfile(clixon_handle h, } } } - if (xml_default_recurse(xt, 0) < 0) + if (xml_default_recurse(xt, 0, 0) < 0) goto done; if ((ret = xml_yang_validate_add(h, xt, &xerr)) < 0) goto done; diff --git a/lib/src/clixon_validate.c b/lib/src/clixon_validate.c index 4116558f..3f276ae6 100644 --- a/lib/src/clixon_validate.c +++ b/lib/src/clixon_validate.c @@ -408,7 +408,7 @@ xml_yang_validate_rpc(clixon_handle h, goto done; /* error or validation fail */ if (ret == 0) goto fail; - if (expanddefault && xml_default_recurse(xn, 0) < 0) + if (expanddefault && xml_default_recurse(xn, 0, 0) < 0) goto done; } // ok: /* pass validation */ @@ -469,7 +469,7 @@ xml_yang_validate_rpc_reply(clixon_handle h, goto done; /* error or validation fail */ if (ret == 0) goto fail; - if (xml_default_recurse(xn, 0) < 0) + if (xml_default_recurse(xn, 0, 0) < 0) goto done; } // ok: /* pass validation */ diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index a60475df..06ff9857 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -1051,7 +1051,6 @@ xml_child_append(cxobj *xp, * @param[in] pos Position * @retval 0 OK * @retval -1 Error - * @see xml_child_append * @note does not do anything with child, you may need to set its parent, etc */ diff --git a/lib/src/clixon_xml_default.c b/lib/src/clixon_xml_default.c index 4828f1a2..d5b31c36 100644 --- a/lib/src/clixon_xml_default.c +++ b/lib/src/clixon_xml_default.c @@ -388,21 +388,6 @@ xml_default(yang_stmt *yt, return retval; } -/*! Recursively fill in default values in an XML tree - * - * @param[in] xt XML tree - * @param[in] state If set expand defaults also for state data, otherwise only config - * @retval 0 OK - * @retval -1 Error - * @see xml_global_defaults - */ -int -xml_default_recurse(cxobj *xn, - int state) -{ - return xml_default_recurse_flag(xn, state, 0x0); -} - /*! Selectively recursively fill in default values in an XML tree using flags * * Skip nodes that are not either CHANGE or "flag" (typically ADD|DEL) @@ -416,9 +401,9 @@ xml_default_recurse(cxobj *xn, * @see xml_default_recurse */ int -xml_default_recurse_flag(cxobj *xn, - int state, - int flag) +xml_default_recurse(cxobj *xn, + int state, + int flag) { int retval = -1; yang_stmt *yn; @@ -444,7 +429,7 @@ xml_default_recurse_flag(cxobj *xn, if (!state && !yang_config(y)) continue; } - if (xml_default_recurse_flag(x, state, flag) < 0) + if (xml_default_recurse(x, state, flag) < 0) goto done; } skip: @@ -567,20 +552,23 @@ xml_global_defaults(clixon_handle h, /*! Recursively find empty nopresence containers and default leaves, optionally purge * + * Semantics of mode parameter somewhat complex * @param[in] xn XML tree - * @param[in] purge 0: Dont remove any nodes + * @param[in] mode 0: Dont remove any nodes * 1: Remove config sub-nodes that are empty non-presence container or default leaf * 2: Remove all sub-nodes that are empty non-presence container or default leaf * 3: Remove all sub-nodes that are empty non-presence containers + * @param[in] flag If set only traverse nodes marked with flag (or CHANGE) * @retval 1 Node is an (recursive) empty non-presence container or default leaf * @retval 0 Other node * @retval -1 Error - * @note xn is not itself removed if purge - * @note for purge=1 are removed only if config or no yang spec(!) + * @note xn is not itself removed if mode + * @note for mode=1 are removed only if config or no yang spec(!) */ int -xml_defaults_nopresence(cxobj *xn, - int purge) +xml_default_nopresence(cxobj *xn, + int mode, + int flag) { int retval = -1; cxobj *x; @@ -592,6 +580,17 @@ xml_defaults_nopresence(cxobj *xn, enum rfc_6020 keyw; int config = 1; + if (flag){ + if (xml_flag(xn, XML_FLAG_CHANGE) != 0) + ; /* continue */ + else if (xml_flag(xn, flag) != 0){ + flag = 0x0; /* Pass all */ + } + else{ + retval = 0; + goto done; + } + } if ((yn = xml_spec(xn)) != NULL){ keyw = yang_keyword_get(yn); if (keyw == Y_CONTAINER && @@ -599,7 +598,7 @@ xml_defaults_nopresence(cxobj *xn, rmx = 1; else if (keyw == Y_LEAF && xml_flag(xn, XML_FLAG_DEFAULT) && - purge != 3) + mode != 3) rmx = 1; config = yang_config_ancestor(yn); } @@ -608,10 +607,10 @@ xml_defaults_nopresence(cxobj *xn, xprev = NULL; while ((x = xml_child_each(xn, x, CX_ELMNT)) != NULL) { /* 1: node is empty non-presence or default leaf (eg rmx) */ - if ((ret = xml_defaults_nopresence(x, purge)) < 0) + if ((ret = xml_default_nopresence(x, mode, flag)) < 0) goto done; if (ret == 1){ - switch (purge){ + switch (mode){ case 1: /* config nodes only */ if (!config) break; diff --git a/lib/src/clixon_xml_io.c b/lib/src/clixon_xml_io.c index 186173e7..46e2f6a1 100644 --- a/lib/src/clixon_xml_io.c +++ b/lib/src/clixon_xml_io.c @@ -119,7 +119,7 @@ xml2output_wdef(cxobj *x, switch (wdef){ case WITHDEFAULTS_EXPLICIT: case WITHDEFAULTS_TRIM: - /* inline of xml_defaults_nopresence() + /* inline of xml_default_nopresence() and xml_flag_state_default_value() */ switch(yang_keyword_get(y)){