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"
18
20
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2);
19
static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
21
static void init_block(HP_BLOCK *block,uint chunk_length, ulong min_records,
24
#define FIXED_REC_OVERHEAD (sizeof(uchar))
25
#define VARIABLE_REC_OVERHEAD (sizeof(uchar**) + sizeof(uchar))
27
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
28
#define VARIABLE_MIN_CHUNK_SIZE \
29
((sizeof(uchar**) + VARIABLE_REC_OVERHEAD + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1))
22
32
/* Create a heap table */
24
34
int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
25
uint reclength, ulong max_records, ulong min_records,
26
HP_CREATE_INFO *create_info, HP_SHARE **res)
35
uint columns, HP_COLUMNDEF *columndef,
36
uint max_key_fieldnr, uint key_part_size,
37
uint reclength, uint keys_memory_size,
38
ulong max_records, ulong min_records,
39
HP_CREATE_INFO *create_info, HP_SHARE **res)
28
41
uint i, j, key_segs, max_length, length;
42
ulong max_rows_for_stated_memory;
29
43
HP_SHARE *share= 0;
58
uint chunk_dataspace_length, chunk_length, is_variable_size;
59
uint fixed_data_length, fixed_column_count;
44
60
HP_KEYDEF *keyinfo;
62
if (create_info->max_chunk_size)
64
uint configured_chunk_size= create_info->max_chunk_size;
66
/* User requested variable-size records, let's see if they're possible */
68
if (configured_chunk_size < key_part_size)
70
/* Eventual chunk_size cannot be smaller than key data,
71
which allows all keys to fit into the first chunk */
72
my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "block_size");
73
pthread_mutex_unlock(&THR_LOCK_heap);
74
return(ER_CANT_USE_OPTION_HERE);
77
if ((reclength - configured_chunk_size) >= VARIABLE_MIN_CHUNK_SIZE<<1)
79
/* Allow variable size only if we're saving at least two smallest chunks */
80
/* There has to be at least one field after indexed fields */
81
/* Note that NULL bits are already included in key_part_size */
83
chunk_dataspace_length= configured_chunk_size;
87
/* max_chunk_size is near the full reclength, let's use fixed size */
89
chunk_dataspace_length= reclength;
92
else if (create_info->is_dynamic)
94
/* User asked for dynamic records - use 256 as the chunk size */
95
if ((key_part_size + VARIABLE_REC_OVERHEAD) > 256)
96
chunk_dataspace_length= key_part_size;
98
chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD;
104
/* if max_chunk_size is not specified, put the whole record in one chunk */
106
chunk_dataspace_length= reclength;
109
if (is_variable_size)
111
/* Check whether we have any variable size records past key data */
112
uint has_variable_fields= 0;
114
fixed_data_length= key_part_size;
115
fixed_column_count= max_key_fieldnr;
117
for (i= max_key_fieldnr; i < columns; i++)
119
HP_COLUMNDEF* column= columndef + i;
120
if (column->type == DRIZZLE_TYPE_VARCHAR && column->length >= 32)
122
/* The field has to be >= 5.0.3 true VARCHAR and have substantial length */
123
/* TODO: do we want to calculate minimum length? */
124
has_variable_fields= 1;
128
if (has_variable_fields)
133
if ((column->offset + column->length) <= chunk_dataspace_length)
135
/* Still no variable-size columns, add one fixed-length */
136
fixed_column_count= i + 1;
137
fixed_data_length= column->offset + column->length;
141
if (!has_variable_fields)
143
/* There is no need to use variable-size records without variable-size columns */
144
/* Reset sizes if it's not variable size anymore */
146
chunk_dataspace_length= reclength;
147
fixed_data_length= reclength;
148
fixed_column_count= columns;
153
fixed_data_length= reclength;
154
fixed_column_count= columns;
47
We have to store sometimes uchar* del_link in records,
48
so the record length should be at least sizeof(uchar*)
158
We store uchar* del_link inside the data area of deleted records,
159
so the data length should be at least sizeof(uchar*)
50
set_if_bigger(reclength, sizeof (uchar*));
161
set_if_bigger(chunk_dataspace_length, sizeof (uchar**));
163
if (is_variable_size)
165
chunk_length= chunk_dataspace_length + VARIABLE_REC_OVERHEAD;
169
chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD;
172
/* Align chunk length to the next pointer */
173
chunk_length= (uint) (chunk_length + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
52
177
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
126
251
if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
127
252
keys*sizeof(HP_KEYDEF)+
253
columns*sizeof(HP_COLUMNDEF)+
128
254
key_segs*sizeof(HA_KEYSEG),
129
255
MYF(MY_ZEROFILL))))
131
share->keydef= (HP_KEYDEF*) (share + 1);
259
Max_records is used for estimating block sizes and for enforcement.
260
Calculate the very maximum number of rows (if everything was one chunk) and
261
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 /
264
(keys_memory_size + chunk_length));
265
max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
266
max_records : max_rows_for_stated_memory);
268
share->column_defs= (HP_COLUMNDEF*) (share + 1);
269
memcpy(share->column_defs, columndef, (size_t) (sizeof(columndef[0]) * columns));
271
share->keydef= (HP_KEYDEF*) (share->column_defs + columns);
132
272
share->key_stat_version= 1;
133
273
keyseg= (HA_KEYSEG*) (share->keydef + keys);
134
init_block(&share->block, reclength + 1, min_records, max_records);
274
init_block(&share->recordspace.block, chunk_length, min_records, max_records);
136
276
memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
137
277
for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
169
309
share->min_records= min_records;
170
310
share->max_records= max_records;
171
311
share->max_table_size= create_info->max_table_size;
172
share->data_length= share->index_length= 0;
173
share->reclength= reclength;
312
share->index_length= 0;
174
313
share->blength= 1;
175
314
share->keys= keys;
176
315
share->max_key_length= max_length;
316
share->column_count= columns;
177
317
share->changed= 0;
178
318
share->auto_key= create_info->auto_key;
179
319
share->auto_key_type= create_info->auto_key_type;
180
320
share->auto_increment= create_info->auto_increment;
322
share->fixed_data_length= fixed_data_length;
323
share->fixed_column_count= fixed_column_count;
325
share->recordspace.chunk_length= chunk_length;
326
share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
327
share->recordspace.is_variable_size= is_variable_size;
328
share->recordspace.total_data_length= 0;
330
if (is_variable_size) {
331
share->recordspace.offset_link= chunk_dataspace_length;
332
share->recordspace.offset_status= share->recordspace.offset_link + sizeof(uchar**);
334
share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
335
share->recordspace.offset_status= chunk_dataspace_length;
181
338
/* Must be allocated separately for rename to work */
182
339
if (!(share->name= my_strdup(name,MYF(0))))