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
#include "heap_priv.h"
18
18
#include <drizzled/common.h>
19
19
#include <drizzled/error.h>
21
21
#include <string.h>
25
using namespace drizzled;
23
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
27
24
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
28
25
uint32_t max_records);
30
27
#define FIXED_REC_OVERHEAD (sizeof(unsigned char))
31
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + ALIGN_SIZE(sizeof(unsigned char)))
28
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + sizeof(unsigned char))
33
30
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
34
31
#define VARIABLE_MIN_CHUNK_SIZE \
38
35
/* Create a heap table */
40
37
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
42
uint32_t key_part_size,
43
uint32_t reclength, uint32_t keys_memory_size,
44
uint32_t max_records, uint32_t min_records,
45
HP_CREATE_INFO *create_info, HP_SHARE **res)
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,
41
uint32_t max_records, uint32_t min_records,
42
HP_CREATE_INFO *create_info, HP_SHARE **res)
47
uint32_t i, key_segs, max_length, length;
44
uint32_t i, j, key_segs, max_length, length;
48
45
uint32_t max_rows_for_stated_memory;
49
46
HP_SHARE *share= 0;
52
if (not create_info->internal_table)
49
if (!create_info->internal_table)
51
pthread_mutex_lock(&THR_LOCK_heap);
55
52
if ((share= hp_find_named_heap(name)) && share->open_count == 0)
75
71
if (configured_chunk_size < key_part_size)
77
73
/* Eventual chunk_size cannot be smaller than key data,
78
which allows all keys to fit into the first chunk */
74
which allows all keys to fit into the first chunk */
79
75
my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "block_size");
80
THR_LOCK_heap.unlock();
76
pthread_mutex_unlock(&THR_LOCK_heap);
81
77
return(ER_CANT_USE_OPTION_HERE);
84
/* max_chunk_size is near the full reclength, let's use fixed size */
85
chunk_dataspace_length= reclength;
80
if ((reclength - configured_chunk_size) >= VARIABLE_MIN_CHUNK_SIZE<<1)
82
/* Allow variable size only if we're saving at least two smallest chunks */
83
/* There has to be at least one field after indexed fields */
84
/* Note that NULL bits are already included in key_part_size */
86
chunk_dataspace_length= configured_chunk_size;
90
/* max_chunk_size is near the full reclength, let's use fixed size */
92
chunk_dataspace_length= reclength;
95
else if (create_info->is_dynamic)
97
/* User asked for dynamic records - use 256 as the chunk size */
98
if ((key_part_size + VARIABLE_REC_OVERHEAD) > 256)
99
chunk_dataspace_length= key_part_size;
101
chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD;
89
107
/* if max_chunk_size is not specified, put the whole record in one chunk */
90
109
chunk_dataspace_length= reclength;
112
if (is_variable_size)
114
/* Check whether we have any variable size records past key data */
115
uint32_t has_variable_fields= 0;
117
fixed_data_length= key_part_size;
118
fixed_column_count= max_key_fieldnr;
120
for (i= max_key_fieldnr; i < columns; i++)
122
HP_COLUMNDEF* column= columndef + i;
123
if (column->type == DRIZZLE_TYPE_VARCHAR && column->length >= 32)
125
/* The field has to be >= 5.0.3 true VARCHAR and have substantial length */
126
/* TODO: do we want to calculate minimum length? */
127
has_variable_fields= 1;
131
if (has_variable_fields)
136
if ((column->offset + column->length) <= chunk_dataspace_length)
138
/* Still no variable-size columns, add one fixed-length */
139
fixed_column_count= i + 1;
140
fixed_data_length= column->offset + column->length;
144
if (!has_variable_fields)
146
/* There is no need to use variable-size records without variable-size columns */
147
/* Reset sizes if it's not variable size anymore */
149
chunk_dataspace_length= reclength;
150
fixed_data_length= reclength;
151
fixed_column_count= columns;
94
156
fixed_data_length= reclength;
95
157
fixed_column_count= columns;
113
180
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
115
182
memset(&keyinfo->block, 0, sizeof(keyinfo->block));
116
for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
183
memset(&keyinfo->rb_tree , 0, sizeof(keyinfo->rb_tree));
184
for (j= length= 0; j < keyinfo->keysegs; j++)
118
186
length+= keyinfo->seg[j].length;
119
187
if (keyinfo->seg[j].null_bit)
122
190
if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
123
191
keyinfo->flag|= HA_NULL_PART_KEY;
192
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
193
keyinfo->rb_tree.size_of_element++;
125
195
switch (keyinfo->seg[j].type) {
196
case HA_KEYTYPE_SHORT_INT:
126
197
case HA_KEYTYPE_LONG_INT:
198
case HA_KEYTYPE_FLOAT:
127
199
case HA_KEYTYPE_DOUBLE:
200
case HA_KEYTYPE_USHORT_INT:
128
201
case HA_KEYTYPE_ULONG_INT:
129
202
case HA_KEYTYPE_LONGLONG:
130
203
case HA_KEYTYPE_ULONGLONG:
204
case HA_KEYTYPE_INT24:
205
case HA_KEYTYPE_UINT24:
206
case HA_KEYTYPE_INT8:
131
207
keyinfo->seg[j].flag|= HA_SWAP_KEY;
133
209
case HA_KEYTYPE_VARBINARY1:
161
237
keyinfo->length= length;
238
length+= keyinfo->rb_tree.size_of_element +
239
((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(unsigned char*) : 0);
162
240
if (length > max_length)
163
241
max_length= length;
164
242
key_segs+= keyinfo->keysegs;
243
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
245
key_segs++; /* additional HA_KEYTYPE_END segment */
246
if (keyinfo->flag & HA_VAR_LENGTH_KEY)
247
keyinfo->get_key_length= hp_rb_var_key_length;
248
else if (keyinfo->flag & HA_NULL_PART_KEY)
249
keyinfo->get_key_length= hp_rb_null_key_length;
251
keyinfo->get_key_length= hp_rb_key_length;
168
if (keys && !(share->keydef= new HP_KEYDEF[keys]))
170
if (keys && !(share->keydef->seg= new HA_KEYSEG[key_segs]))
254
if (!(share= (HP_SHARE*) malloc(sizeof(HP_SHARE)+
255
keys*sizeof(HP_KEYDEF)+
256
columns*sizeof(HP_COLUMNDEF)+
257
key_segs*sizeof(HA_KEYSEG))))
259
memset(share, 0, sizeof(HP_SHARE)+
260
keys*sizeof(HP_KEYDEF)+
261
columns*sizeof(HP_COLUMNDEF)+
262
key_segs*sizeof(HA_KEYSEG));
174
265
Max_records is used for estimating block sizes and for enforcement.
175
266
Calculate the very maximum number of rows (if everything was one chunk) and
176
267
then take either that value or configured max_records (pick smallest one)
178
max_rows_for_stated_memory= (uint32_t)(create_info->max_table_size /
269
max_rows_for_stated_memory= (ha_rows) (create_info->max_table_size /
179
270
(keys_memory_size + chunk_length));
180
271
max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
181
272
max_records : max_rows_for_stated_memory);
274
share->column_defs= (HP_COLUMNDEF*) (share + 1);
275
memcpy(share->column_defs, columndef, (size_t) (sizeof(columndef[0]) * columns));
277
share->keydef= (HP_KEYDEF*) (share->column_defs + columns);
183
278
share->key_stat_version= 1;
184
keyseg= keys ? share->keydef->seg : NULL;
279
keyseg= (HA_KEYSEG*) (share->keydef + keys);
186
280
init_block(&share->recordspace.block, chunk_length, min_records, max_records);
188
282
memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
192
286
memcpy(keyseg, keydef[i].seg,
193
287
(size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
194
288
keyseg+= keydef[i].keysegs;
290
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
292
/* additional HA_KEYTYPE_END keyseg */
293
keyseg->type= HA_KEYTYPE_END;
294
keyseg->length= sizeof(unsigned char*);
299
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
300
(qsort_cmp2)keys_compare, 1, NULL, NULL);
301
keyinfo->delete_key= hp_rb_delete_key;
302
keyinfo->write_key= hp_rb_write_key;
196
306
init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
308
keyinfo->delete_key= hp_delete_key;
309
keyinfo->write_key= hp_write_key;
198
310
keyinfo->hash_buckets= 0;
200
312
if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
219
331
share->recordspace.chunk_length= chunk_length;
220
332
share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
333
share->recordspace.is_variable_size= is_variable_size;
221
334
share->recordspace.total_data_length= 0;
336
if (is_variable_size) {
337
share->recordspace.offset_link= chunk_dataspace_length;
338
share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
224
340
share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
225
341
share->recordspace.offset_status= chunk_dataspace_length;
228
344
/* Must be allocated separately for rename to work */
229
share->name.append(name);
345
if (!(share->name= strdup(name)))
347
free((unsigned char*) share);
350
thr_lock_init(&share->lock);
351
pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
230
352
if (!create_info->internal_table)
232
heap_share_list.push_front(share);
354
share->open_list.data= (void*) share;
355
heap_share_list= list_add(heap_share_list,&share->open_list);
235
358
share->delete_on_close= 1;
237
360
if (!create_info->internal_table)
238
THR_LOCK_heap.unlock();
361
pthread_mutex_unlock(&THR_LOCK_heap);
244
if (share && share->keydef && share->keydef->seg)
245
delete [] share->keydef->seg;
246
if (share && share->keydef)
247
delete [] share->keydef;
250
if (not create_info->internal_table)
251
THR_LOCK_heap.unlock();
367
if (!create_info->internal_table)
368
pthread_mutex_unlock(&THR_LOCK_heap);
253
370
} /* heap_create */
373
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
375
uint32_t not_used[2];
376
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
377
param->search_flag, not_used);
256
380
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
257
381
uint32_t max_records)
259
uint32_t recbuffer,records_in_block;
383
uint32_t i,recbuffer,records_in_block;
261
max_records= max(min_records,max_records);
385
max_records= cmax(min_records,max_records);
262
386
if (!max_records)
263
387
max_records= 1000; /* As good as quess as anything */
268
392
if (records_in_block < 10 && max_records)
269
393
records_in_block= 10;
270
394
if (!records_in_block || records_in_block*recbuffer >
271
(internal::my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
272
records_in_block= (internal::my_default_record_cache_size - sizeof(HP_PTRS) *
395
(my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
396
records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
273
397
HP_MAX_LEVELS) / recbuffer + 1;
274
398
block->records_in_block= records_in_block;
275
399
block->recbuffer= recbuffer;
276
400
block->last_allocated= 0L;
278
for (uint32_t i= 0; i <= HP_MAX_LEVELS; i++)
402
for (i= 0; i <= HP_MAX_LEVELS; i++)
280
403
block->level_info[i].records_under_level=
281
404
(!i ? 1 : i == 1 ? records_in_block :
282
405
HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
309
result= errno=ENOENT;
431
result= my_errno=ENOENT;
311
THR_LOCK_heap.unlock();
433
pthread_mutex_unlock(&THR_LOCK_heap);
438
void heap_drop_table(HP_INFO *info)
440
pthread_mutex_lock(&THR_LOCK_heap);
441
heap_try_free(info->s);
442
pthread_mutex_unlock(&THR_LOCK_heap);
316
447
void hp_free(HP_SHARE *share)
318
heap_share_list.remove(share); /* If not internal table */
449
if (share->open_list.data) /* If not internal table */
450
heap_share_list= list_delete(heap_share_list, &share->open_list);
319
451
hp_clear(share); /* Remove blocks from memory */
321
delete [] share->keydef->seg;
322
delete [] share->keydef;
452
thr_lock_delete(&share->lock);
453
pthread_mutex_destroy(&share->intern_lock);
454
free((unsigned char*) share->name);
455
free((unsigned char*) share);