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