Obsoleted and removed XMLDB format "tree". This function did not work. Only xml and json allowed.

This commit is contained in:
Olof hagsand 2020-02-02 19:15:39 +01:00
parent 51e17671a8
commit e68753655b
9 changed files with 31 additions and 598 deletions

View file

@ -21,6 +21,7 @@
### Minor changes
* Obsoleted and removed XMLDB format "tree". This function did not work. Only xml and json allowed.
* Test framework
* Added `-- -S <file>` command-line to main example to be able to return any state to main example.
* Added `test/cicd` test scripts for running on a set of other hosts

View file

@ -77,7 +77,6 @@ SRC = clixon_sig.c clixon_uid.c clixon_log.c clixon_err.c clixon_event.c \
clixon_proto.c clixon_proto_client.c \
clixon_xpath.c clixon_xpath_ctx.c clixon_xpath_eval.c clixon_xpath_optimize.c \
clixon_sha1.c clixon_datastore.c clixon_datastore_write.c clixon_datastore_read.c \
clixon_datastore_tree.c \
clixon_netconf_lib.c clixon_stream.c clixon_nacm.c
YACCOBJS := lex.clixon_xml_parse.o clixon_xml_parse.tab.o \

View file

@ -78,7 +78,6 @@
#include "clixon_datastore.h"
#include "clixon_datastore_read.h"
#include "clixon_datastore_tree.h"
#define handle(xh) (assert(text_handle_check(xh)==0),(struct text_handle *)(xh))
@ -335,11 +334,6 @@ xmldb_readfile(clicon_handle h,
goto done;
}
/* Parse file into internal XML tree from different formats */
if (strcmp(format, "tree")==0){
if (datastore_tree_read(h, dbfile, &x0) < 0)
goto done;
}
else{
if ((fd = open(dbfile, O_RDONLY)) < 0) {
clicon_err(OE_UNIX, errno, "open(%s)", dbfile);
goto done;
@ -364,7 +358,6 @@ xmldb_readfile(clicon_handle h,
if (singleconfigroot(x0, &x0) < 0)
goto done;
}
}
/* From Clixon 3.10,datastore files may contain module-state defining
* which modules are used in the file.
*/

View file

@ -1,458 +0,0 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 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 *****
*
* XML file save
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <syslog.h>
#include <fcntl.h>
#include <assert.h>
#include <arpa/inet.h>
#include <sys/param.h>
#include <netinet/in.h>
/* cligen */
#include <cligen/cligen.h>
/* clicon */
#include "clixon_string.h"
#include "clixon_queue.h"
#include "clixon_hash.h"
#include "clixon_err.h"
#include "clixon_log.h"
#include "clixon_handle.h"
#include "clixon_yang.h"
#include "clixon_xml.h"
#include "clixon_datastore_tree.h"
#define align4(s) (((s)/4)*4 + 4)
struct indexlist{
qelem_t il_q; /* this must be there */
uint32_t il_i;
int il_len; /* How many */
};
typedef struct indexlist indexlist;
struct indexhead{
indexlist *ih_list;
};
typedef struct indexhead indexhead;
static int
indexhead_free(indexhead *ih)
{
indexlist *il;
while ((il = ih->ih_list) != NULL)
DELQ(il, ih->ih_list, indexlist*);
return 0;
}
int
index_get(indexhead *ih,
size_t len, /* in bytes */
uint32_t *indexp)
{
int retval = -1;
int nr;
uint32_t index = 0;
struct indexlist *il;
indexlist *new;
nr = len/DF_BLOCK + 1;
if ((new = malloc(sizeof(indexlist))) == NULL){
clicon_err(OE_XML, errno, "malloc");
goto done;
}
memset(new, 0, sizeof(indexlist));
// new->il_i = i; Dont know i yet
new->il_len = nr;
if ((il = ih->ih_list) != NULL) {
il = PREVQ(indexlist*, il);
index = il->il_i + il->il_len;
}
ADDQ(new, ih->ih_list);
new->il_i = index;
*indexp = index;
retval = 0;
done:
return retval;
}
#ifdef NOTYET
int
index_get(indexhead *ih,
size_t len, /* in bytes */
uint32_t *indexp)
{
int retval = -1;
int nr;
uint32_t index = 0;
struct indexlist *il;
indexlist *new;
nr = len/DF_BLOCK + 1;
if ((new = malloc(sizeof(indexlist))) == NULL){
clicon_err(OE_XML, errno, "malloc");
goto done;
}
memset(new, 0, sizeof(indexlist));
// new->il_i = i; Dont know i yet
new->il_len = nr;
/* Find nr conseq blocks */
if ((il = ih->ih_list) != NULL) {
do {
if (il->il_i - index >= nr){ /* Found */
INSQ(new, il);
break;
}
index = il->il_i + il->il_len;
il = NEXTQ(indexlist*, il);
} while (il != ih->ih_list);
ADDQ(new, il); /* after? */
}
else
INSQ(new, ih->ih_list);
new->il_i = index;
*indexp = index;
retval = 0;
done:
return retval;
}
#endif
int
index_dump(FILE *f,
indexhead *ih)
{
indexlist *il;
if ((il = ih->ih_list) != NULL) {
do {
fprintf(f, "%u %d\n", il->il_i, il->il_len);
il = NEXTQ(indexlist*, il);
} while (il != ih->ih_list);
}
return 0;
}
/*
* @param[out] xp
* @param[out] vec If type is CX_ELMNT, points to vector of indexes,...
* @retval -1 Error
* @retval 0 Sanity check failed
* @retval 1 OK xp set (or NULL if empty)
*/
static int
buf2xml(FILE *f,
uint32_t index,
cxobj **xp)
{
int retval = -1;
uint8_t ver;
uint8_t type;
int ptr;
uint32_t len;
cxobj *x = NULL;
char *name;
char *prefix = NULL;
char hdr[8] = {0, };
char *buf = NULL;
int vlen;
int i;
uint32_t ind;
cxobj *xc;
size_t ret;
/* Read hdr
* +-----+-----+-----+-----+-----+-----+-----+-----+
* | ver | type| de | ad | len |
* +-----+-----+-----+-----+-----+-----+-----+-----+
*/
if (fseek(f, index*DF_BLOCK, SEEK_SET) < 0){
clicon_err(OE_UNIX, errno, "fseek");
goto done;
}
if ((ret = fread(hdr, sizeof(char), sizeof(hdr), f)) != sizeof(hdr)){
clicon_err(OE_XML, errno, "fread");
goto done;
}
if ((ver = hdr[0]&0xff) == 0) /* Means empty */
goto ok;
if (ver != 1){
clicon_debug(1, "%s Wrong version: %d", __FUNCTION__, ver);
goto fail;
}
type = hdr[1]&0x0f;
if (type != CX_BODY && type != CX_ELMNT && type != CX_ATTR){
clicon_debug(1, "%s Wrong type: %d", __FUNCTION__, type);
goto fail;
}
if ((hdr[2]&0xff) != 0xde){
clicon_debug(1, "%s Expected 0xde: %x", __FUNCTION__, hdr[2]&0xff);
goto fail;
}
if ((hdr[3]&0xff) != 0xad){
clicon_debug(1, "%s Expected 0xad: %x", __FUNCTION__, hdr[3]&0xff);
goto fail;
}
/* Copy and byte-swap length field */
memcpy(&len, &hdr[4], 4);
len = ntohl(len);
/* Read rest
*/
ptr = 0;
if ((buf = malloc(len - sizeof(hdr))) == NULL){
clicon_err(OE_UNIX, errno, "malloc");
goto done;
}
if ((ret = fread(buf, sizeof(char), len-sizeof(hdr), f)) != len-sizeof(hdr)){
clicon_err(OE_XML, errno, "fread");
goto done;
}
if ((name = strchr(buf, ':')) != NULL){
*name = '\0';
name++;
prefix = buf;
ptr += strlen(prefix)+1;
}
else
name = buf;
ptr += strlen(name) + 1;
ptr = align4(ptr);
if ((x = xml_new(name, NULL, NULL)) == NULL)
goto done;
if (prefix)
if (xml_prefix_set(x, prefix) < 0)
goto done;
xml_type_set(x, type);
if (xml_type(x) != CX_ELMNT){
if (xml_value_set(x, &buf[ptr]) < 0)
goto done;
ptr += strlen(xml_value(x)) +1;
}
else{
vlen = (len - sizeof(hdr) - ptr)/ sizeof(uint32_t);
if (vlen < 0){
clicon_debug(1, "%s Nr of elements should not be negative: %d", __FUNCTION__, vlen);
goto fail;
}
for (i=0; i<vlen; i++){
memcpy(&ind, &buf[ptr], sizeof(uint32_t));
ptr += sizeof(uint32_t);
if (buf2xml(f, ntohl(ind), &xc) < 0)
goto done;
if (xml_addsub(x, xc) < 0)
goto done;
}
}
assert(len == sizeof(hdr)+ptr);
ok:
if (xp)
*xp = x;
retval = 1;
done:
if (buf)
free(buf);
return retval;
fail:
retval = 0;
goto done;
}
/*! Dump xml object to a datastore block
*/
static int
xml2buf(FILE *f,
cxobj *x,
indexhead *ih,
uint32_t *indexp)
{
int retval = -1;
char hdr[8] = {0,};
int len;
int len1;
int ptr;
int i;
char *buf0 = NULL;
char *buf;
uint32_t myindex;
hdr[0] = 1;
hdr[1] = 0x80 | xml_type(x);
hdr[2] = 0xde;
hdr[3] = 0xad;
len = sizeof(hdr);
if (xml_prefix(x))
len += strlen(xml_prefix(x)) + 1; /* colon */
len += strlen(xml_name(x)) + 1; /* end-of-string */
len = align4(len);
switch(xml_type(x)){
case CX_ELMNT:
len += xml_child_nr(x)*sizeof(uint32_t);
break;
case CX_BODY:
case CX_ATTR:
len += strlen(xml_value(x))+1;
break;
default:
break;
}
if (index_get(ih, len, &myindex) < 0)
goto done;
len1 = htonl(len); /* swap */
memcpy(&hdr[4], &len1, 4);
/* Write rest
*/
if ((buf0 = malloc(len)) == NULL){
clicon_err(OE_UNIX, errno, "malloc");
goto done;
}
buf = buf0+sizeof(hdr);
ptr = 0;
if (xml_prefix(x)){
strcpy(buf, xml_prefix(x));
ptr += strlen(xml_prefix(x));
buf[ptr++] = ':';
}
strcpy(&buf[ptr], xml_name(x));
ptr += strlen(xml_name(x)) + 1;
for (i=ptr; i< align4(ptr); i++)
buf[i] = 0;
ptr = align4(ptr);
if (xml_type(x) != CX_ELMNT){
strcpy(&buf[ptr], xml_value(x));
ptr += strlen(xml_value(x)) +1;
}
else{
uint32_t index;
for (i=0; i< xml_child_nr(x); i++){
if (xml2buf(f, xml_child_i(x, i), ih,
&index) < 0)
goto done;
index = htonl(index);
memcpy(&buf[ptr], &index, sizeof(uint32_t));
ptr += sizeof(uint32_t);
}
}
assert(len == sizeof(hdr)+ptr);
/* Note write both here so we dont get an intermediate seek,... */
if (fseek(f, myindex*DF_BLOCK, SEEK_SET) < 0){
clicon_err(OE_UNIX, errno, "fseek");
goto done;
}
memcpy(buf0, hdr, sizeof(hdr));
if (fwrite(buf0, sizeof(char), len, f) == 0){
clicon_err(OE_XML, errno, "fwrite");
goto done;
}
if (indexp)
*indexp = myindex;
retval = 0;
done:
if (buf0)
free(buf0);
return retval;
}
int
datastore_tree_write(clicon_handle h,
char *filename,
cxobj *xt)
{
int retval = -1;
FILE *f = NULL;
indexhead ih = {0,};
if ((f = fopen(filename, "w+b")) == NULL){
clicon_err(OE_XML, errno, "Opening file %s", filename);
goto done;
}
if (xml2buf(f, xt, &ih, NULL) < 0)
goto done;
if (debug)
index_dump(stderr, &ih);
retval = 0;
done:
indexhead_free(&ih);
if (f != NULL)
fclose(f);
return retval;
}
/*
* @retval -1 Error
* @retval 0 Sanity check failed
* @retval 1 OK xp set (or NULL if empty)
*/
int
datastore_tree_read(clicon_handle h,
char *filename,
cxobj **xt)
{
int retval = -1;
FILE *f = NULL;
if ((f = fopen(filename, "r")) == NULL){
clicon_err(OE_XML, errno, "Opening file %s", filename);
goto done;
}
if ((retval = buf2xml(f, 0, xt)) < 0)
goto done;
if (retval == 0 || /* fail */
*xt == NULL){ /* empty */
if ((*xt = xml_new("config", NULL, NULL)) == NULL)
goto done;
xml_type_set(*xt, CX_ELMNT);
}
done:
if (f != NULL)
fclose(f);
return retval;
}

View file

@ -1,90 +0,0 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 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 *****
*
* Datastore block tree file
*/
#ifndef _CLIXON_DATASTORE_TREE_H_
#define _CLIXON_DATASTORE_TREE_H_
/*
* Constants and macros
*/
/* Max of https://github.com/YangModels/yang
* name: receive-recovery-scccp-avp-bad-value-challenge-response
* namespace: urn:ieee:std:802.3:yang:ieee802-ethernet-interface-half-duplex
*/
#define DF_BLOCK 32
/*
* Types
*/
/* On file value (dep of type)
* off: Offset in bytes to where value starts (name ends +1)
* len: Total length in bytes (network byte order)
* childi: Block index to child (network byte order)
* ELMNT:
* +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
* | 1 | 128 | de | ad | len | name ... | 0 |
* +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
* +-----+-----+-----+-----+-----+-----+-----+------+--
* | child0 (index in file)| child1 (index in file)|
* +-----+-----+-----+-----+-----+-----+-----+-----+--
* ATTR:
* +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
* | 1 | 129 | de | ad | len | name ... | 0 |
* +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
* +-----+-----+-----+
* | value ... | 0 |
* +-----+-----+-----+
* BODY: (off = 8)
* +-----+-----+-----+-----+-----+-----+-----+-----+-----+
* | 1 | 130 | de | ad | len | 0 |
* +-----+-----+-----+-----+-----+-----+-----+-----+-----+
* +-----+-----+-----+
* | value ... | 0 |
* +-----+-----+-----+
* FREE
* +------+
* | 0 |
* +------+
*/
/*
* Prototypes
*/
int datastore_tree_write(clicon_handle h, char *filename, cxobj *xt);
int datastore_tree_read(clicon_handle h, char *filename, cxobj **xt);
#endif /* _CLIXON_DATASTORE_TREE_H_ */

View file

@ -80,7 +80,6 @@
#include "clixon_datastore.h"
#include "clixon_datastore_write.h"
#include "clixon_datastore_read.h"
#include "clixon_datastore_tree.h"
/*! Given an attribute name and its expected namespace, find its value
*
@ -954,11 +953,6 @@ xmldb_put(clicon_handle h,
clicon_err(OE_CFG, ENOENT, "No CLICON_XMLDB_FORMAT");
goto done;
}
if (strcmp(format, "tree") == 0){
if (datastore_tree_write(h, dbfile, x0) < 0)
goto done;
}
else{
if ((f = fopen(dbfile, "w")) == NULL){
clicon_err(OE_CFG, errno, "Creating file %s", dbfile);
goto done;
@ -969,7 +963,6 @@ xmldb_put(clicon_handle h,
}
else if (clicon_xml2file(f, x0, 0, clicon_option_bool(h, "CLICON_XMLDB_PRETTY")) < 0)
goto done;
}
/* Remove modules state after writing to file
*/
if (xmodst && xml_purge(xmodst) < 0)

View file

@ -264,7 +264,6 @@ for (( i=0; i<$nr; i++ )); do
done
new "instance-id direct under root single string key k1=a$rnd"
echo ""
expectpart "$($clixon_util_path -f $xml5 -y $ydir -p /a:x5[k1=\"a$rnd\"])" 0 "^0: <x5 xmlns=\"urn:example:a\"><k1>a$rnd</k1><z>foo$rnd</z></x5>$"
# Depth and augment

View file

@ -76,7 +76,7 @@ usage(char *argv0)
"\t-D\t\tDebug\n"
"\t-d <db>\t\tDatabase name. Default: running. Alt: candidate,startup\n"
"\t-b <dir>\tDatabase directory. Mandatory\n"
"\t-f <fmt>\tDatabase format: xml, json, tree\n"
"\t-f <fmt>\tDatabase format: xml or json\n"
"\t-x <xml>\tXML file. Alternative to put <xml> argument\n"
"\t-y <file>\tYang file. Mandatory\n"
"and command is either:\n"

View file

@ -105,10 +105,6 @@ module clixon-config {
enum json{
description "Save and load xmldb as JSON";
}
enum tree{
description "Save and load xmldb as Clixon record-based tree
file format (experimental)";
}
}
}
typedef datastore_cache{