37 using namespace Glass;
42 while (n--) out->put(
' ');
47 out->write(
reinterpret_cast<const char *
>(p), n);
84 *out <<
' ' << escaped;
97 *out <<
"Block [" << n <<
"] level " << j <<
", revision *" <<
REVISION(p)
98 <<
" items (" << (dir_end -
DIR_START) /
D2 <<
") usage "
99 << block_usage(p) <<
"%:\n";
111 int space = block_size -
DIR_END(p);
113 return (space - free) * 100 / space;
125 *out <<
"[" << n <<
"] *" <<
REVISION(p) <<
" ("
126 << (dir_end -
DIR_START) /
D2 <<
") " << block_usage(p) <<
"% ";
129 if (c >=
DIR_START + 6 && c < dir_end - 6) {
140 XAPIAN_NORETURN(
static void failure(
const char *msg,
uint4 n,
int c = 0));
159 const uint8_t * p = C_[j].
get_p();
167 int total_free = block_size - dir_end;
170 failure(
"used more than once in the Btree", n);
175 if (dir_end <= DIR_START || dir_end >
int(block_size) || (dir_end & 1) != 1)
176 failure(
"directory end pointer invalid", n);
179 report_block(3 * (level - j), n, p);
182 report_block_full(3 * (level - j), n, p);
188 if (o >
int(block_size))
189 failure(
"item starts outside block", n, c);
190 if (o - dir_end <
int(max_free))
191 failure(
"item overlaps directory", n, c);
193 int kt_len = item.
size();
194 if (o + kt_len >
int(block_size))
195 failure(
"item ends outside block", n, c);
196 total_free -= kt_len;
199 failure(
"not in sorted order", n, c);
205 if (o >
int(block_size))
206 failure(
"item starts outside block", n, c);
207 if (o - dir_end <
int(max_free))
208 failure(
"item overlaps directory", n, c);
210 int kt_len = item.
size();
211 if (o + kt_len >
int(block_size))
212 failure(
"item ends outside block", n, c);
213 total_free -= kt_len;
216 failure(
"not in sorted order", n, c);
220 failure(
"stored total free space value wrong", n);
225 block_to_cursor(C_, j - 1,
BItem(p, c).block_given_by());
227 block_check(C_, j - 1,
opts, flcheck);
229 const uint8_t * q = C_[j - 1].
get_p();
235 failure(
"leaf key < left dividing key in level above", n, c);
242 failure(
"key < left dividing key in level above", n, c);
247 if (c +
D2 < dir_end) {
250 failure(
"leaf key >= right dividing key in level above", n, c);
253 failure(
"key >= right dividing key in level above", n, c);
258 failure(
"block has greater revision than parent", n);
268 string filename(path);
270 filename += tablename;
273 AutoPtr<GlassTableCheck>
B(
279 if (strcmp(tablename,
"postlist") == 0) {
281 }
else if (strcmp(tablename,
"docdata") == 0) {
283 }
else if (strcmp(tablename,
"termlist") == 0) {
285 }
else if (strcmp(tablename,
"position") == 0) {
287 }
else if (strcmp(tablename,
"spelling") == 0) {
289 }
else if (strcmp(tablename,
"synonym") == 0) {
292 string e =
"Unknown table: ";
301 *out <<
"blocksize=" <<
B->block_size / 1024 <<
"K"
302 " items=" <<
B->item_count
303 <<
" firstunused=" <<
B->free_list.get_first_unused_block()
304 <<
" revision=" <<
B->revision_number
305 <<
" levels=" <<
B->level
307 if (
B->faked_root_block)
310 *out <<
C[
B->level].get_n();
314 if (
B->faked_root_block) {
323 B->block_check(
C,
B->level,
opts, flcheck);
327 if (
B->free_list.empty())
330 while (!
B->free_list.empty()) {
331 uint4 n =
B->free_list.walk(
B.get(),
B->block_size,
true);
337 failure(
"Same block is in freelist more than once", n);
342 failure(
"Used block also in freelist", n);
351 if (count && fd < 0) {
352 string e =
str(count);
353 e +=
" unused block(s) missing from the free list, first is ";
358 if (out &&
opts) *out <<
"B-tree checked okay" << endl;
365 for (
int i = 0; i <= level; ++i)
366 *out <<
"p=" << C_[i].get_p() <<
", "
367 "c=" << C_[i].
c <<
", "
368 "n=[" << C_[i].
get_n() <<
"], "
369 "rewrite=" << C_[i].
rewrite << endl;
Wrapper around standard unique_ptr template.
uint4 count_set_bits(uint4 *p_first_bad_blk) const
Count how many bits are still set.
void print_bytes(int n, const uint8_t *p) const
static GlassTableCheck * check(const char *tablename, const std::string &path, int fd, off_t offset_, const GlassVersion &version_file, int opts, std::ostream *out)
void print_tag(const uint8_t *p, int c, int j) const
void report_cursor(int N, const Glass::Cursor *C_) const
void report_block(int m, int n, const uint8_t *p) const
GlassTableCheck::report_block(m, n, p) prints the block at p, block number n, indented by m spaces.
int block_usage(const uint8_t *p) const
void block_check(Glass::Cursor *C_, int j, int opts, GlassFreeListChecker &flcheck)
void print_spaces(int n) const
void print_key(const uint8_t *p, int c, int j) const
void report_block_full(int m, int n, const uint8_t *p) const
The GlassVersion class manages the revision files.
const RootInfo & get_root(Glass::table_type tbl) const
glass_revision_number_t get_revision() const
uint4 block_given_by() const
Get this item's tag as a block number (this block should not be at level 0).
int size() const
SIZE in diagram above.
bool rewrite
true if the block is not the same as on disk, and so needs rewriting
int c
offset in the block's directory
uint4 get_n() const
Get the block number.
const uint8_t * get_p() const
Get pointer to block.
void read(std::string *key) const
int size() const
SIZE in diagram above.
bool last_component() const
void append_chunk(std::string *tag) const
DatabaseError indicates some sort of database related error.
Constants in the Xapian namespace.
Append a string to an object description, escaping invalid UTF-8.
static void failure(const char *msg, uint4 n, int c=0)
int DIR_END(const uint8_t *b)
int compare(ITEM1 a, ITEM2 b)
Compare two items by their keys.
int TOTAL_FREE(const uint8_t *b)
int GET_LEVEL(const uint8_t *b)
int MAX_FREE(const uint8_t *b)
uint4 REVISION(const uint8_t *b)
string str(int value)
Convert int to std::string.
const int DBCHECK_SHOW_FREELIST
Show the bitmap for the B-tree.
const int DBCHECK_SHOW_STATS
Show statistics for the B-tree.
const int DBCHECK_SHORT_TREE
Show a short-format display of the B-tree contents.
const int DBCHECK_FULL_TREE
Show a full display of the B-tree contents.
void description_append(std::string &desc, const std::string &s)