00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "heap_priv.h"
00017
00018 #include <drizzled/common.h>
00019 #include <drizzled/error.h>
00020
00021 #include <string.h>
00022 #include <algorithm>
00023
00024 using namespace std;
00025 using namespace drizzled;
00026
00027 static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
00028 uint32_t max_records);
00029
00030 static const int FIXED_REC_OVERHEAD = (sizeof(unsigned char));
00031 static const int VARIABLE_REC_OVERHEAD = (sizeof(unsigned char**) + ALIGN_SIZE(sizeof(unsigned char)));
00032
00033
00034 static const int VARIABLE_MIN_CHUNK_SIZE =
00035 ((sizeof(unsigned char**) + VARIABLE_REC_OVERHEAD + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1));
00036
00037
00038
00039
00040 int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
00041 uint32_t columns,
00042 uint32_t key_part_size,
00043 uint32_t reclength, uint32_t keys_memory_size,
00044 uint32_t max_records, uint32_t min_records,
00045 HP_CREATE_INFO *create_info, HP_SHARE **res)
00046 {
00047 uint32_t i, key_segs, max_length, length;
00048 uint32_t max_rows_for_stated_memory;
00049 HP_SHARE *share= 0;
00050 HA_KEYSEG *keyseg;
00051
00052 if (not create_info->internal_table)
00053 {
00054 THR_LOCK_heap.lock();
00055 if ((share= hp_find_named_heap(name)) && share->open_count == 0)
00056 {
00057 hp_free(share);
00058 share= 0;
00059 }
00060 }
00061
00062 if (!share)
00063 {
00064 size_t chunk_dataspace_length;
00065 uint32_t chunk_length;
00066 uint32_t fixed_data_length, fixed_column_count;
00067 HP_KEYDEF *keyinfo;
00068
00069 if (create_info->max_chunk_size)
00070 {
00071 uint32_t configured_chunk_size= create_info->max_chunk_size;
00072
00073
00074
00075 if (configured_chunk_size < key_part_size)
00076 {
00077
00078
00079 my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "block_size");
00080 THR_LOCK_heap.unlock();
00081 return(ER_CANT_USE_OPTION_HERE);
00082 }
00083
00084
00085 chunk_dataspace_length= reclength;
00086 }
00087 else
00088 {
00089
00090 chunk_dataspace_length= reclength;
00091 }
00092
00093 {
00094 fixed_data_length= reclength;
00095 fixed_column_count= columns;
00096 }
00097
00098
00099
00100
00101
00102 set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
00103
00104 {
00105 chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD;
00106 }
00107
00108
00109 chunk_length= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
00110
00111
00112
00113 for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
00114 {
00115 memset(&keyinfo->block, 0, sizeof(keyinfo->block));
00116 for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
00117 {
00118 length+= keyinfo->seg[j].length;
00119 if (keyinfo->seg[j].null_bit)
00120 {
00121 length++;
00122 if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
00123 keyinfo->flag|= HA_NULL_PART_KEY;
00124 }
00125 switch (keyinfo->seg[j].type) {
00126 case HA_KEYTYPE_LONG_INT:
00127 case HA_KEYTYPE_DOUBLE:
00128 case HA_KEYTYPE_ULONG_INT:
00129 case HA_KEYTYPE_LONGLONG:
00130 case HA_KEYTYPE_ULONGLONG:
00131 keyinfo->seg[j].flag|= HA_SWAP_KEY;
00132 break;
00133 case HA_KEYTYPE_VARBINARY1:
00134
00135 keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
00136
00137 case HA_KEYTYPE_VARTEXT1:
00138 keyinfo->flag|= HA_VAR_LENGTH_KEY;
00139 length+= 2;
00140
00141 keyinfo->seg[j].bit_start= 1;
00142 break;
00143 case HA_KEYTYPE_VARBINARY2:
00144
00145
00146 case HA_KEYTYPE_VARTEXT2:
00147 keyinfo->flag|= HA_VAR_LENGTH_KEY;
00148 length+= 2;
00149
00150 keyinfo->seg[j].bit_start= 2;
00151
00152
00153
00154
00155 keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
00156 break;
00157 default:
00158 break;
00159 }
00160 }
00161 keyinfo->length= length;
00162 if (length > max_length)
00163 max_length= length;
00164 key_segs+= keyinfo->keysegs;
00165 }
00166 share= new HP_SHARE;
00167
00168 if (keys && !(share->keydef= new HP_KEYDEF[keys]))
00169 goto err;
00170 if (keys && !(share->keydef->seg= new HA_KEYSEG[key_segs]))
00171 goto err;
00172
00173
00174
00175
00176
00177
00178 max_rows_for_stated_memory= (uint32_t)(create_info->max_table_size /
00179 (keys_memory_size + chunk_length));
00180 max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
00181 max_records : max_rows_for_stated_memory);
00182
00183 share->key_stat_version= 1;
00184 keyseg= keys ? share->keydef->seg : NULL;
00185
00186 init_block(&share->recordspace.block, chunk_length, min_records, max_records);
00187
00188 memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
00189 for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
00190 {
00191 keyinfo->seg= keyseg;
00192 memcpy(keyseg, keydef[i].seg,
00193 (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
00194 keyseg+= keydef[i].keysegs;
00195 {
00196 init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
00197 max_records);
00198 keyinfo->hash_buckets= 0;
00199 }
00200 if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
00201 share->auto_key= i + 1;
00202 }
00203 share->min_records= min_records;
00204 share->max_records= max_records;
00205 share->max_table_size= create_info->max_table_size;
00206 share->index_length= 0;
00207 share->blength= 1;
00208 share->keys= keys;
00209 share->max_key_length= max_length;
00210 share->column_count= columns;
00211 share->changed= 0;
00212 share->auto_key= create_info->auto_key;
00213 share->auto_key_type= create_info->auto_key_type;
00214 share->auto_increment= create_info->auto_increment;
00215
00216 share->fixed_data_length= fixed_data_length;
00217 share->fixed_column_count= fixed_column_count;
00218
00219 share->recordspace.chunk_length= chunk_length;
00220 share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
00221 share->recordspace.total_data_length= 0;
00222
00223 {
00224 share->recordspace.offset_link= 1<<22;
00225 share->recordspace.offset_status= chunk_dataspace_length;
00226 }
00227
00228
00229 share->name.append(name);
00230 if (!create_info->internal_table)
00231 {
00232 heap_share_list.push_front(share);
00233 }
00234 else
00235 share->delete_on_close= 1;
00236 }
00237 if (!create_info->internal_table)
00238 THR_LOCK_heap.unlock();
00239
00240 *res= share;
00241 return(0);
00242
00243 err:
00244 if (share && share->keydef && share->keydef->seg)
00245 delete [] share->keydef->seg;
00246 if (share && share->keydef)
00247 delete [] share->keydef;
00248 if (share)
00249 delete share;
00250 if (not create_info->internal_table)
00251 THR_LOCK_heap.unlock();
00252 return(1);
00253 }
00254
00255
00256 static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
00257 uint32_t max_records)
00258 {
00259 uint32_t recbuffer,records_in_block;
00260
00261 max_records= max(min_records,max_records);
00262 if (!max_records)
00263 max_records= 1000;
00264
00265
00266 recbuffer= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
00267 records_in_block= max_records / 10;
00268 if (records_in_block < 10 && max_records)
00269 records_in_block= 10;
00270 if (!records_in_block || records_in_block*recbuffer >
00271 (internal::my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
00272 records_in_block= (internal::my_default_record_cache_size - sizeof(HP_PTRS) *
00273 HP_MAX_LEVELS) / recbuffer + 1;
00274 block->records_in_block= records_in_block;
00275 block->recbuffer= recbuffer;
00276 block->last_allocated= 0L;
00277
00278 for (uint32_t i= 0; i <= HP_MAX_LEVELS; i++)
00279 {
00280 block->level_info[i].records_under_level=
00281 (!i ? 1 : i == 1 ? records_in_block :
00282 HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
00283 }
00284 }
00285
00286
00287 static inline void heap_try_free(HP_SHARE *share)
00288 {
00289 if (share->open_count == 0)
00290 hp_free(share);
00291 else
00292 share->delete_on_close= 1;
00293 }
00294
00295
00296 int heap_delete_table(const char *name)
00297 {
00298 int result;
00299 register HP_SHARE *share;
00300
00301 THR_LOCK_heap.lock();
00302 if ((share= hp_find_named_heap(name)))
00303 {
00304 heap_try_free(share);
00305 result= 0;
00306 }
00307 else
00308 {
00309 result= errno=ENOENT;
00310 }
00311 THR_LOCK_heap.unlock();
00312 return(result);
00313 }
00314
00315
00316 void hp_free(HP_SHARE *share)
00317 {
00318 heap_share_list.remove(share);
00319 hp_clear(share);
00320 if (share->keydef)
00321 delete [] share->keydef->seg;
00322 delete [] share->keydef;
00323 delete share;
00324 }