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