2 * Copyright (C) 1994-2002, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
6 * $Id: rstemp.c,v 1.30 2002-03-20 20:24:30 adam Exp $
17 #include <sys/types.h>
23 static void *r_create(RSET ct, const struct rset_control *sel, void *parms);
24 static RSFD r_open (RSET ct, int flag);
25 static void r_close (RSFD rfd);
26 static void r_delete (RSET ct);
27 static void r_rewind (RSFD rfd);
28 static int r_count (RSET ct);
29 static int r_read (RSFD rfd, void *buf, int *term_index);
30 static int r_write (RSFD rfd, const void *buf);
32 static const struct rset_control control =
45 const struct rset_control *rset_kind_temp = &control;
47 struct rset_temp_info {
50 size_t key_size; /* key size */
51 char *buf_mem; /* window buffer */
52 size_t buf_size; /* size of window */
53 size_t pos_end; /* last position in set */
54 size_t pos_cur; /* current position in set */
55 size_t pos_buf; /* position of first byte in window */
56 size_t pos_border; /* position of last byte+1 in window */
57 int dirty; /* window is dirty */
58 int hits; /* no of hits */
60 int (*cmp)(const void *p1, const void *p2);
63 struct rset_temp_rfd {
64 struct rset_temp_info *info;
65 struct rset_temp_rfd *next;
70 static void *r_create(RSET ct, const struct rset_control *sel, void *parms)
72 rset_temp_parms *temp_parms = (rset_temp_parms *) parms;
73 struct rset_temp_info *info;
75 info = (struct rset_temp_info *) xmalloc (sizeof(struct rset_temp_info));
78 info->key_size = temp_parms->key_size;
79 info->buf_size = 4096;
80 info->buf_mem = (char *) xmalloc (info->buf_size);
86 info->cmp = temp_parms->cmp;
87 if (!temp_parms->temp_path)
88 info->temp_path = NULL;
91 info->temp_path = (char *) xmalloc (strlen(temp_parms->temp_path)+1);
92 strcpy (info->temp_path, temp_parms->temp_path);
94 ct->no_rset_terms = 1;
95 ct->rset_terms = (RSET_TERM *) xmalloc (sizeof(*ct->rset_terms));
96 ct->rset_terms[0] = temp_parms->rset_term;
101 static RSFD r_open (RSET ct, int flag)
103 struct rset_temp_info *info = (struct rset_temp_info *) ct->buf;
104 struct rset_temp_rfd *rfd;
106 assert (info->fd == -1);
109 if (flag & RSETF_WRITE)
110 info->fd = open (info->fname, O_BINARY|O_RDWR|O_CREAT, 0666);
112 info->fd = open (info->fname, O_BINARY|O_RDONLY);
115 logf (LOG_FATAL|LOG_ERRNO, "open %s", info->fname);
119 rfd = (struct rset_temp_rfd *) xmalloc (sizeof(*rfd));
123 rfd->countp = &ct->rset_terms[0]->count;
124 rfd->buf = xmalloc (info->key_size);
130 flush current window to file if file is assocated with set
132 static void r_flush (RSFD rfd, int mk)
134 struct rset_temp_info *info = ((struct rset_temp_rfd*) rfd)->info;
136 if (!info->fname && mk)
141 sprintf (template, "%s/zrsXXXXXX", info->temp_path);
143 info->fd = mkstemp (template);
147 logf (LOG_FATAL|LOG_ERRNO, "mkstemp %s", template);
150 info->fname = (char *) xmalloc (strlen(template)+1);
151 strcpy (info->fname, template);
153 char *s = (char*) tempnam (info->temp_path, "zrs");
154 info->fname = (char *) xmalloc (strlen(s)+1);
155 strcpy (info->fname, s);
157 logf (LOG_DEBUG, "creating tempfile %s", info->fname);
158 info->fd = open (info->fname, O_BINARY|O_RDWR|O_CREAT, 0666);
161 logf (LOG_FATAL|LOG_ERRNO, "open %s", info->fname);
166 if (info->fname && info->fd != -1 && info->dirty)
171 if (lseek (info->fd, info->pos_buf, SEEK_SET) == -1)
173 logf (LOG_FATAL|LOG_ERRNO, "lseek %s", info->fname);
176 count = info->buf_size;
177 if (count > info->pos_end - info->pos_buf)
178 count = info->pos_end - info->pos_buf;
179 if ((r = write (info->fd, info->buf_mem, count)) < (int) count)
182 logf (LOG_FATAL|LOG_ERRNO, "read %s", info->fname);
184 logf (LOG_FATAL, "write of %ld but got %ld",
185 (long) count, (long) r);
192 static void r_close (RSFD rfd)
194 struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
197 if (info->fname && info->fd != -1)
202 xfree (((struct rset_temp_rfd *)rfd)->buf);
206 static void r_delete (RSET ct)
208 struct rset_temp_info *info = (struct rset_temp_info*) ct->buf;
211 unlink (info->fname);
212 xfree (info->buf_mem);
213 logf (LOG_DEBUG, "r_delete: set size %ld", (long) info->pos_end);
216 logf (LOG_DEBUG, "r_delete: unlink %s", info->fname);
217 unlink (info->fname);
221 xfree (info->temp_path);
222 rset_term_destroy (ct->rset_terms[0]);
223 xfree (ct->rset_terms);
228 read from file to window if file is assocated with set -
231 static void r_reread (RSFD rfd)
233 struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
240 info->pos_border = info->pos_cur + info->buf_size;
241 if (info->pos_border > info->pos_end)
242 info->pos_border = info->pos_end;
243 count = info->pos_border - info->pos_buf;
246 if (lseek (info->fd, info->pos_buf, SEEK_SET) == -1)
248 logf (LOG_FATAL|LOG_ERRNO, "lseek %s", info->fname);
251 if ((r = read (info->fd, info->buf_mem, count)) < (int) count)
254 logf (LOG_FATAL|LOG_ERRNO, "read %s", info->fname);
256 logf (LOG_FATAL, "read of %ld but got %ld",
257 (long) count, (long) r);
263 info->pos_border = info->pos_end;
266 static void r_rewind (RSFD rfd)
268 struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
276 static int r_count (RSET ct)
278 struct rset_temp_info *info = (struct rset_temp_info *) ct->buf;
280 return info->pos_end / info->key_size;
283 static int r_read (RSFD rfd, void *buf, int *term_index)
285 struct rset_temp_rfd *mrfd = (struct rset_temp_rfd*) rfd;
286 struct rset_temp_info *info = mrfd->info;
288 size_t nc = info->pos_cur + info->key_size;
290 if (nc > info->pos_border)
292 if (nc > info->pos_end)
295 info->pos_buf = info->pos_cur;
298 memcpy (buf, info->buf_mem + (info->pos_cur - info->pos_buf),
303 if (*mrfd->countp == 0 || (*info->cmp)(buf, mrfd->buf) > 1)
305 memcpy (mrfd->buf, buf, mrfd->info->key_size);
311 static int r_write (RSFD rfd, const void *buf)
313 struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
315 size_t nc = info->pos_cur + info->key_size;
317 if (nc > info->pos_buf + info->buf_size)
320 info->pos_buf = info->pos_cur;
321 if (info->pos_buf < info->pos_end)
325 memcpy (info->buf_mem + (info->pos_cur - info->pos_buf), buf,
328 if (nc > info->pos_end)
329 info->pos_border = info->pos_end = nc;