2 * Copyright (C) 1994, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.1 1994-09-26 16:07:56 quinn
8 * Most of the functionality in place.
13 * This module accesses and rearranges the records of the tables.
23 int is_mbuf_size[3] = { 0, 1024, 4096 };
26 * TODO: make internal memory-management scheme for these units.
29 is_mblock *xmalloc_mblock()
33 tmp = xmalloc(sizeof(is_mblock));
38 is_mbuf *xmalloc_mbuf(int type)
42 tmp = xmalloc(sizeof(is_mbuf) + is_mbuf_size[type]);
44 tmp->refcount = type ? 1 : 0;
45 tmp->offset = tmp->num = tmp->cur_record = 0;
46 tmp->data = (char*) tmp + sizeof(is_mbuf);
52 void xfree_mblock(is_mblock *p)
59 void xfree_mbuf(is_mblock *p)
65 void is_m_establish_tab(ISAM is, is_mtable *tab, ISAM_P pos)
67 tab->data = xmalloc_mblock();
70 tab->pos_type = is_type(pos);
71 tab->num_records = -1;
72 tab->data->num_records = -1;
73 tab->data->diskpos = is_block(pos);
74 tab->data->state = IS_MBSTATE_UNREAD;
76 tab->cur_mblock = tab->data;
77 tab->cur_mblock->cur_mbuf = 0;
83 tab->data->num_records = 0;
84 tab->data->diskpos = -1;
85 tab->data->state = IS_MBSTATE_CLEAN;
86 tab->data->data = xmalloc_mbuf(IS_MBUF_TYPE_LARGE);
87 tab->cur_mblock = tab->data;
88 tab->cur_mblock->cur_mbuf = tab->data->data;
89 tab->cur_mblock->cur_mbuf->cur_record = 0;
94 void is_m_rewind(is_mtable *tab)
96 tab->cur_mblock = tab->data;
99 tab->data->cur_mbuf = tab->data->data;
101 tab->data->data->cur_record = 0;
105 static int read_current_full(is_mtable *tab, is_mblock *mblock)
107 if (is_p_read_full(tab, mblock) < 0)
109 if (mblock->nextpos && !mblock->next)
111 mblock->next = xmalloc_mblock();
112 mblock->next->diskpos = mblock->nextpos;
113 mblock->next->state = IS_MBSTATE_UNREAD;
114 mblock->next->data = 0;
116 mblock->cur_mbuf = mblock->data;
117 mblock->data->cur_record = 0;
121 int is_m_read_full(is_mtable *tab, is_mblock *mblock)
123 return read_current_full(tab, mblock);
127 * replace the record right behind the pointer.
129 void is_m_replace_record(is_mtable *tab, const void *rec)
131 is_mbuf *mbuf = tab->cur_mblock->cur_mbuf;
133 /* we assume that block is already in memory and that we are in the
134 * right mbuf, and that it has space for us. */
135 memcpy(mbuf->data + mbuf->offset + (mbuf->cur_record - 1) *
136 is_keysize(tab->is), rec, is_keysize(tab->is));
137 tab->cur_mblock->state = IS_MBSTATE_DIRTY;
141 * Delete the record right behind the pointer.
143 void is_m_delete_record(is_mtable *tab)
147 mbuf = tab->cur_mblock->cur_mbuf;
148 if (mbuf->cur_record >= mbuf->num) /* top of mbuf */
153 else /* middle of a block */
155 new = xmalloc_mbuf(IS_MBUF_TYPE_SMALL);
156 new->next = mbuf->next;
158 new->data = mbuf->data;
160 new->offset = mbuf->offset + mbuf->cur_record * is_keysize(tab->is);
161 new->num = mbuf->num - mbuf->cur_record;
162 mbuf->num = mbuf->cur_record -1;
164 mbuf->cur_record = 0;
167 tab->cur_mblock->num_records--;
168 tab->cur_mblock->state = tab->data->state = IS_MBSTATE_DIRTY;
171 int is_m_write_record(is_mtable *tab, const void *rec)
173 is_mbuf *mbuf, *oldnext, *dmbuf;
175 /* make sure block is all in memory */
176 if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
177 if (read_current_full(tab, tab->cur_mblock) < 0)
179 mbuf = tab->cur_mblock->cur_mbuf;
180 if (mbuf->cur_record >= mbuf->num) /* top of mbuf */
182 /* mbuf is reference or full */
183 if (mbuf->refcount != 1 || mbuf->offset + (mbuf->num + 1) *
184 is_keysize(tab->is) > is_mbuf_size[mbuf->type])
186 oldnext = mbuf->next;
187 mbuf->next = xmalloc_mbuf(IS_MBUF_TYPE_LARGE);
188 mbuf->next->next = oldnext;
190 tab->cur_mblock->cur_mbuf = mbuf;
191 mbuf->cur_record = 0;
196 oldnext = mbuf->next;
197 mbuf->next = xmalloc_mbuf(IS_MBUF_TYPE_MEDIUM);
198 mbuf->next->next = dmbuf = xmalloc_mbuf(IS_MBUF_TYPE_SMALL);
199 dmbuf->data = mbuf->data;
200 dmbuf->next = oldnext;
201 dmbuf->offset = mbuf->offset + mbuf->cur_record * is_keysize(tab->is);
202 dmbuf->num = mbuf->num - mbuf->cur_record;
203 mbuf->num -= dmbuf->num;
205 mbuf = tab->cur_mblock->cur_mbuf = mbuf->next;
206 mbuf->cur_record = 0;
208 log(LOG_DEBUG, "is_m_write_rec(rec == %d)", mbuf->cur_record);
209 memcpy(mbuf->data + mbuf->offset + mbuf->cur_record * is_keysize(tab->is),
210 rec, is_keysize(tab->is));
214 tab->cur_mblock->num_records++;
215 tab->cur_mblock->state = tab->data->state = IS_MBSTATE_DIRTY;
219 void is_m_unread_record(is_mtable *tab)
221 assert(tab->cur_mblock->cur_mbuf->cur_record);
222 tab->cur_mblock->cur_mbuf->cur_record--;
226 * non-destructive read.
228 int is_m_peek_record(is_mtable *tab, void *rec)
232 /* make sure block is all in memory */
233 if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
234 if (read_current_full(tab, tab->cur_mblock) < 0)
236 mbuf = tab->cur_mblock->cur_mbuf;
237 if (mbuf->cur_record >= mbuf->num) /* are we at end of mbuf? */
239 if (!mbuf->next) /* end of mblock */
241 if (tab->cur_mblock->next)
243 tab->cur_mblock = tab->cur_mblock->next;
244 if (tab->cur_mblock->next->state <= IS_MBSTATE_PARTIAL)
245 if (read_current_full(tab, tab->cur_mblock->next) < 0)
247 mbuf = tab->cur_mblock->next->data;
250 return 0; /* EOTable */
254 mbuf->cur_record = 0;
256 memcpy(rec, mbuf->data + mbuf->offset + mbuf->cur_record *
257 is_keysize(tab->is), is_keysize(tab->is));
261 int is_m_read_record(is_mtable *tab, void *buf)
265 /* make sure block is all in memory */
266 if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
267 if (read_current_full(tab, tab->cur_mblock) < 0)
269 mbuf = tab->cur_mblock->cur_mbuf;
270 if (mbuf->cur_record >= mbuf->num) /* are we at end of mbuf? */
272 if (!mbuf->next) /* end of mblock */
274 if (tab->cur_mblock->next)
276 tab->cur_mblock = tab->cur_mblock->next;
277 if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
278 if (read_current_full(tab, tab->cur_mblock) < 0)
280 tab->cur_mblock->cur_mbuf = mbuf = tab->cur_mblock->data;
283 return 0; /* EOTable */
286 tab->cur_mblock->cur_mbuf = mbuf = mbuf->next;
287 mbuf->cur_record = 0;
289 memcpy(buf, mbuf->data + mbuf->offset + mbuf->cur_record *
290 is_keysize(tab->is), is_keysize(tab->is));
296 * TODO: optimize this function by introducing a higher-level search.
298 int is_m_seek_record(is_mtable *tab, const void *rec)
300 char peek[IS_MAX_RECORD];
305 if (is_m_read_record(tab, &peek) <= 0)
307 if ((rs = (*tab->is->cmp)(peek, rec)) > 0)
309 is_m_unread_record(tab);