1 /* Copyright (c) 2000, 2002-2007 MySQL AB
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.
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.
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 */
16 /* Check that heap-structure is ok */
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
);
27 Check if keys and rows are ok in a heap table
32 print_status Prints some extra status
35 Doesn't change the state of the table handler
42 int heap_check_heap(HP_INFO
*info
, my_bool print_status
)
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");
51 for (error
=key
= 0 ; key
< share
->keys
; key
++)
53 if (share
->keydef
[key
].algorithm
== HA_KEY_ALG_BTREE
)
54 error
|= check_one_rb_key(info
, key
, share
->records
, print_status
);
56 error
|= check_one_key(share
->keydef
+ key
, key
, share
->records
,
57 share
->blength
, print_status
);
60 This is basicly the same code as in hp_scan, but we repeat it here to
61 get shorter DBUG log file.
63 for (pos
=next_block
= 0 ; ; pos
++)
67 info
->current_ptr
+= share
->block
.recbuffer
;
71 next_block
+= share
->block
.records_in_block
;
72 if (next_block
>= share
->records
+share
->deleted
)
74 next_block
= share
->records
+share
->deleted
;
75 if (pos
>= next_block
)
76 break; /* End of file */
79 hp_find_record(info
,pos
);
81 if (!info
->current_ptr
[share
->reclength
])
87 if (records
!= share
->records
|| deleted
!= share
->deleted
)
89 DBUG_PRINT("error",("Found rows: %lu (%lu) deleted %lu (%lu)",
90 records
, (ulong
) share
->records
,
91 deleted
, (ulong
) share
->deleted
));
99 static int check_one_key(HP_KEYDEF
*keydef
, uint keynr
, ulong records
,
100 ulong blength
, my_bool print_status
)
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
;
109 hash_buckets_found
= 0;
110 for (i
=found
=max_links
=seek
=0 ; i
< records
; i
++)
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
)
119 while ((hash_info
=hash_info
->next_key
) && found
< records
+ 1)
122 if ((rec_link
= hp_mask(hp_rec_hashnr(keydef
, hash_info
->ptr_to_rec
),
127 ("Record in wrong link: Link %lu Record: 0x%lx Record-link %lu",
128 i
, (long) hash_info
->ptr_to_rec
, rec_link
));
134 if (links
> max_links
) max_links
=links
;
135 hash_buckets_found
++;
138 if (found
!= records
)
140 DBUG_PRINT("error",("Found %ld of %ld records", found
, records
));
143 if (keydef
->hash_buckets
!= hash_buckets_found
)
145 DBUG_PRINT("error",("Found %ld buckets, stats shows %ld buckets",
146 hash_buckets_found
, (long) keydef
->hash_buckets
));
150 ("records: %ld seeks: %lu max links: %lu hitrate: %.2f "
152 records
,seek
,max_links
,
153 (float) seek
/ (float) (records
? records
: 1),
154 hash_buckets_found
));
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),
164 static int check_one_rb_key(HP_INFO
*info
, uint keynr
, ulong records
,
165 my_bool print_status
)
167 HP_KEYDEF
*keydef
= info
->s
->keydef
+ keynr
;
174 if ((key
= tree_search_edge(&keydef
->rb_tree
, info
->parents
,
175 &info
->last_pos
, offsetof(TREE_ELEMENT
, left
))))
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
))
185 DBUG_PRINT("error",("Record in wrong link: key: %u Record: 0x%lx\n",
186 keynr
, (long) recpos
));
190 key
= tree_search_next(&keydef
->rb_tree
, &info
->last_pos
,
191 offsetof(TREE_ELEMENT
, left
),
192 offsetof(TREE_ELEMENT
, right
));
195 if (found
!= records
)
197 DBUG_PRINT("error",("Found %lu of %lu records", found
, records
));
201 printf("Key: %d records: %ld\n", keynr
, records
);