00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "heap_priv.h"
00019 #ifdef __WIN__
00020 #include <fcntl.h>
00021 #endif
00022
00023 #include <drizzled/error_t.h>
00024
00025 #define LOWFIND 1
00026 #define LOWUSED 2
00027 #define HIGHFIND 4
00028 #define HIGHUSED 8
00029
00030 using namespace drizzled;
00031
00032 static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
00033 uint32_t records);
00034
00035 int heap_write(HP_INFO *info, const unsigned char *record)
00036 {
00037 HP_KEYDEF *keydef, *end;
00038 unsigned char *pos;
00039 HP_SHARE *share=info->getShare();
00040
00041 if ((share->records >= share->max_records && share->max_records) ||
00042 (share->recordspace.total_data_length + share->index_length >= share->max_table_size))
00043 {
00044 return(errno=HA_ERR_RECORD_FILE_FULL);
00045 }
00046
00047 if (!(pos=hp_allocate_chunkset(&share->recordspace, 1)))
00048 return(errno);
00049 share->changed=1;
00050
00051 for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
00052 keydef++)
00053 {
00054 if (hp_write_key(info, keydef, record, pos))
00055 goto err;
00056 }
00057
00058 hp_copy_record_data_to_chunkset(share, record, pos);
00059
00060 if (++share->records == share->blength)
00061 share->blength+= share->blength;
00062
00063 info->current_ptr=pos;
00064 info->current_hash_ptr=0;
00065 info->update|=HA_STATE_AKTIV;
00066 if (share->auto_key)
00067 heap_update_auto_increment(info, record);
00068 return(0);
00069
00070 err:
00071 info->errkey= keydef - share->keydef;
00072 while (keydef >= share->keydef)
00073 {
00074 if (hp_delete_key(info, keydef, record, pos, 0))
00075 break;
00076 keydef--;
00077 }
00078
00079 hp_free_chunks(&share->recordspace, pos);
00080
00081 return(errno);
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
00110 const unsigned char *record, unsigned char *recpos)
00111 {
00112 HP_SHARE *share = info->getShare();
00113 int flag;
00114 uint32_t halfbuff,hashnr,first_index;
00115 unsigned char *ptr_to_rec= NULL,*ptr_to_rec2= NULL;
00116 HASH_INFO *empty, *gpos= NULL, *gpos2= NULL, *pos;
00117
00118 flag=0;
00119 if (!(empty= hp_find_free_hash(share,&keyinfo->block,share->records)))
00120 return(-1);
00121 halfbuff= (long) share->blength >> 1;
00122 pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff));
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 if (pos != empty)
00141 {
00142 do
00143 {
00144 hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
00145 if (flag == 0)
00146 {
00147
00148
00149
00150
00151 if (hp_mask(hashnr, share->blength, share->records) != first_index)
00152 break;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 if (!(hashnr & halfbuff))
00166 {
00167
00168 if (!(flag & LOWFIND))
00169 {
00170
00171 if (flag & HIGHFIND)
00172 {
00173 flag=LOWFIND | HIGHFIND;
00174
00175 gpos=empty;
00176 ptr_to_rec=pos->ptr_to_rec;
00177 empty=pos;
00178 }
00179 else
00180 {
00181
00182
00183
00184
00185 flag=LOWFIND | LOWUSED;
00186 gpos=pos;
00187 ptr_to_rec=pos->ptr_to_rec;
00188 }
00189 }
00190 else
00191 {
00192
00193 if (!(flag & LOWUSED))
00194 {
00195
00196 gpos->ptr_to_rec=ptr_to_rec;
00197 gpos->next_key=pos;
00198 flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED);
00199 }
00200 gpos=pos;
00201 ptr_to_rec=pos->ptr_to_rec;
00202 }
00203 }
00204 else
00205 {
00206
00207 if (!(flag & HIGHFIND))
00208 {
00209 flag= (flag & LOWFIND) | HIGHFIND;
00210
00211 gpos2= empty;
00212 empty= pos;
00213 ptr_to_rec2=pos->ptr_to_rec;
00214 }
00215 else
00216 {
00217 if (!(flag & HIGHUSED))
00218 {
00219
00220 gpos2->ptr_to_rec=ptr_to_rec2;
00221 gpos2->next_key=pos;
00222 flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED);
00223 }
00224 gpos2=pos;
00225 ptr_to_rec2=pos->ptr_to_rec;
00226 }
00227 }
00228 }
00229 while ((pos=pos->next_key));
00230
00231 if ((flag & (LOWFIND | HIGHFIND)) == (LOWFIND | HIGHFIND))
00232 {
00233
00234
00235
00236
00237 keyinfo->hash_buckets++;
00238 }
00239
00240 if ((flag & (LOWFIND | LOWUSED)) == LOWFIND)
00241 {
00242 gpos->ptr_to_rec=ptr_to_rec;
00243 gpos->next_key=0;
00244 }
00245 if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND)
00246 {
00247 gpos2->ptr_to_rec=ptr_to_rec2;
00248 gpos2->next_key=0;
00249 }
00250 }
00251
00252
00253 pos=hp_find_hash(&keyinfo->block, hp_mask(hp_rec_hashnr(keyinfo, record),
00254 share->blength, share->records + 1));
00255 if (pos == empty)
00256 {
00257 pos->ptr_to_rec=recpos;
00258 pos->next_key=0;
00259 keyinfo->hash_buckets++;
00260 }
00261 else
00262 {
00263
00264 empty[0]=pos[0];
00265 gpos=hp_find_hash(&keyinfo->block,
00266 hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
00267 share->blength, share->records + 1));
00268 if (pos == gpos)
00269 {
00270 pos->ptr_to_rec=recpos;
00271 pos->next_key=empty;
00272 }
00273 else
00274 {
00275 keyinfo->hash_buckets++;
00276 pos->ptr_to_rec=recpos;
00277 pos->next_key=0;
00278 hp_movelink(pos, gpos, empty);
00279 }
00280
00281
00282 if ((keyinfo->flag & HA_NOSAME) && pos == gpos &&
00283 (!(keyinfo->flag & HA_NULL_PART_KEY) ||
00284 !hp_if_null_in_key(keyinfo, record)))
00285 {
00286 pos=empty;
00287 do
00288 {
00289 if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
00290 {
00291 return(errno=HA_ERR_FOUND_DUPP_KEY);
00292 }
00293 } while ((pos=pos->next_key));
00294 }
00295 }
00296 return(0);
00297 }
00298
00299
00300
00301 static HASH_INFO *hp_find_free_hash(HP_SHARE *info,
00302 HP_BLOCK *block, uint32_t records)
00303 {
00304 uint32_t block_pos;
00305 size_t length;
00306
00307 if (records < block->last_allocated)
00308 return hp_find_hash(block,records);
00309 if (!(block_pos=(records % block->records_in_block)))
00310 {
00311 if (hp_get_new_block(block,&length))
00312 return(NULL);
00313 info->index_length+=length;
00314 }
00315 block->last_allocated=records+1;
00316 return((HASH_INFO*) ((unsigned char*) block->level_info[0].last_blocks+
00317 block_pos*block->recbuffer));
00318 }