50 #include <sys/types.h>
74 #undef BTREE_DEBUG_FULL
76 #ifdef BTREE_DEBUG_FULL
79 static void print_key(
const uint8_t * p,
int c,
int j);
80 static void print_tag(
const uint8_t * p,
int c,
int j);
98 uint8_t *temp =
new uint8_t[size];
99 memset(temp, 0, size);
151 #define SEQ_START_POINT (-10)
166 #define BYTE_PAIR_RANGE (1 << 2 * CHAR_BIT)
173 LOGCALL_VOID(DB,
"ChertTable::read_block", n | (
void*)p);
174 if (
rare(handle == -2))
180 Assert(n / CHAR_BIT < base.get_bit_map_size());
182 io_read_block(handle,
reinterpret_cast<char *
>(p), block_size, n);
185 if (
rare(dir_end <
DIR_START ||
unsigned(dir_end) > block_size)) {
186 string msg(
"dir_end invalid in block ");
204 Assert(n / CHAR_BIT < base.get_bit_map_size());
222 latest_revision_number = revision_number;
225 io_write_block(handle,
reinterpret_cast<const char *
>(p), block_size, n);
253 LOGCALL_VOID(DB,
"ChertTable::set_overwritten", NO_ARGS);
258 throw Xapian::DatabaseModifiedError(
"The revision being read has been discarded - you should call Xapian::Database::reopen() and retry the operation");
274 LOGCALL_VOID(DB,
"ChertTable::block_to_cursor", (
void*)C_ | j | n);
275 if (n == C_[j].n)
return;
276 uint8_t * p = C_[j].
p;
283 write_block(C_[j].n, p);
291 memcpy(p,
C[j].p, block_size);
306 string msg =
"Expected block ";
308 msg +=
" to be level ";
346 uint8_t * p =
C[j].p;
348 if (
C[j].rewrite)
return;
352 if (base.block_free_at_start(n)) {
358 n = base.next_free_block();
362 if (j == level)
return;
399 if (c < j && i < c &&
Item(p, c).key() <= key)
402 if (c < j && i < c && key <
Item(p, c).key())
407 int k = i + ((j - i)/(
D2 * 2))*
D2;
408 if (key <
Item(p, k).
key()) j = k;
else i = k;
435 LOGCALL(DB,
bool,
"ChertTable::find", (
void*)C_);
440 for (
int j = level; j > 0; --j) {
442 c = find_in_block(p, key,
false, C_[j].c);
443 #ifdef BTREE_DEBUG_FULL
444 printf(
"Block in ChertTable:find - code position 1");
445 report_block_full(j, C_[j].n, p);
448 block_to_cursor(C_, j - 1,
Item(p, c).block_given_by());
451 c = find_in_block(p, key,
true, C_[0].c);
452 #ifdef BTREE_DEBUG_FULL
453 printf(
"Block in ChertTable:find - code position 2");
454 report_block_full(0, C_[0].n, p);
474 uint8_t * b = buffer;
483 memmove(p + e, b + e, block_size - e);
508 C[level].n = base.next_free_block();
509 C[level].rewrite =
true;
519 add_item(item, level);
545 uint4 blocknumber =
C[j - 1].n;
549 const int newkey_len = newkey.
length();
557 const int min_len = min(newkey_len, prevkey.
length());
558 while (i < min_len && prevkey[i] == newkey[i]) {
563 if (i < newkey_len) i++;
572 uint8_t b[UCHAR_MAX + 6];
582 uint8_t * p =
C[j - 1].p;
586 auto byte_addr =
const_cast<uint8_t*
>(newkey.
get_address());
593 AssertEq(
C[j].c, find_in_block(
C[j].p, item.
key(),
false,
C[j].c));
606 LOGCALL(DB,
int,
"ChertTable::mid_point", (
void*)p);
609 int size = block_size -
TOTAL_FREE(p) - dir_end;
614 if (l < n - size)
RETURN(c);
641 int kt_len = kt_.
size();
642 int needed = kt_len +
D2;
653 memmove(p + c +
D2, p + c, dir_end - c);
657 int o = dir_end + new_max;
676 uint8_t * p =
C[j].p;
680 int needed = kt_.
size() +
D2;
699 C[j].n = base.next_free_block();
701 memcpy(split_p, p, block_size);
714 bool add_to_upper_half;
716 add_to_upper_half = (c >= m);
720 add_to_upper_half = (
TOTAL_FREE(split_p) < needed);
723 if (add_to_upper_half) {
728 add_item_to_block(p, kt_, c);
733 add_item_to_block(split_p, kt_, c);
736 write_block(split_n, split_p);
739 if (j == level) split_root(split_n);
754 add_item_to_block(p, kt_, c);
773 LOGCALL_VOID(DB,
"ChertTable::delete_item", j | repeatedly);
775 uint8_t * p =
C[j].p;
782 memmove(p + c, p + c +
D2, dir_end - c);
787 if (!repeatedly)
return;
790 base.free_block(
C[j].n);
791 C[j].rewrite =
false;
793 C[j + 1].rewrite =
true;
794 delete_item(j + 1,
true);
803 base.free_block(
C[level].n);
804 C[level].rewrite =
false;
808 block_to_cursor(
C, level, new_root);
848 LOGCALL(DB,
int,
"ChertTable::add_kt", found);
864 uint8_t * p =
C[0].p;
869 int kt_size = kt.size();
870 int needed = kt_size - item.
size();
877 kt.get_address(), kt_size);
881 int new_max =
MAX_FREE(p) - kt_size;
884 memmove(p + o, kt.get_address(), kt_size);
890 delete_item(0,
false);
896 if (changed_n ==
C[0].n && changed_c ==
C[0].c) {
897 if (seq_count < 0) seq_count++;
916 LOGCALL(DB,
int,
"ChertTable::delete_kt", NO_ARGS);
919 bool found = find(
C);
934 delete_item(0,
true);
980 LOGCALL_VOID(DB,
"ChertTable::add", key | tag | already_compressed);
983 if (handle < 0) create_and_open(block_size);
987 bool compressed =
false;
988 if (already_compressed) {
992 "DONT_COMPRESS clashes with zlib constant");
994 "DONT_COMPRESS clashes with zlib constant");
996 "DONT_COMPRESS clashes with zlib constant");
999 "DONT_COMPRESS clashes with zlib constant");
1002 lazy_alloc_deflate_zstream();
1004 deflate_zstream->next_in =
1005 reinterpret_cast<Bytef *
>(
const_cast<char *
>(tag.data()));
1006 deflate_zstream->avail_in =
static_cast<uInt
>(tag.size());
1009 unsigned long blk_len = tag.size() - 1;
1010 unsigned char * blk =
new unsigned char[blk_len];
1011 deflate_zstream->next_out = blk;
1012 deflate_zstream->avail_out =
static_cast<uInt
>(blk_len);
1014 int err = deflate(deflate_zstream, Z_FINISH);
1015 if (err == Z_STREAM_END) {
1018 tag.assign(
reinterpret_cast<const char *
>(blk), deflate_zstream->total_out);
1028 const size_t cd = kt.key().length() +
K1 +
I2 +
C2 +
C2;
1029 const size_t L = max_item_size - cd;
1031 bool found = find(
C);
1033 uint8_t * p =
C[0].p;
1049 size_t last = tag.length() % L;
1050 if (n >= last || (full_compaction && n >= key.size() + 34))
1056 int m = tag.empty() ? 1 : (tag.length() - first_L + L - 1) / L + 1;
1067 size_t residue = tag.length();
1068 int replacement =
false;
1070 kt.set_components_of(m);
1071 for (i = 1; i <= m; i++) {
1072 size_t l = (i == m ? residue : (i == 1 ? first_L : L));
1073 Assert(cd + l <= block_size);
1074 Assert(string::size_type(o + l) <= tag.length());
1075 kt.set_tag(cd, tag.data() + o, l, compressed);
1076 kt.set_component_of(i);
1081 if (i > 1) found = find(
C);
1083 if (n > 0) replacement =
true;
1086 for (i = m + 1; i <= n; i++) {
1087 kt.set_component_of(i);
1090 if (!replacement) ++item_count;
1091 Btree_modified =
true;
1092 if (cursor_created_since_last_modification) {
1093 cursor_created_since_last_modification =
false;
1107 LOGCALL(DB,
bool,
"ChertTable::del", key);
1120 if (key.empty())
RETURN(
false);
1123 int n = delete_kt();
1124 if (n <= 0)
RETURN(
false);
1126 for (
int i = 2; i <= n; i++) {
1127 kt.set_component_of(i);
1132 Btree_modified =
true;
1133 if (cursor_created_since_last_modification) {
1134 cursor_created_since_last_modification =
false;
1143 LOGCALL(DB,
bool,
"ChertTable::readahead_key", key);
1164 Key ktkey = kt.key();
1168 const uint8_t * p =
C[level].p;
1169 int c = find_in_block(p, ktkey,
false,
C[level].c);
1173 if (n != last_readahead && n !=
C[level - 1].n) {
1177 Assert(n / CHAR_BIT < base.get_bit_map_size());
1189 LOGCALL(DB,
bool,
"ChertTable::get_exact_entry", key | tag);
1205 (void)read_tag(
C, &tag,
false);
1212 LOGCALL(DB,
bool,
"ChertTable::key_exists", key);
1225 LOGCALL(DB,
bool,
"ChertTable::read_tag",
Literal(
"C_") | tag | keep_compressed);
1226 Item item(C_[0].p, C_[0].c);
1234 if (n > 1) tag->reserve((max_item_size - (1 +
K1 +
I2 +
C2 +
C2)) * n);
1239 for (
int i = 2; i <= n; i++) {
1247 if (!compressed || keep_compressed)
RETURN(compressed);
1255 utag.reserve(tag->size() + tag->size() / 2);
1259 lazy_alloc_inflate_zstream();
1261 inflate_zstream->next_in =
1262 reinterpret_cast<Bytef*
>(
const_cast<char *
>(tag->data()));
1263 inflate_zstream->avail_in =
static_cast<uInt
>(tag->size());
1266 while (err != Z_STREAM_END) {
1267 inflate_zstream->next_out = buf;
1268 inflate_zstream->avail_out =
static_cast<uInt
>(
sizeof(buf));
1269 err = inflate(inflate_zstream, Z_SYNC_FLUSH);
1270 if (err == Z_BUF_ERROR && inflate_zstream->avail_in == 0) {
1271 LOGLINE(DB,
"Z_BUF_ERROR - faking checksum of " << inflate_zstream->adler);
1274 inflate_zstream->next_in = header2;
1275 inflate_zstream->avail_in = 4;
1276 err = inflate(inflate_zstream, Z_SYNC_FLUSH);
1277 if (err == Z_STREAM_END)
break;
1280 if (err != Z_OK && err != Z_STREAM_END) {
1281 if (err == Z_MEM_ERROR)
throw std::bad_alloc();
1282 string msg =
"inflate failed";
1283 if (inflate_zstream->msg) {
1285 msg += inflate_zstream->msg;
1291 utag.append(
reinterpret_cast<const char *
>(buf),
1292 inflate_zstream->next_out - buf);
1294 if (utag.size() != inflate_zstream->total_out) {
1295 string msg =
"compressed tag didn't expand to the expected size: ";
1296 msg +=
str(utag.size());
1299 msg +=
str(
size_t(inflate_zstream->total_out));
1311 LOGCALL_VOID(DB,
"ChertTable::set_full_compaction", parity);
1314 if (parity) seq_count = 0;
1315 full_compaction = parity;
1335 LOGCALL(DB,
bool,
"ChertTable::basic_open", revision_supplied | revision_);
1339 const size_t BTREE_BASES = 2;
1341 static const char basenames[BTREE_BASES] = {
'A',
'B' };
1344 bool base_ok[BTREE_BASES];
1347 bool valid_base =
false;
1349 for (
size_t i = 0; i < BTREE_BASES; ++i) {
1350 bool ok = bases[i].
read(
name, basenames[i], writable, err_msg);
1365 string message =
"Error opening table '";
1372 if (revision_supplied) {
1373 bool found_revision =
false;
1374 for (
size_t i = 0; i < BTREE_BASES; ++i) {
1375 if (base_ok[i] && bases[i].get_revision() == revision_) {
1377 found_revision =
true;
1381 if (!found_revision) {
1390 for (
size_t i = 0; i < BTREE_BASES; ++i) {
1391 if (base_ok[i] && bases[i].get_revision() >= highest_revision) {
1401 for (
size_t i = 0; i < BTREE_BASES; ++i) {
1402 LOGLINE(DB,
"Checking (ch == " << ch <<
") against "
1403 "basenames[" << i <<
"] == " << basenames[i]);
1404 LOGLINE(DB,
"bases[" << i <<
"].get_revision() == " <<
1405 bases[i].get_revision());
1406 LOGLINE(DB,
"base_ok[" << i <<
"] == " << base_ok[i]);
1407 if (ch == basenames[i]) {
1411 size_t otherbase_num = 1 - i;
1412 if (base_ok[otherbase_num]) {
1413 other_base = &bases[otherbase_num];
1427 revision_number = base.get_revision();
1428 block_size = base.get_block_size();
1429 root = base.get_root();
1430 level = base.get_level();
1434 item_count = base.get_item_count();
1435 faked_root_block = base.get_have_fakeroot();
1436 sequential = base.get_sequential();
1438 if (other_base != 0) {
1440 if (revision_number > latest_revision_number)
1441 latest_revision_number = revision_number;
1443 latest_revision_number = revision_number;
1454 if (cursor_created_since_last_modification) {
1455 cursor_created_since_last_modification =
false;
1468 if (faked_root_block) {
1470 uint8_t * p =
C[0].p;
1476 memset(p, 0, block_size);
1478 int o = block_size -
I2 -
K1 -
C2 -
C2;
1497 C[0].n = base.next_free_block();
1501 block_to_cursor(
C, level, root);
1503 if (
REVISION(
C[level].p) > revision_number) set_overwritten();
1513 LOGCALL(DB,
bool,
"ChertTable::do_open_to_write", revision_supplied | revision_ | create_db);
1521 if (lazy && !create_db && errno == ENOENT) {
1522 revision_number = revision_;
1525 string message(create_db ?
"Couldn't create " :
"Couldn't open ");
1527 message +=
"DB read/write: ";
1532 if (!basic_open(revision_supplied, revision_)) {
1535 if (!revision_supplied) {
1546 for (
int j = 0; j <= level; j++) {
1548 C[j].p =
new uint8_t[block_size];
1550 split_p =
new uint8_t[block_size];
1563 bool readonly_,
int compress_strategy_,
bool lazy_)
1564 : tablename(tablename_),
1568 latest_revision_number(0),
1571 faked_root_block(
true),
1584 Btree_modified(
false),
1585 full_compaction(
false),
1586 writable(!readonly_),
1587 cursor_created_since_last_modification(
false),
1590 compress_strategy(compress_strategy_),
1591 deflate_zstream(NULL),
1592 inflate_zstream(NULL),
1596 LOGCALL_CTOR(DB,
"ChertTable", tablename_ | path_ | readonly_ | compress_strategy_ | lazy_);
1630 err = deflateInit2(
deflate_zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
1632 if (
rare(err != Z_OK)) {
1633 if (err == Z_MEM_ERROR) {
1636 throw std::bad_alloc();
1638 string msg =
"deflateInit2 failed (";
1669 if (
rare(err != Z_OK)) {
1670 if (err == Z_MEM_ERROR) {
1673 throw std::bad_alloc();
1675 string msg =
"inflateInit2 failed (";
1690 LOGCALL(DB,
bool,
"ChertTable::exists", NO_ARGS);
1709 LOGCALL_VOID(DB,
"ChertTable::set_block_size", block_size_);
1712 (block_size_ & (block_size_ - 1)) != 0) {
1721 LOGCALL_VOID(DB,
"ChertTable::create_and_open", block_size_);
1789 for (
int j =
level; j >= 0; j--) {
1814 for (
int j =
level; j >= 0; j--) {
1827 const string * changes_tail)
1875 string basefile =
name;
1886 (void)unlink(tmp.c_str());
1891 string msg(
"Couldn't update base file ");
1911 LOGCALL_VOID(DB,
"ChertTable::write_changed_blocks", changes_fd);
1920 io_write(changes_fd, buf.data(), buf.size());
1931 io_write(changes_fd, buf.data(), buf.size());
1937 io_write(changes_fd,
reinterpret_cast<const char *
>(p),
1949 io_write(changes_fd, buf.data(), buf.size());
1988 for (
int j = 0; j <=
level; j++) {
2009 LOGCALL(DB,
bool,
"ChertTable::do_open_to_read", revision_supplied | revision_);
2020 string message(
"Couldn't open ");
2022 message +=
"DB to read: ";
2027 if (!
basic_open(revision_supplied, revision_)) {
2030 if (revision_supplied) {
2040 for (
int j = 0; j <=
level; j++) {
2070 LOGLINE(DB,
"opening for particular revision at path " <<
name);
2101 uint8_t * p = C_[0].
p;
2105 if (n == 0)
RETURN(
false);
2119 for (j = 1; j <=
level; ++j) {
2120 if (n ==
C[j].n)
break;
2122 if (j <=
level)
continue;
2152 uint8_t * p = C_[0].
p;
2175 for (j = 1; j <=
level; ++j) {
2176 if (n ==
C[j].n)
break;
2178 if (j <=
level)
continue;
2205 LOGCALL(DB,
bool,
"ChertTable::prev_default",
Literal(
"C_") | j);
2206 uint8_t * p = C_[j].
p;
2228 LOGCALL(DB,
bool,
"ChertTable::next_default",
Literal(
"C_") | j);
2229 uint8_t * p = C_[j].
p;
2248 #ifdef BTREE_DEBUG_FULL
2249 printf(
"Block in ChertTable:next_default");
2250 report_block_full(j - 1, C_[j - 1].n, C_[j - 1].p);
2279 LOGCALL(DB,
bool,
"Key::operator<",
static_cast<const void*
>(key2.
p));
2281 int key2_len = key2.
length();
2282 if (key1_len == key2_len) {
2289 int k_smaller = (key2_len < key1_len ? key2_len : key1_len);
2292 int diff = memcmp(
p +
K1, key2.
p +
K1, k_smaller);
2293 if (diff != 0)
RETURN(diff < 0);
2297 RETURN(key1_len < key2_len);
2302 LOGCALL(DB,
bool,
"Key::operator==",
static_cast<const void*
>(key2.
p));
Btree base file implementation.
Interface to Btree cursors.
const size_t COMPRESS_MIN
#define SEQ_START_POINT
Flip to sequential addition block-splitting after this number of observed sequential additions (in ne...
static uint8_t * zeroed_new(size_t size)
void SET_LEVEL(uint8_t *b, int x)
void SET_MAX_FREE(uint8_t *b, int x)
int TOTAL_FREE(const uint8_t *b)
#define CHERT_BTREE_MAX_KEY_LEN
The largest possible value of a key_len.
int GET_LEVEL(const uint8_t *b)
unsigned REVISION(const uint8_t *b)
void SET_DIR_END(uint8_t *b, int x)
void SET_REVISION(uint8_t *b, uint4 rev)
const int BTREE_CURSOR_LEVELS
int DIR_END(const uint8_t *b)
int MAX_FREE(const uint8_t *b)
const size_t BLOCK_CAPACITY
Even for items of at maximum size, it must be possible to get this number of items in a block.
int getint4(const unsigned char *p, int c)
void setD(unsigned char *p, int c, int x)
void SET_TOTAL_FREE(uint8_t *b, int x)
#define CHERT_DEFAULT_BLOCK_SIZE
The default block size to use in a B-tree table.
unsigned int chert_revision_number_t
A type used to store a revision number for a table.
A cursor pointing to a position in a Btree table, for reading several entries in order,...
bool find_entry(const string &key)
Position the cursor on the highest entry with key <= key.
bool next()
Advance to the next key.
void set_root(uint4 root_)
void set_sequential(bool sequential_)
void write_to_file(const std::string &filename, char base_letter, const std::string &tablename, int changes_fd, const std::string *changes_tail)
Write the btree base file to disk.
bool find_changed_block(uint4 *n) const
Find the first changed block at or after position *n.
bool get_have_fakeroot() const
void set_level(uint4 level_)
chert_tablesize_t get_item_count() const
bool read(const std::string &name, char ch, bool read_bitmap, std::string &err_msg)
Read values from a base file.
void set_have_fakeroot(bool have_fakeroot_)
void set_block_size(uint4 block_size_)
void set_item_count(chert_tablesize_t item_count_)
uint4 get_block_size() const
void set_revision(uint4 revision_)
bool get_sequential() const
uint4 get_revision() const
uint4 get_last_block() const
void calculate_last_block()
Class managing a Btree table in a Chert database.
void open()
Open the btree at the latest revision.
void set_overwritten() const
bool do_open_to_read(bool revision_supplied, chert_revision_number_t revision_)
Perform the opening operation to read.
ChertCursor * cursor_get() const
Get a cursor for reading from the table.
int mid_point(uint8_t *p) const
mid_point(p) finds the directory entry in c that determines the approximate mid point of the data in ...
bool cursor_created_since_last_modification
Flag for tracking when cursors need to rebuild.
bool readahead_key(const string &key) const
bool basic_open(bool revision_supplied, chert_revision_number_t revision)
bool sequential
true iff the data has been written in a single write in sequential order.
bool next_default(Cursor *C_, int j) const
uint4 changed_n
the last block to be changed by an addition
void commit(chert_revision_number_t revision, int changes_fd=-1, const std::string *changes_tail=NULL)
Commit any outstanding changes to the table.
void read_block(uint4 n, uint8_t *p) const
read_block(n, p) reads block n of the DB file to address p.
bool writable
Set to true when the database is opened to write.
void set_block_size(unsigned int block_size_)
Set the block size.
static void throw_database_closed()
Throw an exception indicating that the database is closed.
void flush_db()
Flush any outstanding changes to the DB file of the table.
uint4 root
the root block of the B-tree
bool key_exists(const std::string &key) const
Check if a key exists in the Btree.
unsigned long cursor_version
Version count for tracking when cursors need to rebuild.
bool really_empty() const
Return true if there are no entries in the table.
ChertTable_base base
For writing back as file baseA or baseB.
z_stream * inflate_zstream
Zlib state object for inflating.
int changed_c
directory offset corresponding to last block to be changed by an addition
bool both_bases
set to true if baseA and baseB both exist as valid bases.
bool get_exact_entry(const std::string &key, std::string &tag) const
Read an entry from the table, if and only if it is exactly that being asked for.
int add_kt(bool found)
add_kt(found) adds the item (key-tag pair) at B->kt into the B-tree, using cursor C.
bool del(const std::string &key)
Delete an entry from the table.
int seq_count
count of the number of successive instances of purely sequential addition, starting at SEQ_START_POIN...
void write_changed_blocks(int changes_fd)
Append the list of blocks changed to a changeset file.
bool next_for_sequential(Cursor *C_, int dummy) const
void split_root(uint4 split_n)
Btree needs to gain a new level to insert more items: so split root block and construct a new one.
chert_revision_number_t revision_number
revision number of the opened B-tree.
void form_key(const std::string &key) const
void set_full_compaction(bool parity)
int level
number of levels, counting from 0
void add_item_to_block(uint8_t *p, Item_wr kt, int c)
add_item_to_block(p, kt_, c) adds item kt_ to the block at p.
ChertTable(const ChertTable &)
Copying not allowed.
bool do_open_to_write(bool revision_supplied, chert_revision_number_t revision_, bool create_db=false)
Perform the opening operation to write.
std::string name
The path name of the B tree.
uint8_t * split_p
Buffer used when splitting a block.
void write_block(uint4 n, const uint8_t *p) const
write_block(n, p) writes block n in the DB file from address p.
char other_base_letter() const
Item_wr kt
buffer of size block_size for making up key-tag items
chert_revision_number_t latest_revision_number
Revision number of the other base, or zero if there is only one base file.
bool read_tag(Cursor *C_, std::string *tag, bool keep_compressed) const
Read the tag value for the key pointed to by cursor C_.
chert_tablesize_t item_count
keeps a count of the number of items in the B-tree.
bool find(Cursor *) const
find(C_) searches for the key of B->kt in the B-tree.
~ChertTable()
Close the Btree.
void erase()
Erase this table from disk.
bool prev_for_sequential(Cursor *C_, int dummy) const
void delete_item(int j, bool repeatedly)
ChertTable::delete_item(j, repeatedly) is (almost) the converse of add_item.
unsigned int block_size
block size of the B tree in bytes
bool prev_default(Cursor *C_, int j) const
static int find_in_block(const uint8_t *p, Key key, bool leaf, int c)
find_in_block(p, key, leaf, c) searches for the key in the block at p.
char base_letter
the value 'A' or 'B' of the current base
int compress_strategy
DONT_COMPRESS or Z_DEFAULT_STRATEGY, Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE.
bool exists() const
Determine whether the btree exists on disk.
void cancel()
Cancel any outstanding changes.
void alter()
Btree::alter(); is called when the B-tree is to be altered.
int handle
File descriptor of the table.
void add(const std::string &key, std::string tag, bool already_compressed=false)
Add a key/tag pair to the table, replacing any existing pair with the same key.
Cursor C[BTREE_CURSOR_LEVELS]
bool lazy
If true, don't create the table until it's needed.
void lazy_alloc_inflate_zstream() const
Allocate the zstream for inflating, if not already allocated.
void create_and_open(unsigned int blocksize)
Create a new empty btree structure on disk and open it at the initial revision.
void enter_key(int j, Key prevkey, Key newkey)
enter_key(j, prevkey, newkey) is called after a block split.
z_stream * deflate_zstream
Zlib state object for deflating.
uint8_t * buffer
buffer of size block_size for reforming blocks
void add_item(Item_wr kt, int j)
ChertTable::add_item(kt_, j) adds item kt_ to the block at cursor level C[j].
void compact(uint8_t *p)
compact(p) compact the block at p by shuffling all the items up to the end.
void block_to_cursor(Cursor *C_, int j, uint4 n) const
const char * tablename
The name of the table (used when writing changesets).
bool faked_root_block
true if the root block is faked (not written to disk).
bool Btree_modified
Set to true the first time the B-tree is modified.
void lazy_alloc_deflate_zstream() const
Allocate the zstream for deflating, if not already allocated.
static uint4 block_given_by(const uint8_t *p, int c)
block_given_by(p, c) finds the item at block address p, directory offset c, and returns its tag value...
void close(bool permanent=false)
Close the Btree.
uint8_t * p
pointer to a block
int c
offset in the block's directory
bool rewrite
true if the block is not the same as on disk, and so needs rewriting
int components_of() const
bool get_compressed() const
int size() const
I in diagram above.
void append_chunk(std::string *tag) const
uint4 block_given_by() const
Get this item's tag as a block number (this block should not be at level 0).
void set_block_given_by(uint4 n)
Set this item's tag to point to block n (this block should not be at level 0).
void form_null_key(uint4 n)
Form an item with a null key and with block number n in the tag.
void set_key_and_block(Key newkey, int truncate_size, uint4 n)
bool operator<(Key key2) const
Compares this key with key2.
bool operator==(Key key2) const
const uint8_t * get_address() const
Indicates an attempt to access a closed database.
DatabaseCorruptError indicates database corruption was detected.
DatabaseError indicates some sort of database related error.
DatabaseModifiedError indicates a database was modified.
DatabaseOpeningError indicates failure to open a database.
UnimplementedError indicates an attempt to use an unimplemented feature.
#define LOGCALL(CATEGORY, TYPE, FUNC, PARAMS)
#define LOGCALL_CTOR(CATEGORY, CLASS, PARAMS)
#define LOGCALL_STATIC(CATEGORY, TYPE, FUNC, PARAMS)
#define LOGCALL_VOID(CATEGORY, FUNC, PARAMS)
#define LOGCALL_DTOR(CATEGORY, CLASS)
void errno_to_string(int e, string &s)
Convert errno value to std::string, thread-safe if possible.
Hierarchy of classes which Xapian can throw as exceptions.
Utility functions for testing files.
bool file_exists(const char *path)
Test if a file exists.
void io_read_block(int fd, char *p, size_t n, off_t b, off_t o)
Read block b size n bytes into buffer p from file descriptor fd, offset o.
int io_open_block_wr(const char *filename, bool anew)
Open a block-based file for writing.
bool io_unlink(const std::string &filename)
Delete a file.
void io_write(int fd, const char *p, size_t n)
Write n bytes from block pointed to by p to file descriptor fd.
bool io_tmp_rename(const std::string &tmp_file, const std::string &real_file)
Rename a temporary file to its final position.
void io_write_block(int fd, const char *p, size_t n, off_t b, off_t o)
Write block b size n bytes from buffer p to file descriptor fd, offset o.
Wrappers for low-level POSIX I/O routines.
bool io_sync(int fd)
Ensure all data previously written to file descriptor fd has been written to disk.
bool io_full_sync(int fd)
bool io_readahead_block(int, size_t, off_t, off_t=0)
Readahead block b size n bytes from file descriptor fd.
int io_open_block_rd(const char *filename)
Open a block-based file for reading.
string str(int value)
Convert int to std::string.
int revision()
Report the revision of the library which the program is linked with.
Various assertion macros.
#define AssertParanoid(COND)
#define AssertEqParanoid(A, B)
#define AssertRel(A, REL, B)
Pack types into strings and unpack them again.
void pack_uint(std::string &s, U value)
Append an encoded unsigned integer to a string.
void pack_string(std::string &s, const std::string &value)
Append an encoded std::string to a string.
Convert types to std::string.
Various handy helpers which std::string really should provide.
#define STRINGIZE(X)
The STRINGIZE macro converts its parameter into a string constant.
functions for reading and writing different width words
void aligned_write4(unsigned char *ptr, T value)