16 #include "heap_priv.h"
17 #include <drizzled/internal/my_sys.h>
18 #include <drizzled/common.h>
19 #include <drizzled/error.h>
25 using namespace drizzled;
27 static void init_block(
HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
28 uint32_t max_records);
30 static const int FIXED_REC_OVERHEAD = (
sizeof(
unsigned char));
31 static const int VARIABLE_REC_OVERHEAD = (
sizeof(
unsigned char**) + ALIGN_SIZE(
sizeof(
unsigned char)));
34 static const int VARIABLE_MIN_CHUNK_SIZE =
35 ((
sizeof(
unsigned char**) + VARIABLE_REC_OVERHEAD +
sizeof(
unsigned char**) - 1) & ~(
sizeof(
unsigned char**) - 1));
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,
47 uint32_t i, key_segs, max_length, length;
48 uint32_t max_rows_for_stated_memory;
52 if (not create_info->internal_table)
55 if ((share= hp_find_named_heap(name)) && share->open_count == 0)
64 size_t chunk_dataspace_length;
65 uint32_t chunk_length;
66 uint32_t fixed_data_length, fixed_column_count;
69 if (create_info->max_chunk_size)
71 uint32_t configured_chunk_size= create_info->max_chunk_size;
75 if (configured_chunk_size < key_part_size)
79 my_error(ER_CANT_USE_OPTION_HERE, MYF(0),
"block_size");
80 THR_LOCK_heap.unlock();
81 return(ER_CANT_USE_OPTION_HERE);
85 chunk_dataspace_length= reclength;
90 chunk_dataspace_length= reclength;
94 fixed_data_length= reclength;
95 fixed_column_count= columns;
102 set_if_bigger(chunk_dataspace_length,
sizeof (
unsigned char**));
105 chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD;
109 chunk_length= (uint) (chunk_length +
sizeof(
unsigned char**) - 1) & ~(
sizeof(
unsigned char**) - 1);
113 for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
115 memset(&keyinfo->block, 0,
sizeof(keyinfo->block));
116 for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
118 length+= keyinfo->seg[j].length;
119 if (keyinfo->seg[j].null_bit)
122 if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
123 keyinfo->flag|= HA_NULL_PART_KEY;
125 switch (keyinfo->seg[j].type) {
126 case HA_KEYTYPE_LONG_INT:
127 case HA_KEYTYPE_DOUBLE:
128 case HA_KEYTYPE_ULONG_INT:
129 case HA_KEYTYPE_LONGLONG:
130 case HA_KEYTYPE_ULONGLONG:
131 keyinfo->seg[j].flag|= HA_SWAP_KEY;
133 case HA_KEYTYPE_VARBINARY1:
135 keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
137 case HA_KEYTYPE_VARTEXT1:
138 keyinfo->flag|= HA_VAR_LENGTH_KEY;
141 keyinfo->seg[j].bit_start= 1;
143 case HA_KEYTYPE_VARBINARY2:
146 case HA_KEYTYPE_VARTEXT2:
147 keyinfo->flag|= HA_VAR_LENGTH_KEY;
150 keyinfo->seg[j].bit_start= 2;
155 keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
161 keyinfo->length= length;
162 if (length > max_length)
164 key_segs+= keyinfo->keysegs;
168 if (keys && !(share->keydef=
new HP_KEYDEF[keys]))
170 if (keys && !(share->keydef->seg=
new HA_KEYSEG[key_segs]))
178 max_rows_for_stated_memory= (uint32_t)(create_info->max_table_size /
179 (keys_memory_size + chunk_length));
180 max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
181 max_records : max_rows_for_stated_memory);
183 share->key_stat_version= 1;
184 keyseg= keys ? share->keydef->seg : NULL;
186 init_block(&share->recordspace.block, chunk_length, min_records, max_records);
188 memcpy(share->keydef, keydef, (
size_t) (
sizeof(keydef[0]) * keys));
189 for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
191 keyinfo->seg= keyseg;
192 memcpy(keyseg, keydef[i].seg,
193 (
size_t) (
sizeof(keyseg[0]) * keydef[i].keysegs));
194 keyseg+= keydef[i].keysegs;
196 init_block(&keyinfo->block,
sizeof(
HASH_INFO), min_records,
198 keyinfo->hash_buckets= 0;
200 if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
201 share->auto_key= i + 1;
203 share->min_records= min_records;
204 share->max_records= max_records;
205 share->max_table_size= create_info->max_table_size;
206 share->index_length= 0;
209 share->max_key_length= max_length;
210 share->column_count= columns;
212 share->auto_key= create_info->auto_key;
213 share->auto_key_type= create_info->auto_key_type;
214 share->auto_increment= create_info->auto_increment;
216 share->fixed_data_length= fixed_data_length;
217 share->fixed_column_count= fixed_column_count;
219 share->recordspace.chunk_length= chunk_length;
220 share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
221 share->recordspace.total_data_length= 0;
224 share->recordspace.offset_link= 1<<22;
225 share->recordspace.offset_status= chunk_dataspace_length;
229 share->name.append(name);
230 if (!create_info->internal_table)
232 heap_share_list.push_front(share);
235 share->delete_on_close= 1;
237 if (!create_info->internal_table)
238 THR_LOCK_heap.unlock();
244 if (share && share->keydef)
245 delete[] share->keydef->seg;
247 delete[] share->keydef;
249 if (not create_info->internal_table)
250 THR_LOCK_heap.unlock();
255 static void init_block(
HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
256 uint32_t max_records)
258 uint32_t recbuffer,records_in_block;
260 max_records= max(min_records,max_records);
265 recbuffer= (uint) (chunk_length +
sizeof(
unsigned char**) - 1) & ~(
sizeof(
unsigned char**) - 1);
266 records_in_block= max_records / 10;
267 if (records_in_block < 10 && max_records)
268 records_in_block= 10;
269 if (!records_in_block || records_in_block*recbuffer >
270 (internal::my_default_record_cache_size-
sizeof(
HP_PTRS)*HP_MAX_LEVELS))
271 records_in_block= (internal::my_default_record_cache_size -
sizeof(
HP_PTRS) *
272 HP_MAX_LEVELS) / recbuffer + 1;
273 block->records_in_block= records_in_block;
274 block->recbuffer= recbuffer;
275 block->last_allocated= 0L;
277 for (uint32_t i= 0; i <= HP_MAX_LEVELS; i++)
279 block->level_info[i].records_under_level=
280 (!i ? 1 : i == 1 ? records_in_block :
281 HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
286 static inline void heap_try_free(
HP_SHARE *share)
288 if (share->open_count == 0)
291 share->delete_on_close= 1;
295 int heap_delete_table(
const char *name)
300 THR_LOCK_heap.lock();
301 if ((share= hp_find_named_heap(name)))
303 heap_try_free(share);
308 result= errno=ENOENT;
310 THR_LOCK_heap.unlock();
317 heap_share_list.remove(share);
320 delete[] share->keydef->seg;
321 delete[] share->keydef;