~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/_check.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}