IDZEBRA  2.1.2
commit.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) Index Data
3 
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 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 
34 static int log_level = 0;
35 
36 #if CF_OPTIMIZE_COMMIT
37 struct map_cache_entity {
38  int from;
39  int to;
40 };
41 
42 struct map_cache {
43  int max;
44  int no;
45 
46  struct map_cache_entity *map;
47  char *buf;
48  CFile cf;
49 };
50 
51 static 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 
65 static 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 
71 static 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 
77 static 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 
106 static 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 
115 static 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 
130 static 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 
187 static 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 
int block_size
Definition: cfile.h:60
zint no[HASH_BUCKET]
Definition: cfile.h:34
MFile rmf
Definition: cfile.h:82
struct CFile_head head
Definition: cfile.h:70
#define CFILE_STATE_FLAT
state of CFile is a flat file file
Definition: cfile.h:54
#define HASH_BUCKET
number of blocks in hash bucket
Definition: cfile.h:30
static int cf_commit_flat(CFile cf)
Definition: commit.c:187
CFile hash structure on disc.
Definition: cfile.h:33
MFile hash_mf
Definition: cfile.h:73
zint first_bucket
Definition: cfile.h:62
int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
writes block to metafile
Definition: mfile.c:484
All in-memory information per CFile.
Definition: cfile.h:68
char * iobuf
Definition: cfile.h:81
static int log_level
Definition: commit.c:34
zint bucket_in_memory
Definition: cfile.h:79
#define HASH_BSIZE
Definition: cfile.h:48
static int cf_commit_hash(CFile cf)
Definition: commit.c:130
int cf_commit(CFile cf)
Definition: commit.c:257
MFile block_mf
Definition: cfile.h:72
int mf_read(MFile mf, zint no, int offset, int nbytes, void *buf)
reads block from metafile
Definition: mfile.c:451
zint flat_bucket
Definition: cfile.h:64
int state
Definition: cfile.h:58
long zint
Zebra integer.
Definition: util.h:66
#define CFILE_STATE_HASH
state of CFile is a hash structure
Definition: cfile.h:51
zint next_bucket
Definition: cfile.h:63
zint vno[HASH_BUCKET]
Definition: cfile.h:35
#define ZINT_FORMAT
Definition: util.h:72