IDZEBRA  2.1.2
isams.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 
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <stdio.h>
28 
29 #include <yaz/log.h>
30 #include <yaz/xmalloc.h>
31 #include <idzebra/isams.h>
32 
33 typedef struct {
36 } ISAMS_head;
37 
38 typedef unsigned ISAMS_BLOCK_SIZE;
39 
40 struct ISAMS_s {
44  char *merge_buf;
45 
47  int debug;
49 };
50 
51 struct ISAMS_PP_s {
53  char *buf;
55  int block_no;
57  int numKeys;
58  int numRead;
59 };
60 
62 {
63  m->codec.start = NULL;
64  m->codec.decode = NULL;
65  m->codec.encode = NULL;
66  m->codec.stop = NULL;
67  m->codec.reset = NULL;
68 
69  m->compare_item = NULL;
70  m->log_item = NULL;
71 
72  m->debug = 1;
73  m->block_size = 128;
74 }
75 
76 ISAMS isams_open (BFiles bfs, const char *name, int writeflag,
77  ISAMS_M *method)
78 {
79  ISAMS is = (ISAMS) xmalloc (sizeof(*is));
80 
81  is->method = (ISAMS_M *) xmalloc (sizeof(*is->method));
82  memcpy (is->method, method, sizeof(*method));
83  is->block_size = is->method->block_size;
84  is->debug = is->method->debug;
85 
86  is->bf = bf_open (bfs, name, is->block_size, writeflag);
87 
88  if (!bf_read (is->bf, 0, 0, sizeof(ISAMS_head), &is->head))
89  {
90  is->head.last_block = 1;
91  is->head.last_offset = 0;
92  }
93  memcpy (&is->head_old, &is->head, sizeof(is->head));
94  is->merge_buf = (char *) xmalloc(2*is->block_size);
95  memset(is->merge_buf, 0, 2*is->block_size);
96  return is;
97 }
98 
100 {
101  if (memcmp(&is->head, &is->head_old, sizeof(is->head)))
102  {
103  if (is->head.last_offset)
104  bf_write(is->bf, is->head.last_block, 0, is->head.last_offset,
105  is->merge_buf);
106  bf_write (is->bf, 0, 0, sizeof(is->head), &is->head);
107  }
108  bf_close (is->bf);
109  xfree (is->merge_buf);
110  xfree (is->method);
111  xfree (is);
112  return 0;
113 }
114 
116 {
117  char i_item[128];
118  int i_more, i_mode;
119  void *r_clientData;
120  int first_block = is->head.last_block;
121  int first_offset = is->head.last_offset;
122  int count = 0;
123 
124  r_clientData = (*is->method->codec.start)();
125 
126  is->head.last_offset += sizeof(int);
127  if (is->head.last_offset > is->block_size)
128  {
129  if (is->debug > 2)
130  yaz_log (YLOG_LOG, "first_block=%d", first_block);
131  bf_write(is->bf, is->head.last_block, 0, 0, is->merge_buf);
132  (is->head.last_block)++;
133  is->head.last_offset -= is->block_size;
134  memcpy (is->merge_buf, is->merge_buf + is->block_size,
135  is->head.last_offset);
136  }
137  while (1)
138  {
139  char *tmp_ptr = i_item;
140  i_more = (*data->read_item)(data->clientData, &tmp_ptr, &i_mode);
141  assert (i_mode);
142 
143  if (!i_more)
144  break;
145  else
146  {
147  char *r_out_ptr = is->merge_buf + is->head.last_offset;
148 
149  const char *i_item_ptr = i_item;
150  (*is->method->codec.encode)(r_clientData, &r_out_ptr, &i_item_ptr);
151  is->head.last_offset = r_out_ptr - is->merge_buf;
152  if (is->head.last_offset > is->block_size)
153  {
154  bf_write(is->bf, is->head.last_block, 0, 0, is->merge_buf);
155  (is->head.last_block)++;
156  is->head.last_offset -= is->block_size;
157  memcpy (is->merge_buf, is->merge_buf + is->block_size,
158  is->head.last_offset);
159  }
160  count++;
161  }
162  }
163  (*is->method->codec.stop)(r_clientData);
164  if (first_block == is->head.last_block)
165  memcpy(is->merge_buf + first_offset, &count, sizeof(int));
166  else if (first_block == is->head.last_block-1)
167  {
168  int gap = first_offset + sizeof(int) - is->block_size;
169  assert (gap <= (int) sizeof(int));
170  if (gap > 0)
171  {
172  if (gap < (int) sizeof(int))
173  bf_write(is->bf, first_block, first_offset, sizeof(int)-gap,
174  &count);
175  memcpy (is->merge_buf, ((char*)&count)+(sizeof(int)-gap), gap);
176  }
177  else
178  bf_write(is->bf, first_block, first_offset, sizeof(int), &count);
179  }
180  else
181  {
182  bf_write(is->bf, first_block, first_offset, sizeof(int), &count);
183  }
184  return first_block * is->block_size + first_offset;
185 }
186 
188 {
189  ISAMS_PP pp = (ISAMS_PP) xmalloc (sizeof(*pp));
190 
191  if (is->debug > 1)
192  yaz_log (YLOG_LOG, "isams: isams_pp_open pos=%ld", (long) pos);
193  pp->is = is;
194  pp->decodeClientData = (*is->method->codec.start)();
195  pp->numKeys = 0;
196  pp->numRead = 0;
197  pp->buf = (char *) xmalloc(is->block_size*2);
198  pp->block_no = (int) (pos/is->block_size);
199  pp->block_offset = (int) (pos - pp->block_no * is->block_size);
200  if (is->debug)
201  yaz_log (YLOG_LOG, "isams: isams_pp_open off=%d no=%d",
202  pp->block_offset, pp->block_no);
203  if (pos)
204  {
205  bf_read (is->bf, pp->block_no, 0, 0, pp->buf);
206  bf_read (is->bf, pp->block_no+1, 0, 0, pp->buf + is->block_size);
207  memcpy(&pp->numKeys, pp->buf + pp->block_offset, sizeof(int));
208  if (is->debug)
209  yaz_log (YLOG_LOG, "isams: isams_pp_open numKeys=%d", pp->numKeys);
210  pp->block_offset += sizeof(int);
211  }
212  return pp;
213 }
214 
216 {
217  (*pp->is->method->codec.stop)(pp->decodeClientData);
218  xfree(pp->buf);
219  xfree(pp);
220 }
221 
223 {
224  return pp->numKeys;
225 }
226 
227 int isams_pp_read (ISAMS_PP pp, void *buf)
228 {
229  char *cp = buf;
230  return isams_read_item (pp, &cp);
231 }
232 
233 int isams_read_item (ISAMS_PP pp, char **dst)
234 {
235  const char *src;
236  if (pp->numRead >= pp->numKeys)
237  return 0;
238  (pp->numRead)++;
239  if (pp->block_offset > pp->is->block_size)
240  {
241  pp->block_offset -= pp->is->block_size;
242  (pp->block_no)++;
243  memcpy (pp->buf, pp->buf + pp->is->block_size, pp->is->block_size);
244  bf_read (pp->is->bf, pp->block_no+1, 0, 0,
245  pp->buf + pp->is->block_size);
246  }
247  src = pp->buf + pp->block_offset;
248  (*pp->is->method->codec.decode)(pp->decodeClientData, dst, &src);
249  pp->block_offset = src - pp->buf;
250  return 1;
251 }
252 
253 
254 /*
255  * Local variables:
256  * c-basic-offset: 4
257  * c-file-style: "Stroustrup"
258  * indent-tabs-mode: nil
259  * End:
260  * vim: shiftwidth=4 tabstop=8 expandtab
261  */
262 
int(* compare_item)(const void *a, const void *b)
Definition: isams.h:34
ISAM_CODEC codec
Definition: isams.h:37
void isams_getmethod(ISAMS_M *m)
Definition: isams.c:61
struct ISAMS_s * ISAMS
Definition: isams.h:30
int isams_pp_num(ISAMS_PP pp)
Definition: isams.c:222
zint ISAM_P
Definition: isamc.h:28
struct ISAMS_PP_s * ISAMS_PP
Definition: isams.h:31
char * buf
Definition: isams.c:53
Definition: isams.c:40
int block_no
Definition: isams.c:55
int isams_pp_read(ISAMS_PP pp, void *buf)
Definition: isams.c:227
ISAMS is
Definition: isams.c:52
ISAMS_PP isams_pp_open(ISAMS is, ISAM_P pos)
Definition: isams.c:187
void(* reset)(void *p)
Definition: isam-codec.h:28
void(* decode)(void *p, char **dst, const char **src)
Definition: isam-codec.h:26
unsigned ISAMS_BLOCK_SIZE
Definition: isams.c:38
int last_block
Definition: isams.c:35
ISAM_P isams_merge(ISAMS is, ISAMS_I data)
Definition: isams.c:115
int debug
Definition: isams.h:39
ISAMS_head head_old
Definition: isams.c:43
int numKeys
Definition: isams.c:57
int last_offset
Definition: isams.c:34
int block_size
Definition: isams.h:40
void * clientData
Definition: isams.h:45
int(* read_item)(void *clientData, char **dst, int *insertMode)
Definition: isams.h:44
int debug
Definition: isams.c:47
ISAMS_M * method
Definition: isams.c:41
int block_size
Definition: isams.c:46
void bf_close(BFile bf)
closes a Block file (may call exit)
Definition: bfile.c:151
void *(* start)(void)
Definition: isam-codec.h:24
int bf_read(BFile bf, zint no, int offset, int nbytes, void *buf)
read from block file (may call exit)
Definition: bfile.c:319
void(* stop)(void *p)
Definition: isam-codec.h:25
void(* log_item)(int logmask, const void *p, const char *txt)
Definition: isams.h:35
ISAMS isams_open(BFiles bfs, const char *name, int writeflag, ISAMS_M *method)
Definition: isams.c:76
int bf_write(BFile bf, zint no, int offset, int nbytes, const void *buf)
writes block of bytes to file (may call exit)
Definition: bfile.c:346
int numRead
Definition: isams.c:58
ISAMS_head head
Definition: isams.c:42
int isams_read_item(ISAMS_PP pp, char **dst)
Definition: isams.c:233
BFile bf
Definition: isams.c:48
int block_offset
Definition: isams.c:54
void isams_pp_close(ISAMS_PP pp)
Definition: isams.c:215
char * merge_buf
Definition: isams.c:44
BFile bf_open(BFiles bfs, const char *name, int block_size, int wflag)
opens and returns a Block file handle
Definition: bfile.c:261
void(* encode)(void *p, char **dst, const char **src)
Definition: isam-codec.h:27
void * decodeClientData
Definition: isams.c:56
int isams_close(ISAMS is)
Definition: isams.c:99