Towards GPL
[idzebra-moved-to-github.git] / bfile / bfile.c
1 /* $Id: bfile.c,v 1.35 2002-08-02 19:26:55 adam Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #ifdef WIN32
30 #include <io.h>
31 #else
32 #include <unistd.h>
33 #endif
34
35 #include <zebrautl.h>
36 #include <bfile.h>
37 #include "cfile.h"
38
39 struct BFiles_struct {
40     MFile_area commit_area;
41     MFile_area_struct *register_area;
42     char *base;
43     char *cache_fname;
44 };
45
46 BFiles bfs_create (const char *spec, const char *base)
47 {
48     BFiles bfs = (BFiles) xmalloc (sizeof(*bfs));
49     bfs->commit_area = NULL;
50     bfs->base = 0;
51     bfs->cache_fname = 0;
52     if (base)
53         bfs->base = xstrdup (base);
54     bfs->register_area = mf_init("register", spec, base);
55     if (!bfs->register_area)
56     {
57         bfs_destroy(bfs);
58         return 0;
59     }
60     return bfs;
61 }
62
63 void bfs_destroy (BFiles bfs)
64 {
65     if (!bfs)
66         return;
67     xfree (bfs->cache_fname);
68     xfree (bfs->base);
69     mf_destroy (bfs->commit_area);
70     mf_destroy (bfs->register_area);
71     xfree (bfs);
72 }
73
74 static FILE *open_cache (BFiles bfs, const char *flags)
75 {
76     FILE *file;
77
78     file = fopen (bfs->cache_fname, flags);
79     return file;
80 }
81
82 static void unlink_cache (BFiles bfs)
83 {
84     unlink (bfs->cache_fname);
85 }
86
87 void bf_cache (BFiles bfs, const char *spec)
88 {
89     if (spec)
90     {
91         yaz_log (LOG_LOG, "enabling cache spec=%s", spec);
92         if (!bfs->commit_area)
93             bfs->commit_area = mf_init ("shadow", spec, bfs->base);
94         if (bfs->commit_area)
95         {
96             bfs->cache_fname = xmalloc (strlen(bfs->commit_area->dirs->name)+
97                                        8);
98             strcpy (bfs->cache_fname, bfs->commit_area->dirs->name);
99             strcat (bfs->cache_fname, "/cache");
100             yaz_log (LOG_LOG, "cache_fname = %s", bfs->cache_fname);
101         }
102     }
103     else
104         bfs->commit_area = NULL;
105 }
106
107 int bf_close (BFile bf)
108 {
109     zebra_lock_rdwr_destroy (&bf->rdwr_lock);
110     if (bf->cf)
111         cf_close (bf->cf);
112     mf_close (bf->mf);
113     xfree (bf);
114     return 0;
115 }
116
117 BFile bf_open (BFiles bfs, const char *name, int block_size, int wflag)
118 {
119     BFile tmp = (BFile) xmalloc(sizeof(BFile_struct));
120
121     if (bfs->commit_area)
122     {
123         int first_time;
124
125         tmp->mf = mf_open (bfs->register_area, name, block_size, 0);
126         tmp->cf = cf_open (tmp->mf, bfs->commit_area, name, block_size,
127                            wflag, &first_time);
128         if (first_time)
129         {
130             FILE *outf;
131
132             outf = open_cache (bfs, "ab");
133             if (!outf)
134             {
135                 logf (LOG_FATAL|LOG_ERRNO, "open %s", bfs->cache_fname);
136                 exit (1);
137             }
138             fprintf (outf, "%s %d\n", name, block_size);
139             fclose (outf);
140         }
141     }
142     else
143     {
144         tmp->mf = mf_open(bfs->register_area, name, block_size, wflag);
145         tmp->cf = NULL;
146     }
147     if (!tmp->mf)
148     {
149         logf (LOG_FATAL, "mf_open failed for %s", name);
150         xfree (tmp);
151         return 0;
152     }
153     zebra_lock_rdwr_init (&tmp->rdwr_lock);
154     return(tmp);
155 }
156
157 int bf_read (BFile bf, int no, int offset, int nbytes, void *buf)
158 {
159     int r;
160
161     zebra_lock_rdwr_rlock (&bf->rdwr_lock);
162     if (bf->cf)
163     {
164         if ((r = cf_read (bf->cf, no, offset, nbytes, buf)) == -1)
165             r = mf_read (bf->mf, no, offset, nbytes, buf);
166     }
167     else 
168         r = mf_read (bf->mf, no, offset, nbytes, buf);
169     zebra_lock_rdwr_runlock (&bf->rdwr_lock);
170     return r;
171 }
172
173 int bf_write (BFile bf, int no, int offset, int nbytes, const void *buf)
174 {
175     int r;
176     zebra_lock_rdwr_wlock (&bf->rdwr_lock);
177     if (bf->cf)
178         r = cf_write (bf->cf, no, offset, nbytes, buf);
179     else
180         r = mf_write (bf->mf, no, offset, nbytes, buf);
181     zebra_lock_rdwr_wunlock (&bf->rdwr_lock);
182     return r;
183 }
184
185 int bf_commitExists (BFiles bfs)
186 {
187     FILE *inf;
188
189     inf = open_cache (bfs, "rb");
190     if (inf)
191     {
192         fclose (inf);
193         return 1;
194     }
195     return 0;
196 }
197
198 void bf_reset (BFiles bfs)
199 {
200     if (!bfs)
201         return;
202     mf_reset (bfs->commit_area);
203     mf_reset (bfs->register_area);
204 }
205
206 void bf_commitExec (BFiles bfs)
207 {
208     FILE *inf;
209     int block_size;
210     char path[256];
211     MFile mf;
212     CFile cf;
213     int first_time;
214
215     assert (bfs->commit_area);
216     if (!(inf = open_cache (bfs, "rb")))
217     {
218         logf (LOG_LOG, "No commit file");
219         return ;
220     }
221     while (fscanf (inf, "%s %d", path, &block_size) == 2)
222     {
223         mf = mf_open (bfs->register_area, path, block_size, 1);
224         cf = cf_open (mf, bfs->commit_area, path, block_size, 0, &first_time);
225
226         cf_commit (cf);
227
228         cf_close (cf);
229         mf_close (mf);
230     }
231     fclose (inf);
232 }
233
234 void bf_commitClean (BFiles bfs, const char *spec)
235 {
236     FILE *inf;
237     int block_size;
238     char path[256];
239     MFile mf;
240     CFile cf;
241     int mustDisable = 0;
242     int firstTime;
243
244     if (!bfs->commit_area)
245     {
246         bf_cache (bfs, spec);
247         mustDisable = 1;
248     }
249
250     if (!(inf = open_cache (bfs, "rb")))
251         return ;
252     while (fscanf (inf, "%s %d", path, &block_size) == 2)
253     {
254         mf = mf_open (bfs->register_area, path, block_size, 0);
255         cf = cf_open (mf, bfs->commit_area, path, block_size, 1, &firstTime);
256         cf_unlink (cf);
257         cf_close (cf);
258         mf_close (mf);
259     }
260     fclose (inf);
261     unlink_cache (bfs);
262     if (mustDisable)
263         bf_cache (bfs, 0);
264 }