formalizing xmldb api
This commit is contained in:
parent
540cd96e74
commit
ee9b74d735
13 changed files with 252 additions and 166 deletions
|
|
@ -438,7 +438,7 @@ from_client_unlock(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
xmldb_unlock(h, db, pid);
|
xmldb_unlock(h, db);
|
||||||
if (cprintf(cbret, "<rpc-reply><ok/></rpc-reply>") < 0)
|
if (cprintf(cbret, "<rpc-reply><ok/></rpc-reply>") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -496,7 +496,7 @@ from_client_kill_session(clicon_handle h,
|
||||||
if (1 || (kill (pid, 0) != 0 && errno == ESRCH)){ /* Nothing there */
|
if (1 || (kill (pid, 0) != 0 && errno == ESRCH)){ /* Nothing there */
|
||||||
/* clear from locks */
|
/* clear from locks */
|
||||||
if (xmldb_islocked(h, db) == pid)
|
if (xmldb_islocked(h, db) == pid)
|
||||||
xmldb_unlock(h, db, pid);
|
xmldb_unlock(h, db);
|
||||||
}
|
}
|
||||||
else{ /* failed to kill client */
|
else{ /* failed to kill client */
|
||||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
#include "backend_handle.h"
|
#include "backend_handle.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* 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 */
|
/*! Terminate. Cannot use h after this */
|
||||||
static int
|
static int
|
||||||
|
|
@ -129,6 +129,7 @@ usage(char *argv0, clicon_handle h)
|
||||||
" -D <level>\tdebug\n"
|
" -D <level>\tdebug\n"
|
||||||
" -f <file>\tCLICON config file (mandatory)\n"
|
" -f <file>\tCLICON config file (mandatory)\n"
|
||||||
" -d <dir>\tSpecify backend plugin directory (default: %s)\n"
|
" -d <dir>\tSpecify backend plugin directory (default: %s)\n"
|
||||||
|
" -b <dir>\tSpecify XMLDB database directory\n"
|
||||||
" -z\t\tKill other config daemon and exit\n"
|
" -z\t\tKill other config daemon and exit\n"
|
||||||
" -F\t\tforeground\n"
|
" -F\t\tforeground\n"
|
||||||
" -1\t\tonce (dont wait for events)\n"
|
" -1\t\tonce (dont wait for events)\n"
|
||||||
|
|
@ -140,7 +141,6 @@ usage(char *argv0, clicon_handle h)
|
||||||
" -c <file>\tLoad specified application config.\n"
|
" -c <file>\tLoad specified application config.\n"
|
||||||
" -r\t\tReload running database\n"
|
" -r\t\tReload running database\n"
|
||||||
" -p \t\tPrint database yang specification\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 <group>\tClient membership required to this group (default: %s)\n"
|
" -g <group>\tClient membership required to this group (default: %s)\n"
|
||||||
" -y <file>\tOverride yang spec file (dont include .yang suffix)\n"
|
" -y <file>\tOverride yang spec file (dont include .yang suffix)\n"
|
||||||
" -x <plugin>\tXMLDB plugin\n",
|
" -x <plugin>\tXMLDB plugin\n",
|
||||||
|
|
@ -308,7 +308,6 @@ main(int argc, char **argv)
|
||||||
clicon_handle h;
|
clicon_handle h;
|
||||||
int help = 0;
|
int help = 0;
|
||||||
int printspec = 0;
|
int printspec = 0;
|
||||||
int printalt = 0;
|
|
||||||
int pid;
|
int pid;
|
||||||
char *pidfile;
|
char *pidfile;
|
||||||
char *sock;
|
char *sock;
|
||||||
|
|
@ -387,6 +386,11 @@ main(int argc, char **argv)
|
||||||
usage(argv[0], h);
|
usage(argv[0], h);
|
||||||
clicon_option_str_set(h, "CLICON_BACKEND_DIR", optarg);
|
clicon_option_str_set(h, "CLICON_BACKEND_DIR", optarg);
|
||||||
break;
|
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 */
|
case 'F' : /* foreground */
|
||||||
foreground = 1;
|
foreground = 1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -425,9 +429,6 @@ main(int argc, char **argv)
|
||||||
case 'p' : /* Print spec */
|
case 'p' : /* Print spec */
|
||||||
printspec++;
|
printspec++;
|
||||||
break;
|
break;
|
||||||
case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */
|
|
||||||
printalt++;
|
|
||||||
break;
|
|
||||||
case 'y' :{ /* yang module */
|
case 'y' :{ /* yang module */
|
||||||
/* Set revision to NULL, extract dir and module */
|
/* Set revision to NULL, extract dir and module */
|
||||||
char *str = strdup(optarg);
|
char *str = strdup(optarg);
|
||||||
|
|
|
||||||
|
|
@ -152,87 +152,20 @@ api_data_get_gen(clicon_handle h,
|
||||||
int head)
|
int head)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cg_var *cv;
|
|
||||||
char *val;
|
|
||||||
char *v;
|
|
||||||
int i;
|
|
||||||
cbuf *path = NULL;
|
cbuf *path = NULL;
|
||||||
cbuf *path1 = NULL;
|
|
||||||
cbuf *cbx = NULL;
|
cbuf *cbx = NULL;
|
||||||
cxobj **vec = NULL;
|
cxobj **vec = NULL;
|
||||||
yang_spec *yspec;
|
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;
|
cxobj *xret = NULL;
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
yspec = clicon_dbspec_yang(h);
|
yspec = clicon_dbspec_yang(h);
|
||||||
if ((path = cbuf_new()) == NULL)
|
if ((path = cbuf_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if ((path1 = cbuf_new()) == NULL) /* without [] qualifiers */
|
if (xml_apipath2xpath(yspec, pcvec, pi, path) < 0){
|
||||||
goto done;
|
|
||||||
cv = NULL;
|
|
||||||
cprintf(path1, "/");
|
|
||||||
/* translate eg a/b=c -> a/[b=c] */
|
|
||||||
for (i=pi; i<cvec_len(pcvec); i++){
|
|
||||||
cv = cvec_i(pcvec, i);
|
|
||||||
name = cv_name_get(cv);
|
|
||||||
clicon_debug(1, "[%d] cvname:%s", i, name);
|
|
||||||
clicon_debug(1, "cv2str%d", cv2str(cv, NULL, 0));
|
|
||||||
if (i == pi){
|
|
||||||
if ((y = yang_find_topnode(yspec, name)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "No yang node found: %s", name);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
assert(y!=NULL);
|
|
||||||
if ((y = yang_find_syntax((yang_node*)y, name)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "No yang node found: %s", name);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Check if has value, means '=' */
|
|
||||||
if (cv2str(cv, NULL, 0) > 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);
|
notfound(r);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
clicon_debug(1, "ykey:%s", ykey->ys_argument);
|
|
||||||
|
|
||||||
/* The value is a list of keys: <key>[ <key>]* */
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clicon_debug(1, "%s path:%s", __FUNCTION__, cbuf_get(path));
|
clicon_debug(1, "%s path:%s", __FUNCTION__, cbuf_get(path));
|
||||||
if (clicon_rpc_get_config(h, "running", cbuf_get(path), &xret) < 0){
|
if (clicon_rpc_get_config(h, "running", cbuf_get(path), &xret) < 0){
|
||||||
notfound(r);
|
notfound(r);
|
||||||
|
|
@ -267,8 +200,6 @@ api_data_get_gen(clicon_handle h,
|
||||||
cbuf_free(cbx);
|
cbuf_free(cbx);
|
||||||
if (path)
|
if (path)
|
||||||
cbuf_free(path);
|
cbuf_free(path);
|
||||||
if (path1)
|
|
||||||
cbuf_free(path1);
|
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -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 /
|
./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
|
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 '<config>eth66</config>'
|
||||||
<config>eth66</config>
|
|
||||||
|
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 / '<config><interfaces><interface><name>eth0</name><enabled>true</enabled></interface></interfaces></config>'
|
||||||
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
@ -89,10 +90,10 @@ usage(char *argv0)
|
||||||
"\t-m <module>\tYang module. Mandatory\n"
|
"\t-m <module>\tYang module. Mandatory\n"
|
||||||
"and command is either:\n"
|
"and command is either:\n"
|
||||||
"\tget <xpath>\n"
|
"\tget <xpath>\n"
|
||||||
"\tput (set|merge|delete) <api_path> \tXML on stdin\n"
|
"\tput (set|merge|delete) <api_path> <xml>\n"
|
||||||
"\tcopy <fromdb> <todb>\n"
|
"\tcopy <todb>\n"
|
||||||
"\tlock <pid>\n"
|
"\tlock <pid>\n"
|
||||||
"\tunlock <pid>\n"
|
"\tunlock\n"
|
||||||
"\tunlock_all <pid>\n"
|
"\tunlock_all <pid>\n"
|
||||||
"\tislocked\n"
|
"\tislocked\n"
|
||||||
"\texists\n"
|
"\texists\n"
|
||||||
|
|
@ -212,18 +213,18 @@ main(int argc, char **argv)
|
||||||
if (xmldb_setopt(h, "yangspec", yspec) < 0)
|
if (xmldb_setopt(h, "yangspec", yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (strcmp(cmd, "get")==0){
|
if (strcmp(cmd, "get")==0){
|
||||||
if (argc < 2)
|
if (argc != 2)
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
if (xmldb_get(h, db, argv[1], &xt, NULL, 0) < 0)
|
if (xmldb_get(h, db, argv[1], &xt, NULL, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_xml2file(stdout, xt, 0, 1);
|
clicon_xml2file(stdout, xt, 0, 1);
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "put")==0){
|
else if (strcmp(cmd, "put")==0){
|
||||||
if (argc < 3)
|
if (argc != 4)
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
if (xml_operation(argv[1], &op) < 0)
|
if (xml_operation(argv[1], &op) < 0)
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
if (clicon_xml_parse_file(0, &xt, "</clicon>") < 0)
|
if (clicon_xml_parse_str(argv[3], &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xt, 0, &xn) < 0)
|
if (xml_rootchild(xt, 0, &xn) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -233,50 +234,59 @@ main(int argc, char **argv)
|
||||||
xml_free(xn);
|
xml_free(xn);
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "copy")==0){
|
else if (strcmp(cmd, "copy")==0){
|
||||||
if (argc < 3)
|
if (argc != 2)
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
if (xmldb_copy(h, argv[1], argv[2]) < 0)
|
if (xmldb_copy(h, db, argv[1]) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "lock")==0){
|
else if (strcmp(cmd, "lock")==0){
|
||||||
if (argc < 2)
|
if (argc != 2)
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
pid = atoi(argv[1]);
|
pid = atoi(argv[1]);
|
||||||
if (xmldb_lock(h, db, pid) < 0)
|
if (xmldb_lock(h, db, pid) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "unlock")==0){
|
else if (strcmp(cmd, "unlock")==0){
|
||||||
if (argc < 2)
|
if (argc != 1)
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
pid = atoi(argv[1]);
|
if (xmldb_unlock(h, db) < 0)
|
||||||
if (xmldb_unlock(h, db, pid) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "unlock_all")==0){
|
else if (strcmp(cmd, "unlock_all")==0){
|
||||||
if (argc < 2)
|
if (argc != 2)
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
pid = atoi(argv[1]);
|
pid = atoi(argv[1]);
|
||||||
if (xmldb_unlock_all(h, pid) < 0)
|
if (xmldb_unlock_all(h, pid) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "islocked")==0){
|
else if (strcmp(cmd, "islocked")==0){
|
||||||
|
if (argc != 1)
|
||||||
|
usage(argv0);
|
||||||
if ((ret = xmldb_islocked(h, db)) < 0)
|
if ((ret = xmldb_islocked(h, db)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
fprintf(stdout, "islocked: %d\n", ret);
|
fprintf(stdout, "islocked: %d\n", ret);
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "exists")==0){
|
else if (strcmp(cmd, "exists")==0){
|
||||||
|
if (argc != 1)
|
||||||
|
usage(argv0);
|
||||||
if ((ret = xmldb_exists(h, db)) < 0)
|
if ((ret = xmldb_exists(h, db)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
fprintf(stdout, "exists: %d\n", ret);
|
fprintf(stdout, "exists: %d\n", ret);
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "delete")==0){
|
else if (strcmp(cmd, "delete")==0){
|
||||||
|
if (argc != 1)
|
||||||
|
usage(argv0);
|
||||||
if (xmldb_delete(h, db) < 0)
|
if (xmldb_delete(h, db) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "init")==0){
|
else if (strcmp(cmd, "init")==0){
|
||||||
|
if (argc != 1)
|
||||||
|
usage(argv0);
|
||||||
if (xmldb_init(h, db) < 0)
|
if (xmldb_init(h, db) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
clicon_err(OE_DB, 0, "Unrecognized command: %s", cmd);
|
||||||
done:
|
done:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ static int _startup_locked = 0;
|
||||||
* The filename reside in CLICON_XMLDB_DIR option
|
* The filename reside in CLICON_XMLDB_DIR option
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
db2file(struct kv_handle *kh,
|
kv_db2file(struct kv_handle *kh,
|
||||||
char *db,
|
char *db,
|
||||||
char **filename)
|
char **filename)
|
||||||
{
|
{
|
||||||
|
|
@ -180,7 +180,7 @@ db2file(struct kv_handle *kh,
|
||||||
strcmp(db, "candidate") != 0 &&
|
strcmp(db, "candidate") != 0 &&
|
||||||
strcmp(db, "startup") != 0 &&
|
strcmp(db, "startup") != 0 &&
|
||||||
strcmp(db, "tmp") != 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;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cb, "%s/%s_db", dir, db);
|
cprintf(cb, "%s/%s_db", dir, db);
|
||||||
|
|
@ -616,7 +616,7 @@ kv_get(xmldb_handle xh,
|
||||||
|
|
||||||
|
|
||||||
clicon_debug(2, "%s", __FUNCTION__);
|
clicon_debug(2, "%s", __FUNCTION__);
|
||||||
if (db2file(kh, db, &dbfile) < 0)
|
if (kv_db2file(kh, db, &dbfile) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (dbfile==NULL){
|
if (dbfile==NULL){
|
||||||
clicon_err(OE_XML, 0, "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) */
|
/* Read in complete database (this can be optimized) */
|
||||||
if ((npairs = db_regexp(dbfile, "", __FUNCTION__, &pairs, 0)) < 0)
|
if ((npairs = db_regexp(dbfile, "", __FUNCTION__, &pairs, 0)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xt = xml_new_spec("clicon", NULL, yspec)) == NULL)
|
if ((xt = xml_new_spec("config", NULL, yspec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* Translate to complete xml tree */
|
/* Translate to complete xml tree */
|
||||||
for (i = 0; i < npairs; i++) {
|
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");
|
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (db2file(kh, db, &filename) < 0)
|
if (kv_db2file(kh, db, &filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xk == NULL || *xk!='/'){
|
if (xk == NULL || *xk!='/'){
|
||||||
clicon_err(OE_DB, 0, "Invalid key: %s", 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)
|
if ((vec = clicon_strsep(xk, "/", &nvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Remove trailing '/'. Like in /a/ -> /a */
|
||||||
|
if (nvec > 1 && !strlen(vec[nvec-1]))
|
||||||
|
nvec--;
|
||||||
if (nvec < 2){
|
if (nvec < 2){
|
||||||
clicon_err(OE_XML, 0, "Malformed key: %s", xk);
|
clicon_err(OE_XML, 0, "Malformed key: %s", xk);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1066,7 +1069,7 @@ xmldb_put_restconf_api_path(struct kv_handle *kh,
|
||||||
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (db2file(kh, db, &filename) < 0)
|
if (kv_db2file(kh, db, &filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (api_path == NULL || *api_path!='/'){
|
if (api_path == NULL || *api_path!='/'){
|
||||||
clicon_err(OE_DB, 0, "Invalid api path: %s", 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)
|
if ((vec = clicon_strsep(api_path, "/", &nvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Remove trailing '/'. Like in /a/ -> /a */
|
||||||
|
if (nvec > 1 && !strlen(vec[nvec-1]))
|
||||||
|
nvec--;
|
||||||
if (nvec < 2){
|
if (nvec < 2){
|
||||||
clicon_err(OE_XML, 0, "Malformed key: %s", api_path);
|
clicon_err(OE_XML, 0, "Malformed key: %s", api_path);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1266,13 +1272,14 @@ kv_put(xmldb_handle xh,
|
||||||
yang_spec *yspec;
|
yang_spec *yspec;
|
||||||
char *dbfilename = NULL;
|
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));
|
return xmldb_put_xkey(kh, db, op, api_path, xml_body(xt));
|
||||||
if ((yspec = kh->kh_yangspec) == NULL){
|
if ((yspec = kh->kh_yangspec) == NULL){
|
||||||
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (db2file(kh, db, &dbfilename) < 0)
|
if (kv_db2file(kh, db, &dbfilename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (op == OP_REPLACE){
|
if (op == OP_REPLACE){
|
||||||
if (db_delete(dbfilename) < 0)
|
if (db_delete(dbfilename) < 0)
|
||||||
|
|
@ -1281,7 +1288,8 @@ kv_put(xmldb_handle xh,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL){
|
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)
|
if (xmldb_put_restconf_api_path(kh, db, op, api_path, x) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1323,9 +1331,9 @@ kv_copy(xmldb_handle xh,
|
||||||
char *tofile = NULL;
|
char *tofile = NULL;
|
||||||
|
|
||||||
/* XXX lock */
|
/* XXX lock */
|
||||||
if (db2file(kh, from, &fromfile) < 0)
|
if (kv_db2file(kh, from, &fromfile) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (db2file(kh, to, &tofile) < 0)
|
if (kv_db2file(kh, to, &tofile) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_file_copy(fromfile, tofile) < 0)
|
if (clicon_file_copy(fromfile, tofile) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1350,16 +1358,25 @@ kv_lock(xmldb_handle xh,
|
||||||
char *db,
|
char *db,
|
||||||
int pid)
|
int pid)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
// struct kv_handle *kh = handle(xh);
|
// struct kv_handle *kh = handle(xh);
|
||||||
|
fprintf(stderr, "%s %s %d\n", __FUNCTION__, db, pid);
|
||||||
if (strcmp("running", db) == 0)
|
if (strcmp("running", db) == 0)
|
||||||
_running_locked = pid;
|
_running_locked = pid;
|
||||||
else if (strcmp("candidate", db) == 0)
|
else if (strcmp("candidate", db) == 0)
|
||||||
_candidate_locked = pid;
|
_candidate_locked = pid;
|
||||||
else if (strcmp("startup", db) == 0)
|
else if (strcmp("startup", db) == 0)
|
||||||
_startup_locked = pid;
|
_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);
|
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
|
/*! Unlock database
|
||||||
|
|
@ -1372,18 +1389,24 @@ kv_lock(xmldb_handle xh,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
kv_unlock(xmldb_handle xh,
|
kv_unlock(xmldb_handle xh,
|
||||||
char *db,
|
char *db)
|
||||||
int pid)
|
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
// struct kv_handle *kh = handle(xh);
|
// struct kv_handle *kh = handle(xh);
|
||||||
|
fprintf(stderr, "%s %s\n", __FUNCTION__, db);
|
||||||
if (strcmp("running", db) == 0)
|
if (strcmp("running", db) == 0)
|
||||||
_running_locked = 0;
|
_running_locked = 0;
|
||||||
else if (strcmp("candidate", db) == 0)
|
else if (strcmp("candidate", db) == 0)
|
||||||
_candidate_locked = 0;
|
_candidate_locked = 0;
|
||||||
else if (strcmp("startup", db) == 0)
|
else if (strcmp("startup", db) == 0)
|
||||||
_startup_locked = 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)
|
/*! Unlock all databases locked by pid (eg process dies)
|
||||||
|
|
@ -1418,15 +1441,21 @@ int
|
||||||
kv_islocked(xmldb_handle xh,
|
kv_islocked(xmldb_handle xh,
|
||||||
char *db)
|
char *db)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
// struct kv_handle *kh = handle(xh);
|
// 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)
|
if (strcmp("running", db) == 0)
|
||||||
return (_running_locked);
|
retval = _running_locked;
|
||||||
else if (strcmp("candidate", db) == 0)
|
else if (strcmp("candidate", db) == 0)
|
||||||
return(_candidate_locked);
|
retval = _candidate_locked;
|
||||||
else if (strcmp("startup", db) == 0)
|
else if (strcmp("startup", db) == 0)
|
||||||
return(_startup_locked);
|
retval = _startup_locked;
|
||||||
return 0;
|
else
|
||||||
|
clicon_err(OE_DB, 0, "No such database: %s", db);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Check if db exists
|
/*! Check if db exists
|
||||||
|
|
@ -1445,7 +1474,7 @@ kv_exists(xmldb_handle xh,
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
if (db2file(kh, db, &filename) < 0)
|
if (kv_db2file(kh, db, &filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (lstat(filename, &sb) < 0)
|
if (lstat(filename, &sb) < 0)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1471,7 +1500,7 @@ kv_delete(xmldb_handle xh,
|
||||||
struct kv_handle *kh = handle(xh);
|
struct kv_handle *kh = handle(xh);
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
|
|
||||||
if (db2file(kh, db, &filename) < 0)
|
if (kv_db2file(kh, db, &filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (db_delete(filename) < 0)
|
if (db_delete(filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1496,7 +1525,7 @@ kv_init(xmldb_handle xh,
|
||||||
struct kv_handle *kh = handle(xh);
|
struct kv_handle *kh = handle(xh);
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
|
|
||||||
if (db2file(kh, db, &filename) < 0)
|
if (kv_db2file(kh, db, &filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (db_init(filename) < 0)
|
if (db_init(filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -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_dump(FILE *f, char *dbfilename, char *rxkey);
|
||||||
int kv_copy(xmldb_handle h, char *from, char *to);
|
int kv_copy(xmldb_handle h, char *from, char *to);
|
||||||
int kv_lock(xmldb_handle h, char *db, int pid);
|
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_unlock_all(xmldb_handle h, int pid);
|
||||||
int kv_islocked(xmldb_handle h, char *db);
|
int kv_islocked(xmldb_handle h, char *db);
|
||||||
int kv_exists(xmldb_handle h, char *db);
|
int kv_exists(xmldb_handle h, char *db);
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ static int _startup_locked = 0;
|
||||||
* The filename reside in CLICON_XMLDB_DIR option
|
* The filename reside in CLICON_XMLDB_DIR option
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
db2file(struct text_handle *th,
|
text_db2file(struct text_handle *th,
|
||||||
char *db,
|
char *db,
|
||||||
char **filename)
|
char **filename)
|
||||||
{
|
{
|
||||||
|
|
@ -126,7 +126,7 @@ db2file(struct text_handle *th,
|
||||||
strcmp(db, "candidate") != 0 &&
|
strcmp(db, "candidate") != 0 &&
|
||||||
strcmp(db, "startup") != 0 &&
|
strcmp(db, "startup") != 0 &&
|
||||||
strcmp(db, "tmp") != 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;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cb, "%s/%s_db", dir, db);
|
cprintf(cb, "%s/%s_db", dir, db);
|
||||||
|
|
@ -292,7 +292,7 @@ text_get(xmldb_handle xh,
|
||||||
int i;
|
int i;
|
||||||
struct text_handle *th = handle(xh);
|
struct text_handle *th = handle(xh);
|
||||||
|
|
||||||
if (db2file(th, db, &dbfile) < 0)
|
if (text_db2file(th, db, &dbfile) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (dbfile==NULL){
|
if (dbfile==NULL){
|
||||||
clicon_err(OE_XML, 0, "dbfile NULL");
|
clicon_err(OE_XML, 0, "dbfile NULL");
|
||||||
|
|
@ -348,7 +348,6 @@ text_get(xmldb_handle xh,
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Modify database provided an xml tree and an operation
|
/*! Modify database provided an xml tree and an operation
|
||||||
|
|
@ -380,10 +379,37 @@ text_put(xmldb_handle xh,
|
||||||
cxobj *xt)
|
cxobj *xt)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
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;
|
retval = 0;
|
||||||
// done:
|
done:
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,8 +467,7 @@ text_lock(xmldb_handle xh,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
text_unlock(xmldb_handle xh,
|
text_unlock(xmldb_handle xh,
|
||||||
char *db,
|
char *db)
|
||||||
int pid)
|
|
||||||
{
|
{
|
||||||
// struct text_handle *th = handle(xh);
|
// struct text_handle *th = handle(xh);
|
||||||
|
|
||||||
|
|
@ -515,7 +540,7 @@ text_exists(xmldb_handle xh,
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
if (db2file(th, db, &filename) < 0)
|
if (text_db2file(th, db, &filename) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (lstat(filename, &sb) < 0)
|
if (lstat(filename, &sb) < 0)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -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_dump(FILE *f, char *dbfilename, char *rxkey);
|
||||||
int text_copy(xmldb_handle h, char *from, char *to);
|
int text_copy(xmldb_handle h, char *from, char *to);
|
||||||
int text_lock(xmldb_handle h, char *db, int pid);
|
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_unlock_all(xmldb_handle h, int pid);
|
||||||
int text_islocked(xmldb_handle h, char *db);
|
int text_islocked(xmldb_handle h, char *db);
|
||||||
int text_exists(xmldb_handle h, char *db);
|
int text_exists(xmldb_handle h, char *db);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
typedef int (xmldb_lock_t)(xmldb_handle xh, char *db, int pid);
|
||||||
|
|
||||||
/* Type of xmldb unlock function */
|
/* 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 */
|
/* Type of xmldb unlock_all function */
|
||||||
typedef int (xmldb_unlock_all_t)(xmldb_handle xh, int pid);
|
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);
|
char *api_path, cxobj *xt);
|
||||||
int xmldb_copy(clicon_handle h, char *from, char *to);
|
int xmldb_copy(clicon_handle h, char *from, char *to);
|
||||||
int xmldb_lock(clicon_handle h, char *db, int pid);
|
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_unlock_all(clicon_handle h, int pid);
|
||||||
int xmldb_islocked(clicon_handle h, char *db);
|
int xmldb_islocked(clicon_handle h, char *db);
|
||||||
int xmldb_exists(clicon_handle h, char *db);
|
int xmldb_exists(clicon_handle h, char *db);
|
||||||
|
|
|
||||||
|
|
@ -68,5 +68,6 @@ int xml_tree_prune_unmarked(cxobj *xt, int *upmark);
|
||||||
int xml_default(cxobj *x, void *arg);
|
int xml_default(cxobj *x, void *arg);
|
||||||
int xml_order(cxobj *x, void *arg);
|
int xml_order(cxobj *x, void *arg);
|
||||||
int xml_sanity(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_ */
|
#endif /* _CLIXON_XML_MAP_H_ */
|
||||||
|
|
|
||||||
|
|
@ -843,7 +843,7 @@ clicon_xml2file(FILE *f,
|
||||||
int level,
|
int level,
|
||||||
int prettyprint)
|
int prettyprint)
|
||||||
{
|
{
|
||||||
cbuf *cb;
|
cbuf *cb = NULL;
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
if ((cb = cbuf_new()) == NULL){
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@
|
||||||
the terms of any one of the Apache License version 2 or the GPL.
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****
|
***** END LICENSE BLOCK *****
|
||||||
*/
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -169,7 +169,6 @@ xmldb_plugin_unload(clicon_handle h)
|
||||||
* datastore. Note also that the xmldb handle is hidden in the clicon
|
* 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
|
* handle, the clixon user does not need to handle it. Note also that
|
||||||
* typically only the backend invokes the datastore.
|
* typically only the backend invokes the datastore.
|
||||||
* XXX what args does connect have?
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xmldb_connect(clicon_handle h)
|
xmldb_connect(clicon_handle h)
|
||||||
|
|
@ -320,7 +319,6 @@ xmldb_setopt(clicon_handle h,
|
||||||
* @see xpath_vec
|
* @see xpath_vec
|
||||||
* @see xmldb_get
|
* @see xmldb_get
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
xmldb_get(clicon_handle h,
|
xmldb_get(clicon_handle h,
|
||||||
char *db,
|
char *db,
|
||||||
|
|
@ -345,8 +343,16 @@ xmldb_get(clicon_handle h,
|
||||||
clicon_err(OE_DB, 0, "Not connected to datastore plugin");
|
clicon_err(OE_DB, 0, "Not connected to datastore plugin");
|
||||||
goto done;
|
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);
|
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:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
@ -395,6 +401,7 @@ xmldb_put(clicon_handle h,
|
||||||
clicon_err(OE_DB, 0, "Not connected to datastore plugin");
|
clicon_err(OE_DB, 0, "Not connected to datastore plugin");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
#if 0 /* XXX DEBUG */
|
||||||
{
|
{
|
||||||
cbuf *cb = cbuf_new();
|
cbuf *cb = cbuf_new();
|
||||||
if (clicon_xml2cbuf(cb, xt, 0, 0) < 0)
|
if (clicon_xml2cbuf(cb, xt, 0, 0) < 0)
|
||||||
|
|
@ -404,6 +411,7 @@ xmldb_put(clicon_handle h,
|
||||||
db, op, api_path, cbuf_get(cb));
|
db, op, api_path, cbuf_get(cb));
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
retval = xa->xa_put_fn(xh, db, op, api_path, xt);
|
retval = xa->xa_put_fn(xh, db, op, api_path, xt);
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -485,8 +493,7 @@ xmldb_lock(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xmldb_unlock(clicon_handle h,
|
xmldb_unlock(clicon_handle h,
|
||||||
char *db,
|
char *db)
|
||||||
int pid)
|
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
xmldb_handle xh;
|
xmldb_handle xh;
|
||||||
|
|
@ -504,7 +511,7 @@ xmldb_unlock(clicon_handle h,
|
||||||
clicon_err(OE_DB, 0, "Not connected to datastore plugin");
|
clicon_err(OE_DB, 0, "Not connected to datastore plugin");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = xa->xa_unlock_fn(xh, db, pid);
|
retval = xa->xa_unlock_fn(xh, db);
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1248,3 +1248,85 @@ xml_sanity(cxobj *xt,
|
||||||
return retval;
|
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<cvec_len(pcvec); i++){
|
||||||
|
cv = cvec_i(pcvec, i);
|
||||||
|
name = cv_name_get(cv);
|
||||||
|
clicon_debug(1, "[%d] cvname:%s", i, name);
|
||||||
|
clicon_debug(1, "cv2str%d", cv2str(cv, NULL, 0));
|
||||||
|
if (i == pi){
|
||||||
|
if ((y = yang_find_topnode(yspec, name)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "No yang node found: %s", name);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
assert(y!=NULL);
|
||||||
|
if ((y = yang_find_syntax((yang_node*)y, name)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "No yang node found: %s", name);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check if has value, means '=' */
|
||||||
|
if (cv2str(cv, NULL, 0) > 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: <key>[ <key>]* */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue