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