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