Fixed bug #454: Indexing with grs.regx much slower than version 1.3.32.
[idzebra-moved-to-github.git] / index / reckeys.c
1 /* $Id: reckeys.c,v 1.5 2006-05-22 13:28:00 adam Exp $
2    Copyright (C) 1995-2006
3    Index Data ApS
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <ctype.h>
27
28 #include <yaz/nmem.h>
29 #include "index.h"
30 #include "reckeys.h"
31
32 struct zebra_rec_key_entry {
33     char *buf;
34     size_t len;
35     struct it_key key;
36     struct zebra_rec_key_entry *next;
37 };
38
39 struct zebra_rec_keys_t_ {
40     size_t buf_used;
41     size_t buf_max;
42     size_t fetch_offset;
43     char *buf;
44     void *encode_handle;
45     void *decode_handle;
46     char owner_of_buffer;
47
48     NMEM nmem;
49     size_t hash_size;
50     struct zebra_rec_key_entry **entries; 
51 };
52
53
54 struct zebra_rec_key_entry **zebra_rec_keys_mk_hash(zebra_rec_keys_t p,
55                                                     const char *buf,
56                                                     size_t len,
57                                                     const struct it_key *key)
58 {
59     unsigned h = 0;
60     size_t i;
61     for (i = 0; i<len; i++)
62         h = h * 65509 + buf[i];
63     for (i = 0; i<key->len; i++)
64         h = h * 65509 + key->mem[i];
65     return &p->entries[h % (unsigned) p->hash_size];
66 }
67
68 static void init_hash(zebra_rec_keys_t p)
69 {
70     p->entries = 0;
71     nmem_reset(p->nmem);
72     if (p->hash_size)
73     {
74         size_t i;
75         p->entries = nmem_malloc(p->nmem, p->hash_size * sizeof(*p->entries));
76         for (i = 0; i<p->hash_size; i++)
77             p->entries[i] = 0;
78     }
79 }
80
81 zebra_rec_keys_t zebra_rec_keys_open()
82 {
83     zebra_rec_keys_t p = xmalloc(sizeof(*p));
84     p->buf_used = 0;
85     p->buf_max = 0;
86     p->fetch_offset = 0;
87     p->buf = 0;
88     p->owner_of_buffer = 1;
89     p->encode_handle = iscz1_start();
90     p->decode_handle = iscz1_start(); 
91
92     p->nmem = nmem_create();
93     p->hash_size = 1023;
94     p->entries = 0;
95
96     init_hash(p);
97
98     return p;
99 }
100
101 void zebra_rec_keys_set_buf(zebra_rec_keys_t p, char *buf, size_t sz,
102                             int copy_buf)
103 {
104     if (p->owner_of_buffer)
105         xfree(p->buf);
106     p->buf_used = sz;
107     p->buf_max = sz;
108     if (!copy_buf)
109     {
110         p->buf = buf;
111     }
112     else
113     {
114         if (!sz)
115             p->buf = 0;
116         else
117         {
118             p->buf = xmalloc(sz);
119             memcpy(p->buf, buf, sz);
120         }
121     }
122     p->owner_of_buffer = copy_buf;
123 }
124         
125 void zebra_rec_keys_get_buf(zebra_rec_keys_t p, char **buf, size_t *sz)
126 {
127     *buf = p->buf;
128     *sz = p->buf_used;
129
130     p->buf = 0;
131     p->buf_max = 0;
132     p->buf_used = 0;
133 }
134
135 void zebra_rec_keys_close(zebra_rec_keys_t p)
136 {
137     if (!p)
138         return;
139     
140     if (p->owner_of_buffer)
141         xfree(p->buf);
142     if (p->encode_handle)
143         iscz1_stop(p->encode_handle);
144     if (p->decode_handle)
145         iscz1_stop(p->decode_handle);
146     nmem_destroy(p->nmem);
147     xfree(p);
148 }
149
150 int zebra_rec_keys_add_hash(zebra_rec_keys_t keys, 
151                             const char *str, size_t slen,
152                             const struct it_key *key)
153 {
154     struct zebra_rec_key_entry **kep = zebra_rec_keys_mk_hash(keys,
155                                                               str, slen, key);
156     while (*kep)
157     {
158         struct zebra_rec_key_entry *e = *kep;
159         if (slen == e->len && !memcmp(str, e->buf, slen) &&
160             !key_compare(key, &e->key))
161         {
162             return 0;
163         }
164         kep = &(*kep)->next;
165     }
166     *kep = nmem_malloc(keys->nmem, sizeof(**kep));
167     (*kep)->next = 0;
168     (*kep)->len = slen;
169     memcpy(&(*kep)->key, key, sizeof(*key));
170     (*kep)->buf = nmem_malloc(keys->nmem, slen);
171     memcpy((*kep)->buf, str, slen);
172     return 1;
173 }
174
175 void zebra_rec_keys_write(zebra_rec_keys_t keys, 
176                           const char *str, size_t slen,
177                           const struct it_key *key)
178 {
179     char *dst;
180     const char *src = (char*) key;
181     
182     assert(keys->owner_of_buffer);
183
184     if (!zebra_rec_keys_add_hash(keys, str, slen, key))
185         return;  /* key already there . Omit it */
186     if (keys->buf_used+1024 > keys->buf_max)
187     {
188         char *b = (char *) xmalloc (keys->buf_max += 128000);
189         if (keys->buf_used > 0)
190             memcpy (b, keys->buf, keys->buf_used);
191         xfree (keys->buf);
192         keys->buf = b;
193     }
194     dst = keys->buf + keys->buf_used;
195
196     iscz1_encode(keys->encode_handle, &dst, &src);
197
198     memcpy (dst, str, slen);
199     dst += slen;
200     *dst++ = '\0';
201     keys->buf_used = dst - keys->buf;
202 }
203
204 void zebra_rec_keys_reset(zebra_rec_keys_t keys)
205 {
206     assert(keys);
207     keys->buf_used = 0;
208     
209     iscz1_reset(keys->encode_handle);
210
211     init_hash(keys);
212
213 }
214
215 int zebra_rec_keys_rewind(zebra_rec_keys_t keys)
216 {
217     assert(keys);
218     iscz1_reset(keys->decode_handle);
219     keys->fetch_offset = 0;
220     if (keys->buf_used == 0)
221         return 0;
222     return 1;
223 }
224
225 int zebra_rec_keys_empty(zebra_rec_keys_t keys)
226 {
227     if (keys->buf_used == 0)
228         return 1;
229     return 0;
230 }
231
232 int zebra_rec_keys_read(zebra_rec_keys_t keys,
233                         const char **str, size_t *slen,
234                         struct it_key *key)
235 {
236     assert(keys);
237     if (keys->fetch_offset == keys->buf_used)
238         return 0;
239     else
240     {
241         const char *src = keys->buf + keys->fetch_offset;
242         char *dst = (char*) key;
243         
244         assert (keys->fetch_offset < keys->buf_used);
245
246         /* store the destination key */
247         iscz1_decode(keys->decode_handle, &dst, &src);
248         
249         /* store pointer to string and length of it */
250         *str = src;
251         *slen = strlen(src);
252         src += *slen + 1;
253         
254         keys->fetch_offset = src - keys->buf;
255     }
256     return 1;
257 }
258 /*
259  * Local variables:
260  * c-basic-offset: 4
261  * indent-tabs-mode: nil
262  * End:
263  * vim: shiftwidth=4 tabstop=8 expandtab
264  */
265