12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
/* functions on blocks; Keys and records are saved in blocks */
18
#include "heap_priv.h"
23
21
Find record according to record-position.
25
The record is located by factoring position number pos into (p_0, p_1, ...)
23
The record is located by factoring position number pos into (p_0, p_1, ...)
27
25
pos = SUM_i(block->level_info[i].records_under_level * p_i)
28
26
{p_0, p_1, ...} serve as indexes to descend the blocks tree.
31
unsigned char *hp_find_block(HP_BLOCK *block, uint32_t pos)
29
uchar *hp_find_block(HP_BLOCK *block, uint32_t pos)
34
HP_PTRS *ptr; /* block base ptr */
32
register HP_PTRS *ptr; /* block base ptr */
36
for (i= block->levels-1, ptr=block->root ; i > 0 ; i--)
34
for (i=block->levels-1, ptr=block->root ; i > 0 ; i--)
38
36
ptr=(HP_PTRS*)ptr->blocks[pos/block->level_info[i].records_under_level];
39
37
pos%=block->level_info[i].records_under_level;
41
return (unsigned char*) ptr+ pos*block->recbuffer;
39
return (uchar*) ptr+ pos*block->recbuffer;
69
67
Allocate space for leaf block plus space for upper level blocks up to
70
first level that has a free slot to put the pointer.
68
first level that has a free slot to put the pointer.
71
69
In some cases we actually allocate more then we need:
72
70
Consider e.g. a situation where we have one level 1 block and one level 0
73
block, the level 0 block is full and this function is called. We only
74
need a leaf block in this case. Nevertheless, we will get here with i=1
75
and will also allocate sizeof(HP_PTRS) for non-leaf block and will never
71
block, the level 0 block is full and this function is called. We only
72
need a leaf block in this case. Nevertheless, we will get here with i=1
73
and will also allocate sizeof(HP_PTRS) for non-leaf block and will never
77
This doesn't add much overhead - with current values of sizeof(HP_PTRS)
75
This doesn't add much overhead - with current values of sizeof(HP_PTRS)
78
76
and my_default_record_cache_size we get about 1/128 unused memory.
80
78
*alloc_length=sizeof(HP_PTRS)*i+block->records_in_block* block->recbuffer;
81
if (!(root=(HP_PTRS*) malloc(*alloc_length)))
79
if (!(root=(HP_PTRS*) my_malloc(*alloc_length,MYF(MY_WME))))
103
101
/* Occupy the free slot we've found at level i */
104
102
block->level_info[i].last_blocks->
105
103
blocks[HP_PTRS_IN_NOD - block->level_info[i].free_ptrs_in_block--]=
106
(unsigned char*) root;
108
106
/* Add a block subtree with each node having one left-most child */
109
for (uint32_t j= i-1 ; j >0 ; j--)
107
for (j=i-1 ; j >0 ; j--)
111
109
block->level_info[j].last_blocks= root++;
112
block->level_info[j].last_blocks->blocks[0]=(unsigned char*) root;
110
block->level_info[j].last_blocks->blocks[0]=(uchar*) root;
113
111
block->level_info[j].free_ptrs_in_block=HP_PTRS_IN_NOD-1;
117
115
root now points to last (block->records_in_block* block->recbuffer)
118
116
allocated bytes. Use it as a leaf block.
126
124
/* free all blocks under level */
128
unsigned char *hp_free_level(HP_BLOCK *block, uint32_t level, HP_PTRS *pos, unsigned char *last_pos)
126
uchar *hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, uchar *last_pos)
131
unsigned char *next_ptr;
135
next_ptr=(unsigned char*) pos+block->recbuffer;
132
next_ptr=(uchar*) pos+block->recbuffer;
139
135
max_pos= (block->level_info[level-1].last_blocks == pos) ?
140
136
HP_PTRS_IN_NOD - block->level_info[level-1].free_ptrs_in_block :
143
next_ptr=(unsigned char*) (pos+1);
144
for (int i= 0; i < max_pos ; i++)
139
next_ptr=(uchar*) (pos+1);
140
for (i=0 ; i < max_pos ; i++)
145
141
next_ptr=hp_free_level(block,level-1,
146
142
(HP_PTRS*) pos->blocks[i],next_ptr);
149
if ((unsigned char*) pos != last_pos)
144
if ((uchar*) pos != last_pos)
151
free((unsigned char*) pos);
146
my_free((uchar*) pos,MYF(0));
154
149
return next_ptr; /* next memory position */