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