Work on optimized on commit operation.
[idzebra-moved-to-github.git] / bfile / commit.c
1 /*
2  * Copyright (C) 1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: commit.c,v $
7  * Revision 1.12  1996-04-24 13:29:16  adam
8  * Work on optimized on commit operation.
9  *
10  * Revision 1.11  1996/04/23  12:36:41  adam
11  * Started work on more efficient commit operation.
12  *
13  * Revision 1.10  1996/04/18  16:02:56  adam
14  * Changed logging a bit.
15  * Removed warning message when commiting flat shadow files.
16  *
17  * Revision 1.9  1996/04/12  07:01:57  adam
18  * Yet another bug fix (next_block was initialized to 0; now set to 1).
19  *
20  * Revision 1.8  1996/02/07 14:03:49  adam
21  * Work on flat indexed shadow files.
22  *
23  * Revision 1.7  1996/02/07  10:08:46  adam
24  * Work on flat shadow (not finished yet).
25  *
26  * Revision 1.6  1995/12/15  12:36:53  adam
27  * Moved hash file information to union.
28  * Renamed commit files.
29  *
30  * Revision 1.5  1995/12/12  15:57:55  adam
31  * Implemented mf_unlink. cf_unlink uses mf_unlink.
32  *
33  * Revision 1.4  1995/12/11  09:03:55  adam
34  * New function: cf_unlink.
35  * New member of commit file head: state (0) deleted, (1) hash file.
36  *
37  * Revision 1.3  1995/12/01  16:24:29  adam
38  * Commit files use separate meta file area.
39  *
40  * Revision 1.2  1995/12/01  11:37:24  adam
41  * Cached/commit files implemented as meta-files.
42  *
43  * Revision 1.1  1995/11/30  08:33:13  adam
44  * Started work on commit facility.
45  *
46  */
47
48 #include <assert.h>
49 #include <stdlib.h>
50
51 #include <alexutil.h>
52 #include <mfile.h>
53 #include "cfile.h"
54
55 #define CF_OPTIMIZE_COMMIT 0
56
57 void cf_unlink (CFile cf)
58 {
59     if (cf->bucket_in_memory)
60     {
61         logf (LOG_FATAL, "Cannot unlink potential dirty cache");
62         exit (1);
63     }
64     cf->head.state = 0;
65     cf->dirty = 1;
66     mf_unlink (cf->block_mf);
67     mf_unlink (cf->hash_mf);
68 }
69
70
71 #if CF_OPTIMIZE_COMMIT
72 struct map_cache_entity {
73     int from;
74     int to;
75 };
76
77 struct map_cache {
78     int max;
79     int no;
80
81     struct map_cache_entity *map;
82     char *buf;
83     CFile cf;
84 };
85
86 static struct map_cache *map_cache_init (CFile cf)
87 {
88     int mem_max = 2000000;
89     struct map_cache *m_p;
90
91     m_p = xmalloc (sizeof(*m_p));
92     m_p->cf = cf;
93     m_p->max = mem_max / cf->head.block_size;
94     m_p->buf = xmalloc (mem_max);
95     m_p->no = 0;
96     m_p->map = xmalloc (sizeof(*m_p->map) * m_p->max);
97     return m_p;
98 }
99
100 static int map_cache_cmp_from (const void *p1, const void *p2)
101 {
102     return ((struct map_cache_entity*) p1)->from -
103         ((struct map_cache_entity*) p2)->from;
104 }
105
106 static int map_cache_cmp_to (const void *p1, const void *p2)
107 {
108     return ((struct map_cache_entity*) p1)->to -
109         ((struct map_cache_entity*) p2)->to;
110 }
111
112 static void map_cache_flush (struct map_cache *m_p)
113 {
114     int i;
115
116     qsort (m_p->map, m_p->no, sizeof(*m_p->map), map_cache_cmp_from);
117     assert (m_p->no < 2 || m_p->map[0].from < m_p->map[1].from);
118     for (i = 0; i<m_p->no; i++)
119     {
120         if (!mf_read (m_p->cf->block_mf, m_p->map[i].from, 0, 0,
121                       m_p->buf + i * m_p->cf->head.block_size))
122         {
123             logf (LOG_FATAL, "read commit block at position %d",
124                   m_p->map[i].from);
125             exit (1);
126         }
127         m_p->map[i].from = i;
128     }
129     qsort (m_p->map, m_p->no, sizeof(*m_p->map), map_cache_cmp_to);
130     assert (m_p->no < 2 || m_p->map[0].to < m_p->map[1].to);
131     for (i = 0; i<m_p->no; i++)
132     {
133         mf_write (m_p->cf->rmf, m_p->map[i].to, 0, 0,
134                   m_p->buf + m_p->map[i].from * m_p->cf->head.block_size);
135     }    
136     m_p->no = 0;
137 }
138
139 static void map_cache_del (struct map_cache *m_p)
140 {
141     map_cache_flush (m_p);
142     xfree (m_p->map);
143     xfree (m_p->buf);
144     xfree (m_p);
145 }
146
147 static void map_cache_add (struct map_cache *m_p, int from, int to)
148 {
149     int i = m_p->no;
150
151     m_p->map[i].from = from;
152     m_p->map[i].to = to;
153     m_p->no = ++i;
154     if (i == m_p->max)
155         map_cache_flush (m_p);
156 }
157
158 /* CF_OPTIMIZE_COMMIT */
159 #endif
160
161 static void cf_commit_hash (CFile cf)
162
163     int i, bucket_no;
164     int hash_bytes;
165     struct CFile_ph_bucket *p;
166 #if CF_OPTIMIZE_COMMIT
167     struct map_cache *m_p;
168 #endif
169
170 #if CF_OPTIMIZE_COMMIT
171     m_p = map_cache_init (cf);
172 #endif
173
174     p = xmalloc (sizeof(*p));
175     hash_bytes = cf->head.hash_size * sizeof(int);
176     bucket_no = cf->head.first_bucket;
177     for (; bucket_no < cf->head.next_bucket; bucket_no++)
178     {
179         if (!mf_read (cf->hash_mf, bucket_no, 0, 0, p))
180         {
181             logf (LOG_FATAL, "read commit hash");
182             exit (1);
183         }
184         for (i = 0; i<HASH_BUCKET && p->vno[i]; i++)
185         {
186 #if CF_OPTIMIZE_COMMIT
187             map_cache_add (m_p, p->vno[i], p->no[i]);
188 #else
189             if (!mf_read (cf->block_mf, p->vno[i], 0, 0, cf->iobuf))
190             {
191                 logf (LOG_FATAL, "read commit block");
192                 exit (1);
193             }
194             mf_write (cf->rmf, p->no[i], 0, 0, cf->iobuf);
195 #endif
196         }
197     }
198 #if CF_OPTIMIZE_COMMIT
199     map_cache_del (m_p);
200 #endif
201     xfree (p);
202 }
203
204 static void cf_commit_flat (CFile cf)
205 {
206     int *fp;
207     int hno;
208     int i, vno = 0;
209
210 #if CF_OPTIMIZE_COMMIT
211     struct map_cache *m_p;
212 #endif
213
214
215 #if CF_OPTIMIZE_COMMIT
216     m_p = map_cache_init (cf);
217 #endif
218     fp = xmalloc (HASH_BSIZE);
219     for (hno = cf->head.next_bucket; hno < cf->head.flat_bucket; hno++)
220     {
221         if (hno == cf->head.flat_bucket-1)
222         {
223             for (i = 0; i < (HASH_BSIZE/sizeof(int)); i++)
224                 fp[i] = 0;
225         }
226         if (!mf_read (cf->hash_mf, hno, 0, 0, fp) &&
227             hno != cf->head.flat_bucket-1)
228         {
229             logf (LOG_FATAL, "read index block hno=%d (%d-%d) commit",
230                   hno, cf->head.next_bucket, cf->head.flat_bucket-1);
231         }
232         for (i = 0; i < (HASH_BSIZE/sizeof(int)); i++)
233         {
234             if (fp[i])
235             {
236 #if CF_OPTIMIZE_COMMIT
237                 map_cache_add (m_p, fp[i], vno);
238 #else
239                 if (!mf_read (cf->block_mf, fp[i], 0, 0, cf->iobuf))
240                 {
241                     logf (LOG_FATAL, "read data block hno=%d (%d-%d) "
242                                      "i=%d commit block at %d (->%d)",
243                           hno, cf->head.next_bucket, cf->head.flat_bucket-1,
244                           i, fp[i], vno);
245                     exit (1);
246                 }
247                 mf_write (cf->rmf, vno, 0, 0, cf->iobuf);
248
249 #endif
250             }
251             vno++;
252         }
253     }
254 #if CF_OPTIMIZE_COMMIT
255     map_cache_del (m_p);
256 #endif
257     xfree (fp);
258 }
259
260 void cf_commit (CFile cf)
261 {
262
263     if (cf->bucket_in_memory)
264     {
265         logf (LOG_FATAL, "Cannot commit potential dirty cache");
266         exit (1);
267     }
268     if (cf->head.state == 1)
269         cf_commit_hash (cf);
270     else if (cf->head.state == 2)
271         cf_commit_flat (cf);
272 }
273