1
/* Copyright (C) 2000-2006 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
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,
22
/* Create a heap table */
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)
28
uint i, j, key_segs, max_length, length;
31
DBUG_ENTER("heap_create");
33
if (!create_info->internal_table)
35
pthread_mutex_lock(&THR_LOCK_heap);
36
if ((share= hp_find_named_heap(name)) && share->open_count == 0)
46
DBUG_PRINT("info",("Initializing new table"));
49
We have to store sometimes uchar* del_link in records,
50
so the record length should be at least sizeof(uchar*)
52
set_if_bigger(reclength, sizeof (uchar*));
54
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
56
bzero((char*) &keyinfo->block,sizeof(keyinfo->block));
57
bzero((char*) &keyinfo->rb_tree ,sizeof(keyinfo->rb_tree));
58
for (j= length= 0; j < keyinfo->keysegs; j++)
60
length+= keyinfo->seg[j].length;
61
if (keyinfo->seg[j].null_bit)
64
if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
65
keyinfo->flag|= HA_NULL_PART_KEY;
66
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
67
keyinfo->rb_tree.size_of_element++;
69
switch (keyinfo->seg[j].type) {
70
case HA_KEYTYPE_SHORT_INT:
71
case HA_KEYTYPE_LONG_INT:
72
case HA_KEYTYPE_FLOAT:
73
case HA_KEYTYPE_DOUBLE:
74
case HA_KEYTYPE_USHORT_INT:
75
case HA_KEYTYPE_ULONG_INT:
76
case HA_KEYTYPE_LONGLONG:
77
case HA_KEYTYPE_ULONGLONG:
78
case HA_KEYTYPE_INT24:
79
case HA_KEYTYPE_UINT24:
81
keyinfo->seg[j].flag|= HA_SWAP_KEY;
83
case HA_KEYTYPE_VARBINARY1:
84
/* Case-insensitiveness is handled in coll->hash_sort */
85
keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
87
case HA_KEYTYPE_VARTEXT1:
88
if (!my_binary_compare(keyinfo->seg[j].charset))
89
keyinfo->flag|= HA_END_SPACE_KEY;
90
keyinfo->flag|= HA_VAR_LENGTH_KEY;
92
/* Save number of bytes used to store length */
93
keyinfo->seg[j].bit_start= 1;
95
case HA_KEYTYPE_VARBINARY2:
96
/* Case-insensitiveness is handled in coll->hash_sort */
98
case HA_KEYTYPE_VARTEXT2:
99
if (!my_binary_compare(keyinfo->seg[j].charset))
100
keyinfo->flag|= HA_END_SPACE_KEY;
101
keyinfo->flag|= HA_VAR_LENGTH_KEY;
103
/* Save number of bytes used to store length */
104
keyinfo->seg[j].bit_start= 2;
106
Make future comparison simpler by only having to check for
109
keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
114
if (keyinfo->seg[j].flag & HA_END_SPACE_ARE_EQUAL)
115
keyinfo->flag|= HA_END_SPACE_KEY;
117
keyinfo->length= length;
118
length+= keyinfo->rb_tree.size_of_element +
119
((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(uchar*) : 0);
120
if (length > max_length)
122
key_segs+= keyinfo->keysegs;
123
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
125
key_segs++; /* additional HA_KEYTYPE_END segment */
126
if (keyinfo->flag & HA_VAR_LENGTH_KEY)
127
keyinfo->get_key_length= hp_rb_var_key_length;
128
else if (keyinfo->flag & HA_NULL_PART_KEY)
129
keyinfo->get_key_length= hp_rb_null_key_length;
131
keyinfo->get_key_length= hp_rb_key_length;
134
if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
135
keys*sizeof(HP_KEYDEF)+
136
key_segs*sizeof(HA_KEYSEG),
139
share->keydef= (HP_KEYDEF*) (share + 1);
140
share->key_stat_version= 1;
141
keyseg= (HA_KEYSEG*) (share->keydef + keys);
142
init_block(&share->block, reclength + 1, min_records, max_records);
144
memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
145
for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
147
keyinfo->seg= keyseg;
148
memcpy(keyseg, keydef[i].seg,
149
(size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
150
keyseg+= keydef[i].keysegs;
152
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
154
/* additional HA_KEYTYPE_END keyseg */
155
keyseg->type= HA_KEYTYPE_END;
156
keyseg->length= sizeof(uchar*);
161
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(uchar*),
162
(qsort_cmp2)keys_compare, 1, NULL, NULL);
163
keyinfo->delete_key= hp_rb_delete_key;
164
keyinfo->write_key= hp_rb_write_key;
168
init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
170
keyinfo->delete_key= hp_delete_key;
171
keyinfo->write_key= hp_write_key;
172
keyinfo->hash_buckets= 0;
174
if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
175
share->auto_key= i + 1;
177
share->min_records= min_records;
178
share->max_records= max_records;
179
share->max_table_size= create_info->max_table_size;
180
share->data_length= share->index_length= 0;
181
share->reclength= reclength;
184
share->max_key_length= max_length;
186
share->auto_key= create_info->auto_key;
187
share->auto_key_type= create_info->auto_key_type;
188
share->auto_increment= create_info->auto_increment;
189
/* Must be allocated separately for rename to work */
190
if (!(share->name= my_strdup(name,MYF(0))))
192
my_free((uchar*) share,MYF(0));
196
thr_lock_init(&share->lock);
197
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
199
if (!create_info->internal_table)
201
share->open_list.data= (void*) share;
202
heap_share_list= list_add(heap_share_list,&share->open_list);
205
share->delete_on_close= 1;
207
if (!create_info->internal_table)
208
pthread_mutex_unlock(&THR_LOCK_heap);
214
if (!create_info->internal_table)
215
pthread_mutex_unlock(&THR_LOCK_heap);
220
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
223
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
224
param->search_flag, not_used);
227
static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
230
uint i,recbuffer,records_in_block;
232
max_records= max(min_records,max_records);
234
max_records= 1000; /* As good as quess as anything */
235
recbuffer= (uint) (reclength + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
236
records_in_block= max_records / 10;
237
if (records_in_block < 10 && max_records)
238
records_in_block= 10;
239
if (!records_in_block || records_in_block*recbuffer >
240
(my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
241
records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
242
HP_MAX_LEVELS) / recbuffer + 1;
243
block->records_in_block= records_in_block;
244
block->recbuffer= recbuffer;
245
block->last_allocated= 0L;
247
for (i= 0; i <= HP_MAX_LEVELS; i++)
248
block->level_info[i].records_under_level=
249
(!i ? 1 : i == 1 ? records_in_block :
250
HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
254
static inline void heap_try_free(HP_SHARE *share)
256
if (share->open_count == 0)
259
share->delete_on_close= 1;
263
int heap_delete_table(const char *name)
266
register HP_SHARE *share;
267
DBUG_ENTER("heap_delete_table");
269
pthread_mutex_lock(&THR_LOCK_heap);
270
if ((share= hp_find_named_heap(name)))
272
heap_try_free(share);
277
result= my_errno=ENOENT;
279
pthread_mutex_unlock(&THR_LOCK_heap);
284
void heap_drop_table(HP_INFO *info)
286
DBUG_ENTER("heap_drop_table");
287
pthread_mutex_lock(&THR_LOCK_heap);
288
heap_try_free(info->s);
289
pthread_mutex_unlock(&THR_LOCK_heap);
294
void hp_free(HP_SHARE *share)
296
if (share->open_list.data) /* If not internal table */
297
heap_share_list= list_delete(heap_share_list, &share->open_list);
298
hp_clear(share); /* Remove blocks from memory */
300
thr_lock_delete(&share->lock);
301
VOID(pthread_mutex_destroy(&share->intern_lock));
303
my_free((uchar*) share->name, MYF(0));
304
my_free((uchar*) share, MYF(0));