IDZEBRA 2.2.8
commit.c
Go to the documentation of this file.
1/* This file is part of the Zebra server.
2 Copyright (C) Index Data
3
4Zebra is free software; you can redistribute it and/or modify it under
5the terms of the GNU General Public License as published by the Free
6Software Foundation; either version 2, or (at your option) any later
7version.
8
9Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18*/
19
20
21#if HAVE_CONFIG_H
22#include <config.h>
23#endif
24#include <assert.h>
25#include <stdlib.h>
26
27#include <idzebra/util.h>
28#include <yaz/xmalloc.h>
29#include "mfile.h"
30#include "cfile.h"
31
32#define CF_OPTIMIZE_COMMIT 0
33
34static int log_level = 0;
35
36#if CF_OPTIMIZE_COMMIT
37struct map_cache_entity {
38 int from;
39 int to;
40};
41
42struct map_cache {
43 int max;
44 int no;
45
46 struct map_cache_entity *map;
47 char *buf;
48 CFile cf;
49};
50
51static struct map_cache *map_cache_init (CFile cf)
52{
53 int mem_max = 2000000;
54 struct map_cache *m_p;
55
56 m_p = xmalloc (sizeof(*m_p));
57 m_p->cf = cf;
58 m_p->max = mem_max / cf->head.block_size;
59 m_p->buf = xmalloc (mem_max);
60 m_p->no = 0;
61 m_p->map = xmalloc (sizeof(*m_p->map) * m_p->max);
62 return m_p;
63}
64
65static int map_cache_cmp_from (const void *p1, const void *p2)
66{
67 return ((struct map_cache_entity*) p1)->from -
68 ((struct map_cache_entity*) p2)->from;
69}
70
71static int map_cache_cmp_to(const void *p1, const void *p2)
72{
73 return ((struct map_cache_entity*) p1)->to -
74 ((struct map_cache_entity*) p2)->to;
75}
76
77static int map_cache_flush(struct map_cache *m_p)
78{
79 int i;
80
81 qsort (m_p->map, m_p->no, sizeof(*m_p->map), map_cache_cmp_from);
82 assert (m_p->no < 2 || m_p->map[0].from < m_p->map[1].from);
83 for (i = 0; i<m_p->no; i++)
84 {
85 if (mf_read(m_p->cf->block_mf, m_p->map[i].from, 0, 0,
86 m_p->buf + i * m_p->cf->head.block_size) != 1)
87 {
88 yaz_log (YLOG_FATAL, "read commit block at position %d",
89 m_p->map[i].from);
90 return -1;
91 }
92 m_p->map[i].from = i;
93 }
94 qsort (m_p->map, m_p->no, sizeof(*m_p->map), map_cache_cmp_to);
95 assert (m_p->no < 2 || m_p->map[0].to < m_p->map[1].to);
96 for (i = 0; i<m_p->no; i++)
97 {
98 if (mf_write(m_p->cf->rmf, m_p->map[i].to, 0, 0,
99 m_p->buf + m_p->map[i].from * m_p->cf->head.block_size))
100 return -1;
101 }
102 m_p->no = 0;
103 return 0;
104}
105
106static int map_cache_del(struct map_cache *m_p)
107{
108 int r = map_cache_flush(m_p);
109 xfree (m_p->map);
110 xfree (m_p->buf);
111 xfree (m_p);
112 return r;
113}
114
115static int map_cache_add(struct map_cache *m_p, int from, int to)
116{
117 int i = m_p->no;
118
119 m_p->map[i].from = from;
120 m_p->map[i].to = to;
121 m_p->no = ++i;
122 if (i == m_p->max)
123 return map_cache_flush(m_p);
124 return 0;
125}
126
127/* CF_OPTIMIZE_COMMIT */
128#endif
129
130static int cf_commit_hash (CFile cf)
131{
132 int r = 0;
133 int i;
134 zint bucket_no;
135 struct CFile_ph_bucket *p;
136#if CF_OPTIMIZE_COMMIT
137 struct map_cache *m_p;
138#endif
139
140#if CF_OPTIMIZE_COMMIT
141 m_p = map_cache_init (cf);
142#endif
143
144 p = (struct CFile_ph_bucket *) xmalloc (sizeof(*p));
145 bucket_no = cf->head.first_bucket;
146 for (; bucket_no < cf->head.next_bucket; bucket_no++)
147 {
148 if (mf_read (cf->hash_mf, bucket_no, 0, 0, p) != 1)
149 {
150 yaz_log (YLOG_FATAL, "read commit hash");
151 r = -1;
152 goto out;
153 }
154 for (i = 0; i<HASH_BUCKET && p->vno[i]; i++)
155 {
156#if CF_OPTIMIZE_COMMIT
157 if (map_cache_add(m_p, p->vno[i], p->no[i]))
158 {
159 r = -1;
160 goto out;
161 }
162#else
163 if (mf_read(cf->block_mf, p->vno[i], 0, 0, cf->iobuf) != 1)
164 {
165 yaz_log (YLOG_FATAL, "read commit block");
166 r = -1;
167 goto out;
168 }
169 if (mf_write(cf->rmf, p->no[i], 0, 0, cf->iobuf))
170 {
171 yaz_log (YLOG_FATAL, "write commit block");
172 r = -1;
173 goto out;
174 }
175#endif
176 }
177 }
178 out:
179#if CF_OPTIMIZE_COMMIT
180 if (map_cache_del(m_p))
181 r = -1;
182#endif
183 xfree(p);
184 return r;
185}
186
187static int cf_commit_flat(CFile cf)
188{
189 zint *fp;
190 zint hno;
191 int i;
192 int r = 0;
193 zint vno = 0;
194
195#if CF_OPTIMIZE_COMMIT
196 struct map_cache *m_p;
197#endif
198
199
200#if CF_OPTIMIZE_COMMIT
201 m_p = map_cache_init (cf);
202#endif
203 fp = (zint *) xmalloc (HASH_BSIZE);
204 for (hno = cf->head.next_bucket; hno < cf->head.flat_bucket; hno++)
205 {
206 for (i = 0; i < (int) (HASH_BSIZE/sizeof(zint)); i++)
207 fp[i] = 0;
208 if (!mf_read (cf->hash_mf, hno, 0, 0, fp) &&
209 hno != cf->head.flat_bucket-1)
210 {
211 yaz_log (YLOG_FATAL, "read index block hno=" ZINT_FORMAT
212 " (" ZINT_FORMAT "-" ZINT_FORMAT ") commit",
213 hno, cf->head.next_bucket, cf->head.flat_bucket-1);
214 r = -1;
215 goto out;
216 }
217 for (i = 0; i < (int) (HASH_BSIZE/sizeof(zint)); i++)
218 {
219 if (fp[i])
220 {
221#if CF_OPTIMIZE_COMMIT
222 if (map_cache_add(m_p, fp[i], vno))
223 {
224 r = -1;
225 goto out;
226 }
227#else
228 if (mf_read (cf->block_mf, fp[i], 0, 0, cf->iobuf) != 1)
229 {
230 yaz_log (YLOG_FATAL, "read data block hno=" ZINT_FORMAT " (" ZINT_FORMAT "-" ZINT_FORMAT ") "
231 "i=%d commit block at " ZINT_FORMAT " (->" ZINT_FORMAT")",
232 hno, cf->head.next_bucket, cf->head.flat_bucket-1,
233 i, fp[i], vno);
234 r = -1;
235 goto out;
236 }
237 if (mf_write(cf->rmf, vno, 0, 0, cf->iobuf))
238 {
239 r = -1;
240 goto out;
241 }
242#endif
243 }
244 vno++;
245 }
246 }
247 out:
248#if CF_OPTIMIZE_COMMIT
249 if (map_cache_del(m_p))
250 r = -1;
251#endif
252 yaz_log(log_level, "cf_commit_flat r=%d", r);
253 xfree(fp);
254 return r;
255}
256
258{
259 if (cf->bucket_in_memory)
260 {
261 yaz_log(YLOG_FATAL, "cf_commit: dirty cache");
262 return -1;
263 }
264 yaz_log(log_level, "cf_commit: state=%d", cf->head.state);
265 if (cf->head.state == CFILE_STATE_HASH)
266 return cf_commit_hash(cf);
267 else if (cf->head.state == CFILE_STATE_FLAT)
268 return cf_commit_flat(cf);
269 else
270 {
271 yaz_log(YLOG_FATAL, "cf_commit: bad state=%d", cf->head.state);
272 return -1;
273 }
274}
275
276/*
277 * Local variables:
278 * c-basic-offset: 4
279 * c-file-style: "Stroustrup"
280 * indent-tabs-mode: nil
281 * End:
282 * vim: shiftwidth=4 tabstop=8 expandtab
283 */
284
#define CFILE_STATE_HASH
state of CFile is a hash structure
Definition cfile.h:51
#define CFILE_STATE_FLAT
state of CFile is a flat file file
Definition cfile.h:54
#define HASH_BSIZE
Definition cfile.h:48
#define HASH_BUCKET
number of blocks in hash bucket
Definition cfile.h:30
static int cf_commit_flat(CFile cf)
Definition commit.c:187
static int cf_commit_hash(CFile cf)
Definition commit.c:130
static int log_level
Definition commit.c:34
int cf_commit(CFile cf)
Definition commit.c:257
int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
writes block to metafile
Definition mfile.c:486
int mf_read(MFile mf, zint no, int offset, int nbytes, void *buf)
reads block from metafile
Definition mfile.c:453
int state
Definition cfile.h:58
zint flat_bucket
Definition cfile.h:64
int block_size
Definition cfile.h:60
zint first_bucket
Definition cfile.h:62
zint next_bucket
Definition cfile.h:63
CFile hash structure on disc.
Definition cfile.h:33
zint vno[HASH_BUCKET]
Definition cfile.h:35
zint no[HASH_BUCKET]
Definition cfile.h:34
All in-memory information per CFile.
Definition cfile.h:69
MFile rmf
Definition cfile.h:82
MFile block_mf
Definition cfile.h:72
char * iobuf
Definition cfile.h:81
zint bucket_in_memory
Definition cfile.h:79
struct CFile_head head
Definition cfile.h:70
MFile hash_mf
Definition cfile.h:73
long zint
Zebra integer.
Definition util.h:66
#define ZINT_FORMAT
Definition util.h:72