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"
20
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
21
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
22
uint32_t max_records);
24
#define FIXED_REC_OVERHEAD (sizeof(unsigned char))
25
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + sizeof(unsigned char))
27
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
28
#define VARIABLE_MIN_CHUNK_SIZE \
29
((sizeof(unsigned char**) + VARIABLE_REC_OVERHEAD + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1))
18
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,
32
22
/* Create a heap table */
34
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
35
uint32_t columns, HP_COLUMNDEF *columndef,
36
uint32_t max_key_fieldnr, uint32_t key_part_size,
37
uint32_t reclength, uint32_t keys_memory_size,
38
uint32_t max_records, uint32_t min_records,
39
HP_CREATE_INFO *create_info, HP_SHARE **res)
24
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)
41
uint32_t i, j, key_segs, max_length, length;
42
uint32_t max_rows_for_stated_memory;
28
uint i, j, key_segs, max_length, length;
43
29
HP_SHARE *share= 0;
31
DBUG_ENTER("heap_create");
46
33
if (!create_info->internal_table)
58
uint32_t chunk_dataspace_length, chunk_length, is_variable_size;
59
uint32_t fixed_data_length, fixed_column_count;
60
45
HP_KEYDEF *keyinfo;
62
if (create_info->max_chunk_size)
64
uint32_t 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
uint32_t 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;
46
DBUG_PRINT("info",("Initializing new table"));
158
We store unsigned char* del_link inside the data area of deleted records,
159
so the data length should be at least sizeof(unsigned char*)
49
We have to store sometimes uchar* del_link in records,
50
so the record length should be at least sizeof(uchar*)
161
set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
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(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
52
set_if_bigger(reclength, sizeof (uchar*));
177
54
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
179
memset(&keyinfo->block, 0, sizeof(keyinfo->block));
180
memset(&keyinfo->rb_tree , 0, sizeof(keyinfo->rb_tree));
56
bzero((char*) &keyinfo->block,sizeof(keyinfo->block));
57
bzero((char*) &keyinfo->rb_tree ,sizeof(keyinfo->rb_tree));
181
58
for (j= length= 0; j < keyinfo->keysegs; j++)
183
60
length+= keyinfo->seg[j].length;
251
128
if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
252
129
keys*sizeof(HP_KEYDEF)+
253
columns*sizeof(HP_COLUMNDEF)+
254
130
key_segs*sizeof(HA_KEYSEG),
255
131
MYF(MY_ZEROFILL))))
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);
133
share->keydef= (HP_KEYDEF*) (share + 1);
272
134
share->key_stat_version= 1;
273
135
keyseg= (HA_KEYSEG*) (share->keydef + keys);
274
init_block(&share->recordspace.block, chunk_length, min_records, max_records);
136
init_block(&share->block, reclength + 1, min_records, max_records);
276
138
memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
277
139
for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
286
148
/* additional HA_KEYTYPE_END keyseg */
287
149
keyseg->type= HA_KEYTYPE_END;
288
keyseg->length= sizeof(unsigned char*);
150
keyseg->length= sizeof(uchar*);
290
152
keyseg->null_bit= 0;
293
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
155
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(uchar*),
294
156
(qsort_cmp2)keys_compare, 1, NULL, NULL);
295
157
keyinfo->delete_key= hp_rb_delete_key;
296
158
keyinfo->write_key= hp_rb_write_key;
309
171
share->min_records= min_records;
310
172
share->max_records= max_records;
311
173
share->max_table_size= create_info->max_table_size;
312
share->index_length= 0;
174
share->data_length= share->index_length= 0;
175
share->reclength= reclength;
313
176
share->blength= 1;
314
177
share->keys= keys;
315
178
share->max_key_length= max_length;
316
share->column_count= columns;
317
179
share->changed= 0;
318
180
share->auto_key= create_info->auto_key;
319
181
share->auto_key_type= create_info->auto_key_type;
320
182
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(unsigned char**);
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;
338
183
/* Must be allocated separately for rename to work */
339
184
if (!(share->name= my_strdup(name,MYF(0))))
341
free((unsigned char*) share);
186
my_free((uchar*) share,MYF(0));
344
189
thr_lock_init(&share->lock);
345
pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
190
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
346
191
if (!create_info->internal_table)
348
193
share->open_list.data= (void*) share;
355
200
pthread_mutex_unlock(&THR_LOCK_heap);
361
206
if (!create_info->internal_table)
362
207
pthread_mutex_unlock(&THR_LOCK_heap);
364
209
} /* heap_create */
367
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
212
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
369
uint32_t not_used[2];
370
215
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
371
216
param->search_flag, not_used);
374
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
375
uint32_t max_records)
219
static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
377
uint32_t i,recbuffer,records_in_block;
222
uint i,recbuffer,records_in_block;
379
max_records= cmax(min_records,max_records);
224
max_records= max(min_records,max_records);
380
225
if (!max_records)
381
226
max_records= 1000; /* As good as quess as anything */
383
/* we want to start each chunk at 8 bytes boundary, round recbuffer to the next 8 */
384
recbuffer= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
227
recbuffer= (uint) (reclength + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
385
228
records_in_block= max_records / 10;
386
229
if (records_in_block < 10 && max_records)
387
230
records_in_block= 10;