Removed a crash on zebraidx init, if the register area isn't there
[idzebra-moved-to-github.git] / bfile / bfile.c
1 /*
2  * Copyright (C) 1994-1999, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: bfile.c,v $
7  * Revision 1.34  2002-07-16 13:17:53  heikki
8  * Removed a crash on zebraidx init, if the register area isn't there
9  *
10  * Revision 1.33  2002/04/04 14:14:13  adam
11  * Multiple registers (alpha early)
12  *
13  * Revision 1.32  2000/03/15 15:00:30  adam
14  * First work on threaded version.
15  *
16  * Revision 1.31  1999/12/08 15:03:11  adam
17  * Implemented bf_reset.
18  *
19  * Revision 1.30  1999/10/14 14:33:49  adam
20  * Added truncation 5=106.
21  *
22  * Revision 1.29  1999/05/26 07:49:12  adam
23  * C++ compilation.
24  *
25  * Revision 1.28  1999/05/12 13:08:05  adam
26  * First version of ISAMS.
27  *
28  * Revision 1.27  1999/02/02 14:50:01  adam
29  * Updated WIN32 code specific sections. Changed header.
30  *
31  * Revision 1.26  1998/02/17 10:32:52  adam
32  * Fixed bug: binary files weren't opened with flag b on NT.
33  *
34  * Revision 1.25  1997/10/27 14:25:38  adam
35  * Fixed memory leaks.
36  *
37  * Revision 1.24  1997/09/18 08:59:16  adam
38  * Extra generic handle for the character mapping routines.
39  *
40  * Revision 1.23  1997/09/17 12:19:06  adam
41  * Zebra version corresponds to YAZ version 1.4.
42  * Changed Zebra server so that it doesn't depend on global common_resource.
43  *
44  * Revision 1.22  1997/09/09 13:37:52  adam
45  * Partial port to WIN95/NT.
46  *
47  * Revision 1.21  1996/10/29 13:56:13  adam
48  * Include of zebrautl.h instead of alexutil.h.
49  *
50  * Revision 1.20  1996/03/26 15:59:04  adam
51  * The directory of the shadow table file can be specified by the new
52  * bf_lockDir call.
53  *
54  * Revision 1.19  1996/02/05  12:28:58  adam
55  * Removed a LOG_LOG message.
56  *
57  * Revision 1.18  1996/01/02  08:59:06  quinn
58  * Changed "commit" setting to "shadow".
59  *
60  * Revision 1.17  1995/12/11  09:03:51  adam
61  * New function: cf_unlink.
62  * New member of commit file head: state (0) deleted, (1) hash file.
63  *
64  * Revision 1.16  1995/12/08  16:21:13  adam
65  * Work on commit/update.
66  *
67  * Revision 1.15  1995/12/01  16:24:28  adam
68  * Commit files use separate meta file area.
69  *
70  * Revision 1.14  1995/12/01  11:37:21  adam
71  * Cached/commit files implemented as meta-files.
72  *
73  * Revision 1.13  1995/11/30  17:00:49  adam
74  * Several bug fixes. Commit system runs now.
75  *
76  * Revision 1.12  1995/11/30  08:33:10  adam
77  * Started work on commit facility.
78  *
79  * Revision 1.11  1995/09/04  12:33:21  adam
80  * Various cleanup. YAZ util used instead.
81  *
82  * Revision 1.10  1994/08/25  10:15:54  quinn
83  * Trivial
84  *
85  * Revision 1.9  1994/08/24  08:45:48  quinn
86  * Using mfile.
87  *
88  * Revision 1.8  1994/08/23  15:03:34  quinn
89  * *** empty log message ***
90  *
91  * Revision 1.7  1994/08/23  14:25:45  quinn
92  * Added O_CREAT because some geek wanted it. Sheesh.
93  *
94  * Revision 1.6  1994/08/23  14:21:38  quinn
95  * Fixed call to log
96  *
97  * Revision 1.5  1994/08/18  08:10:08  quinn
98  * Minimal changes
99  *
100  * Revision 1.4  1994/08/17  14:27:32  quinn
101  * last mods
102  *
103  * Revision 1.2  1994/08/17  14:09:32  quinn
104  * Compiles cleanly (still only dummy).
105  *
106  * Revision 1.1  1994/08/17  13:55:08  quinn
107  * New blocksystem. dummy only
108  *
109  */
110
111 #include <stdio.h>
112 #include <stdlib.h>
113 #include <string.h>
114 #include <assert.h>
115 #ifdef WIN32
116 #include <io.h>
117 #else
118 #include <unistd.h>
119 #endif
120
121 #include <zebrautl.h>
122 #include <bfile.h>
123 #include "cfile.h"
124
125 struct BFiles_struct {
126     MFile_area commit_area;
127     MFile_area_struct *register_area;
128     char *base;
129     char *cache_fname;
130 };
131
132 BFiles bfs_create (const char *spec, const char *base)
133 {
134     BFiles bfs = (BFiles) xmalloc (sizeof(*bfs));
135     bfs->commit_area = NULL;
136     bfs->base = 0;
137     bfs->cache_fname = 0;
138     if (base)
139         bfs->base = xstrdup (base);
140     bfs->register_area = mf_init("register", spec, base);
141     if (!bfs->register_area)
142     {
143         bfs_destroy(bfs);
144         return 0;
145     }
146     return bfs;
147 }
148
149 void bfs_destroy (BFiles bfs)
150 {
151     if (!bfs)
152         return;
153     xfree (bfs->cache_fname);
154     xfree (bfs->base);
155     mf_destroy (bfs->commit_area);
156     mf_destroy (bfs->register_area);
157     xfree (bfs);
158 }
159
160 static FILE *open_cache (BFiles bfs, const char *flags)
161 {
162     FILE *file;
163
164     file = fopen (bfs->cache_fname, flags);
165     return file;
166 }
167
168 static void unlink_cache (BFiles bfs)
169 {
170     unlink (bfs->cache_fname);
171 }
172
173 void bf_cache (BFiles bfs, const char *spec)
174 {
175     if (spec)
176     {
177         yaz_log (LOG_LOG, "enabling cache spec=%s", spec);
178         if (!bfs->commit_area)
179             bfs->commit_area = mf_init ("shadow", spec, bfs->base);
180         if (bfs->commit_area)
181         {
182             bfs->cache_fname = xmalloc (strlen(bfs->commit_area->dirs->name)+
183                                        8);
184             strcpy (bfs->cache_fname, bfs->commit_area->dirs->name);
185             strcat (bfs->cache_fname, "/cache");
186             yaz_log (LOG_LOG, "cache_fname = %s", bfs->cache_fname);
187         }
188     }
189     else
190         bfs->commit_area = NULL;
191 }
192
193 int bf_close (BFile bf)
194 {
195     zebra_lock_rdwr_destroy (&bf->rdwr_lock);
196     if (bf->cf)
197         cf_close (bf->cf);
198     mf_close (bf->mf);
199     xfree (bf);
200     return 0;
201 }
202
203 BFile bf_open (BFiles bfs, const char *name, int block_size, int wflag)
204 {
205     BFile tmp = (BFile) xmalloc(sizeof(BFile_struct));
206
207     if (bfs->commit_area)
208     {
209         int first_time;
210
211         tmp->mf = mf_open (bfs->register_area, name, block_size, 0);
212         tmp->cf = cf_open (tmp->mf, bfs->commit_area, name, block_size,
213                            wflag, &first_time);
214         if (first_time)
215         {
216             FILE *outf;
217
218             outf = open_cache (bfs, "ab");
219             if (!outf)
220             {
221                 logf (LOG_FATAL|LOG_ERRNO, "open %s", bfs->cache_fname);
222                 exit (1);
223             }
224             fprintf (outf, "%s %d\n", name, block_size);
225             fclose (outf);
226         }
227     }
228     else
229     {
230         tmp->mf = mf_open(bfs->register_area, name, block_size, wflag);
231         tmp->cf = NULL;
232     }
233     if (!tmp->mf)
234     {
235         logf (LOG_FATAL, "mf_open failed for %s", name);
236         xfree (tmp);
237         return 0;
238     }
239     zebra_lock_rdwr_init (&tmp->rdwr_lock);
240     return(tmp);
241 }
242
243 int bf_read (BFile bf, int no, int offset, int nbytes, void *buf)
244 {
245     int r;
246
247     zebra_lock_rdwr_rlock (&bf->rdwr_lock);
248     if (bf->cf)
249     {
250         if ((r = cf_read (bf->cf, no, offset, nbytes, buf)) == -1)
251             r = mf_read (bf->mf, no, offset, nbytes, buf);
252     }
253     else 
254         r = mf_read (bf->mf, no, offset, nbytes, buf);
255     zebra_lock_rdwr_runlock (&bf->rdwr_lock);
256     return r;
257 }
258
259 int bf_write (BFile bf, int no, int offset, int nbytes, const void *buf)
260 {
261     int r;
262     zebra_lock_rdwr_wlock (&bf->rdwr_lock);
263     if (bf->cf)
264         r = cf_write (bf->cf, no, offset, nbytes, buf);
265     else
266         r = mf_write (bf->mf, no, offset, nbytes, buf);
267     zebra_lock_rdwr_wunlock (&bf->rdwr_lock);
268     return r;
269 }
270
271 int bf_commitExists (BFiles bfs)
272 {
273     FILE *inf;
274
275     inf = open_cache (bfs, "rb");
276     if (inf)
277     {
278         fclose (inf);
279         return 1;
280     }
281     return 0;
282 }
283
284 void bf_reset (BFiles bfs)
285 {
286     if (!bfs)
287         return;
288     mf_reset (bfs->commit_area);
289     mf_reset (bfs->register_area);
290 }
291
292 void bf_commitExec (BFiles bfs)
293 {
294     FILE *inf;
295     int block_size;
296     char path[256];
297     MFile mf;
298     CFile cf;
299     int first_time;
300
301     assert (bfs->commit_area);
302     if (!(inf = open_cache (bfs, "rb")))
303     {
304         logf (LOG_LOG, "No commit file");
305         return ;
306     }
307     while (fscanf (inf, "%s %d", path, &block_size) == 2)
308     {
309         mf = mf_open (bfs->register_area, path, block_size, 1);
310         cf = cf_open (mf, bfs->commit_area, path, block_size, 0, &first_time);
311
312         cf_commit (cf);
313
314         cf_close (cf);
315         mf_close (mf);
316     }
317     fclose (inf);
318 }
319
320 void bf_commitClean (BFiles bfs, const char *spec)
321 {
322     FILE *inf;
323     int block_size;
324     char path[256];
325     MFile mf;
326     CFile cf;
327     int mustDisable = 0;
328     int firstTime;
329
330     if (!bfs->commit_area)
331     {
332         bf_cache (bfs, spec);
333         mustDisable = 1;
334     }
335
336     if (!(inf = open_cache (bfs, "rb")))
337         return ;
338     while (fscanf (inf, "%s %d", path, &block_size) == 2)
339     {
340         mf = mf_open (bfs->register_area, path, block_size, 0);
341         cf = cf_open (mf, bfs->commit_area, path, block_size, 1, &firstTime);
342         cf_unlink (cf);
343         cf_close (cf);
344         mf_close (mf);
345     }
346     fclose (inf);
347     unlink_cache (bfs);
348     if (mustDisable)
349         bf_cache (bfs, 0);
350 }