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>
38
38
/* Create a heap table */
40
40
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)
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,
44
uint32_t max_records, uint32_t min_records,
45
HP_CREATE_INFO *create_info, HP_SHARE **res)
47
uint32_t i, key_segs, max_length, length;
47
uint32_t i, j, key_segs, max_length, length;
48
48
uint32_t max_rows_for_stated_memory;
49
49
HP_SHARE *share= 0;
52
if (not create_info->internal_table)
52
if (!create_info->internal_table)
54
pthread_mutex_lock(&THR_LOCK_heap);
55
55
if ((share= hp_find_named_heap(name)) && share->open_count == 0)
75
75
if (configured_chunk_size < key_part_size)
77
77
/* Eventual chunk_size cannot be smaller than key data,
78
which allows all keys to fit into the first chunk */
78
which allows all keys to fit into the first chunk */
79
79
my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "block_size");
80
THR_LOCK_heap.unlock();
80
pthread_mutex_unlock(&THR_LOCK_heap);
81
81
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;
84
if ((reclength - configured_chunk_size) >= VARIABLE_MIN_CHUNK_SIZE<<1)
86
/* Allow variable size only if we're saving at least two smallest chunks */
87
/* There has to be at least one field after indexed fields */
88
/* Note that NULL bits are already included in key_part_size */
90
chunk_dataspace_length= configured_chunk_size;
94
/* max_chunk_size is near the full reclength, let's use fixed size */
96
chunk_dataspace_length= reclength;
99
else if (create_info->is_dynamic)
101
/* User asked for dynamic records - use 256 as the chunk size */
102
if ((key_part_size + VARIABLE_REC_OVERHEAD) > 256)
103
chunk_dataspace_length= key_part_size;
105
chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD;
89
111
/* if max_chunk_size is not specified, put the whole record in one chunk */
90
113
chunk_dataspace_length= reclength;
116
if (is_variable_size)
118
/* Check whether we have any variable size records past key data */
119
uint32_t has_variable_fields= 0;
121
fixed_data_length= key_part_size;
122
fixed_column_count= max_key_fieldnr;
124
for (i= max_key_fieldnr; i < columns; i++)
126
HP_COLUMNDEF* column= columndef + i;
127
if (column->type == DRIZZLE_TYPE_VARCHAR && column->length >= 32)
129
/* The field has to be >= 5.0.3 true VARCHAR and have substantial length */
130
/* TODO: do we want to calculate minimum length? */
131
has_variable_fields= 1;
135
if (has_variable_fields)
140
if ((column->offset + column->length) <= chunk_dataspace_length)
142
/* Still no variable-size columns, add one fixed-length */
143
fixed_column_count= i + 1;
144
fixed_data_length= column->offset + column->length;
148
if (!has_variable_fields)
150
/* There is no need to use variable-size records without variable-size columns */
151
/* Reset sizes if it's not variable size anymore */
153
chunk_dataspace_length= reclength;
154
fixed_data_length= reclength;
155
fixed_column_count= columns;
94
160
fixed_data_length= reclength;
95
161
fixed_column_count= columns;
113
184
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
115
186
memset(&keyinfo->block, 0, sizeof(keyinfo->block));
116
for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
187
memset(&keyinfo->rb_tree , 0, sizeof(keyinfo->rb_tree));
188
for (j= length= 0; j < keyinfo->keysegs; j++)
118
190
length+= keyinfo->seg[j].length;
119
191
if (keyinfo->seg[j].null_bit)
122
194
if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
123
195
keyinfo->flag|= HA_NULL_PART_KEY;
196
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
197
keyinfo->rb_tree.size_of_element++;
125
199
switch (keyinfo->seg[j].type) {
200
case HA_KEYTYPE_SHORT_INT:
126
201
case HA_KEYTYPE_LONG_INT:
202
case HA_KEYTYPE_FLOAT:
127
203
case HA_KEYTYPE_DOUBLE:
204
case HA_KEYTYPE_USHORT_INT:
128
205
case HA_KEYTYPE_ULONG_INT:
129
206
case HA_KEYTYPE_LONGLONG:
130
207
case HA_KEYTYPE_ULONGLONG:
208
case HA_KEYTYPE_INT24:
209
case HA_KEYTYPE_UINT24:
210
case HA_KEYTYPE_INT8:
131
211
keyinfo->seg[j].flag|= HA_SWAP_KEY;
133
213
case HA_KEYTYPE_VARBINARY1:
161
241
keyinfo->length= length;
242
length+= keyinfo->rb_tree.size_of_element +
243
((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(unsigned char*) : 0);
162
244
if (length > max_length)
163
245
max_length= length;
164
246
key_segs+= keyinfo->keysegs;
247
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
249
key_segs++; /* additional HA_KEYTYPE_END segment */
250
if (keyinfo->flag & HA_VAR_LENGTH_KEY)
251
keyinfo->get_key_length= hp_rb_var_key_length;
252
else if (keyinfo->flag & HA_NULL_PART_KEY)
253
keyinfo->get_key_length= hp_rb_null_key_length;
255
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]))
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));
174
278
Max_records is used for estimating block sizes and for enforcement.
192
298
memcpy(keyseg, keydef[i].seg,
193
299
(size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
194
300
keyseg+= keydef[i].keysegs;
302
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
304
/* additional HA_KEYTYPE_END keyseg */
305
keyseg->type= HA_KEYTYPE_END;
306
keyseg->length= sizeof(unsigned char*);
311
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
312
(qsort_cmp2)keys_compare, 1, NULL, NULL);
313
keyinfo->delete_key= hp_rb_delete_key;
314
keyinfo->write_key= hp_rb_write_key;
196
318
init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
320
keyinfo->delete_key= hp_delete_key;
321
keyinfo->write_key= hp_write_key;
198
322
keyinfo->hash_buckets= 0;
200
324
if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
219
343
share->recordspace.chunk_length= chunk_length;
220
344
share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
345
share->recordspace.is_variable_size= is_variable_size;
221
346
share->recordspace.total_data_length= 0;
348
if (is_variable_size) {
349
share->recordspace.offset_link= chunk_dataspace_length;
350
share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
224
352
share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
225
353
share->recordspace.offset_status= chunk_dataspace_length;
228
356
/* Must be allocated separately for rename to work */
229
share->name.append(name);
357
if (!(share->name= strdup(name)))
361
thr_lock_init(&share->lock);
362
pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
230
363
if (!create_info->internal_table)
232
365
heap_share_list.push_front(share);
235
368
share->delete_on_close= 1;
237
370
if (!create_info->internal_table)
238
THR_LOCK_heap.unlock();
371
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();
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);
385
if (!create_info->internal_table)
386
pthread_mutex_unlock(&THR_LOCK_heap);
253
388
} /* heap_create */
391
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
393
uint32_t not_used[2];
394
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
395
param->search_flag, not_used);
256
398
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
257
399
uint32_t max_records)
259
uint32_t recbuffer,records_in_block;
401
uint32_t i,recbuffer,records_in_block;
261
403
max_records= max(min_records,max_records);
262
404
if (!max_records)
268
410
if (records_in_block < 10 && max_records)
269
411
records_in_block= 10;
270
412
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) *
413
(my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
414
records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
273
415
HP_MAX_LEVELS) / recbuffer + 1;
274
416
block->records_in_block= records_in_block;
275
417
block->recbuffer= recbuffer;
276
418
block->last_allocated= 0L;
278
for (uint32_t i= 0; i <= HP_MAX_LEVELS; i++)
420
for (i= 0; i <= HP_MAX_LEVELS; i++)
280
421
block->level_info[i].records_under_level=
281
422
(!i ? 1 : i == 1 ? records_in_block :
282
423
HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
309
result= errno=ENOENT;
449
result= my_errno=ENOENT;
311
THR_LOCK_heap.unlock();
451
pthread_mutex_unlock(&THR_LOCK_heap);
456
void heap_drop_table(HP_INFO *info)
458
pthread_mutex_lock(&THR_LOCK_heap);
459
heap_try_free(info->s);
460
pthread_mutex_unlock(&THR_LOCK_heap);
316
465
void hp_free(HP_SHARE *share)
318
467
heap_share_list.remove(share); /* If not internal table */
319
468
hp_clear(share); /* Remove blocks from memory */
469
thr_lock_delete(&share->lock);
470
pthread_mutex_destroy(&share->intern_lock);
471
if (share->keydef && share->keydef->seg)
472
free(share->keydef->seg);
320
473
if (share->keydef)
321
delete [] share->keydef->seg;
322
delete [] share->keydef;
475
free(share->column_defs);
476
free((unsigned char*) share->name);
477
free((unsigned char*) share);