87
89
The allocation and contents of the actual chunks varies between
88
90
fixed and variable-size modes. Total chunk length is always
89
aligned to the next sizeof(uchar*). Here is the format of
91
aligned to the next sizeof(unsigned char*). Here is the format of
91
uchar[] - sizeof=chunk_dataspace_length, but at least
92
sizeof(uchar*) bytes. Keeps actual data or pointer
93
unsigned char[] - sizeof=chunk_dataspace_length, but at least
94
sizeof(unsigned char*) bytes. Keeps actual data or pointer
93
95
to the next deleted chunk.
94
96
chunk_dataspace_length equals to full record length
95
uchar - status field (1 means "in use", 0 means "deleted")
97
unsigned char - status field (1 means "in use", 0 means "deleted")
96
98
Variable-size uses different format:
97
uchar[] - sizeof=chunk_dataspace_length, but at least
98
sizeof(uchar*) bytes. Keeps actual data or pointer
99
unsigned char[] - sizeof=chunk_dataspace_length, but at least
100
sizeof(unsigned char*) bytes. Keeps actual data or pointer
99
101
to the next deleted chunk.
100
102
chunk_dataspace_length is set according to table
101
103
setup (block_size)
102
uchar* - pointer to the next chunk in this chunkset,
104
unsigned char* - pointer to the next chunk in this chunkset,
103
105
or NULL for the last chunk
104
uchar - status field (1 means "first", 0 means "deleted",
106
unsigned char - status field (1 means "first", 0 means "deleted",
105
107
2 means "linked")
107
109
When allocating a new chunkset of N chunks, Heap Engine will try
112
114
Freeing chunks will place them at the front of free list
113
115
referenced by del_link in HP_DATASPACE. The newly freed chunk
114
116
will contain reference to the previously freed chunk in its first
115
sizeof(uchar*) of the payload space.
117
sizeof(unsigned char*) of the payload space.
117
119
Here is open issues:
118
120
1. It is not very nice to require people to keep key columns
144
146
5. In variable-size format status should be moved to lower
145
147
bits of the "next" pointer. Pointer is always aligned
146
to sizeof(uchar*), which is at least 4, leaving 2 lower
148
to sizeof(unsigned char*), which is at least 4, leaving 2 lower
147
149
bits free. This will save 8 bytes per chunk
148
150
on 64-bit platform.
149
151
6. As we do not want to modify FRM format, BLOCK_SIZE option
167
169
if (info->block.levels)
169
VOID(hp_free_level(&info->block,info->block.levels,info->block.root,
171
hp_free_level(&info->block,info->block.levels,info->block.root,
172
174
info->block.levels=0;
173
175
info->del_chunk_count= info->chunk_count= 0;
189
191
@return Pointer to the first chunk in the new or updated chunkset, or NULL if unsuccessful
192
static uchar *hp_allocate_variable_chunkset(HP_DATASPACE *info,
193
uint chunk_count, uchar* existing_set)
194
static unsigned char *hp_allocate_variable_chunkset(HP_DATASPACE *info,
195
uint32_t chunk_count, unsigned char* existing_set)
195
197
int alloc_count= chunk_count, i;
196
uchar *first_chunk= 0, *curr_chunk= 0, *prev_chunk= 0, *last_existing_chunk= 0;
198
unsigned char *first_chunk= 0, *curr_chunk= 0, *prev_chunk= 0, *last_existing_chunk= 0;
198
200
assert(alloc_count);
216
218
/* We came through all chunks and there is more left, let's truncate the list */
217
*((uchar**)(prev_chunk + info->offset_link)) = NULL;
219
*((unsigned char**)(prev_chunk + info->offset_link)) = NULL;
218
220
hp_free_chunks(info, curr_chunk);
238
240
/* Truncate whatever was added at the end of the existing chunkset */
239
241
prev_chunk= last_existing_chunk;
240
curr_chunk= *((uchar**)(prev_chunk + info->offset_link));
241
*((uchar**)(prev_chunk + info->offset_link)) = NULL;
242
curr_chunk= *((unsigned char**)(prev_chunk + info->offset_link));
243
*((unsigned char**)(prev_chunk + info->offset_link)) = NULL;
242
244
hp_free_chunks(info, curr_chunk);
244
246
else if (first_chunk)
253
255
/* mark as if this chunk is last in the chunkset */
254
*((uchar**) (curr_chunk + info->offset_link))= 0;
256
*((unsigned char**) (curr_chunk + info->offset_link))= 0;
258
260
/* tie them into a linked list */
259
*((uchar**) (prev_chunk + info->offset_link))= curr_chunk;
261
*((unsigned char**) (prev_chunk + info->offset_link))= curr_chunk;
260
262
curr_chunk[info->offset_status]= CHUNK_STATUS_LINKED; /* Record linked from active */
287
289
@return Pointer to the first chunk in the new or updated chunkset, or NULL if unsuccessful
290
uchar *hp_allocate_chunkset(HP_DATASPACE *info, uint chunk_count)
292
unsigned char *hp_allocate_chunkset(HP_DATASPACE *info, uint32_t chunk_count)
294
unsigned char* result;
295
297
if (info->is_variable_size)
323
325
@return Error code or zero if successful
326
int hp_reallocate_chunkset(HP_DATASPACE *info, uint chunk_count, uchar* pos)
328
int hp_reallocate_chunkset(HP_DATASPACE *info, uint32_t chunk_count, unsigned char* pos)
329
331
if (!info->is_variable_size)
331
333
/* Update should never change chunk_count in fixed-size mode */
332
my_errno=HA_ERR_WRONG_COMMAND;
334
errno=HA_ERR_WRONG_COMMAND;
336
338
/* Reallocate never moves the first chunk */
337
339
if (!hp_allocate_variable_chunkset(info, chunk_count, pos))
351
353
@return Pointer to the chunk, or NULL if unsuccessful
354
static uchar *hp_allocate_one_chunk(HP_DATASPACE *info)
356
static unsigned char *hp_allocate_one_chunk(HP_DATASPACE *info)
358
unsigned char* curr_chunk;
357
359
size_t length, block_pos;
359
361
if (info->del_link)
361
363
curr_chunk=info->del_link;
362
info->del_link= *((uchar**) curr_chunk);
364
info->del_link= *((unsigned char**) curr_chunk);
363
365
info->del_chunk_count--;
365
367
return curr_chunk;
396
398
@param pos pointer to the head of the chunkset
399
void hp_free_chunks(HP_DATASPACE *info, uchar *pos)
401
void hp_free_chunks(HP_DATASPACE *info, unsigned char *pos)
401
uchar* curr_chunk= pos;
403
unsigned char* curr_chunk= pos;
403
405
while (curr_chunk) {
404
406
info->del_chunk_count++;
405
*((uchar**) curr_chunk)= info->del_link;
407
*((unsigned char**) curr_chunk)= info->del_link;
406
408
info->del_link= curr_chunk;
408
410
curr_chunk[info->offset_status]= CHUNK_STATUS_DELETED;