static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, ulong blength, my_bool print_status) { int error; ulong i,found,max_links,seek,links; ulong rec_link; /* Only used with debugging */ ulong hash_buckets_found; HASH_INFO *hash_info; error=0; hash_buckets_found= 0; for (i=found=max_links=seek=0 ; i < records ; i++) { hash_info=hp_find_hash(&keydef->block,i); if (hash_info->hash_of_key != hp_rec_hashnr(keydef, hash_info->ptr_to_rec)) { DBUG_PRINT("error", ("Found row with wrong hash_of_key at position %lu", i)); error= 1; } if (hp_mask(hash_info->hash_of_key, blength, records) == i) { found++; seek++; links=1; while ((hash_info=hash_info->next_key) && found < records + 1) { seek+= ++links; if ((rec_link= hp_mask(hash_info->hash_of_key, blength, records)) != i) { DBUG_PRINT("error", ("Record in wrong link: Link %lu Record: 0x%lx Record-link %lu", i, (long) hash_info->ptr_to_rec, rec_link)); error=1; } else found++; } if (links > max_links) max_links=links; hash_buckets_found++; } } if (found != records) { DBUG_PRINT("error",("Found %ld of %ld records", found, records)); error=1; } if (keydef->hash_buckets != hash_buckets_found) { DBUG_PRINT("error",("Found %ld buckets, stats shows %ld buckets", hash_buckets_found, (long) keydef->hash_buckets)); error=1; } DBUG_PRINT("info", ("key: %u records: %ld seeks: %lu max links: %lu " "hitrate: %.2f buckets: %lu", keynr, records,seek,max_links, (float) seek / (float) (records ? records : 1), hash_buckets_found)); if (print_status) printf("Key: %u records: %ld seeks: %lu max links: %lu " "hitrate: %.2f buckets: %lu\n", keynr, records, seek, max_links, (float) seek / (float) (records ? records : 1), hash_buckets_found); return error; }
uchar *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key, uint nextflag) { HASH_INFO *pos,*prev_ptr; int flag; uint old_nextflag; HP_SHARE *share=info->s; DBUG_ENTER("hp_search"); old_nextflag=nextflag; flag=1; prev_ptr=0; if (share->records) { pos=hp_find_hash(&keyinfo->block, hp_mask(hp_hashnr(keyinfo, key), share->blength, share->records)); do { if (!hp_key_cmp(keyinfo, pos->ptr_to_rec, key)) { switch (nextflag) { case 0: /* Search after key */ DBUG_PRINT("exit", ("found key at 0x%lx", (long) pos->ptr_to_rec)); info->current_hash_ptr=pos; DBUG_RETURN(info->current_ptr= pos->ptr_to_rec); case 1: /* Search next */ if (pos->ptr_to_rec == info->current_ptr) nextflag=0; break; case 2: /* Search previous */ if (pos->ptr_to_rec == info->current_ptr) { set_my_errno(HA_ERR_KEY_NOT_FOUND); /* If gpos == 0 */ info->current_hash_ptr=prev_ptr; DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0); } prev_ptr=pos; /* Prev. record found */ break; case 3: /* Search same */ if (pos->ptr_to_rec == info->current_ptr) { info->current_hash_ptr=pos; DBUG_RETURN(info->current_ptr); } } } if (flag) { flag=0; /* Reset flag */ if (hp_find_hash(&keyinfo->block, hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec), share->blength, share->records)) != pos) break; /* Wrong link */ } } while ((pos=pos->next_key)); } set_my_errno(HA_ERR_KEY_NOT_FOUND); if (nextflag == 2 && ! info->current_ptr) { /* Do a previous from end */ info->current_hash_ptr=prev_ptr; DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0); } if (old_nextflag && nextflag) set_my_errno(HA_ERR_RECORD_CHANGED); /* Didn't find old record */ DBUG_PRINT("exit",("Error: %d",my_errno())); info->current_hash_ptr=0; DBUG_RETURN((info->current_ptr= 0)); }