MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
_check.c
1 /* Copyright (C) 2000-2006 MySQL AB
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 /* Check that heap-structure is ok */
17 
18 #include "heapdef.h"
19 
20 static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
21  ulong blength, my_bool print_status);
22 static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
23  my_bool print_status);
24 
25 
26 /*
27  Check if keys and rows are ok in a heap table
28 
29  SYNOPSIS
30  heap_check_heap()
31  info Table handler
32  print_status Prints some extra status
33 
34  NOTES
35  Doesn't change the state of the table handler
36 
37  RETURN VALUES
38  0 ok
39  1 error
40 */
41 
42 int heap_check_heap(HP_INFO *info, my_bool print_status)
43 {
44  int error;
45  uint key;
46  ulong records=0, deleted=0, pos, next_block;
47  HP_SHARE *share=info->s;
48  HP_INFO save_info= *info; /* Needed because scan_init */
49  DBUG_ENTER("heap_check_heap");
50 
51  for (error=key= 0 ; key < share->keys ; key++)
52  {
53  if (share->keydef[key].algorithm == HA_KEY_ALG_BTREE)
54  error|= check_one_rb_key(info, key, share->records, print_status);
55  else
56  error|= check_one_key(share->keydef + key, key, share->records,
57  share->blength, print_status);
58  }
59  /*
60  This is basicly the same code as in hp_scan, but we repeat it here to
61  get shorter DBUG log file.
62  */
63  for (pos=next_block= 0 ; ; pos++)
64  {
65  if (pos < next_block)
66  {
67  info->current_ptr+= share->block.recbuffer;
68  }
69  else
70  {
71  next_block+= share->block.records_in_block;
72  if (next_block >= share->records+share->deleted)
73  {
74  next_block= share->records+share->deleted;
75  if (pos >= next_block)
76  break; /* End of file */
77  }
78  }
79  hp_find_record(info,pos);
80 
81  if (!info->current_ptr[share->reclength])
82  deleted++;
83  else
84  records++;
85  }
86 
87  if (records != share->records || deleted != share->deleted)
88  {
89  DBUG_PRINT("error",("Found rows: %lu (%lu) deleted %lu (%lu)",
90  records, (ulong) share->records,
91  deleted, (ulong) share->deleted));
92  error= 1;
93  }
94  *info= save_info;
95  DBUG_RETURN(error);
96 }
97 
98 
99 static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
100  ulong blength, my_bool print_status)
101 {
102  int error;
103  ulong i,found,max_links,seek,links;
104  ulong rec_link; /* Only used with debugging */
105  ulong hash_buckets_found;
106  HASH_INFO *hash_info;
107 
108  error=0;
109  hash_buckets_found= 0;
110  for (i=found=max_links=seek=0 ; i < records ; i++)
111  {
112  hash_info=hp_find_hash(&keydef->block,i);
113  if (hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
114  blength,records) == i)
115  {
116  found++;
117  seek++;
118  links=1;
119  while ((hash_info=hash_info->next_key) && found < records + 1)
120  {
121  seek+= ++links;
122  if ((rec_link = hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
123  blength, records))
124  != i)
125  {
126  DBUG_PRINT("error",
127  ("Record in wrong link: Link %lu Record: 0x%lx Record-link %lu",
128  i, (long) hash_info->ptr_to_rec, rec_link));
129  error=1;
130  }
131  else
132  found++;
133  }
134  if (links > max_links) max_links=links;
135  hash_buckets_found++;
136  }
137  }
138  if (found != records)
139  {
140  DBUG_PRINT("error",("Found %ld of %ld records", found, records));
141  error=1;
142  }
143  if (keydef->hash_buckets != hash_buckets_found)
144  {
145  DBUG_PRINT("error",("Found %ld buckets, stats shows %ld buckets",
146  hash_buckets_found, (long) keydef->hash_buckets));
147  error=1;
148  }
149  DBUG_PRINT("info",
150  ("records: %ld seeks: %lu max links: %lu hitrate: %.2f "
151  "buckets: %lu",
152  records,seek,max_links,
153  (float) seek / (float) (records ? records : 1),
154  hash_buckets_found));
155  if (print_status)
156  printf("Key: %d records: %ld seeks: %lu max links: %lu "
157  "hitrate: %.2f buckets: %lu\n",
158  keynr, records, seek, max_links,
159  (float) seek / (float) (records ? records : 1),
160  hash_buckets_found);
161  return error;
162 }
163 
164 static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
165  my_bool print_status)
166 {
167  HP_KEYDEF *keydef= info->s->keydef + keynr;
168  int error= 0;
169  ulong found= 0;
170  uchar *key, *recpos;
171  uint key_length;
172  uint not_used[2];
173 
174  if ((key= tree_search_edge(&keydef->rb_tree, info->parents,
175  &info->last_pos, offsetof(TREE_ELEMENT, left))))
176  {
177  do
178  {
179  memcpy(&recpos, key + (*keydef->get_key_length)(keydef,key), sizeof(uchar*));
180  key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0);
181  if (ha_key_cmp(keydef->seg, (uchar*) info->recbuf, (uchar*) key,
182  key_length, SEARCH_FIND | SEARCH_SAME, not_used))
183  {
184  error= 1;
185  DBUG_PRINT("error",("Record in wrong link: key: %u Record: 0x%lx\n",
186  keynr, (long) recpos));
187  }
188  else
189  found++;
190  key= tree_search_next(&keydef->rb_tree, &info->last_pos,
191  offsetof(TREE_ELEMENT, left),
192  offsetof(TREE_ELEMENT, right));
193  } while (key);
194  }
195  if (found != records)
196  {
197  DBUG_PRINT("error",("Found %lu of %lu records", found, records));
198  error= 1;
199  }
200  if (print_status)
201  printf("Key: %d records: %ld\n", keynr, records);
202  return error;
203 }