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; i 0){
- if ((val = cv2str_dup(cv)) == NULL)
- goto done;
- v = val;
- /* XXX sync with yang */
- while((v=index(v, ',')) != NULL){
- *v = '\0';
- v++;
- }
- /* Find keys */
- if ((ykey = yang_find((yang_node*)y, Y_KEY, NULL)) == NULL){
- clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key",
- __FUNCTION__, y->ys_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; i 0){
+ if ((val = cv2str_dup(cv)) == NULL)
+ goto done;
+ v = val;
+ /* XXX sync with yang */
+ while((v=index(v, ',')) != NULL){
+ *v = '\0';
+ v++;
+ }
+ /* Find keys */
+ if ((ykey = yang_find((yang_node*)y, Y_KEY, NULL)) == NULL){
+ clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key",
+ __FUNCTION__, y->ys_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;
+}