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