]> mj.ucw.cz Git - libucw.git/blob - ucw/conf-journal.c
75af51ad69d3021743cf796945901c9663a8e818
[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--2012 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 struct old_pools {
20   struct old_pools *prev;
21   struct mempool *pool;
22 };                              // link-list of older cf_pool's
23
24 struct cf_journal_item {
25   struct cf_journal_item *prev;
26   byte *ptr;
27   uns len;
28   byte copy[0];
29 };
30
31 void
32 cf_journal_block(void *ptr, uns len)
33 {
34   struct cf_context *cc = cf_get_context();
35   if (!cc->need_journal)
36     return;
37   struct cf_journal_item *ji = cf_malloc(sizeof(struct cf_journal_item) + len);
38   ji->prev = cc->journal;
39   ji->ptr = ptr;
40   ji->len = len;
41   memcpy(ji->copy, ptr, len);
42   cc->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_context *cc = cf_get_context();
50   struct cf_journal_item *curr, *prev, *next;
51   for (next=NULL, curr=cc->journal; curr; next=curr, curr=prev)
52   {
53     prev = curr->prev;
54     curr->prev = next;
55     for (uns i=0; i<curr->len; i++)
56     {
57       byte x = curr->copy[i];
58       curr->copy[i] = curr->ptr[i];
59       curr->ptr[i] = x;
60     }
61   }
62   cc->journal = next;
63 }
64
65 struct cf_journal_item *
66 cf_journal_new_transaction(uns new_pool)
67 {
68   struct cf_context *cc = cf_get_context();
69   if (new_pool)
70     cc->pool = mp_new(1<<10);
71   struct cf_journal_item *oldj = cc->journal;
72   cc->journal = NULL;
73   return oldj;
74 }
75
76 void
77 cf_journal_commit_transaction(uns new_pool, struct cf_journal_item *oldj)
78 {
79   struct cf_context *cc = cf_get_context();
80   if (new_pool)
81   {
82     struct old_pools *p = cf_malloc(sizeof(struct old_pools));
83     p->prev = cc->pools;
84     p->pool = cc->pool;
85     cc->pools = p;
86   }
87   if (oldj)
88   {
89     struct cf_journal_item **j = &cc->journal;
90     while (*j)
91       j = &(*j)->prev;
92     *j = oldj;
93   }
94 }
95
96 void
97 cf_journal_rollback_transaction(uns new_pool, struct cf_journal_item *oldj)
98 {
99   struct cf_context *cc = cf_get_context();
100   if (!cc->need_journal)
101     die("Cannot rollback the configuration, because the journal is disabled.");
102   cf_journal_swap();
103   cc->journal = oldj;
104   if (new_pool)
105   {
106     mp_delete(cc->pool);
107     cc->pool = cc->pools ? cc->pools->pool : NULL;
108   }
109 }
110
111 void
112 cf_journal_delete(void)
113 {
114   struct cf_context *cc = cf_get_context();
115   for (struct old_pools *p=cc->pools; p; p=cc->pools)
116   {
117     cc->pools = p->prev;
118     mp_delete(p->pool);
119   }
120 }
121
122 /* TODO: more space efficient journal */