]> mj.ucw.cz Git - libucw.git/blob - lib/conf-journal.c
conf2.c split into 7 smaller modules conf-*.c with include conf-internal.h
[libucw.git] / lib / 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 "lib/lib.h"
12 #include "lib/conf.h"
13 #include "lib/conf-internal.h"
14 #include "lib/mempool.h"
15
16 #include <string.h>
17
18 static struct old_pools {
19   struct old_pools *prev;
20   struct mempool *pool;
21 } *pools;                       // link-list of older cf_pool's
22
23 uns cf_need_journal = 1;        // some programs do not need journal
24 static struct cf_journal_item {
25   struct cf_journal_item *prev;
26   byte *ptr;
27   uns len;
28   byte copy[0];
29 } *journal;
30
31 void
32 cf_journal_block(void *ptr, uns len)
33 {
34   if (!cf_need_journal)
35     return;
36   struct cf_journal_item *ji = cf_malloc(sizeof(struct cf_journal_item) + len);
37   ji->prev = journal;
38   ji->ptr = ptr;
39   ji->len = len;
40   memcpy(ji->copy, ptr, len);
41   journal = ji;
42 }
43
44 void
45 cf_journal_swap(void)
46   // swaps the contents of the memory and the journal, and reverses the list
47 {
48   struct cf_journal_item *curr, *prev, *next;
49   for (next=NULL, curr=journal; curr; next=curr, curr=prev)
50   {
51     prev = curr->prev;
52     curr->prev = next;
53     for (uns i=0; i<curr->len; i++)
54     {
55       byte x = curr->copy[i];
56       curr->copy[i] = curr->ptr[i];
57       curr->ptr[i] = x;
58     }
59   }
60   journal = next;
61 }
62
63 struct cf_journal_item *
64 cf_journal_new_transaction(uns new_pool)
65 {
66   if (new_pool)
67     cf_pool = mp_new(1<<10);
68   struct cf_journal_item *oldj = journal;
69   journal = NULL;
70   return oldj;
71 }
72
73 void
74 cf_journal_commit_transaction(uns new_pool, struct cf_journal_item *oldj)
75 {
76   if (new_pool)
77   {
78     struct old_pools *p = cf_malloc(sizeof(struct old_pools));
79     p->prev = pools;
80     p->pool = cf_pool;
81     pools = p;
82   }
83   if (oldj)
84   {
85     struct cf_journal_item **j = &journal;
86     while (*j)
87       j = &(*j)->prev;
88     *j = oldj;
89   }
90 }
91
92 void
93 cf_journal_rollback_transaction(uns new_pool, struct cf_journal_item *oldj)
94 {
95   if (!cf_need_journal)
96     die("Cannot rollback the configuration, because the journal is disabled.");
97   cf_journal_swap();
98   journal = oldj;
99   if (new_pool)
100   {
101     mp_delete(cf_pool);
102     cf_pool = pools ? pools->pool : NULL;
103   }
104 }
105
106 void
107 cf_journal_delete(void)
108 {
109   for (struct old_pools *p=pools; p; p=pools)
110   {
111     pools = p->prev;
112     mp_delete(p->pool);
113   }
114 }
115
116 /* TODO: more space efficient journal */