IDZEBRA  2.2.7
bfile.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 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #ifdef WIN32
28 #include <io.h>
29 #endif
30 
31 #if HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 
35 #include <yaz/xmalloc.h>
36 #include <idzebra/util.h>
37 #include <idzebra/bfile.h>
38 #include "mfile.h"
39 #include "cfile.h"
40 
42 {
45  struct CFile_struct *cf;
47 };
48 
49 struct BFiles_struct {
52  char *base;
53  char *cache_fname;
54 };
55 
56 BFiles bfs_create (const char *spec, const char *base)
57 {
58  BFiles bfs = (BFiles) xmalloc(sizeof(*bfs));
59  bfs->commit_area = 0;
60  bfs->base = 0;
61  bfs->cache_fname = 0;
62  if (base)
63  bfs->base = xstrdup(base);
64  bfs->register_area = mf_init("register", spec, base, 0);
65  if (!bfs->register_area)
66  {
67  bfs_destroy(bfs);
68  return 0;
69  }
70  return bfs;
71 }
72 
74 {
75  if (!bfs)
76  return;
77  xfree(bfs->cache_fname);
78  xfree(bfs->base);
79  mf_destroy(bfs->commit_area);
81  xfree(bfs);
82 }
83 
84 static FILE *open_cache(BFiles bfs, const char *flags)
85 {
86  return fopen(bfs->cache_fname, flags);
87 }
88 
89 static void unlink_cache(BFiles bfs)
90 {
91  if (bfs->cache_fname)
92  unlink(bfs->cache_fname);
93 }
94 
95 ZEBRA_RES bf_cache(BFiles bfs, const char *spec)
96 {
97  if (spec)
98  {
99  yaz_log(YLOG_LOG, "enabling shadow spec=%s", spec);
100  if (!bfs->commit_area)
101  bfs->commit_area = mf_init("shadow", spec, bfs->base, 1);
102  if (bfs->commit_area)
103  {
104  bfs->cache_fname = xmalloc(strlen(bfs->commit_area->dirs->name)+
105  8);
106  strcpy(bfs->cache_fname, bfs->commit_area->dirs->name);
107  strcat(bfs->cache_fname, "/cache");
108  yaz_log(YLOG_LOG, "cache_fname = %s", bfs->cache_fname);
109  }
110  else
111  {
112  yaz_log(YLOG_WARN, "shadow could not be enabled");
113  return ZEBRA_FAIL;
114  }
115  }
116  else
117  bfs->commit_area = 0;
118  return ZEBRA_OK;
119 }
120 
122 {
123  int ret = 0;
125  if (bf->cf)
126  {
127  if (cf_close(bf->cf))
128  ret = -1;
129  }
130  if (bf->mf)
131  {
132  if (mf_close(bf->mf))
133  ret = -1;
134  }
135  xfree(bf);
136  return ret;
137 }
138 
139 void bf_close(BFile bf)
140 {
141  if (bf_close2(bf))
142  {
143  zebra_exit("bf_close");
144  }
145 }
146 
147 
148 #define HEADER_SIZE 256
149 
150 BFile bf_open(BFiles bfs, const char *name, int block_size, int wflag)
151 {
152  BFile bf = (BFile) xmalloc(sizeof(*bf));
153 
154  bf->block_size = block_size;
155  bf->cf = 0;
156  bf->mf = 0;
158 
159  if (bfs->commit_area)
160  {
161  int first_time;
162 
163  bf->mf = mf_open(bfs->register_area, name, block_size, 0);
164  bf->cf = cf_open(bf->mf, bfs->commit_area, name, block_size,
165  wflag, &first_time);
166  if (!bf->cf)
167  {
168  yaz_log(YLOG_FATAL, "cf_open failed for %s", name);
169  bf_close(bf);
170  return 0;
171  }
172  if (first_time)
173  {
174  FILE *outf;
175 
176  outf = open_cache(bfs, "ab");
177  if (!outf)
178  {
179  yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", bfs->cache_fname);
180  bf_close(bf);
181  return 0;
182  }
183  fprintf(outf, "%s %d\n", name, block_size);
184  if (fclose(outf))
185  {
186  yaz_log(YLOG_FATAL|YLOG_ERRNO, "fclose %s", bfs->cache_fname);
187  bf_close(bf);
188  return 0;
189  }
190  }
191  }
192  else
193  {
194  bf->mf = mf_open(bfs->register_area, name, block_size, wflag);
195  }
196  if (!bf->mf)
197  {
198  yaz_log(YLOG_FATAL, "mf_open failed for %s", name);
199  bf_close(bf);
200  return 0;
201  }
202  return bf;
203 }
204 
205 int bf_read(BFile bf, zint no, int offset, int nbytes, void *buf)
206 {
207  int ret = bf_read2(bf, no, offset, nbytes, buf);
208 
209  if (ret == -1)
210  {
211  zebra_exit("bf_read");
212  }
213  return ret;
214 }
215 
216 int bf_read2(BFile bf, zint no, int offset, int nbytes, void *buf)
217 {
218  int ret;
219 
221  if (bf->cf)
222  {
223  if ((ret = cf_read(bf->cf, no, offset, nbytes, buf)) == 0)
224  ret = mf_read(bf->mf, no, offset, nbytes, buf);
225  }
226  else
227  ret = mf_read(bf->mf, no, offset, nbytes, buf);
229  return ret;
230 }
231 
232 int bf_write(BFile bf, zint no, int offset, int nbytes, const void *buf)
233 {
234  int ret = bf_write2(bf, no, offset, nbytes, buf);
235 
236  if (ret == -1)
237  {
238  zebra_exit("bf_write");
239  }
240  return ret;
241 }
242 
243 int bf_write2(BFile bf, zint no, int offset, int nbytes, const void *buf)
244 {
245  int r;
247  if (bf->cf)
248  r = cf_write(bf->cf, no, offset, nbytes, buf);
249  else
250  r = mf_write(bf->mf, no, offset, nbytes, buf);
252  return r;
253 }
254 
256 {
257  FILE *inf;
258 
259  inf = open_cache(bfs, "rb");
260  if (inf)
261  {
262  fclose(inf);
263  return 1;
264  }
265  return 0;
266 }
267 
268 void bf_reset(BFiles bfs)
269 {
270  if (!bfs)
271  return;
272  mf_reset(bfs->commit_area, 1);
273  mf_reset(bfs->register_area, 1);
274  unlink_cache(bfs);
275 }
276 
278 {
279  FILE *inf;
280  int block_size;
281  char path[256];
282  MFile mf;
283  CFile cf;
284  int first_time;
285  int r = 0;
286 
287  assert(bfs->commit_area);
288  if (!(inf = open_cache(bfs, "rb")))
289  {
290  yaz_log(YLOG_LOG, "No commit file");
291  return -1;
292  }
293  while (fscanf(inf, "%s %d", path, &block_size) == 2)
294  {
295  mf = mf_open(bfs->register_area, path, block_size, 1);
296  if (!mf)
297  {
298  r = -1;
299  break;
300  }
301  cf = cf_open(mf, bfs->commit_area, path, block_size, 0, &first_time);
302  if (!cf)
303  {
304  mf_close(mf);
305  r = -1;
306  break;
307  }
308 
309  r = cf_commit(cf);
310 
311  cf_close(cf);
312  mf_close(mf);
313 
314  if (r)
315  break;
316  }
317  fclose(inf);
318  return r;
319 }
320 
321 void bf_commitClean(BFiles bfs, const char *spec)
322 {
323  int mustDisable = 0;
324 
325  if (!bfs->commit_area)
326  {
327  bf_cache(bfs, spec);
328  mustDisable = 1;
329  }
330 
331  mf_reset(bfs->commit_area, 1);
332 
333  unlink_cache(bfs);
334  if (mustDisable)
335  bf_cache(bfs, 0);
336 }
337 
338 int bfs_register_directory_stat(BFiles bfs, int no, const char **directory,
339  double *used_bytes, double *max_bytes)
340 {
341  return mf_area_directory_stat(bfs->register_area, no, directory,
342  used_bytes, max_bytes);
343 }
344 
345 
346 int bfs_shadow_directory_stat(BFiles bfs, int no, const char **directory,
347  double *used_bytes, double *max_bytes)
348 {
349  if (!bfs->commit_area)
350  return 0;
351  return mf_area_directory_stat(bfs->commit_area, no, directory,
352  used_bytes, max_bytes);
353 }
354 
355 /* unimplemented functions not in use, but kept to ensure ABI */
356 void bf_xclose(void) {}
357 void bf_xopen(void) {}
358 void bf_alloc(void) {}
359 void bf_free(void) {}
360 
361 
362 /*
363  * Local variables:
364  * c-basic-offset: 4
365  * c-file-style: "Stroustrup"
366  * indent-tabs-mode: nil
367  * End:
368  * vim: shiftwidth=4 tabstop=8 expandtab
369  */
370 
int bf_write2(BFile bf, zint no, int offset, int nbytes, const void *buf)
writes block of bytes to file
Definition: bfile.c:243
int bf_read(BFile bf, zint no, int offset, int nbytes, void *buf)
read from block file (may call exit)
Definition: bfile.c:205
void bf_xopen(void)
Definition: bfile.c:357
static FILE * open_cache(BFiles bfs, const char *flags)
Definition: bfile.c:84
int bf_read2(BFile bf, zint no, int offset, int nbytes, void *buf)
read from block file
Definition: bfile.c:216
ZEBRA_RES bf_cache(BFiles bfs, const char *spec)
enables or disables shadow for block files
Definition: bfile.c:95
int bfs_register_directory_stat(BFiles bfs, int no, const char **directory, double *used_bytes, double *max_bytes)
Definition: bfile.c:338
void bf_close(BFile bf)
closes a Block file (may call exit)
Definition: bfile.c:139
BFile bf_open(BFiles bfs, const char *name, int block_size, int wflag)
opens and returns a Block file handle
Definition: bfile.c:150
static void unlink_cache(BFiles bfs)
Definition: bfile.c:89
void bf_alloc(void)
Definition: bfile.c:358
int bf_write(BFile bf, zint no, int offset, int nbytes, const void *buf)
writes block of bytes to file (may call exit)
Definition: bfile.c:232
void bf_reset(BFiles bfs)
Removes register and shadow completely.
Definition: bfile.c:268
void bfs_destroy(BFiles bfs)
destroys a block files handle
Definition: bfile.c:73
void bf_commitClean(BFiles bfs, const char *spec)
Cleans shadow files (remove them)
Definition: bfile.c:321
int bf_close2(BFile bf)
closes a Block file
Definition: bfile.c:121
void bf_xclose(void)
Definition: bfile.c:356
int bfs_shadow_directory_stat(BFiles bfs, int no, const char **directory, double *used_bytes, double *max_bytes)
Definition: bfile.c:346
BFiles bfs_create(const char *spec, const char *base)
creates a Block files collection
Definition: bfile.c:56
int bf_commitExec(BFiles bfs)
Executes commit operation.
Definition: bfile.c:277
int bf_commitExists(BFiles bfs)
Check if there is content in shadow area (to be committed).
Definition: bfile.c:255
void bf_free(void)
Definition: bfile.c:359
Zebra Block File Layer.
struct BFile_struct * BFile
A Block File.
Definition: bfile.h:43
struct BFiles_struct * BFiles
A collection of BFile(s).
Definition: bfile.h:38
CFile cf_open(MFile mf, MFile_area area, const char *fname, int block_size, int wflag, int *firstp)
Definition: cfile.c:82
int cf_read(CFile cf, zint no, int offset, int nbytes, void *buf)
reads block from commit area
Definition: cfile.c:542
int cf_write(CFile cf, zint no, int offset, int nbytes, const void *buf)
writes block to commit area
Definition: cfile.c:579
int cf_close(CFile cf)
Definition: cfile.c:616
int cf_commit(CFile cf) ZEBRA_GCC_ATTR((warn_unused_result))
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_area_directory_stat(MFile_area ma, int no, const char **directory, double *used_bytes, double *max_bytes)
metafile area statistics
Definition: mfile.c:612
int mf_read(MFile mf, zint no, int offset, int nbytes, void *buf)
reads block from metafile
Definition: mfile.c:453
void mf_reset(MFile_area ma, int unlink_flag)
reset all files in a metafile area (optionally delete them as well)
Definition: mfile.c:326
void mf_destroy(MFile_area ma)
destroys metafile area handle
Definition: mfile.c:309
MFile_area mf_init(const char *name, const char *spec, const char *base, int only_shadow_files)
creates a metafile area
Definition: mfile.c:196
int mf_close(MFile mf)
closes metafile
Definition: mfile.c:431
MFile mf_open(MFile_area ma, const char *name, int block_size, int wflag)
opens metafile
Definition: mfile.c:353
static FILE * outf
Definition: readfile.c:38
static FILE * inf
Definition: readfile.c:37
Zebra_lock_rdwr rdwr_lock
Definition: bfile.c:44
int block_size
Definition: bfile.c:46
MFile mf
Definition: bfile.c:43
struct CFile_struct * cf
Definition: bfile.c:45
char * cache_fname
Definition: bfile.c:53
char * base
Definition: bfile.c:52
MFile_area register_area
Definition: bfile.c:51
MFile_area commit_area
Definition: bfile.c:50
All in-memory information per CFile.
Definition: cfile.h:69
mf_dir * dirs
Definition: mfile.h:96
char name[FILENAME_MAX+1]
Definition: mfile.h:57
long zint
Zebra integer.
Definition: util.h:66
#define ZEBRA_FAIL
Definition: util.h:81
void zebra_exit(const char *msg)
Definition: exit.c:26
#define ZEBRA_OK
Definition: util.h:82
short ZEBRA_RES
Common return type for Zebra API.
Definition: util.h:80
int zebra_lock_rdwr_rlock(Zebra_lock_rdwr *p)
Definition: zebra-lock.c:111
int zebra_lock_rdwr_wlock(Zebra_lock_rdwr *p)
Definition: zebra-lock.c:123
int zebra_lock_rdwr_destroy(Zebra_lock_rdwr *p)
Definition: zebra-lock.c:100
int zebra_lock_rdwr_wunlock(Zebra_lock_rdwr *p)
Definition: zebra-lock.c:155
int zebra_lock_rdwr_runlock(Zebra_lock_rdwr *p)
Definition: zebra-lock.c:135
int zebra_lock_rdwr_init(Zebra_lock_rdwr *p)
Definition: zebra-lock.c:89