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