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