2 * Copyright (c) 1995-1996, Index Data.
3 * See the file LICENSE for details.
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.3 1996-11-01 08:59:14 adam
8 * First version of isc_merge that supports update/delete.
10 * Revision 1.2 1996/10/29 16:44:56 adam
13 * Revision 1.1 1996/10/29 13:40:48 adam
20 * small/empty blocks aren't handled in isc_merge.
21 * delete/update optimization of same key.
22 * implementation of isc_numkeys
32 ISAMC_M isc_getmethod (void)
34 static struct ISAMC_filecat_s def_cat[] = {
36 { 512, 490, 100, 20 },
37 { 4096, 3950, 1000, 20 },
38 {32768, 32000, 10000, 0 },
41 ISAMC_M m = xmalloc (sizeof(*m));
48 m->compare_item = NULL;
56 ISAMC isc_open (const char *name, int writeflag, ISAMC_M method)
59 ISAMC_filecat filecat;
63 is = xmalloc (sizeof(*is));
65 is->method = xmalloc (sizeof(*is->method));
66 memcpy (is->method, method, sizeof(*method));
67 filecat = is->method->filecat;
70 /* determine number of block categories */
71 if (is->method->debug)
72 logf (LOG_LOG, "isc: bsize ifill mfill mblocks");
73 for (i = 0; filecat[i].bsize; i++)
75 if (is->method->debug)
76 logf (LOG_LOG, "isc:%6d %6d %6d %6d",
77 filecat[i].bsize, filecat[i].ifill,
78 filecat[i].mfill, filecat[i].mblocks);
79 if (max_buf_size < filecat[i].mblocks * filecat[i].bsize)
80 max_buf_size = filecat[i].mblocks * filecat[i].bsize;
84 /* max_buf_size is the larget buffer to be used during merge */
85 max_buf_size = (1 + max_buf_size / filecat[i].bsize) * filecat[i].bsize;
86 if (is->method->debug)
87 logf (LOG_LOG, "isc: max_buf_size %d", max_buf_size);
89 assert (is->no_files > 0);
90 is->files = xmalloc (sizeof(*is->files)*is->no_files);
92 is->merge_buf = xmalloc (max_buf_size+128);
95 for (i = 0; i<is->no_files; i++)
99 sprintf (fname, "%s%c", name, i+'A');
100 is->files[i].bf = bf_open (fname, is->method->filecat[i].bsize,
102 is->files[i].head_is_dirty = 0;
103 if (!bf_read (is->files[i].bf, 0, 0, sizeof(ISAMC_head),
106 is->files[i].head.lastblock = 1;
107 is->files[i].head.freelist = 0;
109 is->files[i].no_writes = 0;
110 is->files[i].no_reads = 0;
111 is->files[i].no_skip_writes = 0;
112 is->files[i].no_allocated = 0;
113 is->files[i].no_released = 0;
114 is->files[i].no_remap = 0;
119 int isc_close (ISAMC is)
123 if (is->method->debug)
124 logf (LOG_LOG, "isc: writes reads skipped alloc released remap");
125 for (i = 0; i<is->no_files; i++)
127 assert (is->files[i].bf);
128 if (is->files[i].head_is_dirty)
129 bf_write (is->files[i].bf, 0, 0, sizeof(ISAMC_head),
131 if (is->method->debug)
132 logf (LOG_LOG, "isc:%8d%8d%8d%8d%8d%8d",
133 is->files[i].no_writes,
134 is->files[i].no_reads,
135 is->files[i].no_skip_writes,
136 is->files[i].no_allocated,
137 is->files[i].no_released,
138 is->files[i].no_remap);
139 bf_close (is->files[i].bf);
142 xfree (is->merge_buf);
147 int isc_read_block (ISAMC is, int cat, int pos, char *dst)
149 ++(is->files[cat].no_reads);
150 if (is->method->debug > 2)
151 logf (LOG_LOG, "isc: read_block %d %d", cat, pos);
152 return bf_read (is->files[cat].bf, pos, 0, 0, dst);
155 int isc_write_block (ISAMC is, int cat, int pos, char *src)
157 ++(is->files[cat].no_writes);
158 if (is->method->debug > 2)
159 logf (LOG_LOG, "isc: write_block %d %d", cat, pos);
160 return bf_write (is->files[cat].bf, pos, 0, 0, src);
163 int isc_write_dblock (ISAMC is, int cat, int pos, char *src,
164 int nextpos, int offset)
166 int xoffset = offset + 2*sizeof(int);
167 if (is->method->debug > 2)
168 logf (LOG_LOG, "isc: write_dblock. size=%d nextpos=%d",
170 memcpy (src - sizeof(int)*2, &nextpos, sizeof(int));
171 memcpy (src - sizeof(int), &xoffset, sizeof(int));
172 return isc_write_block (is, cat, pos, src - sizeof(int)*2);
175 int isc_alloc_block (ISAMC is, int cat)
178 char buf[sizeof(int)];
180 is->files[cat].head_is_dirty = 1;
181 (is->files[cat].no_allocated)++;
182 if ((block = is->files[cat].head.freelist))
184 bf_read (is->files[cat].bf, block, 0, sizeof(int), buf);
185 memcpy (&is->files[cat].head.freelist, buf, sizeof(int));
188 block = (is->files[cat].head.lastblock)++;
189 if (is->method->debug > 2)
190 logf (LOG_LOG, "isc: alloc_block in cat %d: %d", cat, block);
194 void isc_release_block (ISAMC is, int cat, int pos)
196 char buf[sizeof(int)];
198 (is->files[cat].no_released)++;
199 is->files[cat].head_is_dirty = 1;
200 memcpy (buf, &is->files[cat].head.freelist, sizeof(int));
201 is->files[cat].head.freelist = pos;
202 bf_write (is->files[cat].bf, pos, 0, sizeof(int), buf);
203 if (is->method->debug > 2)
204 logf (LOG_LOG, "isc: release_block in cat %d: %d", cat, pos);
207 void isc_pp_close (ISAMC_PP pp)
211 (*is->method->code_stop)(ISAMC_DECODE, pp->decodeClientData);
216 ISAMC_PP isc_pp_open (ISAMC is, ISAMC_P ipos)
218 ISAMC_PP pp = xmalloc (sizeof(*pp));
221 pp->cat = isc_type(ipos);
222 pp->next = isc_block(ipos);
224 src = pp->buf = xmalloc (is->method->filecat[pp->cat].bsize);
230 pp->decodeClientData = (*is->method->code_start)(ISAMC_DECODE);
235 /* returns non-zero if item could be read; 0 otherwise */
236 int isc_read_key (ISAMC_PP pp, void *buf)
238 return isc_read_item (pp, (char **) &buf);
241 /* returns non-zero if item could be read; 0 otherwise */
242 int isc_read_item (ISAMC_PP pp, char **dst)
245 char *src = pp->buf + pp->offset;
247 if (pp->offset >= pp->size)
253 isc_read_block (is, pp->cat, pp->pos, src);
254 memcpy (&pp->next, src, sizeof(pp->next));
255 src += sizeof(pp->next);
256 memcpy (&pp->size, src, sizeof(pp->size));
257 src += sizeof(pp->size);
258 /* assume block is non-empty */
259 assert (pp->next != pp->pos);
261 isc_release_block (is, pp->cat, pp->pos);
262 (*is->method->code_item)(ISAMC_DECODE, pp->decodeClientData, dst, &src);
263 pp->offset = src - pp->buf;
266 (*is->method->code_item)(ISAMC_DECODE, pp->decodeClientData, dst, &src);
267 pp->offset = src - pp->buf;
271 int isc_numkeys (ISAMC_PP pp)