2 * Copyright (C) 1994, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.3 1994-09-26 17:11:30 quinn
10 * Revision 1.2 1994/09/26 17:06:35 quinn
13 * Revision 1.1 1994/09/26 16:07:56 quinn
14 * Most of the functionality in place.
19 * This module accesses and rearranges the records of the tables.
29 int is_mbuf_size[3] = { 0, 1024, 4096 };
32 * TODO: make internal memory-management scheme for these units.
35 is_mblock *xmalloc_mblock()
39 tmp = xmalloc(sizeof(is_mblock));
44 is_mbuf *xmalloc_mbuf(int type)
48 tmp = xmalloc(sizeof(is_mbuf) + is_mbuf_size[type]);
50 tmp->refcount = type ? 1 : 0;
51 tmp->offset = tmp->num = tmp->cur_record = 0;
52 tmp->data = (char*) tmp + sizeof(is_mbuf);
58 void xfree_mblock(is_mblock *p)
65 void xfree_mbuf(is_mblock *p)
71 void is_m_establish_tab(ISAM is, is_mtable *tab, ISAM_P pos)
73 tab->data = xmalloc_mblock();
76 tab->pos_type = is_type(pos);
77 tab->num_records = -1;
78 tab->data->num_records = -1;
79 tab->data->diskpos = is_block(pos);
80 tab->data->state = IS_MBSTATE_UNREAD;
82 tab->cur_mblock = tab->data;
83 tab->cur_mblock->cur_mbuf = 0;
89 tab->data->num_records = 0;
90 tab->data->diskpos = -1;
91 tab->data->state = IS_MBSTATE_CLEAN;
92 tab->data->data = xmalloc_mbuf(IS_MBUF_TYPE_LARGE);
93 tab->cur_mblock = tab->data;
94 tab->cur_mblock->cur_mbuf = tab->data->data;
95 tab->cur_mblock->cur_mbuf->cur_record = 0;
100 void is_m_rewind(is_mtable *tab)
102 tab->cur_mblock = tab->data;
105 tab->data->cur_mbuf = tab->data->data;
107 tab->data->data->cur_record = 0;
111 static int read_current_full(is_mtable *tab, is_mblock *mblock)
113 if (is_p_read_full(tab, mblock) < 0)
115 if (mblock->nextpos && !mblock->next)
117 mblock->next = xmalloc_mblock();
118 mblock->next->diskpos = mblock->nextpos;
119 mblock->next->state = IS_MBSTATE_UNREAD;
120 mblock->next->data = 0;
122 mblock->cur_mbuf = mblock->data;
123 mblock->data->cur_record = 0;
127 int is_m_read_full(is_mtable *tab, is_mblock *mblock)
129 return read_current_full(tab, mblock);
133 * replace the record right behind the pointer.
135 void is_m_replace_record(is_mtable *tab, const void *rec)
137 is_mbuf *mbuf = tab->cur_mblock->cur_mbuf;
139 /* we assume that block is already in memory and that we are in the
140 * right mbuf, and that it has space for us. */
141 memcpy(mbuf->data + mbuf->offset + (mbuf->cur_record - 1) *
142 is_keysize(tab->is), rec, is_keysize(tab->is));
143 tab->cur_mblock->state = IS_MBSTATE_DIRTY;
147 * Delete the record right behind the pointer.
149 void is_m_delete_record(is_mtable *tab)
153 mbuf = tab->cur_mblock->cur_mbuf;
154 if (mbuf->cur_record >= mbuf->num) /* top of mbuf */
159 else /* middle of a block */
161 new = xmalloc_mbuf(IS_MBUF_TYPE_SMALL);
162 new->next = mbuf->next;
164 new->data = mbuf->data;
166 new->offset = mbuf->offset + mbuf->cur_record * is_keysize(tab->is);
167 new->num = mbuf->num - mbuf->cur_record;
168 mbuf->num = mbuf->cur_record -1;
170 mbuf->cur_record = 0;
173 tab->cur_mblock->num_records--;
174 tab->cur_mblock->state = tab->data->state = IS_MBSTATE_DIRTY;
177 int is_m_write_record(is_mtable *tab, const void *rec)
179 is_mbuf *mbuf, *oldnext, *dmbuf;
181 /* make sure block is all in memory */
182 if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
183 if (read_current_full(tab, tab->cur_mblock) < 0)
185 mbuf = tab->cur_mblock->cur_mbuf;
186 if (mbuf->cur_record >= mbuf->num) /* top of mbuf */
188 /* mbuf is reference or full */
189 if (mbuf->refcount != 1 || mbuf->offset + (mbuf->num + 1) *
190 is_keysize(tab->is) > is_mbuf_size[mbuf->type])
192 oldnext = mbuf->next;
193 mbuf->next = xmalloc_mbuf(IS_MBUF_TYPE_LARGE);
194 mbuf->next->next = oldnext;
196 tab->cur_mblock->cur_mbuf = mbuf;
197 mbuf->cur_record = 0;
202 oldnext = mbuf->next;
203 mbuf->next = xmalloc_mbuf(IS_MBUF_TYPE_MEDIUM);
204 mbuf->next->next = dmbuf = xmalloc_mbuf(IS_MBUF_TYPE_SMALL);
205 dmbuf->data = mbuf->data;
206 dmbuf->next = oldnext;
207 dmbuf->offset = mbuf->offset + mbuf->cur_record * is_keysize(tab->is);
208 dmbuf->num = mbuf->num - mbuf->cur_record;
209 mbuf->num -= dmbuf->num;
211 mbuf = tab->cur_mblock->cur_mbuf = mbuf->next;
212 mbuf->cur_record = 0;
214 log(LOG_DEBUG, "is_m_write_rec(rec == %d)", mbuf->cur_record);
215 memcpy(mbuf->data + mbuf->offset + mbuf->cur_record * is_keysize(tab->is),
216 rec, is_keysize(tab->is));
220 tab->cur_mblock->num_records++;
221 tab->cur_mblock->state = tab->data->state = IS_MBSTATE_DIRTY;
225 void is_m_unread_record(is_mtable *tab)
227 assert(tab->cur_mblock->cur_mbuf->cur_record);
228 tab->cur_mblock->cur_mbuf->cur_record--;
232 * non-destructive read.
234 int is_m_peek_record(is_mtable *tab, void *rec)
238 /* make sure block is all in memory */
239 if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
240 if (read_current_full(tab, tab->cur_mblock) < 0)
242 mbuf = tab->cur_mblock->cur_mbuf;
243 if (mbuf->cur_record >= mbuf->num) /* are we at end of mbuf? */
245 if (!mbuf->next) /* end of mblock */
247 if (tab->cur_mblock->next)
249 tab->cur_mblock = tab->cur_mblock->next;
250 if (tab->cur_mblock->next->state <= IS_MBSTATE_PARTIAL)
251 if (read_current_full(tab, tab->cur_mblock->next) < 0)
253 mbuf = tab->cur_mblock->next->data;
256 return 0; /* EOTable */
260 mbuf->cur_record = 0;
262 memcpy(rec, mbuf->data + mbuf->offset + mbuf->cur_record *
263 is_keysize(tab->is), is_keysize(tab->is));
267 int is_m_read_record(is_mtable *tab, void *buf)
271 /* make sure block is all in memory */
272 if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
273 if (read_current_full(tab, tab->cur_mblock) < 0)
275 mbuf = tab->cur_mblock->cur_mbuf;
276 if (mbuf->cur_record >= mbuf->num) /* are we at end of mbuf? */
278 if (!mbuf->next) /* end of mblock */
280 if (tab->cur_mblock->next)
282 tab->cur_mblock = tab->cur_mblock->next;
283 if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
284 if (read_current_full(tab, tab->cur_mblock) < 0)
286 tab->cur_mblock->cur_mbuf = mbuf = tab->cur_mblock->data;
289 return 0; /* EOTable */
292 tab->cur_mblock->cur_mbuf = mbuf = mbuf->next;
293 mbuf->cur_record = 0;
295 memcpy(buf, mbuf->data + mbuf->offset + mbuf->cur_record *
296 is_keysize(tab->is), is_keysize(tab->is));
302 * TODO: optimize this function by introducing a higher-level search.
304 int is_m_seek_record(is_mtable *tab, const void *rec)
306 char peek[IS_MAX_RECORD];
311 if (is_m_read_record(tab, &peek) <= 0)
313 if ((rs = (*tab->is->cmp)(peek, rec)) > 0)
315 is_m_unread_record(tab);