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