14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
#include "heapdef.h"
17
#include "libdrizzle/drizzle_com.h"
18
#include "drizzled/error.h"
20
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2);
21
static void init_block(HP_BLOCK *block,uint chunk_length, uint32_t min_records,
18
#include <drizzled/common.h>
19
#include <drizzled/error.h>
23
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
24
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
22
25
uint32_t max_records);
24
#define FIXED_REC_OVERHEAD (sizeof(uchar))
25
#define VARIABLE_REC_OVERHEAD (sizeof(uchar**) + sizeof(uchar))
27
#define FIXED_REC_OVERHEAD (sizeof(unsigned char))
28
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + ALIGN_SIZE(sizeof(unsigned char)))
27
30
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
28
31
#define VARIABLE_MIN_CHUNK_SIZE \
29
((sizeof(uchar**) + VARIABLE_REC_OVERHEAD + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1))
32
((sizeof(unsigned char**) + VARIABLE_REC_OVERHEAD + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1))
32
35
/* Create a heap table */
34
int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
35
uint columns, HP_COLUMNDEF *columndef,
36
uint max_key_fieldnr, uint key_part_size,
37
uint reclength, uint keys_memory_size,
37
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
38
uint32_t columns, HP_COLUMNDEF *columndef,
39
uint32_t max_key_fieldnr, uint32_t key_part_size,
40
uint32_t reclength, uint32_t keys_memory_size,
38
41
uint32_t max_records, uint32_t min_records,
39
42
HP_CREATE_INFO *create_info, HP_SHARE **res)
41
uint i, j, key_segs, max_length, length;
44
uint32_t i, j, key_segs, max_length, length;
42
45
uint32_t max_rows_for_stated_memory;
43
46
HP_SHARE *share= 0;
58
uint chunk_dataspace_length, chunk_length, is_variable_size;
59
uint fixed_data_length, fixed_column_count;
61
size_t chunk_dataspace_length;
62
uint32_t chunk_length, is_variable_size;
63
uint32_t fixed_data_length, fixed_column_count;
60
64
HP_KEYDEF *keyinfo;
62
66
if (create_info->max_chunk_size)
64
uint configured_chunk_size= create_info->max_chunk_size;
68
uint32_t configured_chunk_size= create_info->max_chunk_size;
66
70
/* User requested variable-size records, let's see if they're possible */
158
We store uchar* del_link inside the data area of deleted records,
159
so the data length should be at least sizeof(uchar*)
162
We store unsigned char* del_link inside the data area of deleted records,
163
so the data length should be at least sizeof(unsigned char*)
161
set_if_bigger(chunk_dataspace_length, sizeof (uchar**));
165
set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
163
167
if (is_variable_size)
172
176
/* Align chunk length to the next pointer */
173
chunk_length= (uint) (chunk_length + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
177
chunk_length= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
177
181
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
179
183
memset(&keyinfo->block, 0, sizeof(keyinfo->block));
248
252
keyinfo->get_key_length= hp_rb_key_length;
251
if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
252
keys*sizeof(HP_KEYDEF)+
253
columns*sizeof(HP_COLUMNDEF)+
254
key_segs*sizeof(HA_KEYSEG),
256
if (!(share= (HP_SHARE*) malloc(sizeof(HP_SHARE))))
259
memset(share, 0, sizeof(HP_SHARE));
261
if (keys && !(share->keydef= (HP_KEYDEF*) malloc(keys*sizeof(HP_KEYDEF))))
264
memset(share->keydef, 0, keys*sizeof(HP_KEYDEF));
266
if (keys && !(share->keydef->seg= (HA_KEYSEG*) malloc(key_segs*sizeof(HA_KEYSEG))))
268
if (!(share->column_defs= (HP_COLUMNDEF*)
269
malloc(columns*sizeof(HP_COLUMNDEF))))
272
memset(share->column_defs, 0, columns*sizeof(HP_COLUMNDEF));
259
275
Max_records is used for estimating block sizes and for enforcement.
263
279
max_rows_for_stated_memory= (ha_rows) (create_info->max_table_size /
264
280
(keys_memory_size + chunk_length));
265
max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
281
max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
266
282
max_records : max_rows_for_stated_memory);
268
share->column_defs= (HP_COLUMNDEF*) (share + 1);
269
284
memcpy(share->column_defs, columndef, (size_t) (sizeof(columndef[0]) * columns));
271
share->keydef= (HP_KEYDEF*) (share->column_defs + columns);
272
286
share->key_stat_version= 1;
273
keyseg= (HA_KEYSEG*) (share->keydef + keys);
287
keyseg= keys ? share->keydef->seg : NULL;
274
289
init_block(&share->recordspace.block, chunk_length, min_records, max_records);
276
291
memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
286
301
/* additional HA_KEYTYPE_END keyseg */
287
302
keyseg->type= HA_KEYTYPE_END;
288
keyseg->length= sizeof(uchar*);
303
keyseg->length= sizeof(unsigned char*);
290
305
keyseg->null_bit= 0;
293
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(uchar*),
308
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
294
309
(qsort_cmp2)keys_compare, 1, NULL, NULL);
295
310
keyinfo->delete_key= hp_rb_delete_key;
296
311
keyinfo->write_key= hp_rb_write_key;
330
345
if (is_variable_size) {
331
346
share->recordspace.offset_link= chunk_dataspace_length;
332
share->recordspace.offset_status= share->recordspace.offset_link + sizeof(uchar**);
347
share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
334
349
share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
335
350
share->recordspace.offset_status= chunk_dataspace_length;
338
353
/* Must be allocated separately for rename to work */
339
if (!(share->name= my_strdup(name,MYF(0))))
354
if (!(share->name= strdup(name)))
341
my_free((uchar*) share,MYF(0));
344
358
thr_lock_init(&share->lock);
345
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
359
pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
346
360
if (!create_info->internal_table)
348
share->open_list.data= (void*) share;
349
heap_share_list= list_add(heap_share_list,&share->open_list);
362
heap_share_list.push_front(share);
352
365
share->delete_on_close= 1;
374
if(share && share->keydef && share->keydef->seg)
375
free(share->keydef->seg);
376
if(share && share->keydef)
378
if(share && share->column_defs)
379
free(share->column_defs);
361
382
if (!create_info->internal_table)
362
383
pthread_mutex_unlock(&THR_LOCK_heap);
364
385
} /* heap_create */
367
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
388
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
370
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
390
uint32_t not_used[2];
391
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
371
392
param->search_flag, not_used);
374
static void init_block(HP_BLOCK *block, uint chunk_length, uint32_t min_records,
395
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
375
396
uint32_t max_records)
377
uint i,recbuffer,records_in_block;
398
uint32_t i,recbuffer,records_in_block;
379
max_records= max(min_records,max_records);
400
max_records= cmax(min_records,max_records);
380
401
if (!max_records)
381
402
max_records= 1000; /* As good as quess as anything */
383
404
/* we want to start each chunk at 8 bytes boundary, round recbuffer to the next 8 */
384
recbuffer= (uint) (chunk_length + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
405
recbuffer= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
385
406
records_in_block= max_records / 10;
386
407
if (records_in_block < 10 && max_records)
387
408
records_in_block= 10;
441
462
void hp_free(HP_SHARE *share)
443
if (share->open_list.data) /* If not internal table */
444
heap_share_list= list_delete(heap_share_list, &share->open_list);
464
heap_share_list.remove(share); /* If not internal table */
445
465
hp_clear(share); /* Remove blocks from memory */
446
466
thr_lock_delete(&share->lock);
447
VOID(pthread_mutex_destroy(&share->intern_lock));
448
my_free((uchar*) share->name, MYF(0));
449
my_free((uchar*) share, MYF(0));
467
pthread_mutex_destroy(&share->intern_lock);
469
free(share->keydef->seg);
472
free(share->column_defs);
473
free((unsigned char*) share->name);
474
free((unsigned char*) share);