_check.c 5.64 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2006 MySQL AB
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6

unknown's avatar
unknown committed
7 8 9 10
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
unknown's avatar
unknown committed
11

unknown's avatar
unknown committed
12 13 14 15 16 17 18 19
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* Check that heap-structure is ok */

#include "heapdef.h"

unknown's avatar
unknown committed
20 21
static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
			 ulong blength, my_bool print_status);
unknown's avatar
unknown committed
22 23
static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
			    my_bool print_status);
unknown's avatar
unknown committed
24

unknown's avatar
unknown committed
25

unknown's avatar
unknown committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
/*
  Check if keys and rows are ok in a heap table

  SYNOPSIS
    heap_check_heap()
    info		Table handler
    print_status	Prints some extra status

  NOTES
    Doesn't change the state of the table handler

  RETURN VALUES
    0	ok
    1 error
*/
unknown's avatar
unknown committed
41

unknown's avatar
unknown committed
42
int heap_check_heap(HP_INFO *info, my_bool print_status)
unknown's avatar
unknown committed
43 44 45
{
  int error;
  uint key;
unknown's avatar
unknown committed
46
  ulong records=0, deleted=0, pos, next_block;
unknown's avatar
unknown committed
47
  HP_SHARE *share=info->s;
unknown's avatar
unknown committed
48 49
  HP_INFO save_info= *info;			/* Needed because scan_init */
  DBUG_ENTER("heap_check_heap");
unknown's avatar
unknown committed
50

unknown's avatar
unknown committed
51
  for (error=key= 0 ; key < share->keys ; key++)
52
  {
unknown's avatar
unknown committed
53 54 55 56 57
    if (share->keydef[key].algorithm == HA_KEY_ALG_BTREE)
      error|= check_one_rb_key(info, key, share->records, print_status);
    else
      error|= check_one_key(share->keydef + key, key, share->records,
			    share->blength, print_status);
58
  }
unknown's avatar
unknown committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
  /*
    This is basicly the same code as in hp_scan, but we repeat it here to
    get shorter DBUG log file.
  */
  for (pos=next_block= 0 ; ; pos++)
  {
    if (pos < next_block)
    {
      info->current_ptr+= share->block.recbuffer;
    }
    else
    {
      next_block+= share->block.records_in_block;
      if (next_block >= share->records+share->deleted)
      {
	next_block= share->records+share->deleted;
	if (pos >= next_block)
	  break;				/* End of file */
      }
    }
unknown's avatar
unknown committed
79
    hp_find_record(info,pos);
unknown's avatar
unknown committed
80 81 82 83 84 85

    if (!info->current_ptr[share->reclength])
      deleted++;
    else
      records++;
  }
unknown's avatar
unknown committed
86

unknown's avatar
unknown committed
87 88 89
  if (records != share->records || deleted != share->deleted)
  {
    DBUG_PRINT("error",("Found rows: %lu (%lu)  deleted %lu (%lu)",
unknown's avatar
unknown committed
90 91
			records, (ulong) share->records,
                        deleted, (ulong) share->deleted));
unknown's avatar
unknown committed
92 93 94
    error= 1;
  }
  *info= save_info;
unknown's avatar
unknown committed
95 96 97 98
  DBUG_RETURN(error);
}


unknown's avatar
unknown committed
99 100
static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
			 ulong blength, my_bool print_status)
unknown's avatar
unknown committed
101 102
{
  int error;
unknown's avatar
unknown committed
103 104 105
  ulong i,found,max_links,seek,links;
  ulong rec_link;				/* Only used with debugging */
  ulong hash_buckets_found;
unknown's avatar
unknown committed
106 107 108
  HASH_INFO *hash_info;

  error=0;
109
  hash_buckets_found= 0;
unknown's avatar
unknown committed
110 111 112
  for (i=found=max_links=seek=0 ; i < records ; i++)
  {
    hash_info=hp_find_hash(&keydef->block,i);
113 114
    if (hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
		blength,records) == i)
unknown's avatar
unknown committed
115 116 117 118 119 120 121
    {
      found++;
      seek++;
      links=1;
      while ((hash_info=hash_info->next_key) && found < records + 1)
      {
	seek+= ++links;
122 123
	if ((rec_link = hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
			        blength, records))
unknown's avatar
unknown committed
124 125
	    != i)
	{
unknown's avatar
unknown committed
126 127 128
	  DBUG_PRINT("error",
                     ("Record in wrong link: Link %lu  Record: 0x%lx  Record-link %lu",
                      i, (long) hash_info->ptr_to_rec, rec_link));
unknown's avatar
unknown committed
129 130 131 132 133 134
	  error=1;
	}
	else
	  found++;
      }
      if (links > max_links) max_links=links;
135
      hash_buckets_found++;
unknown's avatar
unknown committed
136 137 138 139
    }
  }
  if (found != records)
  {
140 141 142 143 144 145
    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",
unknown's avatar
unknown committed
146
                        hash_buckets_found, (long) keydef->hash_buckets));
unknown's avatar
unknown committed
147 148 149
    error=1;
  }
  DBUG_PRINT("info",
unknown's avatar
unknown committed
150 151
	     ("records: %ld   seeks: %lu   max links: %lu   hitrate: %.2f   "
              "buckets: %lu",
152
	      records,seek,max_links,
153 154
	      (float) seek / (float) (records ? records : 1), 
              hash_buckets_found));
unknown's avatar
unknown committed
155
  if (print_status)
unknown's avatar
unknown committed
156 157
    printf("Key: %d  records: %ld   seeks: %lu   max links: %lu   "
           "hitrate: %.2f   buckets: %lu\n",
158
	   keynr, records, seek, max_links,
159 160
	   (float) seek / (float) (records ? records : 1), 
           hash_buckets_found);
unknown's avatar
unknown committed
161 162
  return error;
}
unknown's avatar
unknown committed
163 164 165 166 167 168 169 170 171

static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
			    my_bool print_status)
{
  HP_KEYDEF *keydef= info->s->keydef + keynr;
  int error= 0;
  ulong found= 0;
  byte *key, *recpos;
  uint key_length;
172
  uint not_used[2];
unknown's avatar
unknown committed
173 174 175 176 177 178 179 180
  
  if ((key= tree_search_edge(&keydef->rb_tree, info->parents,
			     &info->last_pos, offsetof(TREE_ELEMENT, left))))
  {
    do
    {
      memcpy(&recpos, key + (*keydef->get_key_length)(keydef,key), sizeof(byte*));
      key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0);
unknown's avatar
unknown committed
181
      if (ha_key_cmp(keydef->seg, (uchar*) info->recbuf, (uchar*) key,
182
		     key_length, SEARCH_FIND | SEARCH_SAME, not_used))
unknown's avatar
unknown committed
183 184
      {
	error= 1;
unknown's avatar
unknown committed
185 186
	DBUG_PRINT("error",("Record in wrong link:  key: %u  Record: 0x%lx\n", 
			    keynr, (long) recpos));
unknown's avatar
unknown committed
187 188 189 190 191 192 193 194 195 196
      }
      else
	found++;
      key= tree_search_next(&keydef->rb_tree, &info->last_pos,
			    offsetof(TREE_ELEMENT, left), 
			    offsetof(TREE_ELEMENT, right));
    } while (key);
  }
  if (found != records)
  {
197
    DBUG_PRINT("error",("Found %lu of %lu records", found, records));
unknown's avatar
unknown committed
198 199 200 201 202 203
    error= 1;
  }
  if (print_status)
    printf("Key: %d  records: %ld\n", keynr, records);
  return error;
}