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