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