2 * Copyright (C) 1994-2002, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
6 * $Id: rstemp.c,v 1.32 2002-05-03 13:46:33 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)
142 sprintf (template, "%s/zrsXXXXXX", info->temp_path);
144 sprintf (template, "zrsXXXXXX");
146 info->fd = mkstemp (template);
150 logf (LOG_FATAL|LOG_ERRNO, "mkstemp %s", template);
153 info->fname = (char *) xmalloc (strlen(template)+1);
154 strcpy (info->fname, template);
156 char *s = (char*) tempnam (info->temp_path, "zrs");
157 info->fname = (char *) xmalloc (strlen(s)+1);
158 strcpy (info->fname, s);
160 logf (LOG_DEBUG, "creating tempfile %s", info->fname);
161 info->fd = open (info->fname, O_BINARY|O_RDWR|O_CREAT, 0666);
164 logf (LOG_FATAL|LOG_ERRNO, "open %s", info->fname);
169 if (info->fname && info->fd != -1 && info->dirty)
174 if (lseek (info->fd, info->pos_buf, SEEK_SET) == -1)
176 logf (LOG_FATAL|LOG_ERRNO, "lseek %s", info->fname);
179 count = info->buf_size;
180 if (count > info->pos_end - info->pos_buf)
181 count = info->pos_end - info->pos_buf;
182 if ((r = write (info->fd, info->buf_mem, count)) < (int) count)
185 logf (LOG_FATAL|LOG_ERRNO, "read %s", info->fname);
187 logf (LOG_FATAL, "write of %ld but got %ld",
188 (long) count, (long) r);
195 static void r_close (RSFD rfd)
197 struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
200 if (info->fname && info->fd != -1)
205 xfree (((struct rset_temp_rfd *)rfd)->buf);
209 static void r_delete (RSET ct)
211 struct rset_temp_info *info = (struct rset_temp_info*) ct->buf;
214 unlink (info->fname);
215 xfree (info->buf_mem);
216 logf (LOG_DEBUG, "r_delete: set size %ld", (long) info->pos_end);
219 logf (LOG_DEBUG, "r_delete: unlink %s", info->fname);
220 unlink (info->fname);
224 xfree (info->temp_path);
225 rset_term_destroy (ct->rset_terms[0]);
226 xfree (ct->rset_terms);
231 read from file to window if file is assocated with set -
234 static void r_reread (RSFD rfd)
236 struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
243 info->pos_border = info->pos_cur + info->buf_size;
244 if (info->pos_border > info->pos_end)
245 info->pos_border = info->pos_end;
246 count = info->pos_border - info->pos_buf;
249 if (lseek (info->fd, info->pos_buf, SEEK_SET) == -1)
251 logf (LOG_FATAL|LOG_ERRNO, "lseek %s", info->fname);
254 if ((r = read (info->fd, info->buf_mem, count)) < (int) count)
257 logf (LOG_FATAL|LOG_ERRNO, "read %s", info->fname);
259 logf (LOG_FATAL, "read of %ld but got %ld",
260 (long) count, (long) r);
266 info->pos_border = info->pos_end;
269 static void r_rewind (RSFD rfd)
271 struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
279 static int r_count (RSET ct)
281 struct rset_temp_info *info = (struct rset_temp_info *) ct->buf;
283 return info->pos_end / info->key_size;
286 static int r_read (RSFD rfd, void *buf, int *term_index)
288 struct rset_temp_rfd *mrfd = (struct rset_temp_rfd*) rfd;
289 struct rset_temp_info *info = mrfd->info;
291 size_t nc = info->pos_cur + info->key_size;
293 if (nc > info->pos_border)
295 if (nc > info->pos_end)
298 info->pos_buf = info->pos_cur;
301 memcpy (buf, info->buf_mem + (info->pos_cur - info->pos_buf),
306 if (*mrfd->countp == 0 || (*info->cmp)(buf, mrfd->buf) > 1)
308 memcpy (mrfd->buf, buf, mrfd->info->key_size);
314 static int r_write (RSFD rfd, const void *buf)
316 struct rset_temp_info *info = ((struct rset_temp_rfd*)rfd)->info;
318 size_t nc = info->pos_cur + info->key_size;
320 if (nc > info->pos_buf + info->buf_size)
323 info->pos_buf = info->pos_cur;
324 if (info->pos_buf < info->pos_end)
328 memcpy (info->buf_mem + (info->pos_cur - info->pos_buf), buf,
331 if (nc > info->pos_end)
332 info->pos_border = info->pos_end = nc;