From: Robert Spalek Date: Thu, 20 Apr 2006 13:32:53 +0000 (+0200) Subject: implemented journal and safe (re)loading of cf/files and setting variables X-Git-Tag: holmes-import~645^2~11^2~103 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=6929018be56468bf6a29d9f01164a9bfb5b8885f;p=libucw.git implemented journal and safe (re)loading of cf/files and setting variables --- diff --git a/lib/conf2.c b/lib/conf2.c index c37e2b6d..bdba4456 100644 --- a/lib/conf2.c +++ b/lib/conf2.c @@ -13,28 +13,32 @@ #include "lib/mempool.h" #include +#include #include /* Memory allocation */ -static struct mempool *cf_pool; +static struct old_pools { + struct old_pools *prev; + struct mempool *pool; +} *pools; void * cf_malloc(uns size) { - return mp_alloc(cf_pool, size); + return mp_alloc(pools->pool, size); } void * cf_malloc_zero(uns size) { - return mp_alloc_zero(cf_pool, size); + return mp_alloc_zero(pools->pool, size); } byte * cf_strdup(byte *s) { - return mp_strdup(cf_pool, s); + return mp_strdup(pools->pool, s); } byte * @@ -42,16 +46,141 @@ cf_printf(char *fmt, ...) { va_list args; va_start(args, fmt); - byte *res = mp_vprintf(cf_pool, fmt, args); + byte *res = mp_vprintf(pools->pool, fmt, args); va_end(args); return res; } /* Undo journal */ +static struct journal_item { + struct journal_item *prev; + void *ptr; + uns len; + byte copy[0]; +} *journal; + void -cf_journal_block(void *ptr UNUSED, uns len UNUSED) +cf_journal_block(void *ptr, uns len) +{ + struct journal_item *ji = cf_malloc(sizeof(struct journal_item) + len); + ji->prev = journal; + ji->ptr = ptr; + ji->len = len; + memcpy(ji->copy, ptr, len); + journal = ji; +} + +static void +journal_swap(void) + // swaps the contents of the memory and the journal, and reverses the list +{ + struct journal_item *curr, *prev, *next; + uns max_len = 0; + for (curr=journal; curr; curr=curr->prev) + max_len = MAX(max_len, curr->len); + byte *buf = xmalloc(max_len); + for (next=NULL, curr=journal; curr; next=curr, curr=prev) + { + prev = curr->prev; + curr->prev = next; + memcpy(buf, curr->copy, curr->len); + memcpy(curr->copy, curr->ptr, curr->len); + memcpy(curr->ptr, buf, curr->len); + } + journal = next; + xfree(buf); +} + +static struct journal_item * +journal_new_section(uns new_pool) +{ + if (new_pool) + { + struct old_pools *oldp = pools; + struct mempool *mp = mp_new(1<<14); + pools = mp_alloc(mp, sizeof(struct old_pools)); + pools->prev = oldp; + pools->pool = mp; + } + struct journal_item *oldj = journal; + journal = NULL; + return oldj; +} + +static void +journal_commit_section(struct journal_item *oldj) +{ + struct journal_item **j = &journal; + while (*j) + j = &(*j)->prev; + *j = oldj; +} + +static void +journal_rollback_section(uns new_pool, struct journal_item *oldj) +{ + journal_swap(); + journal = oldj; + if (new_pool) + { + struct old_pools *oldp = pools; + pools = pools->prev; + mp_delete(oldp->pool); + } +} + +/* Safe loading and reloading */ + +static byte *load_file(byte *file); +static byte *load_string(byte *string); + +byte * +cf_reload(byte *file) +{ + journal_swap(); + struct old_pools *oldp = pools; + pools = NULL; + + struct journal_item *oldj = journal_new_section(1); + byte *msg = load_file(file); + if (msg) + { + journal_rollback_section(1, oldj); + pools = oldp; + journal_swap(); + } + else + for (struct old_pools *p=oldp; p; p=oldp) + { + oldp = p->prev; + mp_delete(p->pool); + } + return msg; +} + +byte * +cf_load(byte *file) +{ + struct journal_item *oldj = journal_new_section(1); + byte *msg = load_file(file); + if (!msg) + journal_commit_section(oldj); + else + journal_rollback_section(1, oldj); + return msg; +} + +byte * +cf_set(byte *string) { + struct journal_item *oldj = journal_new_section(0); + byte *msg = load_string(string); + if (!msg) + journal_commit_section(oldj); + else + journal_rollback_section(0, oldj); + return msg; } /* Parsers for standard types */ @@ -210,6 +339,6 @@ cf_parse_dyn(uns number, byte **pars, void **ptr, enum cf_type type) { cf_journal_block(ptr, sizeof(void*)); *ptr = cf_malloc((number+1) * parsers[type].size) + parsers[type].size; - * (uns*) (ptr - parsers[type].size) = number; + * (uns*) (*ptr - parsers[type].size) = number; return ((cf_parser*) parsers[type].parser) (number, pars, *ptr); } diff --git a/lib/conf2.h b/lib/conf2.h index c7a53e06..eb4230df 100644 --- a/lib/conf2.h +++ b/lib/conf2.h @@ -44,7 +44,7 @@ struct cf_section; struct cf_item { enum cf_class cls; byte *name; - int number; // length of an array or #parameters of a parser + int number; // length of an array or #parameters of a parser (negative means at most) void *ptr; // pointer to a global variable or an offset in a section union { enum cf_type type; // type of a static or dynamic attribute @@ -101,6 +101,11 @@ byte *cf_printf(char *fmt, ...); /* Undo journal for error recovery */ void cf_journal_block(void *ptr, uns len); +/* Safe reloading and loading of configuration files */ +byte *cf_reload(byte *file); +byte *cf_load(byte *file); +byte *cf_set(byte *string); + /* Parsers for basic types */ byte *cf_parse_int(uns number, byte **pars, int *ptr); byte *cf_parse_u64(uns number, byte **pars, u64 *ptr);