optimization
This commit is contained in:
parent
14faf93eec
commit
4cb00bedfa
13 changed files with 687 additions and 320 deletions
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
## 3.4.0 (Upcoming)
|
||||
|
||||
* Datastore cache introduced: cache XML tree in memory for faster get access
|
||||
* Better semantic versioning, eg MAJOR/MINOR/PATCH, where increment in PATCH does not change API.
|
||||
|
||||
* Datastore cache introduced: cache XML tree in memory for faster get access. Use CLICON_XMLDB_CACHE configuration option. Default is 1.
|
||||
|
||||
* Moved XML_CHILD_HASH to variable instead of constant.
|
||||
|
||||
|
|
|
|||
|
|
@ -617,6 +617,7 @@ main(int argc, char **argv)
|
|||
char *sock;
|
||||
int sockfamily;
|
||||
char *xmldb_plugin;
|
||||
int xml_cache;
|
||||
|
||||
/* In the startup, logs to stderr & syslog and debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR|CLICON_LOG_SYSLOG);
|
||||
|
|
@ -807,7 +808,8 @@ main(int argc, char **argv)
|
|||
"or create the group and add the user to it. On linux for example:"
|
||||
" sudo groupadd %s\n"
|
||||
" sudo usermod -a -G %s user\n",
|
||||
config_group, clicon_configfile(h), config_group, config_group);
|
||||
config_group, clicon_configfile(h),
|
||||
config_group, config_group);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -829,6 +831,9 @@ main(int argc, char **argv)
|
|||
goto done;
|
||||
if (xmldb_setopt(h, "yangspec", clicon_dbspec_yang(h)) < 0)
|
||||
goto done;
|
||||
if ((xml_cache = clicon_option_bool(h, "CLICON_XMLDB_CACHE")) >= 0)
|
||||
if (xmldb_setopt(h, "xml_cache", (void*)xml_cache) < 0)
|
||||
goto done;
|
||||
/* If startup mode is not defined, eg via OPTION or -s, assume old method */
|
||||
startup_mode = clicon_startup_mode(h);
|
||||
if (startup_mode == -1){ /* Old style, fragmented mode, phase out */
|
||||
|
|
|
|||
|
|
@ -837,7 +837,7 @@ save_config_file(clicon_handle h,
|
|||
clicon_rpc_generate_error("Get configuration", xerr);
|
||||
goto done;
|
||||
}
|
||||
if ((f = fopen(filename, "wb")) == NULL){
|
||||
if ((f = fopen(filename, "w")) == NULL){
|
||||
clicon_err(OE_CFG, errno, "Creating file %s", filename);
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ main(int argc, char **argv)
|
|||
clicon_option_str_set(h, "CLICON_CLI_MODE", optarg);
|
||||
break;
|
||||
case 'q' : /* Quiet mode */
|
||||
clicon_option_str_set(h, "CLICON_QUIET", "on");
|
||||
clicon_quiet_mode_set(h, 1);
|
||||
break;
|
||||
case 'p' : /* Print spec */
|
||||
printspec++;
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ struct db_element{
|
|||
* Assumes single backend
|
||||
* Experimental
|
||||
*/
|
||||
static int datastore_cache = 1;
|
||||
static int xmltree_cache = 1;
|
||||
|
||||
/*! Check struct magic number for sanity checks
|
||||
* return 0 if OK, -1 if fail.
|
||||
|
|
@ -193,7 +193,7 @@ text_disconnect(xmldb_handle xh)
|
|||
if (th->th_dbdir)
|
||||
free(th->th_dbdir);
|
||||
if (th->th_dbs){
|
||||
if (datastore_cache){
|
||||
if (xmltree_cache){
|
||||
if ((keys = hash_keys(th->th_dbs, &klen)) == NULL)
|
||||
return 0;
|
||||
for(i = 0; i < klen; i++)
|
||||
|
|
@ -264,6 +264,9 @@ text_setopt(xmldb_handle xh,
|
|||
goto done;
|
||||
}
|
||||
}
|
||||
else if (strcmp(optname, "xml_cache") == 0){
|
||||
xmltree_cache = (intptr_t)value;
|
||||
}
|
||||
else{
|
||||
clicon_err(OE_PLUGIN, 0, "Option %s not implemented by plugin", optname);
|
||||
goto done;
|
||||
|
|
@ -389,21 +392,6 @@ xml_copy_marked(cxobj *x0,
|
|||
* xpath.
|
||||
* This is a clixon datastore plugin of the the xmldb api
|
||||
* @see xmldb_get
|
||||
#ifdef DATASTORE_CACHE
|
||||
text_get 90%
|
||||
clixon_xml_parse_file 74% (100x)
|
||||
xml_parse 70% (100x)
|
||||
clicon_xml_parseparse 70% (300x)
|
||||
xml_value_append 13% (800K)
|
||||
xml_new
|
||||
xml_purge
|
||||
clicon_xml_parselex 12% (1M)
|
||||
clixon_tree_prune_flagged_sub 12% (100x)
|
||||
xml_purge 12% (58000)
|
||||
yang_key_match 7% (77000)
|
||||
yang_arg2cvec
|
||||
#endif
|
||||
*
|
||||
*/
|
||||
int
|
||||
text_get(xmldb_handle xh,
|
||||
|
|
@ -427,7 +415,7 @@ text_get(xmldb_handle xh,
|
|||
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
||||
goto done;
|
||||
}
|
||||
if (datastore_cache){
|
||||
if (xmltree_cache){
|
||||
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL)
|
||||
xt = de->de_xml;
|
||||
}
|
||||
|
|
@ -471,11 +459,11 @@ text_get(xmldb_handle xh,
|
|||
if (xvec != NULL)
|
||||
for (i=0; i<xlen; i++){
|
||||
xml_flag_set(xvec[i], XML_FLAG_MARK);
|
||||
if (datastore_cache)
|
||||
if (xmltree_cache)
|
||||
xml_apply_ancestor(xvec[i], (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE);
|
||||
}
|
||||
|
||||
if (datastore_cache){
|
||||
if (xmltree_cache){
|
||||
/* Copy the matching parts of the (relevant) XML tree.
|
||||
* If cache was NULL, also write to datastore cache
|
||||
*/
|
||||
|
|
@ -852,7 +840,7 @@ text_put(xmldb_handle xh,
|
|||
xml_name(x1));
|
||||
goto done;
|
||||
}
|
||||
if (datastore_cache){
|
||||
if (xmltree_cache){
|
||||
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL)
|
||||
x0 = de->de_xml;
|
||||
}
|
||||
|
|
@ -921,7 +909,7 @@ text_put(xmldb_handle xh,
|
|||
goto done;
|
||||
|
||||
/* Write back to datastore cache if first time */
|
||||
if (datastore_cache){
|
||||
if (xmltree_cache){
|
||||
struct db_element de0 = {0,};
|
||||
if (de != NULL)
|
||||
de0 = *de;
|
||||
|
|
@ -930,7 +918,28 @@ text_put(xmldb_handle xh,
|
|||
hash_add(th->th_dbs, db, &de0, sizeof(de0));
|
||||
}
|
||||
}
|
||||
|
||||
if (dbfile == NULL){
|
||||
if (text_db2file(th, db, &dbfile) < 0)
|
||||
goto done;
|
||||
if (dbfile==NULL){
|
||||
clicon_err(OE_XML, 0, "dbfile NULL");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
{
|
||||
FILE *f;
|
||||
if ((f = fopen(dbfile, "w")) == NULL){
|
||||
clicon_err(OE_CFG, errno, "Creating file %s", dbfile);
|
||||
goto done;
|
||||
}
|
||||
if (xml_print(f, x0) < 0)
|
||||
goto done;
|
||||
fclose(f);
|
||||
}
|
||||
#else
|
||||
// output:
|
||||
/* Print out top-level xml tree after modification to file */
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
|
|
@ -942,14 +951,6 @@ text_put(xmldb_handle xh,
|
|||
/* Reopen file in write mode */
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
if (dbfile == 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_TRUNC, S_IRWXU)) < 0) {
|
||||
clicon_err(OE_UNIX, errno, "open(%s)", dbfile);
|
||||
goto done;
|
||||
|
|
@ -958,6 +959,7 @@ text_put(xmldb_handle xh,
|
|||
clicon_err(OE_UNIX, errno, "write(%s)", dbfile);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
retval = 0;
|
||||
done:
|
||||
if (dbfile)
|
||||
|
|
@ -966,7 +968,7 @@ text_put(xmldb_handle xh,
|
|||
close(fd);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (!datastore_cache && x0)
|
||||
if (!xmltree_cache && x0)
|
||||
xml_free(x0);
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -988,16 +990,38 @@ text_copy(xmldb_handle xh,
|
|||
char *fromfile = NULL;
|
||||
char *tofile = NULL;
|
||||
struct db_element *de = NULL;
|
||||
struct db_element *de2 = NULL;
|
||||
|
||||
/* XXX lock */
|
||||
if (datastore_cache){
|
||||
/* Just invalidate xml if exists in TO */
|
||||
if (xmltree_cache){
|
||||
/* 1. Free xml tree in "to"
|
||||
|
||||
*/
|
||||
if ((de = hash_value(th->th_dbs, to, NULL)) != NULL){
|
||||
if (de->de_xml != NULL){
|
||||
xml_free(de->de_xml);
|
||||
de->de_xml = NULL;
|
||||
}
|
||||
}
|
||||
/* 2. Copy xml tree from "from" to "to"
|
||||
* 2a) create "to" if it does not exist
|
||||
*/
|
||||
if ((de2 = hash_value(th->th_dbs, from, NULL)) != NULL){
|
||||
if (de2->de_xml != NULL){
|
||||
struct db_element de0 = {0,};
|
||||
cxobj *x, *xcopy;
|
||||
x = de2->de_xml;
|
||||
if (de != NULL)
|
||||
de0 = *de;
|
||||
if ((xcopy = xml_new(xml_name(x), NULL, xml_spec(x))) == NULL)
|
||||
goto done;
|
||||
if (xml_copy(x, xcopy) < 0)
|
||||
goto done;
|
||||
de0.de_xml = xcopy;
|
||||
hash_add(th->th_dbs, to, &de0, sizeof(de0));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (text_db2file(th, from, &fromfile) < 0)
|
||||
goto done;
|
||||
|
|
@ -1153,7 +1177,7 @@ text_delete(xmldb_handle xh,
|
|||
struct db_element *de = NULL;
|
||||
cxobj *xt = NULL;
|
||||
|
||||
if (datastore_cache){
|
||||
if (xmltree_cache){
|
||||
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL){
|
||||
if ((xt = de->de_xml) != NULL){
|
||||
xml_free(xt);
|
||||
|
|
@ -1192,7 +1216,7 @@ text_create(xmldb_handle xh,
|
|||
struct db_element *de = NULL;
|
||||
cxobj *xt = NULL;
|
||||
|
||||
if (datastore_cache){ /* XXX This should nt really happen? */
|
||||
if (xmltree_cache){ /* XXX This should nt really happen? */
|
||||
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL){
|
||||
if ((xt = de->de_xml) != NULL){
|
||||
assert(xt==NULL); /* XXX */
|
||||
|
|
|
|||
|
|
@ -74,53 +74,92 @@ enum startup_mode_t{
|
|||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
|
||||
/* Print registry on file. For debugging. */
|
||||
void clicon_option_dump(clicon_handle h, int dblevel);
|
||||
/* Initialize options: set defaults, read config-file, etc */
|
||||
int clicon_options_main(clicon_handle h);
|
||||
|
||||
void clicon_option_dump(clicon_handle h, int dblevel);
|
||||
|
||||
/*! Check if a clicon option has a value */
|
||||
int clicon_option_exists(clicon_handle h, const char *name);
|
||||
|
||||
/* Get a single option via handle */
|
||||
/* String options, default NULL */
|
||||
char *clicon_option_str(clicon_handle h, const char *name);
|
||||
int clicon_option_int(clicon_handle h, const char *name);
|
||||
/* Set a single option via handle */
|
||||
int clicon_option_str_set(clicon_handle h, const char *name, char *val);
|
||||
|
||||
/* Option values gixen as int, default -1 */
|
||||
int clicon_option_int(clicon_handle h, const char *name);
|
||||
int clicon_option_int_set(clicon_handle h, const char *name, int val);
|
||||
|
||||
/* Option values gixen as bool, default false */
|
||||
int clicon_option_bool(clicon_handle h, const char *name);
|
||||
int clicon_option_bool_set(clicon_handle h, const char *name, int val);
|
||||
|
||||
/* Delete a single option via handle */
|
||||
int clicon_option_del(clicon_handle h, const char *name);
|
||||
|
||||
char *clicon_configfile(clicon_handle h);
|
||||
char *clicon_yang_dir(clicon_handle h);
|
||||
char *clicon_yang_module_main(clicon_handle h);
|
||||
char *clicon_yang_module_revision(clicon_handle h);
|
||||
char *clicon_backend_dir(clicon_handle h);
|
||||
char *clicon_cli_dir(clicon_handle h);
|
||||
char *clicon_clispec_dir(clicon_handle h);
|
||||
char *clicon_netconf_dir(clicon_handle h);
|
||||
char *clicon_restconf_dir(clicon_handle h);
|
||||
char *clicon_xmldb_plugin(clicon_handle h);
|
||||
int clicon_startup_mode(clicon_handle h);
|
||||
int clicon_sock_family(clicon_handle h);
|
||||
char *clicon_sock(clicon_handle h);
|
||||
int clicon_sock_port(clicon_handle h);
|
||||
char *clicon_backend_pidfile(clicon_handle h);
|
||||
char *clicon_sock_group(clicon_handle h);
|
||||
/*-- Standard option access functions for YANG options --*/
|
||||
static inline char *clicon_configfile(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_CONFIGFILE");
|
||||
}
|
||||
static inline char *clicon_yang_dir(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_YANG_DIR");
|
||||
}
|
||||
static inline char *clicon_yang_module_main(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_YANG_MODULE_MAIN");
|
||||
}
|
||||
static inline char *clicon_yang_module_revision(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_YANG_MODULE_REVISION");
|
||||
}
|
||||
static inline char *clicon_backend_dir(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_BACKEND_DIR");
|
||||
}
|
||||
static inline char *clicon_netconf_dir(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_NETCONF_DIR");
|
||||
}
|
||||
static inline char *clicon_restconf_dir(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_RESTCONF_DIR");
|
||||
}
|
||||
static inline char *clicon_cli_dir(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_CLI_DIR");
|
||||
}
|
||||
static inline char *clicon_clispec_dir(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_CLISPEC_DIR");
|
||||
}
|
||||
static inline char *clicon_cli_mode(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_CLI_MODE");
|
||||
}
|
||||
static inline char *clicon_sock(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_SOCK");
|
||||
}
|
||||
static inline char *clicon_sock_group(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_SOCK_GROUP");
|
||||
}
|
||||
static inline char *clicon_backend_pidfile(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_BACKEND_PIDFILE");
|
||||
}
|
||||
static inline char *clicon_master_plugin(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_MASTER_PLUGIN");
|
||||
}
|
||||
static inline char *clicon_xmldb_dir(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_XMLDB_DIR");
|
||||
}
|
||||
static inline char *clicon_xmldb_plugin(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_XMLDB_PLUGIN");
|
||||
}
|
||||
|
||||
char *clicon_master_plugin(clicon_handle h);
|
||||
char *clicon_cli_mode(clicon_handle h);
|
||||
/*-- Specific option access functions for YANG options w type conversion--*/
|
||||
int clicon_cli_genmodel(clicon_handle h);
|
||||
int clicon_cli_varonly(clicon_handle h);
|
||||
int clicon_cli_varonly_set(clicon_handle h, int val);
|
||||
int clicon_cli_genmodel_completion(clicon_handle h);
|
||||
|
||||
char *clicon_xmldb_dir(clicon_handle h);
|
||||
|
||||
char *clicon_quiet_mode(clicon_handle h);
|
||||
enum genmodel_type clicon_cli_genmodel_type(clicon_handle h);
|
||||
|
||||
int clicon_cli_varonly(clicon_handle h);
|
||||
int clicon_sock_family(clicon_handle h);
|
||||
int clicon_sock_port(clicon_handle h);
|
||||
int clicon_autocommit(clicon_handle h);
|
||||
int clicon_autocommit_set(clicon_handle h, int val);
|
||||
int clicon_startup_mode(clicon_handle h);
|
||||
|
||||
/*-- Specific option access functions for non-yang options --*/
|
||||
int clicon_quiet_mode(clicon_handle h);
|
||||
int clicon_quiet_mode_set(clicon_handle h, int val);
|
||||
|
||||
yang_spec * clicon_dbspec_yang(clicon_handle h);
|
||||
int clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys);
|
||||
|
|
@ -128,16 +167,13 @@ int clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys);
|
|||
char *clicon_dbspec_name(clicon_handle h);
|
||||
int clicon_dbspec_name_set(clicon_handle h, char *name);
|
||||
|
||||
plghndl_t clicon_xmldb_plugin_get(clicon_handle h);
|
||||
int clicon_xmldb_plugin_set(clicon_handle h, plghndl_t handle);
|
||||
|
||||
plghndl_t clicon_xmldb_plugin_get(clicon_handle h);
|
||||
|
||||
void *clicon_xmldb_api_get(clicon_handle h);
|
||||
int clicon_xmldb_api_set(clicon_handle h, void *xa_api);
|
||||
|
||||
void *clicon_xmldb_api_get(clicon_handle h);
|
||||
|
||||
void *clicon_xmldb_handle_get(clicon_handle h);
|
||||
int clicon_xmldb_handle_set(clicon_handle h, void *xh);
|
||||
|
||||
void *clicon_xmldb_handle_get(clicon_handle h);
|
||||
|
||||
#endif /* _CLIXON_OPTIONS_H_ */
|
||||
|
|
|
|||
|
|
@ -495,6 +495,49 @@ clicon_option_int_set(clicon_handle h,
|
|||
return clicon_option_str_set(h, name, s);
|
||||
}
|
||||
|
||||
/*! Get options as bool but stored as string
|
||||
*
|
||||
* @param h clicon handle
|
||||
* @param name name of option
|
||||
* @retval 0 false, or does not exist, or does not have a boolean value
|
||||
* @retval 1 true
|
||||
* @code
|
||||
* if (clicon_option_exists(h, "X")
|
||||
* return clicon_option_bool(h, "X");
|
||||
* else
|
||||
* return 0; # default false?
|
||||
* @endcode
|
||||
* Note that 0 can be both error and false.
|
||||
* This means that it should be used together with clicon_option_exists() and
|
||||
* supply a default value as shown in the example.
|
||||
*/
|
||||
int
|
||||
clicon_option_bool(clicon_handle h,
|
||||
const char *name)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if ((s = clicon_option_str(h, name)) == NULL)
|
||||
return 0;
|
||||
if (strcmp(s,"true")==0)
|
||||
return 1;
|
||||
return 0; /* Hopefully false, but anything else than "true" */
|
||||
}
|
||||
|
||||
/*! Set option given as bool
|
||||
*/
|
||||
int
|
||||
clicon_option_bool_set(clicon_handle h,
|
||||
const char *name,
|
||||
int val)
|
||||
{
|
||||
char s[64];
|
||||
|
||||
if (snprintf(s, sizeof(s)-1, "%u", val) < 0)
|
||||
return -1;
|
||||
return clicon_option_str_set(h, name, s);
|
||||
}
|
||||
|
||||
/*! Delete option
|
||||
*/
|
||||
int
|
||||
|
|
@ -507,146 +550,18 @@ clicon_option_del(clicon_handle h,
|
|||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* Specific option access functions.
|
||||
* These should be commonly accessible for all users of clicon lib
|
||||
* Specific option access functions for YANG configuration variables.
|
||||
* Sometimes overridden by command-line options,
|
||||
* such as -f for CLICON_CONFIGFILE
|
||||
* @see yang/clixon-config@<date>.yang
|
||||
* You can always use the basic access functions, such as
|
||||
* clicon_option_str[_set]
|
||||
* But sometimes there are type conversions, etc which makes it more
|
||||
* convenient to make wrapper functions. Or not?
|
||||
*-----------------------------------------------------------------*/
|
||||
|
||||
char *
|
||||
clicon_configfile(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_CONFIGFILE");
|
||||
}
|
||||
|
||||
/*! YANG database specification directory */
|
||||
char *
|
||||
clicon_yang_dir(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_YANG_DIR");
|
||||
}
|
||||
|
||||
/*! YANG main module or absolute file name */
|
||||
char *
|
||||
clicon_yang_module_main(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_YANG_MODULE_MAIN");
|
||||
}
|
||||
|
||||
/*! YANG revision */
|
||||
char *
|
||||
clicon_yang_module_revision(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_YANG_MODULE_REVISION");
|
||||
}
|
||||
|
||||
/*! Directory of backend plugins. If null, no plugins are loaded */
|
||||
char *
|
||||
clicon_backend_dir(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_BACKEND_DIR");
|
||||
}
|
||||
|
||||
/* contains .so files CLICON_CLI_DIR */
|
||||
char *
|
||||
clicon_cli_dir(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_CLI_DIR");
|
||||
}
|
||||
|
||||
/* contains .cli files - CLICON_CLISPEC_DIR */
|
||||
char *
|
||||
clicon_clispec_dir(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_CLISPEC_DIR");
|
||||
}
|
||||
|
||||
char *
|
||||
clicon_netconf_dir(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_NETCONF_DIR");
|
||||
}
|
||||
|
||||
char *
|
||||
clicon_restconf_dir(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_RESTCONF_DIR");
|
||||
}
|
||||
|
||||
char *
|
||||
clicon_xmldb_plugin(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_XMLDB_PLUGIN");
|
||||
}
|
||||
|
||||
int
|
||||
clicon_startup_mode(clicon_handle h)
|
||||
{
|
||||
char *mode;
|
||||
if ((mode = clicon_option_str(h, "CLICON_STARTUP_MODE")) == NULL)
|
||||
return -1;
|
||||
return clicon_str2int(startup_mode_map, mode);
|
||||
}
|
||||
|
||||
/*! Get family of backend socket: AF_UNIX, AF_INET or AF_INET6 */
|
||||
int
|
||||
clicon_sock_family(clicon_handle h)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if ((s = clicon_option_str(h, "CLICON_SOCK_FAMILY")) == NULL)
|
||||
return AF_UNIX;
|
||||
else if (strcmp(s, "IPv4")==0)
|
||||
return AF_INET;
|
||||
else if (strcmp(s, "IPv6")==0)
|
||||
return AF_INET6;
|
||||
else
|
||||
return AF_UNIX; /* default */
|
||||
}
|
||||
|
||||
/*! Get information about socket: unix domain filepath, or addr:path */
|
||||
char *
|
||||
clicon_sock(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_SOCK");
|
||||
}
|
||||
|
||||
/*! Get port for backend socket in case of AF_INET or AF_INET6 */
|
||||
int
|
||||
clicon_sock_port(clicon_handle h)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if ((s = clicon_option_str(h, "CLICON_SOCK_PORT")) == NULL)
|
||||
return -1;
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
char *
|
||||
clicon_backend_pidfile(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_BACKEND_PIDFILE");
|
||||
}
|
||||
|
||||
char *
|
||||
clicon_sock_group(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_SOCK_GROUP");
|
||||
}
|
||||
|
||||
char *
|
||||
clicon_master_plugin(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_MASTER_PLUGIN");
|
||||
}
|
||||
|
||||
/*! Return initial clicon cli mode */
|
||||
char *
|
||||
clicon_cli_mode(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_CLI_MODE");
|
||||
}
|
||||
|
||||
/*! Whether to generate CLIgen syntax from datamodel or not (0 or 1)
|
||||
* Must be used with a previous clicon_option_exists().
|
||||
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL
|
||||
*/
|
||||
int
|
||||
clicon_cli_genmodel(clicon_handle h)
|
||||
|
|
@ -659,7 +574,23 @@ clicon_cli_genmodel(clicon_handle h)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! How to generate and show CLI syntax: VARS|ALL */
|
||||
/*! Generate code for CLI completion of existing db symbols
|
||||
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL_COMPLETION
|
||||
*/
|
||||
int
|
||||
clicon_cli_genmodel_completion(clicon_handle h)
|
||||
{
|
||||
char const *opt = "CLICON_CLI_GENMODEL_COMPLETION";
|
||||
|
||||
if (clicon_option_exists(h, opt))
|
||||
return clicon_option_int(h, opt);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! How to generate and show CLI syntax: VARS|ALL
|
||||
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL_TYPE
|
||||
*/
|
||||
enum genmodel_type
|
||||
clicon_cli_genmodel_type(clicon_handle h)
|
||||
{
|
||||
|
|
@ -683,32 +614,8 @@ clicon_cli_genmodel_type(clicon_handle h)
|
|||
return gt;
|
||||
}
|
||||
|
||||
|
||||
/* eg -q option, dont print notifications on stdout */
|
||||
char *
|
||||
clicon_quiet_mode(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_QUIET");
|
||||
}
|
||||
|
||||
int
|
||||
clicon_autocommit(clicon_handle h)
|
||||
{
|
||||
char const *opt = "CLICON_AUTOCOMMIT";
|
||||
|
||||
if (clicon_option_exists(h, opt))
|
||||
return clicon_option_int(h, opt);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
clicon_autocommit_set(clicon_handle h, int val)
|
||||
{
|
||||
return clicon_option_int_set(h, "CLICON_AUTOCOMMIT", val);
|
||||
}
|
||||
|
||||
/*! Dont include keys in cvec in cli vars callbacks
|
||||
/*! Get Dont include keys in cvec in cli vars callbacks
|
||||
* @see clixon-config@<date>.yang CLICON_CLI_VARONLY
|
||||
*/
|
||||
int
|
||||
clicon_cli_varonly(clicon_handle h)
|
||||
|
|
@ -721,16 +628,43 @@ clicon_cli_varonly(clicon_handle h)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Get family of backend socket: AF_UNIX, AF_INET or AF_INET6
|
||||
* @see clixon-config@<date>.yang CLICON_SOCK_FAMILY
|
||||
*/
|
||||
int
|
||||
clicon_cli_varonly_set(clicon_handle h, int val)
|
||||
clicon_sock_family(clicon_handle h)
|
||||
{
|
||||
return clicon_option_int_set(h, "CLICON_CLI_VARONLY", val);
|
||||
char *s;
|
||||
|
||||
if ((s = clicon_option_str(h, "CLICON_SOCK_FAMILY")) == NULL)
|
||||
return AF_UNIX;
|
||||
else if (strcmp(s, "IPv4")==0)
|
||||
return AF_INET;
|
||||
else if (strcmp(s, "IPv6")==0)
|
||||
return AF_INET6;
|
||||
else
|
||||
return AF_UNIX; /* default */
|
||||
}
|
||||
|
||||
/*! Get port for backend socket in case of AF_INET or AF_INET6
|
||||
* @see clixon-config@<date>.yang CLICON_SOCK_PORT
|
||||
*/
|
||||
int
|
||||
clicon_cli_genmodel_completion(clicon_handle h)
|
||||
clicon_sock_port(clicon_handle h)
|
||||
{
|
||||
char const *opt = "CLICON_CLI_GENMODEL_COMPLETION";
|
||||
char *s;
|
||||
|
||||
if ((s = clicon_option_str(h, "CLICON_SOCK_PORT")) == NULL)
|
||||
return -1;
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
/*! Set if all configuration changes are committed automatically
|
||||
*/
|
||||
int
|
||||
clicon_autocommit(clicon_handle h)
|
||||
{
|
||||
char const *opt = "CLICON_AUTOCOMMIT";
|
||||
|
||||
if (clicon_option_exists(h, opt))
|
||||
return clicon_option_int(h, opt);
|
||||
|
|
@ -738,11 +672,36 @@ clicon_cli_genmodel_completion(clicon_handle h)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Where are "running" and "candidate" databases? */
|
||||
char *
|
||||
clicon_xmldb_dir(clicon_handle h)
|
||||
/*! Which method to boot/start clicon backen
|
||||
*/
|
||||
int
|
||||
clicon_startup_mode(clicon_handle h)
|
||||
{
|
||||
return clicon_option_str(h, "CLICON_XMLDB_DIR");
|
||||
char *mode;
|
||||
if ((mode = clicon_option_str(h, "CLICON_STARTUP_MODE")) == NULL)
|
||||
return -1;
|
||||
return clicon_str2int(startup_mode_map, mode);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* Specific option access functions for non-yang options
|
||||
* Typically dynamic values and more complex datatypes,
|
||||
* Such as handles to plugins, API:s and parsed structures
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
/* eg -q option, dont print notifications on stdout */
|
||||
int
|
||||
clicon_quiet_mode(clicon_handle h)
|
||||
{
|
||||
char *s;
|
||||
if ((s = clicon_option_str(h, "CLICON_QUIET")) == NULL)
|
||||
return 0; /* default */
|
||||
return atoi(s);
|
||||
}
|
||||
int
|
||||
clicon_quiet_mode_set(clicon_handle h, int val)
|
||||
{
|
||||
return clicon_option_int_set(h, "CLICON_QUIET", val);
|
||||
}
|
||||
|
||||
/*! Get YANG specification
|
||||
|
|
@ -796,6 +755,19 @@ clicon_dbspec_name_set(clicon_handle h, char *name)
|
|||
return clicon_option_str_set(h, "dbspec_name", name);
|
||||
}
|
||||
|
||||
/*! Get xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */
|
||||
plghndl_t
|
||||
clicon_xmldb_plugin_get(clicon_handle h)
|
||||
{
|
||||
clicon_hash_t *cdat = clicon_data(h);
|
||||
size_t len;
|
||||
void *p;
|
||||
|
||||
if ((p = hash_value(cdat, "xmldb_plugin", &len)) != NULL)
|
||||
return *(plghndl_t*)p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! Set xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */
|
||||
int
|
||||
clicon_xmldb_plugin_set(clicon_handle h,
|
||||
|
|
@ -808,16 +780,20 @@ clicon_xmldb_plugin_set(clicon_handle h,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Get xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */
|
||||
plghndl_t
|
||||
clicon_xmldb_plugin_get(clicon_handle h)
|
||||
/*! Get XMLDB API struct pointer
|
||||
* @param[in] h Clicon handle
|
||||
* @retval xa XMLDB API struct
|
||||
* @note xa is really of type struct xmldb_api*
|
||||
*/
|
||||
void *
|
||||
clicon_xmldb_api_get(clicon_handle h)
|
||||
{
|
||||
clicon_hash_t *cdat = clicon_data(h);
|
||||
size_t len;
|
||||
void *p;
|
||||
void *xa;
|
||||
|
||||
if ((p = hash_value(cdat, "xmldb_plugin", &len)) != NULL)
|
||||
return *(plghndl_t*)p;
|
||||
if ((xa = hash_value(cdat, "xmldb_api", &len)) != NULL)
|
||||
return *(void**)xa;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -840,20 +816,19 @@ clicon_xmldb_api_set(clicon_handle h,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Get XMLDB API struct pointer
|
||||
/*! Get XMLDB storage handle
|
||||
* @param[in] h Clicon handle
|
||||
* @retval xa XMLDB API struct
|
||||
* @note xa is really of type struct xmldb_api*
|
||||
* @retval xh XMLDB storage handle. If not connected return NULL
|
||||
*/
|
||||
void *
|
||||
clicon_xmldb_api_get(clicon_handle h)
|
||||
clicon_xmldb_handle_get(clicon_handle h)
|
||||
{
|
||||
clicon_hash_t *cdat = clicon_data(h);
|
||||
size_t len;
|
||||
void *xa;
|
||||
void *xh;
|
||||
|
||||
if ((xa = hash_value(cdat, "xmldb_api", &len)) != NULL)
|
||||
return *(void**)xa;
|
||||
if ((xh = hash_value(cdat, "xmldb_handle", &len)) != NULL)
|
||||
return *(void**)xh;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -873,18 +848,4 @@ clicon_xmldb_handle_set(clicon_handle h,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Get XMLDB storage handle
|
||||
* @param[in] h Clicon handle
|
||||
* @retval xh XMLDB storage handle. If not connected return NULL
|
||||
*/
|
||||
void *
|
||||
clicon_xmldb_handle_get(clicon_handle h)
|
||||
{
|
||||
clicon_hash_t *cdat = clicon_data(h);
|
||||
size_t len;
|
||||
void *xh;
|
||||
|
||||
if ((xh = hash_value(cdat, "xmldb_handle", &len)) != NULL)
|
||||
return *(void**)xh;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ pidfile_write(char *pidfile)
|
|||
int retval = -1;
|
||||
|
||||
/* Here, there should be no old agent and no pidfile */
|
||||
if ((f = fopen(pidfile, "wb")) == NULL){
|
||||
if ((f = fopen(pidfile, "w")) == NULL){
|
||||
if (errno == EACCES)
|
||||
clicon_err(OE_DEMON, errno, "Creating pid-file %s (Try run as root?)", pidfile);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
* Constants
|
||||
*/
|
||||
#define BUFLEN 1024 /* Size of xml read buffer */
|
||||
#define XML_INDENT 3 /* maybe we should set this programmatically? */
|
||||
|
||||
/*
|
||||
* Types
|
||||
|
|
@ -104,7 +105,7 @@ static const map_str2int xsmap[] = {
|
|||
};
|
||||
|
||||
/* Hash for XML trees list entries
|
||||
* Experimental
|
||||
* Experimental XXX DOES NOT WORK
|
||||
*/
|
||||
int xml_child_hash = 0;
|
||||
|
||||
|
|
@ -442,7 +443,7 @@ xml_child_each(cxobj *xparent,
|
|||
xn = xparent->x_childvec[i];
|
||||
if (xn == NULL)
|
||||
continue;
|
||||
if (type != CX_ERROR && xml_type(xn) != type)
|
||||
if (type != CX_ERROR && xn->x_type != type)
|
||||
continue;
|
||||
break; /* this is next object after previous */
|
||||
}
|
||||
|
|
@ -931,27 +932,89 @@ xml_free(cxobj *x)
|
|||
* @param[in] level how many spaces to insert before each line
|
||||
* @param[in] prettyprint insert \n and spaces tomake the xml more readable.
|
||||
* @see clicon_xml2cbuf
|
||||
* One can use clicon_xml2cbuf to get common code, but using fprintf is
|
||||
* much faster than using cbuf and then printing that,...
|
||||
*/
|
||||
int
|
||||
clicon_xml2file(FILE *f,
|
||||
cxobj *xn,
|
||||
cxobj *x,
|
||||
int level,
|
||||
int prettyprint)
|
||||
{
|
||||
int retval = -1;
|
||||
cbuf *cb = NULL;
|
||||
char *name;
|
||||
char *namespace;
|
||||
cxobj *xc;
|
||||
int hasbody;
|
||||
int haselement;
|
||||
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
name = xml_name(x);
|
||||
namespace = xml_namespace(x);
|
||||
switch(xml_type(x)){
|
||||
case CX_BODY:
|
||||
fprintf(f, "%s", xml_value(x));
|
||||
break;
|
||||
case CX_ATTR:
|
||||
fprintf(f, " ");
|
||||
if (namespace)
|
||||
fprintf(f, "%s:", namespace);
|
||||
fprintf(f, "%s=\"%s\"", name, xml_value(x));
|
||||
break;
|
||||
case CX_ELMNT:
|
||||
fprintf(f, "%*s<", prettyprint?(level*XML_INDENT):0, "");
|
||||
if (namespace)
|
||||
fprintf(f, "%s:", namespace);
|
||||
fprintf(f, "%s", name);
|
||||
hasbody = 0;
|
||||
haselement = 0;
|
||||
xc = NULL;
|
||||
/* print attributes only */
|
||||
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
|
||||
switch (xc->x_type){
|
||||
case CX_ATTR:
|
||||
if (clicon_xml2file(f, xc, level+1, prettyprint) <0)
|
||||
goto done;
|
||||
break;
|
||||
case CX_BODY:
|
||||
hasbody=1;
|
||||
break;
|
||||
case CX_ELMNT:
|
||||
haselement=1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Check for special case <a/> instead of <a></a>:
|
||||
* Ie, no CX_BODY or CX_ELMNT child.
|
||||
*/
|
||||
if (hasbody==0 && haselement==0)
|
||||
fprintf(f, "/>");
|
||||
else{
|
||||
fprintf(f, ">");
|
||||
if (prettyprint && hasbody == 0)
|
||||
fprintf(f, "\n");
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
|
||||
if (xml_type(xc) != CX_ATTR)
|
||||
if (clicon_xml2file(f, xc, level+1, prettyprint) <0)
|
||||
goto done;
|
||||
}
|
||||
if (clicon_xml2cbuf(cb, xn, level, prettyprint) < 0)
|
||||
goto done;
|
||||
fprintf(f, "%s", cbuf_get(cb));
|
||||
if (prettyprint && hasbody==0)
|
||||
fprintf(f, "%*s", level*XML_INDENT, "");
|
||||
fprintf(f, "</");
|
||||
if (namespace)
|
||||
fprintf(f, "%s:", namespace);
|
||||
fprintf(f, "%s>", name);
|
||||
}
|
||||
if (prettyprint)
|
||||
fprintf(f, "\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}/* switch */
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -971,7 +1034,6 @@ xml_print(FILE *f,
|
|||
return clicon_xml2file(f, xn, 0, 1);
|
||||
}
|
||||
|
||||
#define XML_INDENT 3 /* maybe we should set this programmatically? */
|
||||
|
||||
/*! Print an XML tree structure to a cligen buffer
|
||||
*
|
||||
|
|
@ -987,7 +1049,7 @@ xml_print(FILE *f,
|
|||
* goto err;
|
||||
* cbuf_free(cb);
|
||||
* @endcode
|
||||
* See also clicon_xml2file
|
||||
* @see clicon_xml2file
|
||||
*/
|
||||
int
|
||||
clicon_xml2cbuf(cbuf *cb,
|
||||
|
|
@ -995,48 +1057,67 @@ clicon_xml2cbuf(cbuf *cb,
|
|||
int level,
|
||||
int prettyprint)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xc;
|
||||
char *name;
|
||||
int hasbody;
|
||||
int haselement;
|
||||
char *namespace;
|
||||
|
||||
name = xml_name(x);
|
||||
namespace = xml_namespace(x);
|
||||
switch(xml_type(x)){
|
||||
case CX_BODY:
|
||||
cprintf(cb, "%s", xml_value(x));
|
||||
break;
|
||||
case CX_ATTR:
|
||||
cprintf(cb, " ");
|
||||
if (xml_namespace(x))
|
||||
cprintf(cb, "%s:", xml_namespace(x));
|
||||
if (namespace)
|
||||
cprintf(cb, "%s:", namespace);
|
||||
cprintf(cb, "%s=\"%s\"", name, xml_value(x));
|
||||
break;
|
||||
case CX_ELMNT:
|
||||
cprintf(cb, "%*s<", prettyprint?(level*XML_INDENT):0, "");
|
||||
if (xml_namespace(x))
|
||||
cprintf(cb, "%s:", xml_namespace(x));
|
||||
if (namespace)
|
||||
cprintf(cb, "%s:", namespace);
|
||||
cprintf(cb, "%s", name);
|
||||
hasbody = 0;
|
||||
haselement = 0;
|
||||
xc = NULL;
|
||||
/* print attributes only */
|
||||
while ((xc = xml_child_each(x, xc, CX_ATTR)) != NULL)
|
||||
clicon_xml2cbuf(cb, xc, level+1, prettyprint);
|
||||
while ((xc = xml_child_each(x, xc, -1)) != NULL)
|
||||
switch (xc->x_type){
|
||||
case CX_ATTR:
|
||||
if (clicon_xml2cbuf(cb, xc, level+1, prettyprint) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case CX_BODY:
|
||||
hasbody=1;
|
||||
break;
|
||||
case CX_ELMNT:
|
||||
haselement=1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for special case <a/> instead of <a></a> */
|
||||
if (xml_body(x)==NULL && xml_child_nr_type(x, CX_ELMNT)==0)
|
||||
if (hasbody==0 && haselement==0)
|
||||
cprintf(cb, "/>");
|
||||
else{
|
||||
cprintf(cb, ">");
|
||||
if (prettyprint && xml_body(x)==NULL)
|
||||
if (prettyprint && hasbody == 0)
|
||||
cprintf(cb, "\n");
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
|
||||
if (xml_type(xc) == CX_ATTR)
|
||||
continue;
|
||||
else
|
||||
clicon_xml2cbuf(cb, xc, level+1, prettyprint);
|
||||
}
|
||||
if (prettyprint && xml_body(x)==NULL)
|
||||
while ((xc = xml_child_each(x, xc, -1)) != NULL)
|
||||
if (xml_type(xc) != CX_ATTR)
|
||||
if (clicon_xml2cbuf(cb, xc, level+1, prettyprint) < 0)
|
||||
goto done;
|
||||
if (prettyprint && hasbody == 0)
|
||||
cprintf(cb, "%*s", level*XML_INDENT, "");
|
||||
cprintf(cb, "</");
|
||||
if (xml_namespace(x))
|
||||
cprintf(cb, "%s:", xml_namespace(x));
|
||||
if (namespace)
|
||||
cprintf(cb, "%s:", namespace);
|
||||
cprintf(cb, "%s>", name);
|
||||
}
|
||||
if (prettyprint)
|
||||
|
|
@ -1045,7 +1126,9 @@ clicon_xml2cbuf(cbuf *cb,
|
|||
default:
|
||||
break;
|
||||
}/* switch */
|
||||
return 0;
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Basic xml parsing function.
|
||||
|
|
|
|||
|
|
@ -86,18 +86,21 @@ echo "$clixon_netconf -qf $clixon_cf -y $fyang"
|
|||
new "netconf edit large config"
|
||||
expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang
|
||||
#echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang
|
||||
|
||||
new "netconf edit large config again"
|
||||
expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang
|
||||
#echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang
|
||||
|
||||
rm $fconfig
|
||||
|
||||
new "netconf commit large config"
|
||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf commit same config again"
|
||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf add one small config"
|
||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>x</a><b>y</b></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
|
|
@ -107,9 +110,6 @@ time -p for (( i=0; i<$req; i++ )); do
|
|||
echo "<rpc><edit-config><target><candidate/></target><config><x><y><a>$rnd</a><b>$rnd</b></y></x></config></edit-config></rpc>]]>]]>"
|
||||
done | $clixon_netconf -qf $clixon_cf -y $fyang > /dev/null
|
||||
|
||||
new "netconf commit small config"
|
||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf get large config"
|
||||
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b>"
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ bindir = @bindir@
|
|||
includedir = @includedir@
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
YANGSPECS = clixon-config@2017-07-02.yang
|
||||
YANGSPECS = clixon-config@2017-12-03.yang
|
||||
YANGSPECS += ietf-netconf@2011-06-01.yang
|
||||
|
||||
APPNAME = clixon # subdir ehere these files are installed
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
***** END LICENSE BLOCK *****";
|
||||
|
||||
revision 2017-11-12 {
|
||||
revision 2017-07-02 {
|
||||
description
|
||||
"Added startup config";
|
||||
}
|
||||
|
|
|
|||
256
yang/clixon-config@2017-12-03.yang
Normal file
256
yang/clixon-config@2017-12-03.yang
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
module clixon-config {
|
||||
|
||||
prefix cc;
|
||||
|
||||
organization
|
||||
"Clicon / Clixon";
|
||||
|
||||
contact
|
||||
"Olof Hagsand <olof@hagsand.se>";
|
||||
|
||||
description
|
||||
"Clixon configuration file
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Copyright (C) 2009-2017 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLIXON
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the \"License\");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an \"AS IS\" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the \"GPL\"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****";
|
||||
|
||||
revision 2017-12-03 {
|
||||
description
|
||||
"Added startup config for Clixon 1.3.3 and xmldb_cache in 1.4.0";
|
||||
}
|
||||
typedef startup_mode{
|
||||
description
|
||||
"Which method to boot/start clicon backend.
|
||||
The methods differ in how they reach a running state
|
||||
Which source database to commit from, if any.";
|
||||
type enumeration{
|
||||
enum none{
|
||||
description
|
||||
"Do not touch running state
|
||||
Typically after crash when running state and db are synched";
|
||||
}
|
||||
enum init{
|
||||
description
|
||||
"Initialize running state.
|
||||
Start with a completely clean running state";
|
||||
}
|
||||
enum running{
|
||||
description
|
||||
"Commit running db configuration into running state
|
||||
After reboot if a persistent running db exists";
|
||||
}
|
||||
enum startup{
|
||||
description
|
||||
"Commit startup configuration into running state
|
||||
After reboot when no persistent running db exists";
|
||||
}
|
||||
}
|
||||
}
|
||||
container config {
|
||||
leaf CLICON_CONFIGFILE{
|
||||
type string;
|
||||
description
|
||||
"Location of configuration-file for default values (this file)";
|
||||
}
|
||||
leaf CLICON_YANG_DIR {
|
||||
type string;
|
||||
mandatory true;
|
||||
description
|
||||
"Location of YANG module and submodule files.";
|
||||
}
|
||||
leaf CLICON_YANG_MODULE_MAIN {
|
||||
type string;
|
||||
default "clicon";
|
||||
description
|
||||
"Option used to construct initial yang file:
|
||||
<module>[@<revision>]";
|
||||
}
|
||||
leaf CLICON_YANG_MODULE_REVISION {
|
||||
type string;
|
||||
description
|
||||
"Option used to construct initial yang file:
|
||||
<module>[@<revision>]";
|
||||
}
|
||||
leaf CLICON_BACKEND_DIR {
|
||||
type string;
|
||||
description
|
||||
"Location of backend .so plugins. Load all .so
|
||||
plugins in this dir as backend plugins";
|
||||
}
|
||||
leaf CLICON_NETCONF_DIR {
|
||||
type string;
|
||||
description "Location of netconf (frontend) .so plugins";
|
||||
}
|
||||
leaf CLICON_RESTCONF_DIR {
|
||||
type string;
|
||||
description
|
||||
"Location of restconf (frontend) .so plugins. Load all .so
|
||||
plugins in this dir as restconf code plugins";
|
||||
}
|
||||
leaf CLICON_RESTCONF_PATH {
|
||||
type string;
|
||||
default "/www-data/fastcgi_restconf.sock";
|
||||
description
|
||||
"FastCGI unix socket. Should be specified in webserver
|
||||
Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock";
|
||||
}
|
||||
leaf CLICON_CLI_DIR {
|
||||
type string;
|
||||
description
|
||||
"Location of cli frontend .so plugins. Load all .so
|
||||
plugins in this dir as CLI object plugins";
|
||||
}
|
||||
leaf CLICON_CLISPEC_DIR {
|
||||
type string;
|
||||
description
|
||||
"Location of frontend .cli cligen spec files. Load all .cli
|
||||
files in this dir as CLI specification files";
|
||||
}
|
||||
leaf CLICON_CLISPEC_FILE {
|
||||
type string;
|
||||
description "Specific frontend .cli cligen spec file.";
|
||||
}
|
||||
leaf CLICON_CLI_MODE {
|
||||
type string;
|
||||
default "base";
|
||||
description
|
||||
"Startup CLI mode. This should match a CLICON_MODE set in
|
||||
one of the clispec files";
|
||||
}
|
||||
leaf CLICON_CLI_GENMODEL {
|
||||
type int32;
|
||||
default 1;
|
||||
description
|
||||
"Generate code for CLI completion of existing db symbols.
|
||||
Example: Add name=\"myspec\" in datamodel spec and reference
|
||||
as @myspec";
|
||||
}
|
||||
leaf CLICON_CLI_GENMODEL_COMPLETION {
|
||||
type int32;
|
||||
default 1;
|
||||
description "Generate code for CLI completion of existing db symbols";
|
||||
}
|
||||
leaf CLICON_CLI_GENMODEL_TYPE {
|
||||
type string;
|
||||
default "VARS";
|
||||
description "How to generate and show CLI syntax: VARS|ALL";
|
||||
}
|
||||
leaf CLICON_CLI_VARONLY {
|
||||
type int32;
|
||||
default 1;
|
||||
description
|
||||
"Dont include keys in cvec in cli vars callbacks,
|
||||
ie a & k in 'a <b> k <c>' ignored";
|
||||
}
|
||||
leaf CLICON_CLI_LINESCROLLING {
|
||||
type int32;
|
||||
default 1;
|
||||
description
|
||||
"Set to 0 if you want CLI to wrap to next line.
|
||||
Set to 1 if you want CLI to scroll sideways when approaching
|
||||
right margin";
|
||||
}
|
||||
leaf CLICON_SOCK_FAMILY {
|
||||
type string;
|
||||
default "UNIX";
|
||||
description
|
||||
"Address family for communicating with clixon_backend
|
||||
(UNIX|IPv4|IPv6)";
|
||||
}
|
||||
leaf CLICON_SOCK {
|
||||
type string;
|
||||
mandatory true;
|
||||
description
|
||||
"If family above is AF_UNIX: Unix socket for communicating
|
||||
with clixon_backend. If family is AF_INET: IPv4 address";
|
||||
}
|
||||
leaf CLICON_SOCK_PORT {
|
||||
type int32;
|
||||
default 4535;
|
||||
description
|
||||
"Inet socket port for communicating with clixon_backend
|
||||
(only IPv4|IPv6)";
|
||||
}
|
||||
leaf CLICON_SOCK_GROUP {
|
||||
type string;
|
||||
default "clicon";
|
||||
description "Group membership to access clixon_backend unix socket";
|
||||
}
|
||||
leaf CLICON_BACKEND_PIDFILE {
|
||||
type string;
|
||||
mandatory true;
|
||||
description "Process-id file of backend daemon";
|
||||
}
|
||||
leaf CLICON_AUTOCOMMIT {
|
||||
type int32;
|
||||
default 0;
|
||||
description
|
||||
"Set if all configuration changes are committed automatically
|
||||
on every edit change. Explicit commit commands unnecessary";
|
||||
}
|
||||
leaf CLICON_MASTER_PLUGIN {
|
||||
type string;
|
||||
default "master";
|
||||
description
|
||||
"Name of master plugin (both frontend and backend).
|
||||
Master plugin has special callbacks for frontends.
|
||||
See clicon user manual for more info. (Obsolete?)";
|
||||
}
|
||||
leaf CLICON_XMLDB_DIR {
|
||||
type string;
|
||||
mandatory true;
|
||||
description
|
||||
"Directory where \"running\", \"candidate\" and \"startup\" are placed";
|
||||
}
|
||||
leaf CLICON_XMLDB_PLUGIN {
|
||||
type string;
|
||||
mandatory true;
|
||||
description
|
||||
"XMLDB datastore plugin filename
|
||||
(see datastore/ and clixon_xml_db.[ch])";
|
||||
}
|
||||
leaf CLICON_XMLDB_CACHE {
|
||||
type boolean;
|
||||
default true;
|
||||
description
|
||||
"XMLDB datastore cache.
|
||||
If set, XML parsed tree is stored in memory";
|
||||
}
|
||||
leaf CLICON_USE_STARTUP_CONFIG {
|
||||
type int32;
|
||||
default 0;
|
||||
description
|
||||
"Enabled uses \"startup\" configuration on boot. It is called
|
||||
startup_db and exists in XMLDB_DIR.
|
||||
NOTE: Obsolete with 1.3.3 and CLICON_STARTUP_MODE";
|
||||
}
|
||||
leaf CLICON_STARTUP_MODE {
|
||||
type startup_mode;
|
||||
description "Which method to boot/start clicon backend";
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue