]> mj.ucw.cz Git - libucw.git/blob - ucw/conf-journal.c
Growing arrays now support auto-zeroing mode
[libucw.git] / ucw / conf-journal.c
1 /*
2  *      UCW Library -- Configuration files: journaling
3  *
4  *      (c) 2001--2006 Robert Spalek <robert@ucw.cz>
5  *      (c) 2003--2006 Martin Mares <mj@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "ucw/lib.h"
12 #include "ucw/conf.h"
13 #include "ucw/getopt.h"
14 #include "ucw/conf-internal.h"
15 #include "ucw/mempool.h"
16
17 #include <string.h>
18
19 static struct old_pools {
20   struct old_pools *prev;
21   struct mempool *pool;
22 } *pools;                       // link-list of older cf_pool's
23
24 uns cf_need_journal = 1;        // some programs do not need journal
25 static struct cf_journal_item {
26   struct cf_journal_item *prev;
27   byte *ptr;
28   uns len;
29   byte copy[0];
30 } *journal;
31
32 void
33 cf_journal_block(void *ptr, uns len)
34 {
35   if (!cf_need_journal)
36     return;
37   struct cf_journal_item *ji = cf_malloc(sizeof(struct cf_journal_item) + len);
38   ji->prev = journal;
39   ji->ptr = ptr;
40   ji->len = len;
41   memcpy(ji->copy, ptr, len);
42   journal = ji;
43 }
44
45 void
46 cf_journal_swap(void)
47   // swaps the contents of the memory and the journal, and reverses the list
48 {
49   struct cf_journal_item *curr, *prev, *next;
50   for (next=NULL, curr=journal; curr; next=curr, curr=prev)
51   {
52     prev = curr->prev;
53     curr->prev = next;
54     for (uns i=0; i<curr->len; i++)
55     {
56       byte x = curr->copy[i];
57       curr->copy[i] = curr->ptr[i];
58       curr->ptr[i] = x;
59     }
60   }
61   journal = next;
62 }
63
64 struct cf_journal_item *
65 cf_journal_new_transaction(uns new_pool)
66 {
67   if (new_pool)
68     cf_pool = mp_new(1<<10);
69   struct cf_journal_item *oldj = journal;
70   journal = NULL;
71   return oldj;
72 }
73
74 void
75 cf_journal_commit_transaction(uns new_pool, struct cf_journal_item *oldj)
76 {
77   if (new_pool)
78   {
79     struct old_pools *p = cf_malloc(sizeof(struct old_pools));
80     p->prev = pools;
81     p->pool = cf_pool;
82     pools = p;
83   }
84   if (oldj)
85   {
86     struct cf_journal_item **j = &journal;
87     while (*j)
88       j = &(*j)->prev;
89     *j = oldj;
90   }
91 }
92
93 void
94 cf_journal_rollback_transaction(uns new_pool, struct cf_journal_item *oldj)
95 {
96   if (!cf_need_journal)
97     die("Cannot rollback the configuration, because the journal is disabled.");
98   cf_journal_swap();
99   journal = oldj;
100   if (new_pool)
101   {
102     mp_delete(cf_pool);
103     cf_pool = pools ? pools->pool : NULL;
104   }
105 }
106
107 void
108 cf_journal_delete(void)
109 {
110   for (struct old_pools *p=pools; p; p=pools)
111   {
112     pools = p->prev;
113     mp_delete(p->pool);
114   }
115 }
116
117 /* TODO: more space efficient journal */