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>
26
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
27
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
22
28
uint32_t max_records);
24
#define FIXED_REC_OVERHEAD (sizeof(uchar))
25
#define VARIABLE_REC_OVERHEAD (sizeof(uchar**) + sizeof(uchar))
30
#define FIXED_REC_OVERHEAD (sizeof(unsigned char))
31
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + ALIGN_SIZE(sizeof(unsigned char)))
27
33
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
28
34
#define VARIABLE_MIN_CHUNK_SIZE \
29
((sizeof(uchar**) + VARIABLE_REC_OVERHEAD + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1))
35
((sizeof(unsigned char**) + VARIABLE_REC_OVERHEAD + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1))
32
38
/* 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,
40
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
41
uint32_t columns, HP_COLUMNDEF *columndef,
42
uint32_t max_key_fieldnr, uint32_t key_part_size,
43
uint32_t reclength, uint32_t keys_memory_size,
38
44
uint32_t max_records, uint32_t min_records,
39
45
HP_CREATE_INFO *create_info, HP_SHARE **res)
41
uint i, j, key_segs, max_length, length;
47
uint32_t i, j, key_segs, max_length, length;
42
48
uint32_t max_rows_for_stated_memory;
43
49
HP_SHARE *share= 0;
58
uint chunk_dataspace_length, chunk_length, is_variable_size;
59
uint fixed_data_length, fixed_column_count;
64
size_t chunk_dataspace_length;
65
uint32_t chunk_length, is_variable_size;
66
uint32_t fixed_data_length, fixed_column_count;
60
67
HP_KEYDEF *keyinfo;
62
69
if (create_info->max_chunk_size)
64
uint configured_chunk_size= create_info->max_chunk_size;
71
uint32_t configured_chunk_size= create_info->max_chunk_size;
66
73
/* 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*)
165
We store unsigned char* del_link inside the data area of deleted records,
166
so the data length should be at least sizeof(unsigned char*)
161
set_if_bigger(chunk_dataspace_length, sizeof (uchar**));
168
set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
163
170
if (is_variable_size)
172
179
/* Align chunk length to the next pointer */
173
chunk_length= (uint) (chunk_length + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
180
chunk_length= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
177
184
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
179
186
memset(&keyinfo->block, 0, sizeof(keyinfo->block));
248
255
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),
259
if (!(share= (HP_SHARE*) malloc(sizeof(HP_SHARE))))
262
memset(share, 0, sizeof(HP_SHARE));
264
if (keys && !(share->keydef= (HP_KEYDEF*) malloc(keys*sizeof(HP_KEYDEF))))
267
memset(share->keydef, 0, keys*sizeof(HP_KEYDEF));
269
if (keys && !(share->keydef->seg= (HA_KEYSEG*) malloc(key_segs*sizeof(HA_KEYSEG))))
271
if (!(share->column_defs= (HP_COLUMNDEF*)
272
malloc(columns*sizeof(HP_COLUMNDEF))))
275
memset(share->column_defs, 0, columns*sizeof(HP_COLUMNDEF));
259
278
Max_records is used for estimating block sizes and for enforcement.
260
279
Calculate the very maximum number of rows (if everything was one chunk) and
261
280
then take either that value or configured max_records (pick smallest one)
263
max_rows_for_stated_memory= (ha_rows) (create_info->max_table_size /
282
max_rows_for_stated_memory= (uint32_t)(create_info->max_table_size /
264
283
(keys_memory_size + chunk_length));
265
max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
284
max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
266
285
max_records : max_rows_for_stated_memory);
268
share->column_defs= (HP_COLUMNDEF*) (share + 1);
269
287
memcpy(share->column_defs, columndef, (size_t) (sizeof(columndef[0]) * columns));
271
share->keydef= (HP_KEYDEF*) (share->column_defs + columns);
272
289
share->key_stat_version= 1;
273
keyseg= (HA_KEYSEG*) (share->keydef + keys);
290
keyseg= keys ? share->keydef->seg : NULL;
274
292
init_block(&share->recordspace.block, chunk_length, min_records, max_records);
276
294
memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
286
304
/* additional HA_KEYTYPE_END keyseg */
287
305
keyseg->type= HA_KEYTYPE_END;
288
keyseg->length= sizeof(uchar*);
306
keyseg->length= sizeof(unsigned char*);
290
308
keyseg->null_bit= 0;
293
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(uchar*),
294
(qsort_cmp2)keys_compare, 1, NULL, NULL);
311
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
312
(qsort_cmp2)keys_compare, true, NULL, NULL);
295
313
keyinfo->delete_key= hp_rb_delete_key;
296
314
keyinfo->write_key= hp_rb_write_key;
330
348
if (is_variable_size) {
331
349
share->recordspace.offset_link= chunk_dataspace_length;
332
share->recordspace.offset_status= share->recordspace.offset_link + sizeof(uchar**);
350
share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
334
352
share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
335
353
share->recordspace.offset_status= chunk_dataspace_length;
338
356
/* Must be allocated separately for rename to work */
339
if (!(share->name= my_strdup(name,MYF(0))))
357
if (!(share->name= strdup(name)))
341
my_free((uchar*) share,MYF(0));
344
361
thr_lock_init(&share->lock);
345
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
362
pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
346
363
if (!create_info->internal_table)
348
share->open_list.data= (void*) share;
349
heap_share_list= list_add(heap_share_list,&share->open_list);
365
heap_share_list.push_front(share);
352
368
share->delete_on_close= 1;
377
if(share && share->keydef && share->keydef->seg)
378
free(share->keydef->seg);
379
if(share && share->keydef)
381
if(share && share->column_defs)
382
free(share->column_defs);
361
385
if (!create_info->internal_table)
362
386
pthread_mutex_unlock(&THR_LOCK_heap);
364
388
} /* heap_create */
367
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
391
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,
393
uint32_t not_used[2];
394
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
371
395
param->search_flag, not_used);
374
static void init_block(HP_BLOCK *block, uint chunk_length, uint32_t min_records,
398
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
375
399
uint32_t max_records)
377
uint i,recbuffer,records_in_block;
401
uint32_t i,recbuffer,records_in_block;
379
403
max_records= max(min_records,max_records);
380
404
if (!max_records)
381
405
max_records= 1000; /* As good as quess as anything */
383
407
/* 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);
408
recbuffer= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
385
409
records_in_block= max_records / 10;
386
410
if (records_in_block < 10 && max_records)
387
411
records_in_block= 10;
441
465
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);
467
heap_share_list.remove(share); /* If not internal table */
445
468
hp_clear(share); /* Remove blocks from memory */
446
469
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));
470
pthread_mutex_destroy(&share->intern_lock);
471
if (share->keydef && share->keydef->seg)
472
free(share->keydef->seg);
475
free(share->column_defs);
476
free((unsigned char*) share->name);
477
free((unsigned char*) share);