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