13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
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,
16
#include "heap_priv.h"
18
#include <drizzled/common.h>
19
#include <drizzled/error.h>
20
#include "drizzled/my_error.h"
26
using namespace drizzled;
28
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
29
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
22
30
uint32_t max_records);
24
#define FIXED_REC_OVERHEAD (sizeof(uchar))
25
#define VARIABLE_REC_OVERHEAD (sizeof(uchar**) + sizeof(uchar))
32
#define FIXED_REC_OVERHEAD (sizeof(unsigned char))
33
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + ALIGN_SIZE(sizeof(unsigned char)))
27
35
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
28
36
#define VARIABLE_MIN_CHUNK_SIZE \
29
((sizeof(uchar**) + VARIABLE_REC_OVERHEAD + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1))
37
((sizeof(unsigned char**) + VARIABLE_REC_OVERHEAD + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1))
32
40
/* 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,
42
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
43
uint32_t columns, HP_COLUMNDEF *columndef,
44
uint32_t max_key_fieldnr, uint32_t key_part_size,
45
uint32_t reclength, uint32_t keys_memory_size,
38
46
uint32_t max_records, uint32_t min_records,
39
47
HP_CREATE_INFO *create_info, HP_SHARE **res)
41
uint i, j, key_segs, max_length, length;
49
uint32_t i, j, key_segs, max_length, length;
42
50
uint32_t max_rows_for_stated_memory;
43
51
HP_SHARE *share= 0;
58
uint chunk_dataspace_length, chunk_length, is_variable_size;
59
uint fixed_data_length, fixed_column_count;
66
size_t chunk_dataspace_length;
67
uint32_t chunk_length, is_variable_size;
68
uint32_t fixed_data_length, fixed_column_count;
60
69
HP_KEYDEF *keyinfo;
62
71
if (create_info->max_chunk_size)
64
uint configured_chunk_size= create_info->max_chunk_size;
73
uint32_t configured_chunk_size= create_info->max_chunk_size;
66
75
/* 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*)
167
We store unsigned char* del_link inside the data area of deleted records,
168
so the data length should be at least sizeof(unsigned char*)
161
set_if_bigger(chunk_dataspace_length, sizeof (uchar**));
170
set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
163
172
if (is_variable_size)
190
199
keyinfo->rb_tree.size_of_element++;
192
201
switch (keyinfo->seg[j].type) {
193
case HA_KEYTYPE_SHORT_INT:
194
202
case HA_KEYTYPE_LONG_INT:
195
case HA_KEYTYPE_FLOAT:
196
203
case HA_KEYTYPE_DOUBLE:
197
case HA_KEYTYPE_USHORT_INT:
198
204
case HA_KEYTYPE_ULONG_INT:
199
205
case HA_KEYTYPE_LONGLONG:
200
206
case HA_KEYTYPE_ULONGLONG:
201
case HA_KEYTYPE_INT24:
202
207
case HA_KEYTYPE_UINT24:
203
case HA_KEYTYPE_INT8:
204
208
keyinfo->seg[j].flag|= HA_SWAP_KEY;
206
210
case HA_KEYTYPE_VARBINARY1:
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.
260
276
Calculate the very maximum number of rows (if everything was one chunk) and
261
277
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 /
279
max_rows_for_stated_memory= (uint32_t)(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*),
294
(qsort_cmp2)keys_compare, 1, NULL, NULL);
308
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
309
(qsort_cmp2)keys_compare, true, 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
400
max_records= max(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;
388
409
if (!records_in_block || records_in_block*recbuffer >
389
(my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
390
records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
410
(internal::my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
411
records_in_block= (internal::my_default_record_cache_size - sizeof(HP_PTRS) *
391
412
HP_MAX_LEVELS) / recbuffer + 1;
392
413
block->records_in_block= records_in_block;
393
414
block->recbuffer= recbuffer;
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);
468
if (share->keydef && share->keydef->seg)
469
free(share->keydef->seg);
472
free(share->column_defs);
473
free((unsigned char*) share->name);
474
free((unsigned char*) share);