diff --git a/lib/src/clixon_data.c b/lib/src/clixon_data.c index 1bfba5c1..ba0e6d19 100644 --- a/lib/src/clixon_data.c +++ b/lib/src/clixon_data.c @@ -864,46 +864,6 @@ clicon_argv_set(clixon_handle h, return retval; } -/*! Get xml database element including id, xml cache, empty on startup and dirty bit - * - * @param[in] h Clixon handle - * @param[in] db Name of database - * @retval de Database element - * @retval NULL None found - */ -db_elmnt * -clicon_db_elmnt_get(clixon_handle h, - const char *db) -{ - clicon_hash_t *cdat = clicon_db_elmnt(h); - void *p; - - if ((p = clicon_hash_value(cdat, db, NULL)) != NULL) - return (db_elmnt *)p; - return NULL; -} - -/*! Set xml database element including id, xml cache, empty on startup and dirty bit - * - * @param[in] h Clixon handle - * @param[in] db Name of database - * @param[in] de Database element - * @retval 0 OK - * @retval -1 Error - * @see xmldb_disconnect -*/ -int -clicon_db_elmnt_set(clixon_handle h, - const char *db, - db_elmnt *de) -{ - clicon_hash_t *cdat = clicon_db_elmnt(h); - - if (clicon_hash_add(cdat, db, de, sizeof(*de))==NULL) - return -1; - return 0; -} - /*! Get session id * * @param[in] h Clixon handle diff --git a/lib/src/clixon_datastore.c b/lib/src/clixon_datastore.c index a3e57429..a2d34293 100644 --- a/lib/src/clixon_datastore.c +++ b/lib/src/clixon_datastore.c @@ -85,6 +85,46 @@ #include "clixon_datastore_write.h" #include "clixon_datastore_read.h" +/*! Get xml database element including id, xml cache, empty on startup and dirty bit + * + * @param[in] h Clixon handle + * @param[in] db Name of database + * @retval de Database element + * @retval NULL None found + */ +db_elmnt * +clicon_db_elmnt_get(clixon_handle h, + const char *db) +{ + clicon_hash_t *cdat = clicon_db_elmnt(h); + void *p; + + if ((p = clicon_hash_value(cdat, db, NULL)) != NULL) + return (db_elmnt *)p; + return NULL; +} + +/*! Set xml database element including id, xml cache, empty on startup and dirty bit + * + * @param[in] h Clixon handle + * @param[in] db Name of database + * @param[in] de Database element + * @retval 0 OK + * @retval -1 Error + * @see xmldb_disconnect +*/ +int +clicon_db_elmnt_set(clixon_handle h, + const char *db, + db_elmnt *de) +{ + clicon_hash_t *cdat = clicon_db_elmnt(h); + + if (clicon_hash_add(cdat, db, de, sizeof(*de))==NULL) + return -1; + return 0; +} + /*! Translate from symbolic database name to actual filename in file-system * * @param[in] th text handle handle @@ -182,14 +222,14 @@ xmldb_copy(clixon_handle h, const char *from, const char *to) { - int retval = -1; - char *fromfile = NULL; - char *tofile = NULL; - db_elmnt *de1 = NULL; /* from */ - db_elmnt *de2 = NULL; /* to */ - db_elmnt de0 = {0,}; - cxobj *x1 = NULL; /* from */ - cxobj *x2 = NULL; /* to */ + int retval = -1; + char *fromfile = NULL; + char *tofile = NULL; + db_elmnt *de1 = NULL; /* from */ + db_elmnt *de2 = NULL; /* to */ + db_elmnt de0 = {0,}; + cxobj *x1 = NULL; /* from */ + cxobj *x2 = NULL; /* to */ clixon_debug(CLIXON_DBG_DATASTORE, "%s %s", from, to); /* XXX lock */ @@ -563,6 +603,30 @@ xmldb_modified_get(clixon_handle h, return de->de_modified; } +/*! Set modified flag from datastore + * + * @param[in] h Clixon handle + * @param[in] db Database name + * @param[in] value 0 or 1 + * @retval 0 OK + * @retval -1 Error (datastore does not exist) + * @note This only makes sense for "candidate", see RFC 6241 Sec 7.5 + */ +int +xmldb_modified_set(clixon_handle h, + const char *db, + int value) +{ + db_elmnt *de; + + if ((de = clicon_db_elmnt_get(h, db)) == NULL){ + clixon_err(OE_CFG, EFAULT, "datastore %s does not exist", db); + return -1; + } + de->de_modified = value; + return 0; +} + /*! Get empty flag from datastore (the datastore was empty ON LOAD) * * @param[in] h Clixon handle @@ -584,18 +648,62 @@ xmldb_empty_get(clixon_handle h, return de->de_empty; } -/*! Set modified flag from datastore +/*! Set empty flag from datastore (the datastore was empty ON LOAD) * * @param[in] h Clixon handle * @param[in] db Database name * @param[in] value 0 or 1 * @retval 0 OK * @retval -1 Error (datastore does not exist) - * @note This only makes sense for "candidate", see RFC 6241 Sec 7.5 - * @note This only works if db cache is used,... */ int -xmldb_modified_set(clixon_handle h, +xmldb_empty_set(clixon_handle h, + const char *db, + int value) +{ + db_elmnt *de; + + if ((de = clicon_db_elmnt_get(h, db)) == NULL){ + clixon_err(OE_CFG, EFAULT, "datastore %s does not exist", db); + return -1; + } + de->de_empty = value; + return 0; +} + +/*! Get volatile flag of datastore + * + * Whether to sync to disk on every update (ie xmldb_put) + * @param[in] h Clixon handle + * @param[in] db Database name + * @retval 1 Db was empty on load + * @retval 0 Db was not empty on load + * @retval -1 Error (datastore does not exist) + */ +int +xmldb_volatile_get(clixon_handle h, + const char *db) +{ + db_elmnt *de; + + if ((de = clicon_db_elmnt_get(h, db)) == NULL){ + clixon_err(OE_CFG, EFAULT, "datastore %s does not exist", db); + return -1; + } + return de->de_volatile; +} + +/*! Set datastore status of datastore + * + * Whether to sync to disk on every update (ie xmldb_put) + * @param[in] h Clixon handle + * @param[in] db Database name + * @param[in] value 0 or 1 + * @retval 0 OK + * @retval -1 Error (datastore does not exist) + */ +int +xmldb_volatile_set(clixon_handle h, const char *db, int value) { @@ -605,7 +713,7 @@ xmldb_modified_set(clixon_handle h, clixon_err(OE_CFG, EFAULT, "datastore %s does not exist", db); return -1; } - de->de_modified = value; + de->de_volatile = value; return 0; } diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index ff9a5bbe..fa456d05 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -1314,9 +1314,10 @@ xmldb_put(clixon_handle h, de0.de_xml = x0; de0.de_empty = (xml_child_nr(de0.de_xml) == 0); clicon_db_elmnt_set(h, db, &de0); - /* Write cache to file */ - if (xmldb_write_cache2file(h, db) < 0) - goto done; + /* Write cache to file unless volatile */ + if (xmldb_volatile_get(h, db) == 0) + if (xmldb_write_cache2file(h, db) < 0) + goto done; retval = 1; done: clixon_debug(CLIXON_DBG_DATASTORE | CLIXON_DBG_DETAIL, "retval:%d", retval); diff --git a/lib/src/clixon_xml_default.c b/lib/src/clixon_xml_default.c index d5b31c36..74008cc1 100644 --- a/lib/src/clixon_xml_default.c +++ b/lib/src/clixon_xml_default.c @@ -72,6 +72,9 @@ #include "clixon_xml_nsctx.h" #include "clixon_xml_map.h" #include "clixon_xml_default.h" +#include "clixon_netconf_lib.h" +#include "clixon_yang_module.h" +#include "clixon_datastore.h" /* Forward */ static int xml_default(yang_stmt *yt, cxobj *xt, int state); diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index f74fc015..798dbc2e 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -579,8 +579,8 @@ xml_tree_equal(cxobj *x0, { int retval = 1; /* Not equal */ int eq; - yang_stmt *yc0; - yang_stmt *yc1; + yang_stmt *y0c; + yang_stmt *y1c; char *b0; char *b1; cxobj *x0c; /* x0 child */ @@ -594,41 +594,35 @@ xml_tree_equal(cxobj *x0, for (;;){ if (x0c == NULL && x1c == NULL) goto ok; - else if (x0c == NULL){ - /* If cl:ignore-compare extension, return equal */ - if ((yc1 = xml_spec(x1c)) != NULL){ - if (yang_extension_value(yc1, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0) - goto done; - if (extflag) - goto ok; - } - goto done; - } - else if (x1c == NULL){ - if ((yc0 = xml_spec(x0c)) != NULL){ - if (yang_extension_value(yc0, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0) - goto done; - if (extflag) - goto ok; - } - goto done; - } - if ((yc0 = xml_spec(x0c)) != NULL){ - if (yang_extension_value(yc0, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0) + /* If cl:ignore-compare extension, return equal */ + if (x0c && (y0c = xml_spec(x0c)) != NULL){ + if (yang_extension_value(y0c, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0) goto done; if (extflag){ /* skip */ - x0c = xml_child_each(x0, x0c, CX_ELMNT); - continue; + if (x1c) { + x0c = xml_child_each(x0, x0c, CX_ELMNT); + continue; + } + else + goto ok; } } - if ((yc1 = xml_spec(x1c)) != NULL){ - if (yang_extension_value(yc1, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0) + if (x1c && (y1c = xml_spec(x1c)) != NULL){ + if (yang_extension_value(y1c, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0) goto done; if (extflag){ /* skip */ - x1c = xml_child_each(x1, x1c, CX_ELMNT); - continue; + if (x1c) { + x1c = xml_child_each(x1, x1c, CX_ELMNT); + continue; + } + else + goto ok; } } + if (x0c == NULL) + goto done; + else if (x1c == NULL) + goto done; /* Both x0c and x1c exists, check if they are yang-equal. */ if ((eq = xml_cmp(x0c, x1c, 0, 0, NULL)) != 0){ goto done; @@ -637,11 +631,11 @@ xml_tree_equal(cxobj *x0, /* xml-spec NULL could happen with anydata children for example, * if so, continue compare children but without yang */ - if (yc0 && yc1 && yc0 != yc1){ /* choice */ + if (y0c && y1c && y0c != y1c){ /* choice */ goto done; } else - if (yc0 && yang_keyword_get(yc0) == Y_LEAF){ + if (y0c && yang_keyword_get(y0c) == Y_LEAF){ /* if x0c and x1c are leafs w bodies, then they may be changed */ b0 = xml_body(x0c); b1 = xml_body(x1c);