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