WIN32 compile (again)
[idzebra-moved-to-github.git] / rset / rstemp.c
1 /*
2  * Copyright (C) 1994-2002, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Id: rstemp.c,v 1.28 2002-03-14 18:41:59 adam Exp $
7  */
8
9 #include <fcntl.h>
10 #include <assert.h>
11 #ifdef WIN32
12 #include <io.h>
13 #else
14 #include <unistd.h>
15 #endif
16 #include <string.h>
17 #include <sys/types.h>
18 #include <stdio.h>
19
20 #include <zebrautl.h>
21 #include <rstemp.h>
22
23 static void *r_create(RSET ct, const struct rset_control *sel, void *parms);
24 static RSFD r_open (RSET ct, int flag);
25 static void r_close (RSFD rfd);
26 static void r_delete (RSET ct);
27 static void r_rewind (RSFD rfd);
28 static int r_count (RSET ct);
29 static int r_read (RSFD rfd, void *buf, int *term_index);
30 static int r_write (RSFD rfd, const void *buf);
31
32 static const struct rset_control control = 
33 {
34     "temp",
35     r_create,
36     r_open,
37     r_close,
38     r_delete,
39     r_rewind,
40     r_count,
41     r_read,
42     r_write,
43 };
44
45 const struct rset_control *rset_kind_temp = &control;
46
47 struct rset_temp_info {
48     int     fd;
49     char   *fname;
50     size_t  key_size;      /* key size */
51     char   *buf_mem;       /* window buffer */
52     size_t  buf_size;      /* size of window */
53     size_t  pos_end;       /* last position in set */
54     size_t  pos_cur;       /* current position in set */
55     size_t  pos_buf;       /* position of first byte in window */
56     size_t  pos_border;    /* position of last byte+1 in window */
57     int     dirty;         /* window is dirty */
58     int     hits;          /* no of hits */
59     char   *temp_path;
60 };
61
62 struct rset_temp_rfd {
63     struct rset_temp_info *info;
64     struct rset_temp_rfd *next;
65 };
66
67 static void *r_create(RSET ct, const struct rset_control *sel, void *parms)
68 {
69     rset_temp_parms *temp_parms = (rset_temp_parms *) parms;
70     struct rset_temp_info *info;
71    
72     info = (struct rset_temp_info *) xmalloc (sizeof(struct rset_temp_info));
73     info->fd = -1;
74     info->fname = NULL;
75     info->key_size = temp_parms->key_size;
76     info->buf_size = 4096;
77     info->buf_mem = (char *) xmalloc (info->buf_size);
78     info->pos_cur = 0;
79     info->pos_end = 0;
80     info->pos_buf = 0;
81     info->dirty = 0;
82     info->hits = -1;
83     if (!temp_parms->temp_path)
84         info->temp_path = NULL;
85     else
86     {
87         info->temp_path = (char *) xmalloc (strlen(temp_parms->temp_path)+1);
88         strcpy (info->temp_path, temp_parms->temp_path);
89     }
90     ct->no_rset_terms = 1;
91     ct->rset_terms = (RSET_TERM *) xmalloc (sizeof(*ct->rset_terms));
92     ct->rset_terms[0] = temp_parms->rset_term;
93     return info;
94 }
95
96 static RSFD r_open (RSET ct, int flag)
97 {
98     struct rset_temp_info *info = (struct rset_temp_info *) ct->buf;
99     struct rset_temp_rfd *rfd;
100
101     assert (info->fd == -1);
102     if (info->fname)
103     {
104         if (flag & RSETF_WRITE)
105             info->fd = open (info->fname, O_BINARY|O_RDWR|O_CREAT, 0666);
106         else
107             info->fd = open (info->fname, O_BINARY|O_RDONLY);
108         if (info->fd == -1)
109         {
110             logf (LOG_FATAL|LOG_ERRNO, "open %s", info->fname);
111             exit (1);
112         }
113     }
114     rfd = (struct rset_temp_rfd *) xmalloc (sizeof(*rfd));
115     rfd->info = info;
116     r_rewind (rfd);
117     return rfd;
118 }
119
120 /* r_flush:
121       flush current window to file if file is assocated with set
122  */
123 static void r_flush (RSFD rfd, int mk)
124 {
125     struct rset_temp_info *info = ((struct rset_temp_rfd*) rfd)->info;
126
127     if (!info->fname && mk)
128     {
129 #if 0
130         char template[1024];
131
132         sprintf (template, "%s/zrsXXXXXX", info->temp_path);
133
134         info->fd = mkstemp (template);
135
136         if (info->fd == -1)
137         {
138             logf (LOG_FATAL|LOG_ERRNO, "mkstemp %s", template);
139             exit (1);
140         }
141         info->fname = (char *) xmalloc (strlen(template)+1);
142         strcpy (info->fname, template);
143 #else
144         char *s = (char*) tempnam (info->temp_path, "zrs");
145         info->fname = (char *) xmalloc (strlen(s)+1);
146         strcpy (info->fname, s);
147
148         logf (LOG_DEBUG, "creating tempfile %s", info->fname);
149         info->fd = open (info->fname, O_BINARY|O_RDWR|O_CREAT, 0666);
150         if (info->fd == -1)
151         {
152             logf (LOG_FATAL|LOG_ERRNO, "open %s", info->fname);
153             exit (1);
154         }
155 #endif
156     }
157     if (info->fname && info->fd != -1 && info->dirty)
158     {
159         size_t count;
160         int r;
161         
162         if (lseek (info->fd, info->pos_buf, SEEK_SET) == -1)
163         {
164             logf (LOG_FATAL|LOG_ERRNO, "lseek %s", info->fname);
165             exit (1);
166         }
167         count = info->buf_size;
168         if (count > info->pos_end - info->pos_buf)
169             count = info->pos_end - info->pos_buf;
170         if ((r = write (info->fd, info->buf_mem, count)) < (int) count)
171         {
172             if (r == -1)
173                 logf (LOG_FATAL|LOG_ERRNO, "read %s", info->fname);
174             else
175                 logf (LOG_FATAL, "write of %ld but got %ld",
176                       (long) count, (long) r);
177             exit (1);
178         }
179         info->dirty = 0;
180     }
181 }
182
183 static void r_close (RSFD rfd)
184 {
185     struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
186
187     r_flush (rfd, 0);
188     if (info->fname && info->fd != -1)
189     {
190         close (info->fd);
191         info->fd = -1;
192     }
193     xfree (rfd);
194 }
195
196 static void r_delete (RSET ct)
197 {
198     struct rset_temp_info *info = (struct rset_temp_info*) ct->buf;
199
200     if (info->fname)
201         unlink (info->fname);        
202     xfree (info->buf_mem);
203     logf (LOG_DEBUG, "r_delete: set size %ld", (long) info->pos_end);
204     if (info->fname)
205     {
206         logf (LOG_DEBUG, "r_delete: unlink %s", info->fname);
207         unlink (info->fname);
208         xfree (info->fname);
209     }
210     if (info->temp_path)
211         xfree (info->temp_path);
212     rset_term_destroy (ct->rset_terms[0]);
213     xfree (ct->rset_terms);
214     xfree (info);
215 }
216
217 /* r_reread:
218       read from file to window if file is assocated with set -
219       indicated by fname
220  */
221 static void r_reread (RSFD rfd)
222 {
223     struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
224
225     if (info->fname)
226     {
227         size_t count;
228         int r;
229
230         info->pos_border = info->pos_cur + info->buf_size;
231         if (info->pos_border > info->pos_end)
232             info->pos_border = info->pos_end;
233         count = info->pos_border - info->pos_buf;
234         if (count > 0)
235         {
236             if (lseek (info->fd, info->pos_buf, SEEK_SET) == -1)
237             {
238                 logf (LOG_FATAL|LOG_ERRNO, "lseek %s", info->fname);
239                 exit (1);
240             }
241             if ((r = read (info->fd, info->buf_mem, count)) < (int) count)
242             {
243                 if (r == -1)
244                     logf (LOG_FATAL|LOG_ERRNO, "read %s", info->fname);
245                 else
246                     logf (LOG_FATAL, "read of %ld but got %ld",
247                           (long) count, (long) r);
248                 exit (1);
249             }
250         }
251     }
252     else
253         info->pos_border = info->pos_end;
254 }
255
256 static void r_rewind (RSFD rfd)
257 {
258     struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
259
260     r_flush (rfd, 0);
261     info->pos_cur = 0;
262     info->pos_buf = 0;
263     r_reread (rfd);
264 }
265
266 static int r_count (RSET ct)
267 {
268     struct rset_temp_info *info = (struct rset_temp_info *) ct->buf;
269
270     return info->pos_end / info->key_size;
271 }
272
273 static int r_read (RSFD rfd, void *buf, int *term_index)
274 {
275     struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
276
277     size_t nc = info->pos_cur + info->key_size;
278
279     if (nc > info->pos_border)
280     {
281         if (nc > info->pos_end)
282             return 0;
283         r_flush (rfd, 0);
284         info->pos_buf = info->pos_cur;
285         r_reread (rfd);
286     }
287     memcpy (buf, info->buf_mem + (info->pos_cur - info->pos_buf),
288             info->key_size);
289     info->pos_cur = nc;
290     *term_index = 0;
291     return 1;
292 }
293
294 static int r_write (RSFD rfd, const void *buf)
295 {
296     struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
297
298     size_t nc = info->pos_cur + info->key_size;
299
300     if (nc > info->pos_buf + info->buf_size)
301     {
302         r_flush (rfd, 1);
303         info->pos_buf = info->pos_cur;
304         if (info->pos_buf < info->pos_end)
305             r_reread (rfd);
306     }
307     info->dirty = 1;
308     memcpy (info->buf_mem + (info->pos_cur - info->pos_buf), buf,
309             info->key_size);
310     info->pos_cur = nc;
311     if (nc > info->pos_end)
312         info->pos_border = info->pos_end = nc;
313     return 1;
314 }