Created xmldb plugin api

This commit is contained in:
Olof hagsand 2017-04-09 22:53:48 +02:00
parent 4169bd8d30
commit f6b3e95100
39 changed files with 492 additions and 504 deletions

View file

@ -55,7 +55,7 @@ INCLUDES = -I. @INCLUDES@ -I$(top_srcdir)/lib/clixon -I$(top_srcdir)/include -I$
PLUGIN = $(DATASTORE).so
SRC = clixon_keyvalue.c clixon_qdb.c
SRC = clixon_keyvalue.c clixon_qdb.c clixon_chunk.c
OBJS = $(SRC:.c=.o)

View file

@ -0,0 +1,789 @@
/*
*
***** 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 *****
*/
/* Error handling: dont use clicon_err, treat as unix system calls. That is,
ensure errno is set and return -1/NULL */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/types.h>
/* clicon */
#include "clixon_queue.h"
#include "clixon_chunk.h"
/*
* The chunk head array for the predefined chunk sizes.
*/
static chunk_head_t chunk_heads[CHUNK_HEADS];
/*
* Did we initialize the chunk heads yet?
*/
static int chunk_initialized = 0;
/*
* The pagesize of this system
*/
static int chunk_pagesz;
/*
* List of chunk groups
*/
static chunk_group_t *chunk_grp;
/*
* Hack to tell unchunk() not to remove chunk_group if empty
*/
static int dont_unchunk_group;
/*
* Initialize chunk library
*/
static void
chunk_initialize ()
{
int pgs;
register int idx;
chunk_pagesz = getpagesize();
bzero (&chunk_heads, sizeof (chunk_heads));
for (idx = 0; idx < CHUNK_HEADS; idx++) {
chunk_head_t *chead = &chunk_heads[idx];
/*
* Calculate the size of a block
*/
pgs = (0x01lu << (CHUNK_BASE + idx)) / chunk_pagesz;
if (pgs == 0)
pgs = 1;
chead->ch_blksz = pgs * chunk_pagesz;
/*
* Chunks per block is 1 for all size above a page. For sizes
* (including the chunk header) less than a page it's as many
* as fits
*/
chead->ch_nchkperblk = chead->ch_blksz / (0x01lu << (CHUNK_BASE + idx));
/*
* Size of each chunk is:
* (size + chnkhdr) * ncnkperblk = blksiz - blkhdr
*/
chead->ch_size =
(chead->ch_blksz / chead->ch_nchkperblk)
- sizeof (chunk_t);
}
/* Zero misc variables */
chunk_grp = NULL;
dont_unchunk_group = 0;
chunk_initialized = 1;
}
/*
* chunk_new_block() - Allocate new block, initialize it and it's chunks.
*/
static int
chunk_new_block (chunk_head_t *chead)
{
register int idx;
register char *c;
chunk_block_t *blk;
chunk_t *cnk;
/* Map block header mem */
blk = (chunk_block_t *)
mmap(NULL, sizeof(chunk_block_t),
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
if (blk == MAP_FAILED)
return -1;
memset ((void *)blk, 0, sizeof(*blk));
/* Allocate chunk block */
blk->cb_blk = (void *)
mmap(NULL, chead->ch_blksz,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
if (blk->cb_blk == MAP_FAILED) {
munmap (blk, chead->ch_blksz);
return -1;
}
memset (blk->cb_blk, 0, chead->ch_blksz);
/* Initialize chunk header */
blk->cb_head = chead;
INSQ (blk, chead->ch_blks);
chead->ch_nblks++;
/* Initialize chunks */
c = ((char *)blk->cb_blk);
for (idx = 0; idx < chead->ch_nchkperblk; idx++) {
cnk = (chunk_t *)c;
cnk->c_blk = blk;
INSQ (cnk, chead->ch_free);
chead->ch_nfree++;
c += (chead->ch_size + sizeof (chunk_t));
}
return 0;
}
/*
* chunk_release_block() - Unqueue a block, it's chunks and free mem
*/
static void
chunk_release_block (chunk_block_t *cblk)
{
int idx;
char *c;
chunk_t *cnk;
chunk_head_t *chead;
chead = cblk->cb_head;
/*
* Dequeue block
*/
DELQ (cblk, chead->ch_blks, chunk_block_t *);
chead->ch_nblks--;
/*
* Dequeue all chunks in the block
*/
c = (char *)cblk->cb_blk;
for (idx = 0; idx < chead->ch_nchkperblk; idx++) {
cnk = (chunk_t *)c;
DELQ (cnk, chead->ch_free, chunk_t *);
chead->ch_nfree--;
c += (chead->ch_size + sizeof (chunk_t));
}
/*
* Free block
*/
munmap ((void *)cblk->cb_blk, chead->ch_blksz);
munmap ((void *)cblk, sizeof(*cblk));
}
/*
* chunk_alloc() - Map new chunk of memory
*/
static void *
chunk_alloc (size_t len)
{
register int idx;
chunk_head_t *chead;
chunk_t *cnk;
if (!len)
return (void *)NULL;
/* Find sufficient sized block head */
for (idx = 0; idx < CHUNK_HEADS; idx++)
if (chunk_heads[idx].ch_size >= len)
break;
/* Too large chunk? */
if (idx >= CHUNK_HEADS) {
errno = ENOMEM;
return (void *)NULL;
}
chead = &chunk_heads[idx];
/* Get new block if necessary */
if (!chead->ch_nfree)
if (chunk_new_block (chead))
return (void *)NULL;
/* Move a free chunk to the in-use list */
cnk = chead->ch_free;
DELQ (cnk, chead->ch_free, chunk_t *);
chead->ch_nfree--;
INSQ (cnk, chead->ch_cnks);
/* Add reference to the corresponding block */
cnk->c_blk->cb_ref++;
#ifdef CHUNK_DIAG
/* Clear diag info */
bzero ((void *)&cnk->c_diag, sizeof (cnk->c_diag));
#endif /* CHUNK_DIAG */
/* Return pointer to first byte after the chunk header */
return (void *) (cnk + 1);
}
/*
* chunk() - Map new chunk of memory in group
*/
void *
#ifdef CHUNK_DIAG
_chunk (size_t len, const char *name, const char *file, int line)
#else
chunk (size_t len, const char *name)
#endif
{
int newgrp = 0;
void *ptr = NULL;
chunk_t *cnk;
chunk_group_t *tmp;
chunk_group_t *grp = NULL;
chunk_grpent_t *ent = NULL;
/* Make sure chunk_heads are initialized */
if (!chunk_initialized)
chunk_initialize();
if (!len)
return (void *)NULL;
/* Get actual chunk
*/
ptr = chunk_alloc (len);
if (!ptr)
goto error;
cnk = (chunk_t *) (((char *)ptr) - sizeof (chunk_t));
#ifdef CHUNK_DIAG
/* Store who reuested us
*/
cnk->c_diag.cd_file = file;
cnk->c_diag.cd_line = line;
#endif /* CHUNK_DIAG */
/* No name given. Get an ungrouped chunk
*/
if (!name)
return ptr;
/* Try to find already existing entry
*/
if (chunk_grp) {
tmp = chunk_grp;
do {
if (!strcmp (tmp->cg_name, name)) {
grp = tmp;
break;
}
tmp = NEXTQ(chunk_group_t *, tmp);
} while (tmp != chunk_grp);
}
/* New group.
*/
if ( !grp ) {
grp = (chunk_group_t *) chunk_alloc (sizeof (chunk_group_t));
if (!grp)
goto error;
bzero (grp, sizeof (chunk_group_t));
grp->cg_name = (char *) chunk_alloc (strlen (name) + 1);
if (!grp->cg_name)
goto error;
bcopy (name, grp->cg_name, strlen(name)+1);
newgrp = 1;
}
/* Get new entry.
*/
ent = (chunk_grpent_t *) chunk_alloc (sizeof (chunk_grpent_t));
if (!ent)
goto error;
bzero (ent, sizeof (chunk_grpent_t));
/* Now put everything together
*/
cnk->c_grpent = ent;
ent->ce_cnk = cnk;
ent->ce_grp = grp;
INSQ (ent, grp->cg_ent);
if (newgrp)
INSQ (grp, chunk_grp);
return (ptr);
error:
if (grp && newgrp) {
if (grp->cg_name)
unchunk (grp->cg_name);
unchunk (grp);
}
if (ent)
unchunk (ent);
if (ptr)
unchunk (ptr);
return (void *) NULL;
}
/*
* rechunk() - Resize previously allocated chunk.
*/
void *
#ifdef CHUNK_DIAG
_rechunk (void *ptr, size_t len, const char *name, const char *file, int line)
#else
rechunk (void *ptr, size_t len, const char *name)
#endif
{
int idx;
void *new;
chunk_t *cnk;
chunk_t *newcnk;
chunk_head_t *chead;
chunk_head_t *newchead;
/* No previoud chunk, get new
*/
if (!ptr) {
#ifdef CHUNK_DIAG
return _chunk (len, name, file, line);
#else
return chunk (len, name);
#endif
}
/* Zero length, free chunk
*/
if (len == 0) {
unchunk (ptr);
return (void *) NULL;
}
/* Rewind pointer to beginning of chunk header
*/
cnk = (chunk_t *) (((char *)ptr) - sizeof (chunk_t));
chead = cnk->c_blk->cb_head;
/* Find sufficient sized block head
*/
for (idx = 0; idx < CHUNK_HEADS; idx++)
if (chunk_heads[idx].ch_size >= len)
break;
/* Too large chunk? */
if (idx >= CHUNK_HEADS) {
errno = ENOMEM;
return (void *)NULL;
}
/* Check if chunk size remains unchanged
*/
if (chunk_heads[idx].ch_size == chead->ch_size)
return (ptr);
/* Get new chunk
*/
#ifdef CHUNK_DIAG
new = _chunk (len, name, file, line);
#else
new = chunk (len, name);
#endif
if (!new)
return (void *) NULL;
newcnk = (chunk_t *) (((char *)new) - sizeof (chunk_t));
newchead = newcnk->c_blk->cb_head;
/* Copy contents to new chunk
*/
bcopy (ptr, new, MIN(newchead->ch_size, chead->ch_size));
/* Free old chunk
*/
unchunk (ptr);
return (new);
}
/*
* unchunk() - Release chunk
*/
void
unchunk (void *ptr)
{
chunk_t *cnk;
chunk_head_t *chead;
chunk_block_t *cblk;
chunk_grpent_t *ent;
chunk_group_t *grp;
if (!chunk_initialized)
return;
/* Rewind pointer to beginning of chunk header
*/
cnk = (chunk_t *) (((char *)ptr) - sizeof (chunk_t));
cblk = cnk->c_blk;
chead = cblk->cb_head;
/* Move chunk back to free list
*/
DELQ (cnk, chead->ch_cnks, chunk_t *);
INSQ (cnk, chead->ch_free);
chead->ch_nfree++;
/* If chunk is grouped, remove from group.
*/
ent = cnk->c_grpent;
if (ent) {
grp = ent->ce_grp;
DELQ (ent, grp->cg_ent, chunk_grpent_t *);
unchunk (ent);
cnk->c_grpent = NULL;
/* Group empty? */
if (!dont_unchunk_group && !grp->cg_ent) {
DELQ (grp, chunk_grp, chunk_group_t *);
unchunk(grp->cg_name);
unchunk(grp);
}
}
/* Check block refs is nil, if so free it
*/
cblk->cb_ref--;
if (cblk->cb_ref == 0)
chunk_release_block (cblk);
}
/*
* unchunk_group() - Release all group chunks.
*/
void
unchunk_group (const char *name)
{
chunk_group_t *tmp;
chunk_group_t *grp = NULL;
chunk_t *cnk;
if (!chunk_initialized)
return;
/* Try to find already existing entry
*/
if (chunk_grp) {
tmp = chunk_grp;
do {
if (!strcmp (tmp->cg_name, name)) {
grp = tmp;
break;
}
tmp = NEXTQ(chunk_group_t *, tmp);
} while (tmp != chunk_grp);
}
if (!grp)
return;
/* Walk through all chunks in group an free them
*/
dont_unchunk_group = 1;
while (grp->cg_ent) {
cnk = grp->cg_ent->ce_cnk;
unchunk ((chunk_t *)(((char *)cnk) + sizeof (chunk_t)));
}
dont_unchunk_group = 0;
/* Remove group from list and free it
*/
DELQ (grp, chunk_grp, chunk_group_t *);
unchunk (grp->cg_name);
unchunk (grp);
}
/*
* chunkdup() - Copy block of data to a new chunk of memory in group
*/
void *
#ifdef CHUNK_DIAG
_chunkdup (const void *ptr, size_t len, const char *name, const char *file, int line)
#else
chunkdup (const void *ptr, size_t len, const char *name)
#endif
{
void *new;
/* No input data or no length
*/
if (!ptr || len <= 0)
return (void *)NULL;
/* Get new chunk
*/
#ifdef CHUNK_DIAG
new = _chunk (len, name, file, line);
#else
new = chunk (len, name);
#endif
if (!new)
return (void *)NULL;
/* Copy data to new chunk
*/
memcpy(new, ptr, len);
return (new);
}
/*
* chunksize() - Return size of memory chunk.
*/
size_t
chunksize (void *ptr)
{
chunk_t *cnk;
chunk_head_t *chead;
chunk_block_t *cblk;
if (!chunk_initialized)
return -1;
/* Rewind pointer to beginning of chunk header
*/
cnk = (chunk_t *) (((char *)ptr) - sizeof (chunk_t));
cblk = cnk->c_blk;
chead = cblk->cb_head;
return chead->ch_size;
}
/*
* chunk_strncat() - Concatenate 'n' characters to a chunk allocated string. If
* 'n' is zero, do the whole src string.
*
*/
char *
#ifdef CHUNK_DIAG
_chunk_strncat (const char *dst, const char *src, size_t n, const char *name,
const char *file, int line)
#else
chunk_strncat (const char *dst, const char *src, size_t n, const char *name)
#endif
{
size_t len;
char *new;
void *ptr = (void *)dst;
if (n == 0) /* zero length means cat whole string */
n = strlen(src);
len = (dst ? strlen(dst) : 0) + n + 1;
#ifdef CHUNK_DIAG
ptr = _rechunk(ptr, len, name, file, line);
#else
ptr = rechunk (ptr, len, name);
#endif
if (ptr == NULL)
return NULL;
new = (char *)ptr;
new += strlen(new);
while (n-- > 0 && *src)
*new++ = *src++;
*new = '\0';
return (char *)ptr;
}
/*
* chunk_sprintf() - Format string into new chunk.
*/
char *
#ifdef CHUNK_DIAG
_chunk_sprintf (const char *name, const char *file,
int line, const char *fmt, ...)
#else
chunk_sprintf (const char *name, char *fmt, ...)
#endif
{
size_t len;
char *str;
va_list args;
/* Calculate formatted string length */
va_start(args, fmt);
len = vsnprintf(NULL, 0, fmt, args) + 1;
va_end (args);
/* get chunk */
#ifdef CHUNK_DIAG
str = _chunk (len, name, file, line);
#else
str = chunk (len, name);
#endif
if (str == NULL)
return NULL;
/* Format string */
va_start(args, fmt);
len = vsnprintf(str, len, fmt, args);
va_end (args);
return str;
}
#ifdef CHUNK_DIAG
/*
* chunk_check() - Report all non-freed chunk for given group (if any)
*/
void
chunk_check(FILE *fout, const char *name)
{
int idx;
chunk_t *cnk;
chunk_group_t *tmp;
chunk_group_t *grp = NULL;
chunk_grpent_t *ent;
if (!chunk_initialized)
return;
/* No name given, walk through everything
*/
if (name == (const char *)NULL) {
for (idx = 0; idx < CHUNK_HEADS; idx++) {
chunk_head_t *chead = &chunk_heads[idx];
cnk = chead->ch_cnks;
if (cnk == (chunk_t *)NULL)
continue;
do {
/* If no file name it's an internal chunk */
if (cnk->c_diag.cd_file)
clicon_debug(0,
"%s:%d,\t%zu bytes (%p), group \"%s\"\n",
cnk->c_diag.cd_file,
cnk->c_diag.cd_line,
cnk->c_blk->cb_head->ch_size,
(cnk +1),
cnk->c_grpent ?
cnk->c_grpent->ce_grp->cg_name :
"NULL");
cnk = NEXTQ(chunk_t *, cnk);
} while (cnk != chead->ch_cnks);
}
}
/* Walk through group
*/
else {
/* Try to find already existing entry
*/
if (chunk_grp) {
tmp = chunk_grp;
do {
if (!strcmp (tmp->cg_name, name)) {
grp = tmp;
break;
}
tmp = NEXTQ(chunk_group_t *, tmp);
} while (tmp != chunk_grp);
}
if (!grp)
return;
ent = grp->cg_ent;
do {
cnk = ent->ce_cnk;
fprintf(fout ? fout : stdout,
"%s:%d,\t%zu bytes (%p), group \"%s\"\n",
cnk->c_diag.cd_file,
cnk->c_diag.cd_line,
cnk->c_blk->cb_head->ch_size,
(cnk +1),
cnk->c_grpent ?
cnk->c_grpent->ce_grp->cg_name :
"NULL");
ent = NEXTQ(chunk_grpent_t *, ent);
} while (ent != grp->cg_ent);
}
}
#else /* CHUNK_DIAG */
void
chunk_check(FILE *fout, const char *name)
{
}
#endif /* CHUNK_DIAG */

View file

@ -0,0 +1,177 @@
/*
*
***** 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 *****
*
*/
#ifndef _CLIXON_CHUNK_H_
#define _CLIXON_CHUNK_H_
/*
* Compile with chunk diagnostics. XXX Should be in Makefile.in ??
*/
#undef CHUNK_DIAG
/*
* Base number of bits to shift getting the size of a chunk_head.
*/
#define CHUNK_BASE 6
/*
* Number of predefined chunk sizes. I.e. the number of chunk heads in the
* chunk_heads vector.
*/
#define CHUNK_HEADS (32 - CHUNK_BASE)
#ifdef CHUNK_DIAG
/*
* Chunk diagnostics
*/
typedef struct _chunk_diag_t {
const char *cd_file; /* File which requested chunk */
int cd_line; /* Line in requesting file */
} chunk_diag_t;
#endif /* CHUNK_DIAG */
/*
* The block header.
*/
struct _chunk_head_t;
typedef struct _chunk_head_t chunk_head_t;
typedef struct _chunk_block_t {
qelem_t cb_qelem; /* Circular queue of blocks */
chunk_head_t *cb_head; /* The chunk head I belong to */
void *cb_blk; /* Allocated memory block */
uint16_t cb_ref; /* Number of used chunks of block */
} chunk_block_t;
/*
* The chunk header.
*/
struct _chunk_grpent_t;
typedef struct _chunk_grpent_t chunk_grpent_t;
typedef struct _chunk_t {
qelem_t c_qelem; /* Circular queue of chunks */
chunk_block_t *c_blk; /* The block I belong to */
#ifdef CHUNK_DIAG
chunk_diag_t c_diag; /* The diagnostics structure */
#endif /* CHUNK_DIAG */
chunk_grpent_t *c_grpent;
} chunk_t;
/*
* The head of a chunk size. Each predefined size has it's own head keeping
* track of all blocks and chunks for the size.
*/
struct _chunk_head_t {
size_t ch_size; /* Chunk size */
int ch_nchkperblk; /* Number pf chunks per block */
size_t ch_blksz; /* Size of a block */
int ch_nblks; /* Number of allocated blocks */
chunk_block_t *ch_blks; /* Circular list of blocks */
chunk_t *ch_cnks; /* Circular list of chunks in use */
size_t ch_nfree; /* Number of free chunks */
chunk_t *ch_free; /* Circular list of free chunks */
};
/*
* The chunk group structure.
*/
typedef struct _chunk_group_t {
qelem_t cg_qelem; /* List of chunk groups */
char *cg_name; /* Name of group */
chunk_grpent_t *cg_ent; /* List of chunks in the group */
} chunk_group_t;
/*
* The chunk group entry structure.
*/
struct _chunk_grpent_t {
qelem_t ce_qelem; /* Circular list of entries */
chunk_group_t *ce_grp; /* The group I belong to */
chunk_t *ce_cnk; /* Pointer to the chunk */
};
/*
* Public function declarations
*/
#ifdef CHUNK_DIAG
void *_chunk (size_t, const char *, const char *, int);
#define chunk(siz,label) _chunk((siz),(label),__FILE__,__LINE__)
void *_rechunk (void *, size_t, const char *, const char *, int);
#define rechunk(ptr,siz,label) _rechunk((ptr),(siz),(label),__FILE__,__LINE__)
void *_chunkdup (const void *, size_t, const char *, const char *, int);
#define chunkdup(ptr,siz,label) _chunkdup((ptr),(siz),(label),__FILE__,__LINE__)
char *_chunk_strncat (const char *, const char *, size_t, const char *, const char *, int);
#define chunk_strncat(str,new,n,label) _chunk_strncat((str),(new),(n),(label),__FILE__,__LINE__)
char *_chunk_sprintf (const char *, const char *, int, const char *, ...);
#define chunk_sprintf(label,fmt,...) _chunk_sprintf((label),__FILE__,__LINE__,(fmt),__VA_ARGS__)
#else /* CHUNK_DIAG */
void *chunk (size_t, const char *);
void *rechunk (void *, size_t, const char *);
void *chunkdup (const void *, size_t, const char *);
char *chunk_strncat (const char *, const char *, size_t, const char *);
char *chunk_sprintf (const char *, char *, ...);
#endif /* CHUNK_DIAG */
void unchunk (void *);
void unchunk_group (const char *);
void chunk_check (FILE *, const char *);
size_t chunksize (void *);
#endif /* _CLIXON_CHUNK_H_ */

View file

@ -119,70 +119,6 @@ static int _running_locked = 0;
static int _candidate_locked = 0;
static int _startup_locked = 0;
/*! Lock database
* @param[in] db Database name
* @param[in] pid process/session-id
*/
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;
else if (strcmp("startup", db) == 0)
_startup_locked = pid;
clicon_debug(1, "%s: locked by %u", db, pid);
return 0;
}
/*! Unlock database
* @param[in] db Database name
*/
static int
db_unlock(char *db)
{
if (strcmp("running", db) == 0)
_running_locked = 0;
else if (strcmp("candidate", db) == 0)
_candidate_locked = 0;
else if (strcmp("startup", db) == 0)
_startup_locked = 0;
return 0;
}
/*! Unlock all databases locked by pid (eg process dies)
* @param[in] pid process/session-id
*/
static int
db_unlock_all(int pid)
{
if (_running_locked == pid)
_running_locked = 0;
if (_candidate_locked == pid)
_candidate_locked = 0;
if (_startup_locked == pid)
_startup_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);
else if (strcmp("startup", db) == 0)
return(_startup_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"
@ -273,7 +209,7 @@ append_listkeys(cbuf *ckey,
else
cprintf(ckey, "=");
cprintf(ckey, "%s", bodyenc);
free(bodyenc); bodyenc = NULL;
curl_free(bodyenc); bodyenc = NULL;
}
retval = 0;
done:
@ -436,7 +372,7 @@ get(char *dbname,
goto done;
/* Assume body is created at end of function */
}
free(argdec);
curl_free(argdec);
argdec = NULL;
break;
case Y_LIST:
@ -478,7 +414,7 @@ get(char *dbname,
goto done;
}
cprintf(cb, "[%s=%s]", cv_string_get(cvi), argdec);
free(argdec);
curl_free(argdec);
argdec=NULL;
}
if ((xc = xpath_first(x, cbuf_get(cb))) == NULL){
@ -502,7 +438,7 @@ get(char *dbname,
argdec,
keyname) < 0)
goto done;
free(argdec); argdec = NULL;
curl_free(argdec); argdec = NULL;
} /* while */
}
if (cb){
@ -710,7 +646,7 @@ kv_get(clicon_handle h,
int retval = -1;
yang_spec *yspec;
char *dbname = NULL;
cxobj **xvec;
cxobj **xvec = NULL;
size_t xlen;
int i;
int npairs;
@ -885,7 +821,7 @@ put(char *dbname,
if (cbxk)
cbuf_free(cbxk);
if (bodyenc)
free(bodyenc);
curl_free(bodyenc);
return retval;
}
@ -1400,7 +1336,6 @@ kv_put(clicon_handle h,
return retval;
}
/*! 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
@ -1477,19 +1412,14 @@ kv_lock(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;
if (strcmp("running", db) == 0)
_running_locked = pid;
else if (strcmp("candidate", db) == 0)
_candidate_locked = pid;
else if (strcmp("startup", db) == 0)
_startup_locked = pid;
clicon_debug(1, "%s: locked by %u", db, pid);
return 0;
}
/*! Unlock database
@ -1498,36 +1428,39 @@ kv_lock(clicon_handle h,
* @param[in] pid Process id
* @retval -1 Error
* @retval 0 OK
* Assume all sanity checks have been made
*/
int
kv_unlock(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;
if (strcmp("running", db) == 0)
_running_locked = 0;
else if (strcmp("candidate", db) == 0)
_candidate_locked = 0;
else if (strcmp("startup", db) == 0)
_startup_locked = 0;
return 0;
}
/*! Unlock all databases locked by pid (eg process dies)
* @param[in] h Clicon handle
* @param[in] pid Process / Session id
* @retval -1 Error
* @retval 0 Ok
*/
int
kv_unlock_all(clicon_handle h,
int pid)
{
return db_unlock_all(pid);
if (_running_locked == pid)
_running_locked = 0;
if (_candidate_locked == pid)
_candidate_locked = 0;
if (_startup_locked == pid)
_startup_locked = 0;
return 0;
}
/*! Check if database is locked
@ -1541,7 +1474,13 @@ int
kv_islocked(clicon_handle h,
char *db)
{
return db_islocked(db);
if (strcmp("running", db) == 0)
return (_running_locked);
else if (strcmp("candidate", db) == 0)
return(_candidate_locked);
else if (strcmp("startup", db) == 0)
return(_startup_locked);
return 0;
}
/*! Check if db exists