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