xmldb
This commit is contained in:
parent
ca18b7f49e
commit
0a812696c2
47 changed files with 1818 additions and 1783 deletions
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
* XML database
|
||||
* TODO: xmldb_del: or dbxml_put_xkey delete
|
||||
* TODO: xmldb_get: xpath: only load partial tree
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
|
|
@ -34,6 +33,9 @@
|
|||
#include <limits.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <assert.h>
|
||||
#include <syslog.h>
|
||||
|
||||
|
|
@ -43,6 +45,7 @@
|
|||
/* clicon */
|
||||
#include "clixon_err.h"
|
||||
#include "clixon_log.h"
|
||||
#include "clixon_file.h"
|
||||
#include "clixon_queue.h"
|
||||
#include "clixon_string.h"
|
||||
#include "clixon_chunk.h"
|
||||
|
|
@ -52,8 +55,10 @@
|
|||
#include "clixon_yang.h"
|
||||
#include "clixon_handle.h"
|
||||
#include "clixon_xml.h"
|
||||
#include "clixon_options.h"
|
||||
#include "clixon_xsl.h"
|
||||
#include "clixon_xml_parse.h"
|
||||
#include "clixon_xml_db_rpc.h"
|
||||
#include "clixon_xml_db.h"
|
||||
|
||||
/*
|
||||
|
|
@ -331,7 +336,95 @@ xmlkeyfmt2xpath(char *xkfmt,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Database locking for candidate and running non-persistent
|
||||
* Store an integer for running and candidate containing
|
||||
* the session-id of the client holding the lock.
|
||||
*/
|
||||
static int _running_locked = 0;
|
||||
static int _candidate_locked = 0;
|
||||
|
||||
/*! Lock database
|
||||
*/
|
||||
static int
|
||||
db_lock(char *db,
|
||||
int pid)
|
||||
{
|
||||
if (strcmp("running", db) == 0)
|
||||
_running_locked = pid;
|
||||
else if (strcmp("candidate", db) == 0)
|
||||
_candidate_locked = pid;
|
||||
clicon_debug(1, "%s: locked by %u", db, pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Unlock database
|
||||
*/
|
||||
static int
|
||||
db_unlock(char *db)
|
||||
{
|
||||
if (strcmp("running", db) == 0)
|
||||
_running_locked = 0;
|
||||
else if (strcmp("candidate", db) == 0)
|
||||
_candidate_locked = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! returns id of locker
|
||||
* @retval 0 Not locked
|
||||
* @retval >0 Id of locker
|
||||
*/
|
||||
static int
|
||||
db_islocked(char *db)
|
||||
{
|
||||
if (strcmp("running", db) == 0)
|
||||
return (_running_locked);
|
||||
else if (strcmp("candidate", db) == 0)
|
||||
return(_candidate_locked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Translate from symbolic database name to actual filename in file-system
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] db Symbolic database name, eg "candidate", "running"
|
||||
* @param[out] filename Filename. Unallocate after use with free()
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* The filename reside in CLICON_XMLDB_DIR option
|
||||
*/
|
||||
static int
|
||||
db2file(clicon_handle h,
|
||||
char *db,
|
||||
char **filename)
|
||||
{
|
||||
int retval = -1;
|
||||
cbuf *cb;
|
||||
char *dir;
|
||||
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if ((dir = clicon_xmldb_dir(h)) == NULL){
|
||||
clicon_err(OE_XML, errno, "CLICON_XMLDB_DIR not set");
|
||||
goto done;
|
||||
}
|
||||
if (strcmp(db, "running") != 0 &&
|
||||
strcmp(db, "candidate") != 0 &&
|
||||
strcmp(db, "tmp") != 0){
|
||||
clicon_err(OE_XML, 0, "Unexpected database: %s", db);
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "%s/%s_db", dir, db);
|
||||
if ((*filename = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Help function to append key values from an xml list to a cbuf
|
||||
* Example, a yang node x with keys a and b results in "x/a/b"
|
||||
|
|
@ -415,7 +508,6 @@ create_keyvalues(cxobj *x,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Prune everything that has not been marked
|
||||
* @param[in] xt XML tree with some node marked
|
||||
* @param[out] upmark Set if a child (recursively) has marked set.
|
||||
|
|
@ -672,22 +764,16 @@ xml_default(cxobj *x,
|
|||
* @param[in] dbname Name of database to search in (filename including dir path
|
||||
* @param[in] xpath String with XPATH syntax (or NULL for all)
|
||||
* @param[in] yspec Yang specification
|
||||
* @param[in] vector If set, return list of results in xvec
|
||||
* @param[out] xtop XML tree. Freed by xml_free()
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @code
|
||||
* cxobj *xt;
|
||||
* yang_spec *yspec = clicon_dbspec_yang(h);
|
||||
* if (xmldb_get(dbname, "/interfaces/interface[name="eth*"]", yspec, &xt) < 0)
|
||||
* err;
|
||||
* xml_free(xt);
|
||||
* @endcode
|
||||
*/
|
||||
int
|
||||
xmldb_get(char *dbname,
|
||||
char *xpath,
|
||||
yang_spec *yspec,
|
||||
cxobj **xtop)
|
||||
static int
|
||||
xmldb_get_tree(char *dbname,
|
||||
char *xpath,
|
||||
yang_spec *yspec,
|
||||
cxobj **xtop)
|
||||
{
|
||||
int retval = -1;
|
||||
int i;
|
||||
|
|
@ -780,7 +866,7 @@ xmldb_get(char *dbname,
|
|||
* @see xpath_vec
|
||||
* @see xmldb_get
|
||||
*/
|
||||
int
|
||||
static int
|
||||
xmldb_get_vec(char *dbname,
|
||||
char *xpath,
|
||||
yang_spec *yspec,
|
||||
|
|
@ -803,6 +889,7 @@ xmldb_get_vec(char *dbname,
|
|||
for (i = 0; i < npairs; i++)
|
||||
fprintf(stderr, "%s %s\n", pairs[i].dp_key, pairs[i].dp_val?pairs[i].dp_val:"");
|
||||
|
||||
/* Read in whole tree */
|
||||
for (i = 0; i < npairs; i++) {
|
||||
if (get(dbname,
|
||||
yspec,
|
||||
|
|
@ -827,7 +914,86 @@ xmldb_get_vec(char *dbname,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Local variant of xmldb_get */
|
||||
static int
|
||||
xmldb_get_local(clicon_handle h,
|
||||
char *db,
|
||||
char *xpath,
|
||||
int vector,
|
||||
cxobj **xtop,
|
||||
cxobj ***xvec,
|
||||
size_t *xlen)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_spec *yspec;
|
||||
char *dbname = NULL;
|
||||
|
||||
if (db2file(h, db, &dbname) < 0)
|
||||
goto done;
|
||||
if (dbname==NULL){
|
||||
clicon_err(OE_XML, 0, "dbname NULL");
|
||||
goto done;
|
||||
}
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if (vector){
|
||||
if (xmldb_get_vec(dbname, xpath, yspec, xtop, xvec, xlen) < 0)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if (xmldb_get_tree(dbname, xpath, yspec, xtop) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
if (dbname)
|
||||
free(dbname);
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
/*! Get content of database using xpath.
|
||||
* The function returns a minimal tree that includes all sub-trees that match
|
||||
* xpath.
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] db running | candidate
|
||||
* @param[in] xpath String with XPATH syntax (or NULL for all)
|
||||
* @param[in] vector If set, return list of results in xvec, else single tree.
|
||||
* @param[out] xtop XML tree. Freed by xml_free()
|
||||
* @param[out] xvec Vector of xml trees. Free after use
|
||||
* @param[out] xlen Length of vector.
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @code
|
||||
* cxobj *xt;
|
||||
* cxobj **xvec;
|
||||
* size_t xlen;
|
||||
* yang_spec *yspec = clicon_dbspec_yang(h);
|
||||
* if (xmldb_get(dbname, "/interfaces/interface[name="eth"]", yspec,
|
||||
* 1, &xt, &xvec, &xlen) < 0)
|
||||
* err;
|
||||
* for (i=0; i<xlen; i++){
|
||||
* xn = xv[i];
|
||||
* ...
|
||||
* }
|
||||
* xml_free(xt);
|
||||
* free(xvec);
|
||||
* @endcode
|
||||
* @see xpath_vec
|
||||
* @endcode
|
||||
*/
|
||||
int
|
||||
xmldb_get(clicon_handle h,
|
||||
char *db,
|
||||
char *xpath,
|
||||
int vector,
|
||||
cxobj **xtop,
|
||||
cxobj ***xvec,
|
||||
size_t *xlen)
|
||||
{
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_get_rpc(h, db, xpath, vector, xtop, xvec, xlen);
|
||||
else
|
||||
return xmldb_get_local(h, db, xpath, vector, xtop, xvec, xlen);
|
||||
}
|
||||
|
||||
/*! Get value of the "operation" attribute and change op if given
|
||||
* @param[in] xn XML node
|
||||
|
|
@ -950,13 +1116,57 @@ put(char *dbname,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Local variant of xmldb_put */
|
||||
static int
|
||||
xmldb_put_local(clicon_handle h,
|
||||
char *db,
|
||||
cxobj *xt,
|
||||
enum operation_type op)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x = NULL;
|
||||
yang_stmt *ys;
|
||||
yang_spec *yspec;
|
||||
char *dbfilename = NULL;
|
||||
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if (db2file(h, db, &dbfilename) < 0)
|
||||
goto done;
|
||||
if (op == OP_REPLACE){
|
||||
if (db_delete(dbfilename) < 0)
|
||||
goto done;
|
||||
if (db_init(dbfilename) < 0)
|
||||
goto done;
|
||||
}
|
||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL){
|
||||
if ((ys = yang_find_topnode(yspec, xml_name(x))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "No yang node found: %s", xml_name(x));
|
||||
goto done;
|
||||
}
|
||||
if (put(dbfilename, /* database name */
|
||||
x, /* xml root node */
|
||||
ys, /* yang statement of xml node */
|
||||
op, /* operation, eg merge/delete */
|
||||
"" /* aggregate xml key */
|
||||
) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (dbfilename)
|
||||
free(dbfilename);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Modify database provided an xml tree and an operation
|
||||
* @param[in] dbname Name of database to search in (filename including dir path)
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] db running or candidate
|
||||
* @param[in] xt xml-tree. Top-level symbol is dummy
|
||||
* @param[in] yspec Yang specification
|
||||
* @param[in] op OP_MERGE: just add it.
|
||||
OP_REPLACE: first delete whole database
|
||||
OP_NONE: operation attribute in xml determines operation
|
||||
* OP_REPLACE: first delete whole database
|
||||
* OP_NONE: operation attribute in xml determines operation
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* The xml may contain the "operation" attribute which defines the operation.
|
||||
|
|
@ -968,59 +1178,24 @@ put(char *dbname,
|
|||
* @endcode
|
||||
*/
|
||||
int
|
||||
xmldb_put(char *dbname,
|
||||
xmldb_put(clicon_handle h,
|
||||
char *db,
|
||||
cxobj *xt,
|
||||
yang_spec *yspec,
|
||||
enum operation_type op)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x = NULL;
|
||||
yang_stmt *ys;
|
||||
|
||||
if (op == OP_REPLACE){
|
||||
unlink(dbname);
|
||||
if (db_init(dbname) < 0)
|
||||
goto done;
|
||||
}
|
||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL){
|
||||
if ((ys = yang_find_topnode(yspec, xml_name(x))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "No yang node found: %s", xml_name(x));
|
||||
goto done;
|
||||
}
|
||||
if (put(dbname, /* database name */
|
||||
x, /* xml root node */
|
||||
ys, /* yang statement of xml node */
|
||||
op, /* operation, eg merge/delete */
|
||||
"" /* aggregate xml key */
|
||||
) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_put_rpc(h, db, xt, op);
|
||||
else
|
||||
return xmldb_put_local(h, db, xt, op);
|
||||
}
|
||||
|
||||
|
||||
/*! Modify database provided an XML database key and an operation
|
||||
* @param[in] dbname Name of database to search in (filename including dir path)
|
||||
* @param[in] xk XML Key, eg /aa/bb/17/name
|
||||
* @param[in] val Key value, eg "17"
|
||||
* @param[in] yspec Yang specification
|
||||
* @param[in] op OP_MERGE, OP_REPLACE, OP_REMOVE, etc
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @code
|
||||
* yang_spec *yspec = clicon_dbspec_yang(h);
|
||||
* if (xmldb_put_xkey(dbname, "/aa/bb/17/name", "17", yspec, OP_MERGE) < 0)
|
||||
* err;
|
||||
* @endcode
|
||||
*/
|
||||
int
|
||||
xmldb_put_xkey(char *dbname,
|
||||
char *xk,
|
||||
char *val,
|
||||
yang_spec *yspec,
|
||||
enum operation_type op)
|
||||
/*! Local variant of xmldb_put_xkey */
|
||||
static int
|
||||
xmldb_put_xkey_local(clicon_handle h,
|
||||
char *db,
|
||||
char *xk,
|
||||
char *val,
|
||||
enum operation_type op)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x = NULL;
|
||||
|
|
@ -1040,7 +1215,12 @@ xmldb_put_xkey(char *dbname,
|
|||
int exists;
|
||||
int npairs;
|
||||
struct db_pair *pairs;
|
||||
yang_spec *yspec;
|
||||
char *filename = NULL;
|
||||
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if (db2file(h, db, &filename) < 0)
|
||||
goto done;
|
||||
if (xk == NULL || *xk!='/'){
|
||||
clicon_err(OE_DB, 0, "Invalid key: %s", xk);
|
||||
goto done;
|
||||
|
|
@ -1109,13 +1289,13 @@ xmldb_put_xkey(char *dbname,
|
|||
cbuf_reset(csubkey);
|
||||
cprintf(csubkey, "%s/%s", cbuf_get(ckey), keyname);
|
||||
if (op == OP_MERGE || op == OP_REPLACE || op == OP_CREATE)
|
||||
if (db_set(dbname, cbuf_get(csubkey), val2, strlen(val2)+1) < 0)
|
||||
if (db_set(filename, cbuf_get(csubkey), val2, strlen(val2)+1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (op == OP_MERGE || op == OP_REPLACE || op == OP_CREATE)
|
||||
if (db_set(dbname, cbuf_get(ckey), NULL, 0) < 0)
|
||||
if (db_set(filename, cbuf_get(ckey), NULL, 0) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1124,7 +1304,7 @@ xmldb_put_xkey(char *dbname,
|
|||
/* final key */
|
||||
switch (op){
|
||||
case OP_CREATE:
|
||||
if ((exists = db_exists(dbname, xk)) < 0)
|
||||
if ((exists = db_exists(filename, xk)) < 0)
|
||||
goto done;
|
||||
if (exists == 1){
|
||||
clicon_err(OE_DB, 0, "OP_CREATE: %s already exists in database", xk);
|
||||
|
|
@ -1133,15 +1313,15 @@ xmldb_put_xkey(char *dbname,
|
|||
case OP_MERGE:
|
||||
case OP_REPLACE:
|
||||
if (y->ys_keyword == Y_LEAF || y->ys_keyword == Y_LEAF_LIST){
|
||||
if (db_set(dbname, xk, val, strlen(val)+1) < 0)
|
||||
if (db_set(filename, xk, val, strlen(val)+1) < 0)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if (db_set(dbname, xk, NULL, 0) < 0)
|
||||
if (db_set(filename, xk, NULL, 0) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case OP_DELETE:
|
||||
if ((exists = db_exists(dbname, xk)) < 0)
|
||||
if ((exists = db_exists(filename, xk)) < 0)
|
||||
goto done;
|
||||
if (exists == 0){
|
||||
clicon_err(OE_DB, 0, "OP_DELETE: %s does not exists in database", xk);
|
||||
|
|
@ -1152,10 +1332,10 @@ xmldb_put_xkey(char *dbname,
|
|||
if ((crx = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
cprintf(crx, "^%s.*$", xk);
|
||||
if ((npairs = db_regexp(dbname, cbuf_get(crx), __FUNCTION__, &pairs, 0)) < 0)
|
||||
if ((npairs = db_regexp(filename, cbuf_get(crx), __FUNCTION__, &pairs, 0)) < 0)
|
||||
goto done;
|
||||
for (i = 0; i < npairs; i++) {
|
||||
if (db_del(dbname, pairs[i].dp_key) < 0)
|
||||
if (db_del(filename, pairs[i].dp_key) < 0)
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1164,6 +1344,8 @@ xmldb_put_xkey(char *dbname,
|
|||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (filename)
|
||||
free(filename);
|
||||
if (ckey)
|
||||
cbuf_free(ckey);
|
||||
if (csubkey)
|
||||
|
|
@ -1174,17 +1356,45 @@ xmldb_put_xkey(char *dbname,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Raw dump of database, just keys and values, no xml interpretation
|
||||
* param[in] f File
|
||||
* param[in] dbname Name of database
|
||||
* param[in] rxkey Key regexp, eg "^.*$"
|
||||
|
||||
/*! Modify database provided an XML database key and an operation
|
||||
* @param[in] dbname Name of database to search in (filename including dir path)
|
||||
* @param[in] xk XML Key, eg /aa/bb/17/name
|
||||
* @param[in] val Key value, eg "17"
|
||||
* @param[in] yspec Yang specification
|
||||
* @param[in] op OP_MERGE, OP_REPLACE, OP_REMOVE, etc
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @code
|
||||
* if (xmldb_put_xkey(h, db, "/aa/bb/17/name", "17", OP_MERGE) < 0)
|
||||
* err;
|
||||
* @endcode
|
||||
*/
|
||||
int
|
||||
xmldb_dump(FILE *f,
|
||||
char *dbname,
|
||||
char *rxkey)
|
||||
xmldb_put_xkey(clicon_handle h,
|
||||
char *db,
|
||||
char *xk,
|
||||
char *val,
|
||||
enum operation_type op)
|
||||
{
|
||||
int retval = 0;
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_put_xkey_rpc(h, db, xk, val, op);
|
||||
else
|
||||
return xmldb_put_xkey_local(h, db, xk, val, op);
|
||||
}
|
||||
|
||||
/*! Raw dump of database, just keys and values, no xml interpretation
|
||||
* @param[in] f File
|
||||
* @param[in] dbfile File-name of database. This is a local file
|
||||
* @param[in] rxkey Key regexp, eg "^.*$"
|
||||
* @note This function can only be called locally.
|
||||
*/
|
||||
int
|
||||
xmldb_dump(FILE *f,
|
||||
char *dbfilename,
|
||||
char *rxkey)
|
||||
{
|
||||
int retval = -1;
|
||||
int npairs;
|
||||
struct db_pair *pairs;
|
||||
|
||||
|
|
@ -1193,29 +1403,270 @@ xmldb_dump(FILE *f,
|
|||
rxkey = "^.*$";
|
||||
|
||||
/* Get all keys/values for vector */
|
||||
if ((npairs = db_regexp(dbname, rxkey, __FUNCTION__, &pairs, 0)) < 0)
|
||||
return -1;
|
||||
if ((npairs = db_regexp(dbfilename, rxkey, __FUNCTION__, &pairs, 0)) < 0)
|
||||
goto done;
|
||||
|
||||
for (npairs--; npairs >= 0; npairs--)
|
||||
fprintf(f, "%s %s\n", pairs[npairs].dp_key,
|
||||
pairs[npairs].dp_val?pairs[npairs].dp_val:"");
|
||||
retval = 0;
|
||||
done:
|
||||
unchunk_group(__FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
xmldb_init(char *file)
|
||||
/*! Local variant of xmldb_copy */
|
||||
static int
|
||||
xmldb_copy_local(clicon_handle h,
|
||||
char *from,
|
||||
char *to)
|
||||
{
|
||||
return db_init(file);
|
||||
int retval = -1;
|
||||
char *fromfile = NULL;
|
||||
char *tofile = NULL;
|
||||
|
||||
/* XXX lock */
|
||||
if (db2file(h, from, &fromfile) < 0)
|
||||
goto done;
|
||||
if (db2file(h, to, &tofile) < 0)
|
||||
goto done;
|
||||
if (clicon_file_copy(fromfile, tofile) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
if (fromfile)
|
||||
free(fromfile);
|
||||
if (tofile)
|
||||
free(tofile);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if 1 /* Test program */
|
||||
/*! Copy database
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] from Source database copy
|
||||
* @param[in] to Destination database
|
||||
* @retval -1 Error
|
||||
* @retval 0 OK
|
||||
*/
|
||||
int
|
||||
xmldb_copy(clicon_handle h,
|
||||
char *from,
|
||||
char *to)
|
||||
{
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_copy_rpc(h, from, to);
|
||||
else
|
||||
return xmldb_copy_local(h, from, to);
|
||||
}
|
||||
|
||||
/* Local variant of xmldb_lock */
|
||||
static int
|
||||
xmldb_lock_local(clicon_handle h,
|
||||
char *db,
|
||||
int pid)
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
if (db_islocked(db)){
|
||||
if (pid != db_islocked(db)){
|
||||
clicon_err(OE_DB, 0, "lock failed: locked by %d", db_islocked(db));
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
db_lock(db, pid);
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Lock database
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] db Database
|
||||
* @param[in] pid Process id
|
||||
* @retval -1 Error
|
||||
* @retval 0 OK
|
||||
*/
|
||||
int
|
||||
xmldb_lock(clicon_handle h,
|
||||
char *db,
|
||||
int pid)
|
||||
{
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_lock_rpc(h, db, pid);
|
||||
else
|
||||
return xmldb_lock_local(h, db, pid);
|
||||
}
|
||||
|
||||
/*! Local variant of xmldb_unlock */
|
||||
static int
|
||||
xmldb_unlock_local(clicon_handle h,
|
||||
char *db,
|
||||
int pid)
|
||||
{
|
||||
int retval = -1;
|
||||
int pid1;
|
||||
|
||||
pid1 = db_islocked(db);
|
||||
if (pid1){
|
||||
if (pid == pid1)
|
||||
db_unlock(db);
|
||||
else{
|
||||
clicon_err(OE_DB, 0, "unlock failed: locked by %d", pid1);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Unlock database
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] db Database
|
||||
* @param[in] pid Process id
|
||||
* @retval -1 Error
|
||||
* @retval 0 OK
|
||||
*/
|
||||
int
|
||||
xmldb_unlock(clicon_handle h,
|
||||
char *db,
|
||||
int pid)
|
||||
{
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_unlock_rpc(h, db, pid);
|
||||
else
|
||||
return xmldb_unlock_local(h, db, pid);
|
||||
}
|
||||
|
||||
/*! Local variant of xmldb_islocked */
|
||||
static int
|
||||
xmldb_islocked_local(clicon_handle h,
|
||||
char *db)
|
||||
{
|
||||
return db_islocked(db);
|
||||
}
|
||||
|
||||
/*! Check if database is locked
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] db Database
|
||||
* @retval -1 Error
|
||||
* @retval 0 Not locked
|
||||
* @retval >0 Id of locker
|
||||
*/
|
||||
int
|
||||
xmldb_islocked(clicon_handle h,
|
||||
char *db)
|
||||
{
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_islocked_rpc(h, db);
|
||||
else
|
||||
return xmldb_islocked_local(h, db);
|
||||
}
|
||||
|
||||
/*! Local variant of xmldb_exists */
|
||||
static int
|
||||
xmldb_exists_local(clicon_handle h,
|
||||
char *db)
|
||||
{
|
||||
int retval = -1;
|
||||
char *filename = NULL;
|
||||
struct stat sb;
|
||||
|
||||
if (db2file(h, db, &filename) < 0)
|
||||
goto done;
|
||||
if (lstat(filename, &sb) < 0)
|
||||
retval = 0;
|
||||
else
|
||||
retval = 1;
|
||||
done:
|
||||
if (filename)
|
||||
free(filename);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Check if db exists
|
||||
* @retval -1 Error
|
||||
* @retval 0 No it does not exist
|
||||
* @retval 1 Yes it exists
|
||||
*/
|
||||
int
|
||||
xmldb_exists(clicon_handle h,
|
||||
char *db)
|
||||
{
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_exists_rpc(h, db);
|
||||
else
|
||||
return xmldb_exists_local(h, db);
|
||||
}
|
||||
|
||||
/*! Local variant of xmldb_delete */
|
||||
static int
|
||||
xmldb_delete_local(clicon_handle h,
|
||||
char *db)
|
||||
{
|
||||
int retval = -1;
|
||||
char *filename = NULL;
|
||||
|
||||
if (db2file(h, db, &filename) < 0)
|
||||
goto done;
|
||||
if (db_delete(filename) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
if (filename)
|
||||
free(filename);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Delete database. Remove file */
|
||||
int
|
||||
xmldb_delete(clicon_handle h,
|
||||
char *db)
|
||||
{
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_delete_rpc(h, db);
|
||||
else
|
||||
return xmldb_delete_local(h, db);
|
||||
}
|
||||
|
||||
/*! Local variant of xmldb_init */
|
||||
static int
|
||||
xmldb_init_local(clicon_handle h,
|
||||
char *db)
|
||||
{
|
||||
int retval = -1;
|
||||
char *filename = NULL;
|
||||
|
||||
if (db2file(h, db, &filename) < 0)
|
||||
goto done;
|
||||
if (db_init(filename) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
if (filename)
|
||||
free(filename);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Initialize database */
|
||||
int
|
||||
xmldb_init(clicon_handle h,
|
||||
char *db)
|
||||
{
|
||||
if (clicon_xmldb_rpc(h))
|
||||
return xmldb_init_rpc(h, db);
|
||||
else
|
||||
return xmldb_init_local(h, db);
|
||||
}
|
||||
|
||||
#if 0 /* Test program */
|
||||
/*
|
||||
* Turn this on to get an xpath test program
|
||||
* Usage: clicon_xpath [<xpath>]
|
||||
* read xml from input
|
||||
* Example compile:
|
||||
gcc -g -o xmldb -I. -I../clicon ./clicon_xmldb.c -lclicon -lcligen
|
||||
gcc -g -o xmldb -I. -I../clixon ./clixon_xmldb.c -lclixon -lcligen
|
||||
*/
|
||||
|
||||
static int
|
||||
|
|
@ -1260,7 +1711,7 @@ main(int argc, char **argv)
|
|||
if (argc < 5)
|
||||
usage(argv[0]);
|
||||
xpath = argc>5?argv[5]:NULL;
|
||||
if (xmldb_get(db, xpath, yspec, &xt) < 0)
|
||||
if (xmldb_get(h, db, xpath, 0, &xt, NULL, NULL) < 0)
|
||||
goto done;
|
||||
clicon_xml2file(stdout, xt, 0, 1);
|
||||
}
|
||||
|
|
@ -1283,7 +1734,7 @@ main(int argc, char **argv)
|
|||
op = OP_REMOVE;
|
||||
else
|
||||
usage(argv[0]);
|
||||
if (xmldb_put(db, xn, yspec, op) < 0)
|
||||
if (xmldb_put(h, db, xn, op) < 0)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue