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