IDZEBRA  2.1.2
rstemp.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) Index Data
3 
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 
18 */
19 
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <assert.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #ifdef WIN32
29 #include <io.h>
30 #endif
31 #if HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 #include <sys/types.h>
35 
36 #include <idzebra/util.h>
37 #include <rset.h>
38 
39 static RSFD r_open(RSET ct, int flag);
40 static void r_close(RSFD rfd);
41 static void r_delete(RSET ct);
42 static int r_read(RSFD rfd, void *buf, TERMID *term);
43 static int r_write(RSFD rfd, const void *buf);
44 static void r_pos(RSFD rfd, double *current, double *total);
45 static void r_flush(RSFD rfd, int mk);
46 static void r_reread(RSFD rfd);
47 
48 static const struct rset_control control =
49 {
50  "temp",
51  r_delete,
53  r_open,
54  r_close,
55  0, /* no forward */
56  r_pos,
57  r_read,
58  r_write,
59 };
60 
61 struct rset_private {
62  int fd; /* file descriptor for temp file */
63  char *fname; /* name of temp file */
64  char *buf_mem; /* window buffer */
65  size_t buf_size; /* size of window */
66  size_t pos_end; /* last position in set */
67  size_t pos_buf; /* position of first byte in window */
68  size_t pos_border; /* position of last byte+1 in window */
69  int dirty; /* window is dirty */
70  zint hits; /* no of hits */
71  char *temp_path;
72 };
73 
74 struct rfd_private {
75  void *buf;
76  size_t pos_cur; /* current position in set */
77  /* FIXME - term pos or what ?? */
78  zint cur; /* number of the current hit */
79 };
80 
81 static int log_level = 0;
82 static int log_level_initialized = 0;
83 
84 RSET rset_create_temp(NMEM nmem, struct rset_key_control *kcontrol,
85  int scope, const char *temp_path, TERMID term)
86 {
87  RSET rnew = rset_create_base(&control, nmem, kcontrol, scope, term,
88  0, 0);
89  struct rset_private *info;
91  {
92  log_level = yaz_log_module_level("rstemp");
94  }
95  info = (struct rset_private *) nmem_malloc(rnew->nmem, sizeof(*info));
96  info->fd = -1;
97  info->fname = NULL;
98  info->buf_size = 4096;
99  info->buf_mem = (char *) nmem_malloc(rnew->nmem, info->buf_size);
100  info->pos_end = 0;
101  info->pos_buf = 0;
102  info->dirty = 0;
103  info->hits = 0;
104 
105  if (!temp_path)
106  info->temp_path = NULL;
107  else
108  info->temp_path = nmem_strdup(rnew->nmem, temp_path);
109  rnew->priv = info;
110  return rnew;
111 } /* rstemp_create */
112 
113 static void r_delete(RSET ct)
114 {
115  struct rset_private *info = (struct rset_private*) ct->priv;
116 
117  yaz_log(log_level, "r_delete: set size %ld", (long) info->pos_end);
118  if (info->fname)
119  {
120  yaz_log(log_level, "r_delete: unlink %s", info->fname);
121  unlink(info->fname);
122  }
123 }
124 
125 static RSFD r_open(RSET ct, int flag)
126 {
127  struct rset_private *info = (struct rset_private *) ct->priv;
128  RSFD rfd;
129  struct rfd_private *prfd;
130 
131  if (info->fd == -1 && info->fname)
132  {
133  if (flag & RSETF_WRITE)
134  info->fd = open(info->fname, O_BINARY|O_RDWR|O_CREAT, 0666);
135  else
136  info->fd = open(info->fname, O_BINARY|O_RDONLY);
137  if (info->fd == -1)
138  {
139  yaz_log(YLOG_FATAL|YLOG_ERRNO, "rstemp: open failed %s", info->fname);
140  zebra_exit("r_open");
141  }
142  }
143  rfd = rfd_create_base(ct);
144  if (!rfd->priv)
145  {
146  prfd = (struct rfd_private *) nmem_malloc(ct->nmem, sizeof(*prfd));
147  rfd->priv = (void *)prfd;
148  prfd->buf = nmem_malloc(ct->nmem,ct->keycontrol->key_size);
149  }
150  else
151  prfd= rfd->priv;
152  r_flush(rfd, 0);
153  prfd->pos_cur = 0;
154  info->pos_buf = 0;
155  r_reread(rfd);
156  prfd->cur = 0;
157  return rfd;
158 }
159 
160 /* r_flush:
161  flush current window to file if file is assocated with set
162  */
163 static void r_flush(RSFD rfd, int mk)
164 {
165  struct rset_private *info = rfd->rset->priv;
166 
167  if (!info->fname && mk)
168  {
169 #if HAVE_MKSTEMP
170  char template[1024];
171 
172  *template = '\0';
173 
174  if (info->temp_path)
175  sprintf(template, "%s/", info->temp_path);
176  strcat(template, "zrs_");
177 #if HAVE_UNISTD_H
178  sprintf(template + strlen(template), "%ld_", (long) getpid());
179 #endif
180  strcat(template, "XXXXXX");
181 
182  info->fd = mkstemp(template);
183  if (info->fd == -1)
184  {
185  yaz_log(YLOG_FATAL|YLOG_ERRNO, "rstemp: mkstemp %s", template);
186  zebra_exit("r_flush");
187  }
188  info->fname = nmem_strdup(rfd->rset->nmem, template);
189 #else
190  char *s = (char*) tempnam(info->temp_path, "zrs");
191  info->fname= nmem_strdup(rfd->rset->nmem, s);
192 
193  yaz_log(log_level, "creating tempfile %s", info->fname);
194  info->fd = open(info->fname, O_BINARY|O_RDWR|O_CREAT, 0666);
195  if (info->fd == -1)
196  {
197  yaz_log(YLOG_FATAL|YLOG_ERRNO, "rstemp: open %s", info->fname);
198  zebra_exit("r_flush");
199  }
200 #endif
201  }
202  if (info->fname && info->fd != -1 && info->dirty)
203  {
204  size_t count;
205  int r;
206 
207  if (lseek(info->fd, info->pos_buf, SEEK_SET) == -1)
208  {
209  yaz_log(YLOG_FATAL|YLOG_ERRNO, "rstemp: lseek (1) %s", info->fname);
210  zebra_exit("r_flusxh");
211  }
212  count = info->buf_size;
213  if (count > info->pos_end - info->pos_buf)
214  count = info->pos_end - info->pos_buf;
215  if ((r = write(info->fd, info->buf_mem, count)) < (int) count)
216  {
217  if (r == -1)
218  yaz_log(YLOG_FATAL|YLOG_ERRNO, "rstemp: write %s", info->fname);
219  else
220  yaz_log(YLOG_FATAL, "rstemp: write of %ld but got %ld",
221  (long) count, (long) r);
222  zebra_exit("r_flush");
223  }
224  info->dirty = 0;
225  }
226 }
227 
228 static void r_close(RSFD rfd)
229 {
230  struct rset_private *info = (struct rset_private *)rfd->rset->priv;
231  if (rfd_is_last(rfd))
232  {
233  r_flush(rfd, 0);
234  if (info->fname && info->fd != -1)
235  {
236  close(info->fd);
237  info->fd = -1;
238  }
239  }
240 }
241 
242 
243 /* r_reread:
244  read from file to window if file is assocated with set -
245  indicated by fname
246  */
247 static void r_reread(RSFD rfd)
248 {
249  struct rfd_private *mrfd = (struct rfd_private*) rfd->priv;
250  struct rset_private *info = (struct rset_private *)rfd->rset->priv;
251 
252  if (info->fname)
253  {
254  size_t count;
255  int r;
256 
257  info->pos_border = mrfd->pos_cur +
258  info->buf_size;
259  if (info->pos_border > info->pos_end)
260  info->pos_border = info->pos_end;
261  count = info->pos_border - info->pos_buf;
262  if (count > 0)
263  {
264  if (lseek(info->fd, info->pos_buf, SEEK_SET) == -1)
265  {
266  yaz_log(YLOG_FATAL|YLOG_ERRNO, "rstemp: lseek (2) %s fd=%d", info->fname, info->fd);
267  zebra_exit("r_reread");
268  }
269  if ((r = read(info->fd, info->buf_mem, count)) < (int) count)
270  {
271  if (r == -1)
272  yaz_log(YLOG_FATAL|YLOG_ERRNO, "rstemp: read %s", info->fname);
273  else
274  yaz_log(YLOG_FATAL, "read of %ld but got %ld",
275  (long) count, (long) r);
276  zebra_exit("r_reread");
277  }
278  }
279  }
280  else
281  info->pos_border = info->pos_end;
282 }
283 
284 static int r_read(RSFD rfd, void *buf, TERMID *term)
285 {
286  struct rfd_private *mrfd = (struct rfd_private*) rfd->priv;
287  struct rset_private *info = (struct rset_private *)rfd->rset->priv;
288 
289  size_t nc = mrfd->pos_cur + rfd->rset->keycontrol->key_size;
290 
291  if (mrfd->pos_cur < info->pos_buf || nc > info->pos_border)
292  {
293  if (nc > info->pos_end)
294  return 0;
295  r_flush(rfd, 0);
296  info->pos_buf = mrfd->pos_cur;
297  r_reread(rfd);
298  }
299  memcpy(buf, info->buf_mem + (mrfd->pos_cur - info->pos_buf),
300  rfd->rset->keycontrol->key_size);
301  if (term)
302  *term = rfd->rset->term;
303  /* FIXME - should we store and return terms ?? */
304  mrfd->pos_cur = nc;
305  mrfd->cur++;
306  return 1;
307 }
308 
309 static int r_write(RSFD rfd, const void *buf)
310 {
311  struct rfd_private *mrfd = (struct rfd_private*) rfd->priv;
312  struct rset_private *info = (struct rset_private *)rfd->rset->priv;
313 
314  size_t nc = mrfd->pos_cur + rfd->rset->keycontrol->key_size;
315 
316  if (nc > info->pos_buf + info->buf_size)
317  {
318  r_flush(rfd, 1);
319  info->pos_buf = mrfd->pos_cur;
320  if (info->pos_buf < info->pos_end)
321  r_reread(rfd);
322  }
323  info->dirty = 1;
324  memcpy(info->buf_mem + (mrfd->pos_cur - info->pos_buf), buf,
325  rfd->rset->keycontrol->key_size);
326  mrfd->pos_cur = nc;
327  if (nc > info->pos_end)
328  info->pos_border = info->pos_end = nc;
329  info->hits++;
330  return 1;
331 }
332 
333 static void r_pos(RSFD rfd, double *current, double *total)
334 {
335  struct rfd_private *mrfd = (struct rfd_private*) rfd->priv;
336  struct rset_private *info = (struct rset_private *)rfd->rset->priv;
337 
338  *current = (double) mrfd->cur;
339  *total = (double) info->hits;
340 }
341 /*
342  * Local variables:
343  * c-basic-offset: 4
344  * c-file-style: "Stroustrup"
345  * indent-tabs-mode: nil
346  * End:
347  * vim: shiftwidth=4 tabstop=8 expandtab
348  */
349 
char ** buf
Definition: rsprox.c:65
TERMID term
Definition: rset.h:160
struct rset_key_control * keycontrol
Definition: rset.h:153
char * buf_mem
Definition: rstemp.c:64
RSFD rfd_create_base(RSET rs)
Common constuctor for RFDs.
Definition: rset.c:43
size_t pos_end
Definition: rstemp.c:66
static RSFD r_open(RSET ct, int flag)
Definition: rstemp.c:125
int key_size
Definition: rset.h:128
RSET rset_create_temp(NMEM nmem, struct rset_key_control *kcontrol, int scope, const char *temp_path, TERMID term)
Definition: rstemp.c:84
RSET rset
Definition: rset.h:74
static void r_delete(RSET ct)
Definition: rstemp.c:113
static int r_write(RSFD rfd, const void *buf)
Definition: rstemp.c:309
size_t pos_buf
Definition: rstemp.c:67
const char * scope
Definition: tstlockscope.c:40
size_t pos_cur
Definition: rstemp.c:76
static const struct rset_control control
Definition: rstemp.c:48
static void r_close(RSFD rfd)
Definition: rstemp.c:228
void * priv
Definition: rset.h:155
static void r_pos(RSFD rfd, double *current, double *total)
Definition: rstemp.c:333
static int r_read(RSFD rfd, void *buf, TERMID *term)
Definition: rstemp.c:284
char * temp_path
Definition: rstemp.c:71
static int log_level
Definition: rstemp.c:81
size_t buf_size
Definition: rstemp.c:65
void zebra_exit(const char *msg)
Definition: exit.c:26
void rset_get_one_term(RSET ct, TERMID *terms, int maxterms, int *curterm)
is a getterms function for those that don&#39;t have any
Definition: rset.c:291
static void r_reread(RSFD rfd)
Definition: rstemp.c:247
RSFD * rfd
Definition: rsprox.c:64
long zint
Zebra integer.
Definition: util.h:66
NMEM nmem
Definition: rset.h:156
Definition: rset.h:150
Definition: rset.h:73
zint cur
Definition: rstemp.c:78
static void r_flush(RSFD rfd, int mk)
Definition: rstemp.c:163
zint hits
Definition: rstemp.c:70
size_t pos_border
Definition: rstemp.c:68
void * priv
Definition: rset.h:75
#define O_BINARY
Definition: agrep.c:46
static int log_level_initialized
Definition: rstemp.c:82
char * fname
Definition: rstemp.c:63
Definition: rset.h:50
int dirty
Definition: rstemp.c:69
int rfd_is_last(RSFD rfd)
Test for last use of RFD.
Definition: rset.c:242
int fd
Definition: rstemp.c:62
RSET rset_create_base(const struct rset_control *sel, NMEM nmem, struct rset_key_control *kcontrol, int scope, TERMID term, int no_children, RSET *children)
Common constuctor for RSETs.
Definition: rset.c:164
#define RSETF_WRITE
Definition: rset.h:200