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;
215 if (c > significant_c &&
compare(
BItem(p, c - D2), item) >= 0)
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);
332 if (opts & Xapian::DBCHECK_SHOW_FREELIST)
335 if (opts & Xapian::DBCHECK_SHOW_FREELIST)
337 failure(
"Same block is in freelist more than once", n);
340 if (opts & Xapian::DBCHECK_SHOW_FREELIST)
342 failure(
"Used block also in freelist", n);
345 if (opts & Xapian::DBCHECK_SHOW_FREELIST)
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;
const RootInfo & get_root(Glass::table_type tbl) const
int TOTAL_FREE(const uint8_t *b)
uint4 REVISION(const uint8_t *b)
Constants in the Xapian namespace.
The GlassVersion class manages the revision files.
void print_tag(const uint8_t *p, int c, int j) 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...
const int DBCHECK_SHOW_FREELIST
Show the bitmap for the B-tree.
int size() const
SIZE in diagram above.
void print_bytes(int n, const uint8_t *p) const
int MAX_FREE(const uint8_t *b)
int compare(ITEM1 a, ITEM2 b)
Compare two items by their keys.
static void failure(const char *msg, uint4 n, int c=0)
void read(std::string *key) const
const int DBCHECK_FULL_TREE
Show a full display of the B-tree contents.
void description_append(std::string &desc, const std::string &s)
int GET_LEVEL(const uint8_t *b)
string str(int value)
Convert int to std::string.
uint4 count_set_bits(uint4 *p_first_bad_blk) const
Count how many bits are still set.
void report_cursor(int N, const Glass::Cursor *C_) const
bool last_component() const
void report_block_full(int m, int n, const uint8_t *p) const
int DIR_END(const uint8_t *b)
static GlassTableCheck * check(const char *tablename, const std::string &path, int fd, off_t offset_, const GlassVersion &version_file, int opts, std::ostream *out)
Append a string to an object description, escaping invalid UTF-8.
int size() const
SIZE in diagram above.
void block_check(Glass::Cursor *C_, int j, int opts, GlassFreeListChecker &flcheck)
void append_chunk(std::string *tag) const
int c
offset in the block's directory
int block_usage(const uint8_t *p) const
void print_key(const uint8_t *p, int c, int j) const
void print_spaces(int n) const
const uint8_t * get_p() const
Get pointer to block.
DatabaseError indicates some sort of database related error.
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).
uint4 get_n() const
Get the block number.
Wrapper around standard unique_ptr template.
const int DBCHECK_SHORT_TREE
Show a short-format display of the B-tree contents.
bool rewrite
true if the block is not the same as on disk, and so needs rewriting
const int DBCHECK_SHOW_STATS
Show statistics for the B-tree.