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