]> mj.ucw.cz Git - libucw.git/blob - ucw/conf-journal.c
Merge branch 'master' into dev-sizet
[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   uint len;
28   byte copy[0];
29 };
30
31 void
32 cf_set_journalling(int enable)
33 {
34   struct cf_context *cc = cf_get_context();
35   ASSERT(!cc->journal);
36   cc->enable_journal = enable;
37 }
38
39 void
40 cf_journal_block(void *ptr, uint len)
41 {
42   struct cf_context *cc = cf_get_context();
43   if (!cc->enable_journal)
44     return;
45   struct cf_journal_item *ji = cf_malloc(sizeof(struct cf_journal_item) + len);
46   ji->prev = cc->journal;
47   ji->ptr = ptr;
48   ji->len = len;
49   memcpy(ji->copy, ptr, len);
50   cc->journal = ji;
51 }
52
53 void
54 cf_journal_swap(void)
55   // swaps the contents of the memory and the journal, and reverses the list
56 {
57   struct cf_context *cc = cf_get_context();
58   struct cf_journal_item *curr, *prev, *next;
59   for (next=NULL, curr=cc->journal; curr; next=curr, curr=prev)
60   {
61     prev = curr->prev;
62     curr->prev = next;
63     for (uint i=0; i<curr->len; i++)
64     {
65       byte x = curr->copy[i];
66       curr->copy[i] = curr->ptr[i];
67       curr->ptr[i] = x;
68     }
69   }
70   cc->journal = next;
71 }
72
73 struct cf_journal_item *
74 cf_journal_new_transaction(uint new_pool)
75 {
76   struct cf_context *cc = cf_get_context();
77   if (new_pool)
78     cc->pool = mp_new(1<<10);
79   struct cf_journal_item *oldj = cc->journal;
80   cc->journal = NULL;
81   return oldj;
82 }
83
84 void
85 cf_journal_commit_transaction(uint new_pool, struct cf_journal_item *oldj)
86 {
87   struct cf_context *cc = cf_get_context();
88   if (new_pool)
89   {
90     struct old_pools *p = cf_malloc(sizeof(struct old_pools));
91     p->prev = cc->pools;
92     p->pool = cc->pool;
93     cc->pools = p;
94   }
95   if (oldj)
96   {
97     struct cf_journal_item **j = &cc->journal;
98     while (*j)
99       j = &(*j)->prev;
100     *j = oldj;
101   }
102 }
103
104 void
105 cf_journal_rollback_transaction(uint new_pool, struct cf_journal_item *oldj)
106 {
107   struct cf_context *cc = cf_get_context();
108   if (!cc->enable_journal)
109     return;
110   cf_journal_swap();
111   cc->journal = oldj;
112   if (new_pool)
113   {
114     mp_delete(cc->pool);
115     cc->pool = cc->pools ? cc->pools->pool : NULL;
116   }
117 }
118
119 void
120 cf_journal_delete(void)
121 {
122   struct cf_context *cc = cf_get_context();
123   for (struct old_pools *p=cc->pools; p; p=cc->pools)
124   {
125     cc->pools = p->prev;
126     mp_delete(p->pool);
127   }
128 }