~drizzle-trunk/drizzle/development

1 by brian
clean slate
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
}