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