From ee9b74d7354f8a2928295121a8688cb81bdf76e9 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sun, 16 Apr 2017 19:06:19 +0200 Subject: [PATCH] formalizing xmldb api --- apps/backend/backend_client.c | 4 +- apps/backend/backend_main.c | 13 +++-- apps/restconf/restconf_methods.c | 75 +------------------------ datastore/datastore_client.c | 40 +++++++++----- datastore/keyvalue/clixon_keyvalue.c | 77 ++++++++++++++++++-------- datastore/keyvalue/clixon_keyvalue.h | 2 +- datastore/text/clixon_xmldb_text.c | 43 ++++++++++++--- datastore/text/clixon_xmldb_text.h | 2 +- lib/clixon/clixon_xml_db.h | 4 +- lib/clixon/clixon_xml_map.h | 1 + lib/src/clixon_xml.c | 2 +- lib/src/clixon_xml_db.c | 73 ++++++++++++++----------- lib/src/clixon_xml_map.c | 82 ++++++++++++++++++++++++++++ 13 files changed, 252 insertions(+), 166 deletions(-) diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index f347e6f9..591d0e33 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -438,7 +438,7 @@ from_client_unlock(clicon_handle h, goto ok; } else{ - xmldb_unlock(h, db, pid); + xmldb_unlock(h, db); if (cprintf(cbret, "") < 0) goto done; } @@ -496,7 +496,7 @@ from_client_kill_session(clicon_handle h, if (1 || (kill (pid, 0) != 0 && errno == ESRCH)){ /* Nothing there */ /* clear from locks */ if (xmldb_islocked(h, db) == pid) - xmldb_unlock(h, db, pid); + xmldb_unlock(h, db); } else{ /* failed to kill client */ cprintf(cbret, "" diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index a8d54d97..d3973ac6 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -73,7 +73,7 @@ #include "backend_handle.h" /* Command line options to be passed to getopt(3) */ -#define BACKEND_OPTS "hD:f:d:Fzu:P:1IRCc:rg:pty:x:" +#define BACKEND_OPTS "hD:f:d:b:Fzu:P:1IRCc:rg:py:x:" /*! Terminate. Cannot use h after this */ static int @@ -129,6 +129,7 @@ usage(char *argv0, clicon_handle h) " -D \tdebug\n" " -f \tCLICON config file (mandatory)\n" " -d \tSpecify backend plugin directory (default: %s)\n" + " -b \tSpecify XMLDB database directory\n" " -z\t\tKill other config daemon and exit\n" " -F\t\tforeground\n" " -1\t\tonce (dont wait for events)\n" @@ -140,7 +141,6 @@ usage(char *argv0, clicon_handle h) " -c \tLoad specified application config.\n" " -r\t\tReload running database\n" " -p \t\tPrint database yang specification\n" - " -t \t\tPrint alternate spec translation (eg if YANG print KEY, if KEY print YANG)\n" " -g \tClient membership required to this group (default: %s)\n" " -y \tOverride yang spec file (dont include .yang suffix)\n" " -x \tXMLDB plugin\n", @@ -308,7 +308,6 @@ main(int argc, char **argv) clicon_handle h; int help = 0; int printspec = 0; - int printalt = 0; int pid; char *pidfile; char *sock; @@ -387,6 +386,11 @@ main(int argc, char **argv) usage(argv[0], h); clicon_option_str_set(h, "CLICON_BACKEND_DIR", optarg); break; + case 'b': /* XMLDB database directory */ + if (!strlen(optarg)) + usage(argv[0], h); + clicon_option_str_set(h, "CLICON_XMLDB_DIR", optarg); + break; case 'F' : /* foreground */ foreground = 1; break; @@ -425,9 +429,6 @@ main(int argc, char **argv) case 'p' : /* Print spec */ printspec++; break; - case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */ - printalt++; - break; case 'y' :{ /* yang module */ /* Set revision to NULL, extract dir and module */ char *str = strdup(optarg); diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index 8a74a0d6..f3e61858 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -152,86 +152,19 @@ api_data_get_gen(clicon_handle h, int head) { int retval = -1; - cg_var *cv; - char *val; - char *v; - int i; cbuf *path = NULL; - cbuf *path1 = NULL; cbuf *cbx = NULL; cxobj **vec = NULL; yang_spec *yspec; - yang_stmt *y = NULL; - yang_stmt *ykey; - char *name; - cvec *cvk = NULL; /* vector of index keys */ - cg_var *cvi; cxobj *xret = NULL; clicon_debug(1, "%s", __FUNCTION__); yspec = clicon_dbspec_yang(h); if ((path = cbuf_new()) == NULL) goto done; - if ((path1 = cbuf_new()) == NULL) /* without [] qualifiers */ - goto done; - cv = NULL; - cprintf(path1, "/"); - /* translate eg a/b=c -> a/[b=c] */ - for (i=pi; iys_argument); - notfound(r); - goto done; - } - clicon_debug(1, "ykey:%s", ykey->ys_argument); - - /* The value is a list of keys: [ ]* */ - if ((cvk = yang_arg2cvec(ykey, " ")) == NULL) - goto done; - cvi = NULL; - /* Iterate over individual yang keys */ - cprintf(path, "/%s", name); - v = val; - while ((cvi = cvec_each(cvk, cvi)) != NULL){ - cprintf(path, "[%s=%s]", cv_string_get(cvi), v); - v += strlen(v)+1; - } - if (val) - free(val); - } - else{ - cprintf(path, "%s%s", (i==pi?"":"/"), name); - cprintf(path1, "/%s", name); - } + if (xml_apipath2xpath(yspec, pcvec, pi, path) < 0){ + notfound(r); + goto done; } clicon_debug(1, "%s path:%s", __FUNCTION__, cbuf_get(path)); if (clicon_rpc_get_config(h, "running", cbuf_get(path), &xret) < 0){ @@ -267,8 +200,6 @@ api_data_get_gen(clicon_handle h, cbuf_free(cbx); if (path) cbuf_free(path); - if (path1) - cbuf_free(path1); if (xret) xml_free(xret); return retval; diff --git a/datastore/datastore_client.c b/datastore/datastore_client.c index 7445efc0..2a094e7b 100644 --- a/datastore/datastore_client.c +++ b/datastore/datastore_client.c @@ -35,8 +35,9 @@ ./datastore_client -d candidate -b /usr/local/var/routing -p /home/olof/src/clixon/datastore/keyvalue/keyvalue.so -y /usr/local/share/routing/yang -m ietf-ip get / -sudo ./datastore_client -d candidate -b /usr/local/var/routing -p /home/olof/src/clixon/datastore/keyvalue/keyvalue.so -y /usr/local/share/routing/yang -m ietf-ip put merge /interfaces/interface=eth0 -eth66 +sudo ./datastore_client -d candidate -b /usr/local/var/routing -p /home/olof/src/clixon/datastore/keyvalue/keyvalue.so -y /usr/local/share/routing/yang -m ietf-ip put merge /interfaces/interface=eth66 'eth66' + +sudo ./datastore_client -d candidate -b /usr/local/var/routing -p /home/olof/src/clixon/datastore/keyvalue/keyvalue.so -y /usr/local/share/routing/yang -m ietf-ip put merge / 'eth0true' * */ @@ -89,10 +90,10 @@ usage(char *argv0) "\t-m \tYang module. Mandatory\n" "and command is either:\n" "\tget \n" - "\tput (set|merge|delete) \tXML on stdin\n" - "\tcopy \n" + "\tput (set|merge|delete) \n" + "\tcopy \n" "\tlock \n" - "\tunlock \n" + "\tunlock\n" "\tunlock_all \n" "\tislocked\n" "\texists\n" @@ -212,18 +213,18 @@ main(int argc, char **argv) if (xmldb_setopt(h, "yangspec", yspec) < 0) goto done; if (strcmp(cmd, "get")==0){ - if (argc < 2) + if (argc != 2) usage(argv0); if (xmldb_get(h, db, argv[1], &xt, NULL, 0) < 0) goto done; clicon_xml2file(stdout, xt, 0, 1); } else if (strcmp(cmd, "put")==0){ - if (argc < 3) + if (argc != 4) usage(argv0); if (xml_operation(argv[1], &op) < 0) usage(argv0); - if (clicon_xml_parse_file(0, &xt, "") < 0) + if (clicon_xml_parse_str(argv[3], &xt) < 0) goto done; if (xml_rootchild(xt, 0, &xn) < 0) goto done; @@ -233,50 +234,59 @@ main(int argc, char **argv) xml_free(xn); } else if (strcmp(cmd, "copy")==0){ - if (argc < 3) + if (argc != 2) usage(argv0); - if (xmldb_copy(h, argv[1], argv[2]) < 0) + if (xmldb_copy(h, db, argv[1]) < 0) goto done; } else if (strcmp(cmd, "lock")==0){ - if (argc < 2) + if (argc != 2) usage(argv0); pid = atoi(argv[1]); if (xmldb_lock(h, db, pid) < 0) goto done; } else if (strcmp(cmd, "unlock")==0){ - if (argc < 2) + if (argc != 1) usage(argv0); - pid = atoi(argv[1]); - if (xmldb_unlock(h, db, pid) < 0) + if (xmldb_unlock(h, db) < 0) goto done; } else if (strcmp(cmd, "unlock_all")==0){ - if (argc < 2) + if (argc != 2) usage(argv0); pid = atoi(argv[1]); if (xmldb_unlock_all(h, pid) < 0) goto done; } else if (strcmp(cmd, "islocked")==0){ + if (argc != 1) + usage(argv0); if ((ret = xmldb_islocked(h, db)) < 0) goto done; fprintf(stdout, "islocked: %d\n", ret); } else if (strcmp(cmd, "exists")==0){ + if (argc != 1) + usage(argv0); if ((ret = xmldb_exists(h, db)) < 0) goto done; fprintf(stdout, "exists: %d\n", ret); } else if (strcmp(cmd, "delete")==0){ + if (argc != 1) + usage(argv0); if (xmldb_delete(h, db) < 0) goto done; } else if (strcmp(cmd, "init")==0){ + if (argc != 1) + usage(argv0); if (xmldb_init(h, db) < 0) goto done; } + else + clicon_err(OE_DB, 0, "Unrecognized command: %s", cmd); done: return 0; } diff --git a/datastore/keyvalue/clixon_keyvalue.c b/datastore/keyvalue/clixon_keyvalue.c index ab8565b3..65411349 100644 --- a/datastore/keyvalue/clixon_keyvalue.c +++ b/datastore/keyvalue/clixon_keyvalue.c @@ -160,7 +160,7 @@ static int _startup_locked = 0; * The filename reside in CLICON_XMLDB_DIR option */ static int -db2file(struct kv_handle *kh, +kv_db2file(struct kv_handle *kh, char *db, char **filename) { @@ -180,7 +180,7 @@ db2file(struct kv_handle *kh, strcmp(db, "candidate") != 0 && strcmp(db, "startup") != 0 && strcmp(db, "tmp") != 0){ - clicon_err(OE_XML, 0, "Unexpected database: %s", db); + clicon_err(OE_XML, 0, "No such database: %s", db); goto done; } cprintf(cb, "%s/%s_db", dir, db); @@ -616,7 +616,7 @@ kv_get(xmldb_handle xh, clicon_debug(2, "%s", __FUNCTION__); - if (db2file(kh, db, &dbfile) < 0) + if (kv_db2file(kh, db, &dbfile) < 0) goto done; if (dbfile==NULL){ clicon_err(OE_XML, 0, "dbfile NULL"); @@ -629,7 +629,7 @@ kv_get(xmldb_handle xh, /* Read in complete database (this can be optimized) */ if ((npairs = db_regexp(dbfile, "", __FUNCTION__, &pairs, 0)) < 0) goto done; - if ((xt = xml_new_spec("clicon", NULL, yspec)) == NULL) + if ((xt = xml_new_spec("config", NULL, yspec)) == NULL) goto done; /* Translate to complete xml tree */ for (i = 0; i < npairs; i++) { @@ -836,7 +836,7 @@ xmldb_put_xkey(struct kv_handle *kh, clicon_err(OE_YANG, ENOENT, "No yang spec"); goto done; } - if (db2file(kh, db, &filename) < 0) + if (kv_db2file(kh, db, &filename) < 0) goto done; if (xk == NULL || *xk!='/'){ clicon_err(OE_DB, 0, "Invalid key: %s", xk); @@ -852,6 +852,9 @@ xmldb_put_xkey(struct kv_handle *kh, } if ((vec = clicon_strsep(xk, "/", &nvec)) == NULL) goto done; + /* Remove trailing '/'. Like in /a/ -> /a */ + if (nvec > 1 && !strlen(vec[nvec-1])) + nvec--; if (nvec < 2){ clicon_err(OE_XML, 0, "Malformed key: %s", xk); goto done; @@ -1066,7 +1069,7 @@ xmldb_put_restconf_api_path(struct kv_handle *kh, clicon_err(OE_YANG, ENOENT, "No yang spec"); goto done; } - if (db2file(kh, db, &filename) < 0) + if (kv_db2file(kh, db, &filename) < 0) goto done; if (api_path == NULL || *api_path!='/'){ clicon_err(OE_DB, 0, "Invalid api path: %s", api_path); @@ -1082,6 +1085,9 @@ xmldb_put_restconf_api_path(struct kv_handle *kh, } if ((vec = clicon_strsep(api_path, "/", &nvec)) == NULL) goto done; + /* Remove trailing '/'. Like in /a/ -> /a */ + if (nvec > 1 && !strlen(vec[nvec-1])) + nvec--; if (nvec < 2){ clicon_err(OE_XML, 0, "Malformed key: %s", api_path); goto done; @@ -1266,13 +1272,14 @@ kv_put(xmldb_handle xh, yang_spec *yspec; char *dbfilename = NULL; - if (xml_child_nr(xt)==0 || xml_body(xt)!= NULL) + if ((xml_child_nr(xt)==0 || xml_body(xt)!= NULL) && + api_path && strlen(api_path) && strcmp(api_path,"/")) return xmldb_put_xkey(kh, db, op, api_path, xml_body(xt)); if ((yspec = kh->kh_yangspec) == NULL){ clicon_err(OE_YANG, ENOENT, "No yang spec"); goto done; } - if (db2file(kh, db, &dbfilename) < 0) + if (kv_db2file(kh, db, &dbfilename) < 0) goto done; if (op == OP_REPLACE){ if (db_delete(dbfilename) < 0) @@ -1281,7 +1288,8 @@ kv_put(xmldb_handle xh, goto done; } while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL){ - if (api_path && strlen(api_path)){ + /* An api path that is not / */ + if (api_path && strlen(api_path) && strcmp(api_path,"/")){ if (xmldb_put_restconf_api_path(kh, db, op, api_path, x) < 0) goto done; continue; @@ -1323,9 +1331,9 @@ kv_copy(xmldb_handle xh, char *tofile = NULL; /* XXX lock */ - if (db2file(kh, from, &fromfile) < 0) + if (kv_db2file(kh, from, &fromfile) < 0) goto done; - if (db2file(kh, to, &tofile) < 0) + if (kv_db2file(kh, to, &tofile) < 0) goto done; if (clicon_file_copy(fromfile, tofile) < 0) goto done; @@ -1350,16 +1358,25 @@ kv_lock(xmldb_handle xh, char *db, int pid) { + int retval = -1; // struct kv_handle *kh = handle(xh); - + fprintf(stderr, "%s %s %d\n", __FUNCTION__, db, pid); if (strcmp("running", db) == 0) _running_locked = pid; else if (strcmp("candidate", db) == 0) _candidate_locked = pid; else if (strcmp("startup", db) == 0) _startup_locked = pid; + else{ + clicon_err(OE_DB, 0, "No such database: %s", db); + goto done; + } clicon_debug(1, "%s: locked by %u", db, pid); - return 0; + fprintf(stderr, "running:%d candidate:%d startup:%d\n", + _running_locked, _candidate_locked, _startup_locked); + retval = 0; + done: + return retval; } /*! Unlock database @@ -1372,18 +1389,24 @@ kv_lock(xmldb_handle xh, */ int kv_unlock(xmldb_handle xh, - char *db, - int pid) + char *db) { + int retval = -1; // struct kv_handle *kh = handle(xh); - + fprintf(stderr, "%s %s\n", __FUNCTION__, db); if (strcmp("running", db) == 0) _running_locked = 0; else if (strcmp("candidate", db) == 0) _candidate_locked = 0; else if (strcmp("startup", db) == 0) _startup_locked = 0; - return 0; + else{ + clicon_err(OE_DB, 0, "No such database: %s", db); + goto done; + } + retval = 0; + done: + return retval; } /*! Unlock all databases locked by pid (eg process dies) @@ -1418,15 +1441,21 @@ int kv_islocked(xmldb_handle xh, char *db) { + int retval = -1; // struct kv_handle *kh = handle(xh); + fprintf(stderr, "%s %s\n", __FUNCTION__, db); + fprintf(stderr, "running:%d candidate:%d startup:%d\n", + _running_locked, _candidate_locked, _startup_locked); if (strcmp("running", db) == 0) - return (_running_locked); + retval = _running_locked; else if (strcmp("candidate", db) == 0) - return(_candidate_locked); + retval = _candidate_locked; else if (strcmp("startup", db) == 0) - return(_startup_locked); - return 0; + retval = _startup_locked; + else + clicon_err(OE_DB, 0, "No such database: %s", db); + return retval; } /*! Check if db exists @@ -1445,7 +1474,7 @@ kv_exists(xmldb_handle xh, char *filename = NULL; struct stat sb; - if (db2file(kh, db, &filename) < 0) + if (kv_db2file(kh, db, &filename) < 0) goto done; if (lstat(filename, &sb) < 0) retval = 0; @@ -1471,7 +1500,7 @@ kv_delete(xmldb_handle xh, struct kv_handle *kh = handle(xh); char *filename = NULL; - if (db2file(kh, db, &filename) < 0) + if (kv_db2file(kh, db, &filename) < 0) goto done; if (db_delete(filename) < 0) goto done; @@ -1496,7 +1525,7 @@ kv_init(xmldb_handle xh, struct kv_handle *kh = handle(xh); char *filename = NULL; - if (db2file(kh, db, &filename) < 0) + if (kv_db2file(kh, db, &filename) < 0) goto done; if (db_init(filename) < 0) goto done; diff --git a/datastore/keyvalue/clixon_keyvalue.h b/datastore/keyvalue/clixon_keyvalue.h index 85e6d8ab..88ae2621 100644 --- a/datastore/keyvalue/clixon_keyvalue.h +++ b/datastore/keyvalue/clixon_keyvalue.h @@ -46,7 +46,7 @@ int kv_put(xmldb_handle h, char *db, enum operation_type op, int kv_dump(FILE *f, char *dbfilename, char *rxkey); int kv_copy(xmldb_handle h, char *from, char *to); int kv_lock(xmldb_handle h, char *db, int pid); -int kv_unlock(xmldb_handle h, char *db, int pid); +int kv_unlock(xmldb_handle h, char *db); int kv_unlock_all(xmldb_handle h, int pid); int kv_islocked(xmldb_handle h, char *db); int kv_exists(xmldb_handle h, char *db); diff --git a/datastore/text/clixon_xmldb_text.c b/datastore/text/clixon_xmldb_text.c index f9c67fd7..4b6b3b91 100644 --- a/datastore/text/clixon_xmldb_text.c +++ b/datastore/text/clixon_xmldb_text.c @@ -106,7 +106,7 @@ static int _startup_locked = 0; * The filename reside in CLICON_XMLDB_DIR option */ static int -db2file(struct text_handle *th, +text_db2file(struct text_handle *th, char *db, char **filename) { @@ -126,7 +126,7 @@ db2file(struct text_handle *th, strcmp(db, "candidate") != 0 && strcmp(db, "startup") != 0 && strcmp(db, "tmp") != 0){ - clicon_err(OE_XML, 0, "Unexpected database: %s", db); + clicon_err(OE_XML, 0, "No such database: %s", db); goto done; } cprintf(cb, "%s/%s_db", dir, db); @@ -292,7 +292,7 @@ text_get(xmldb_handle xh, int i; struct text_handle *th = handle(xh); - if (db2file(th, db, &dbfile) < 0) + if (text_db2file(th, db, &dbfile) < 0) goto done; if (dbfile==NULL){ clicon_err(OE_XML, 0, "dbfile NULL"); @@ -348,7 +348,6 @@ text_get(xmldb_handle xh, if (fd != -1) close(fd); return retval; - } /*! Modify database provided an xml tree and an operation @@ -380,10 +379,37 @@ text_put(xmldb_handle xh, cxobj *xt) { int retval = -1; - // struct text_handle *th = handle(xh); + struct text_handle *th = handle(xh); + char *dbfile = NULL; + int fd = -1; + cbuf *cb = NULL; + if (text_db2file(th, db, &dbfile) < 0) + goto done; + if (dbfile==NULL){ + clicon_err(OE_XML, 0, "dbfile NULL"); + goto done; + } + if ((fd = open(dbfile, O_WRONLY | O_CREAT)) == -1) { + clicon_err(OE_UNIX, errno, "open(%s)", dbfile); + goto done; + } + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_XML, errno, "cbuf_new"); + goto done; + } + if (clicon_xml2cbuf(cb, xt, 0, 0) < 0) + goto done; + if (write(fd, cbuf_get(cb), cbuf_len(cb)+1) < 0){ + clicon_err(OE_UNIX, errno, "write(%s)", dbfile); + goto done; + } retval = 0; - // done: + done: + if (fd != -1) + close(fd); + if (cb) + cbuf_free(cb); return retval; } @@ -441,8 +467,7 @@ text_lock(xmldb_handle xh, */ int text_unlock(xmldb_handle xh, - char *db, - int pid) + char *db) { // struct text_handle *th = handle(xh); @@ -515,7 +540,7 @@ text_exists(xmldb_handle xh, char *filename = NULL; struct stat sb; - if (db2file(th, db, &filename) < 0) + if (text_db2file(th, db, &filename) < 0) goto done; if (lstat(filename, &sb) < 0) retval = 0; diff --git a/datastore/text/clixon_xmldb_text.h b/datastore/text/clixon_xmldb_text.h index 83f5db43..c82765bc 100644 --- a/datastore/text/clixon_xmldb_text.h +++ b/datastore/text/clixon_xmldb_text.h @@ -46,7 +46,7 @@ int text_put(xmldb_handle h, char *db, enum operation_type op, int text_dump(FILE *f, char *dbfilename, char *rxkey); int text_copy(xmldb_handle h, char *from, char *to); int text_lock(xmldb_handle h, char *db, int pid); -int text_unlock(xmldb_handle h, char *db, int pid); +int text_unlock(xmldb_handle h, char *db); int text_unlock_all(xmldb_handle h, int pid); int text_islocked(xmldb_handle h, char *db); int text_exists(xmldb_handle h, char *db); diff --git a/lib/clixon/clixon_xml_db.h b/lib/clixon/clixon_xml_db.h index 3cad3679..eced86bf 100644 --- a/lib/clixon/clixon_xml_db.h +++ b/lib/clixon/clixon_xml_db.h @@ -89,7 +89,7 @@ typedef int (xmldb_copy_t)(xmldb_handle xh, char *from, char *to); typedef int (xmldb_lock_t)(xmldb_handle xh, char *db, int pid); /* Type of xmldb unlock function */ -typedef int (xmldb_unlock_t)(xmldb_handle xh, char *db, int pid); +typedef int (xmldb_unlock_t)(xmldb_handle xh, char *db); /* Type of xmldb unlock_all function */ typedef int (xmldb_unlock_all_t)(xmldb_handle xh, int pid); @@ -145,7 +145,7 @@ int xmldb_put(clicon_handle h, char *db, enum operation_type op, char *api_path, cxobj *xt); int xmldb_copy(clicon_handle h, char *from, char *to); int xmldb_lock(clicon_handle h, char *db, int pid); -int xmldb_unlock(clicon_handle h, char *db, int pid); +int xmldb_unlock(clicon_handle h, char *db); int xmldb_unlock_all(clicon_handle h, int pid); int xmldb_islocked(clicon_handle h, char *db); int xmldb_exists(clicon_handle h, char *db); diff --git a/lib/clixon/clixon_xml_map.h b/lib/clixon/clixon_xml_map.h index dcc5f0ee..5f816be2 100644 --- a/lib/clixon/clixon_xml_map.h +++ b/lib/clixon/clixon_xml_map.h @@ -68,5 +68,6 @@ int xml_tree_prune_unmarked(cxobj *xt, int *upmark); int xml_default(cxobj *x, void *arg); int xml_order(cxobj *x, void *arg); int xml_sanity(cxobj *x, void *arg); +int xml_apipath2xpath(yang_spec *yspec, cvec *pcvec, int pi, cbuf *path); #endif /* _CLIXON_XML_MAP_H_ */ diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index 55109dbb..7d1ec8bd 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -843,7 +843,7 @@ clicon_xml2file(FILE *f, int level, int prettyprint) { - cbuf *cb; + cbuf *cb = NULL; int retval = -1; if ((cb = cbuf_new()) == NULL){ diff --git a/lib/src/clixon_xml_db.c b/lib/src/clixon_xml_db.c index 8abfd12b..82a5b1ed 100644 --- a/lib/src/clixon_xml_db.c +++ b/lib/src/clixon_xml_db.c @@ -30,8 +30,8 @@ the terms of any one of the Apache License version 2 or the GPL. ***** END LICENSE BLOCK ***** - */ + */ #include #include @@ -169,7 +169,6 @@ xmldb_plugin_unload(clicon_handle h) * datastore. Note also that the xmldb handle is hidden in the clicon * handle, the clixon user does not need to handle it. Note also that * typically only the backend invokes the datastore. - * XXX what args does connect have? */ int xmldb_connect(clicon_handle h) @@ -201,8 +200,8 @@ xmldb_connect(clicon_handle h) int xmldb_disconnect(clicon_handle h) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -237,8 +236,8 @@ xmldb_getopt(clicon_handle h, char *optname, void **value) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -270,8 +269,8 @@ xmldb_setopt(clicon_handle h, char *optname, void *value) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -320,7 +319,6 @@ xmldb_setopt(clicon_handle h, * @see xpath_vec * @see xmldb_get */ - int xmldb_get(clicon_handle h, char *db, @@ -329,8 +327,8 @@ xmldb_get(clicon_handle h, cxobj ***xvec, size_t *xlen) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -345,8 +343,16 @@ xmldb_get(clicon_handle h, clicon_err(OE_DB, 0, "Not connected to datastore plugin"); goto done; } - clicon_log(LOG_WARNING, "%s: db:%s xpath:%s", __FUNCTION__, db, xpath); retval = xa->xa_get_fn(xh, db, xpath, xtop, xvec, xlen); +#if 0 /* XXX DEBUG */ + if (retval == 0) { + cbuf *cb = cbuf_new(); + clicon_xml2cbuf(cb, *xtop, 0, 0); + clicon_log(LOG_WARNING, "%s: db:%s xpath:%s xml:%s", + __FUNCTION__, db, xpath, cbuf_get(cb)); + cbuf_free(cb); + } +#endif done: return retval; } @@ -379,8 +385,8 @@ xmldb_put(clicon_handle h, char *api_path, cxobj *xt) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -395,6 +401,7 @@ xmldb_put(clicon_handle h, clicon_err(OE_DB, 0, "Not connected to datastore plugin"); goto done; } +#if 0 /* XXX DEBUG */ { cbuf *cb = cbuf_new(); if (clicon_xml2cbuf(cb, xt, 0, 0) < 0) @@ -404,6 +411,7 @@ xmldb_put(clicon_handle h, db, op, api_path, cbuf_get(cb)); cbuf_free(cb); } +#endif retval = xa->xa_put_fn(xh, db, op, api_path, xt); done: return retval; @@ -421,8 +429,8 @@ xmldb_copy(clicon_handle h, char *from, char *to) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -454,8 +462,8 @@ xmldb_lock(clicon_handle h, char *db, int pid) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -485,11 +493,10 @@ xmldb_lock(clicon_handle h, */ int xmldb_unlock(clicon_handle h, - char *db, - int pid) + char *db) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -504,7 +511,7 @@ xmldb_unlock(clicon_handle h, clicon_err(OE_DB, 0, "Not connected to datastore plugin"); goto done; } - retval = xa->xa_unlock_fn(xh, db, pid); + retval = xa->xa_unlock_fn(xh, db); done: return retval; } @@ -519,8 +526,8 @@ int xmldb_unlock_all(clicon_handle h, int pid) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -551,8 +558,8 @@ int xmldb_islocked(clicon_handle h, char *db) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -583,8 +590,8 @@ int xmldb_exists(clicon_handle h, char *db) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -614,8 +621,8 @@ int xmldb_delete(clicon_handle h, char *db) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ @@ -645,8 +652,8 @@ int xmldb_init(clicon_handle h, char *db) { - int retval = -1; - xmldb_handle xh; + int retval = -1; + xmldb_handle xh; struct xmldb_api *xa; if ((xa = clicon_xmldb_api_get(h)) == NULL){ diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 9ac928a6..2d460f55 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -1248,3 +1248,85 @@ xml_sanity(cxobj *xt, return retval; } +/*! Translate from restconf api-path to xml xpath + * eg a/b=c -> a/[b=c] + * @param[in] yspec Yang spec + * @param[in] pcvec api-path as cvec + * @param[in] pi Length of cvec + * @param[out] path The xpath as cligen bif variable string + */ +int +xml_apipath2xpath(yang_spec *yspec, + cvec *pcvec, + int pi, + cbuf *path) +{ + int retval = -1; + int i; + cg_var *cv; + char *name; + cvec *cvk = NULL; /* vector of index keys */ + yang_stmt *y = NULL; + char *val; + char *v; + yang_stmt *ykey; + cg_var *cvi; + + for (i=pi; iys_argument); + goto done; + } + clicon_debug(1, "ykey:%s", ykey->ys_argument); + + /* The value is a list of keys: [ ]* */ + if ((cvk = yang_arg2cvec(ykey, " ")) == NULL) + goto done; + cvi = NULL; + /* Iterate over individual yang keys */ + cprintf(path, "/%s", name); + v = val; + while ((cvi = cvec_each(cvk, cvi)) != NULL){ + cprintf(path, "[%s=%s]", cv_string_get(cvi), v); + v += strlen(v)+1; + } + if (val) + free(val); + } + else{ + cprintf(path, "%s%s", (i==pi?"":"/"), name); + } + } + retval = 0; + done: + return retval; +}