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