xapian-core  2.1.0
glass_table.h
Go to the documentation of this file.
1 
4 /* Copyright 1999,2000,2001 BrightStation PLC
5  * Copyright 2002-2025 Olly Betts
6  * Copyright 2008 Lemur Consulting Ltd
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, see
20  * <https://www.gnu.org/licenses/>.
21  */
22 
23 #ifndef XAPIAN_INCLUDED_GLASS_TABLE_H
24 #define XAPIAN_INCLUDED_GLASS_TABLE_H
25 
26 #include <xapian/constants.h>
27 #include <xapian/error.h>
28 
29 #include "glass_freelist.h"
30 #include "glass_cursor.h"
31 #include "glass_defs.h"
32 
33 #include "io_utils.h"
34 #include "omassert.h"
35 #include "str.h"
36 #include "stringutils.h"
37 #include "wordaccess.h"
38 
40 
41 #include <algorithm>
42 #include <string>
43 #include <string_view>
44 
45 namespace Glass {
46 
49 const size_t BLOCK_CAPACITY = 4;
50 
56 #define GLASS_BTREE_MAX_KEY_LEN 255
57 
58 // FIXME: This named constant probably isn't used everywhere it should be...
59 const int BYTES_PER_BLOCK_NUMBER = 4;
60 
61 /* The B-tree blocks have a number of internal lengths and offsets held in 1, 2
62  or 4 bytes. To make the coding a little clearer,
63  we use for
64  ------ ---
65  K1 the 1 byte length of key
66  I2 the 2 byte length of an item (key-tag pair)
67  D2 the 2 byte offset to the item from the directory
68  X2 the 2 byte component counter that ends each key
69 */
70 
71 const int K1 = 1;
72 const int I2 = 2;
73 const int D2 = 2;
74 const int X2 = 2;
75 
76 /* and when getting or setting them, we use these methods of the various
77  * *Item* classes: */
78 
79 // getD(p, c)
80 // setD(p, c, x)
81 // getI()
82 // setI(x)
83 // getX(p, c)
84 // setX(p, c, x)
85 
86 /* if you've been reading the comments from the top, the next four procedures
87  will not cause any headaches.
88 
89  Recall that a leaf item has this form:
90 
91  i k x
92  | | |
93  I K key X tag
94  ←K→
95  <---SIZE---->
96  <---I--->
97 
98  Except that X is omitted for the first component of a tag (there is a flag
99  bit in the upper bits of I which indicates these).
100 
101  item_of(p, c) returns i, the address of the item at block address p,
102  directory offset c,
103 
104  component_of(p, c) returns the number marked 'x' above,
105 
106  last_component(p, c) returns true if this is a final component.
107 */
108 
109 inline uint4 REVISION(const uint8_t * b) { return aligned_read4(b); }
110 inline int GET_LEVEL(const uint8_t * b) { return b[4]; }
111 inline int MAX_FREE(const uint8_t * b) { return unaligned_read2(b + 5); }
112 inline int TOTAL_FREE(const uint8_t * b) { return unaligned_read2(b + 7); }
113 inline int DIR_END(const uint8_t * b) { return unaligned_read2(b + 9); }
114 const int DIR_START = 11;
115 
116 inline void SET_REVISION(uint8_t * b, uint4 rev) { aligned_write4(b, rev); }
117 inline void SET_LEVEL(uint8_t* b, int x) {
118  AssertRel(x,<,256);
119  b[4] = uint8_t(x);
120 }
121 inline void SET_MAX_FREE(uint8_t * b, int x) { unaligned_write2(b + 5, x); }
122 inline void SET_TOTAL_FREE(uint8_t * b, int x) { unaligned_write2(b + 7, x); }
123 inline void SET_DIR_END(uint8_t * b, int x) { unaligned_write2(b + 9, x); }
124 
125 // The item size is stored in 2 bytes, but the top bit is used to store a flag for
126 // "is the tag data compressed" and the next two bits are used to flag if this is the
127 // first and/or last item for this tag.
128 const int I_COMPRESSED_BIT = 0x80;
129 const int I_LAST_BIT = 0x40;
130 const int I_FIRST_BIT = 0x20;
131 
133 
134 const int ITEM_SIZE_MASK = (0xffff &~ (I_MASK << 8));
135 const size_t MAX_ITEM_SIZE = (ITEM_SIZE_MASK + 3);
136 
138 const int LEVEL_FREELIST = 254;
139 
140 class RootInfo;
141 
142 class Key {
143  const uint8_t *p;
144  public:
145  explicit Key(const uint8_t * p_) : p(p_) { }
146  const uint8_t * get_address() const { return p; }
147  const uint8_t * data() const { return p + K1; }
148  void read(std::string * key) const {
149  key->assign(reinterpret_cast<const char *>(p + K1), length());
150  }
151  int length() const {
152  return p[0];
153  }
154  char operator[](size_t i) const {
155  AssertRel(i,<,size_t(length()));
156  return p[i + K1];
157  }
158 };
159 
160 // LeafItem_wr wants to be "LeafItem with non-const p and more methods" - we can't
161 // achieve that nicely with inheritance, so we use a template base class.
162 template<class T> class LeafItem_base {
163  protected:
164  T p;
165  int get_key_len() const { return p[I2]; }
166  static int getD(const uint8_t * q, int c) {
167  AssertRel(c, >=, DIR_START);
168  AssertRel(c, <, 65535);
169  Assert((c & 1) == 1);
170  return unaligned_read2(q + c);
171  }
172  int getI() const { return unaligned_read2(p); }
173  static int getX(const uint8_t * q, int c) { return unaligned_read2(q + c); }
174  public:
175  /* LeafItem from block address and offset to item pointer */
176  LeafItem_base(T p_, int c) : p(p_ + getD(p_, c)) { }
177  explicit LeafItem_base(T p_) : p(p_) { }
178 
179  void init(T p_, int c) { p = p_ + getD(p_, c); }
180  void init(T p_) { p = p_; }
181 
182  T get_address() const { return p; }
184  int size() const {
185  return (getI() & ITEM_SIZE_MASK) + 3;
186  }
187  bool get_compressed() const { return *p & I_COMPRESSED_BIT; }
188  bool first_component() const { return *p & I_FIRST_BIT; }
189  bool last_component() const { return *p & I_LAST_BIT; }
190  int component_of() const {
191  if (first_component()) return 1;
192  return getX(p, get_key_len() + I2 + K1);
193  }
194  Key key() const { return Key(p + I2); }
195  void append_chunk(std::string * tag) const {
196  // Offset to the start of the tag data.
197  int cd = get_key_len() + I2 + K1;
198  if (!first_component()) cd += X2;
199  // Number of bytes to extract from current component.
200  int l = size() - cd;
201  const char * chunk = reinterpret_cast<const char *>(p + cd);
202  tag->append(chunk, l);
203  }
204  bool decompress_chunk(CompressionStream& comp_stream, string& tag) const {
205  // Offset to the start of the tag data.
206  int cd = get_key_len() + I2 + K1;
207  if (!first_component()) cd += X2;
208  // Number of bytes to extract from current component.
209  int l = size() - cd;
210  const char * chunk = reinterpret_cast<const char *>(p + cd);
211  return comp_stream.decompress_chunk(chunk, l, tag);
212  }
213 };
214 
215 class LeafItem : public LeafItem_base<const uint8_t *> {
216  public:
217  /* LeafItem from block address and offset to item pointer */
218  LeafItem(const uint8_t * p_, int c)
219  : LeafItem_base<const uint8_t *>(p_, c) { }
220  explicit LeafItem(const uint8_t * p_)
221  : LeafItem_base<const uint8_t *>(p_) { }
222 };
223 
224 class LeafItem_wr : public LeafItem_base<uint8_t *> {
225  void set_key_len(int x) {
226  AssertRel(x, >=, 0);
228  p[I2] = uint8_t(x);
229  }
230  void setI(int x) { unaligned_write2(p, x); }
231  static void setX(uint8_t * q, int c, int x) { unaligned_write2(q + c, x); }
232  public:
233  /* LeafItem_wr from block address and offset to item pointer */
234  LeafItem_wr(uint8_t * p_, int c) : LeafItem_base<uint8_t *>(p_, c) { }
235  explicit LeafItem_wr(uint8_t * p_) : LeafItem_base<uint8_t *>(p_) { }
236  void set_component_of(int i) {
237  AssertRel(i,>,1);
238  *p &=~ I_FIRST_BIT;
239  setX(p, get_key_len() + I2 + K1, i);
240  }
241  void set_size(int new_size) {
242  AssertRel(new_size,>=,3);
243  int I = new_size - 3;
244  // We should never be able to pass too large a size here, but don't
245  // corrupt the database if this somehow happens.
246  if (rare(I &~ ITEM_SIZE_MASK)) throw Xapian::DatabaseError("item too large!");
247  setI(I);
248  }
249  void form_key(std::string_view key_) {
250  auto key_len = key_.length();
251  if (key_len > GLASS_BTREE_MAX_KEY_LEN) {
252  // We check term length when a term is added to a document but
253  // glass doubles zero bytes, so this can still happen for terms
254  // which contain one or more zero bytes.
255  std::string msg("Key too long: length was ");
256  msg += str(key_len);
257  msg += " bytes, maximum length of a key is "
259  throw Xapian::InvalidArgumentError(msg);
260  }
261 
262  set_key_len(key_len);
263  *p |= I_FIRST_BIT;
264  if (key_len)
265  std::memmove(p + I2 + K1, key_.data(), key_len);
266  }
267  // FIXME passing cd here is icky
268  void set_tag(int cd, const char *start, int len, bool compressed, int i, int m) {
269  if (len) std::memmove(p + cd, start, len);
270  set_size(cd + len);
271  if (compressed) *p |= I_COMPRESSED_BIT;
272  if (i == m) *p |= I_LAST_BIT;
273  if (i == 1) {
274  *p |= I_FIRST_BIT;
275  } else {
276  set_component_of(i);
277  }
278  }
279  void fake_root_item() {
280  set_key_len(0); // null key length
281  set_size(I2 + K1); // length of the item
283  }
284  operator const LeafItem() const { return LeafItem(p); }
285  static void setD(uint8_t * q, int c, int x) {
286  AssertRel(c, >=, DIR_START);
287  AssertRel(c, <, 65535);
288  Assert((c & 1) == 1);
289  unaligned_write2(q + c, x);
290  }
291 };
292 
293 /* A branch item has this form:
294 
295  k x
296  | |
297  tag K key X
298  ←B→ ←K→
299  <--SIZE--->
300 
301  B = BYTES_PER_BLOCK_NUMBER
302 
303  We can't omit X here, as we've nowhere to store the first and last bit
304  flags which we have in leaf items.
305 */
306 
307 // BItem_wr wants to be "BItem with non-const p and more methods" - we can't
308 // achieve that nicely with inheritance, so we use a template base class.
309 template<class T> class BItem_base {
310  protected:
311  T p;
312  int get_key_len() const { return p[BYTES_PER_BLOCK_NUMBER]; }
313  static int getD(const uint8_t * q, int c) {
314  AssertRel(c, >=, DIR_START);
315  AssertRel(c, <, 65535);
316  Assert((c & 1) == 1);
317  return unaligned_read2(q + c);
318  }
319  static int getX(const uint8_t * q, int c) { return unaligned_read2(q + c); }
320  public:
321  /* BItem from block address and offset to item pointer */
322  BItem_base(T p_, int c) : p(p_ + getD(p_, c)) { }
323  explicit BItem_base(T p_) : p(p_) { }
324  T get_address() const { return p; }
326  int size() const {
327  return get_key_len() + K1 + X2 + BYTES_PER_BLOCK_NUMBER;
328  }
329  Key key() const { return Key(p + BYTES_PER_BLOCK_NUMBER); }
334  return unaligned_read4(p);
335  }
336  int component_of() const {
337  return getX(p, get_key_len() + BYTES_PER_BLOCK_NUMBER + K1);
338  }
339 };
340 
341 class BItem : public BItem_base<const uint8_t *> {
342  public:
343  /* BItem from block address and offset to item pointer */
344  BItem(const uint8_t * p_, int c) : BItem_base<const uint8_t *>(p_, c) { }
345  explicit BItem(const uint8_t * p_) : BItem_base<const uint8_t *>(p_) { }
346 };
347 
348 class BItem_wr : public BItem_base<uint8_t *> {
349  void set_key_len(int x) {
350  AssertRel(x, >=, 0);
352  p[BYTES_PER_BLOCK_NUMBER] = uint8_t(x);
353  }
354  static void setX(uint8_t * q, int c, int x) { unaligned_write2(q + c, x); }
355  public:
356  /* BItem_wr from block address and offset to item pointer */
357  BItem_wr(uint8_t * p_, int c) : BItem_base<uint8_t *>(p_, c) { }
358  explicit BItem_wr(uint8_t * p_) : BItem_base<uint8_t *>(p_) { }
359  void set_component_of(int i) {
361  }
362  void set_key_and_block(Key newkey, uint4 n) {
363  int len = newkey.length() + K1 + X2;
364  // Copy the key size, main part of the key and the count part.
365  std::memcpy(p + BYTES_PER_BLOCK_NUMBER, newkey.get_address(), len);
366  // Set tag contents to block number
368  }
369  // Takes size as we may be truncating newkey.
370  void set_truncated_key_and_block(Key newkey, int new_comp,
371  int truncate_size, uint4 n) {
372  int i = truncate_size;
373  AssertRel(i,<=,newkey.length());
374  // Key size
375  set_key_len(i);
376  // Copy the main part of the key, possibly truncating.
377  std::memcpy(p + BYTES_PER_BLOCK_NUMBER + K1, newkey.get_address() + K1, i);
378  // Set the component count.
379  setX(p, BYTES_PER_BLOCK_NUMBER + K1 + i, new_comp);
380  // Set tag contents to block number
382  }
383 
388  unaligned_write4(p, n);
389  }
394  set_key_len(0); /* null key */
395  set_component_of(0);
396  }
397  operator const BItem() const { return BItem(p); }
398  static void setD(uint8_t * q, int c, int x) {
399  AssertRel(c, >=, DIR_START);
400  AssertRel(c, <, 65535);
401  Assert((c & 1) == 1);
402  unaligned_write2(q + c, x);
403  }
404 };
405 
406 }
407 
408 using Glass::RootInfo;
409 
410 class GlassChanges;
411 
432 class GlassTable {
433  friend class GlassCursor; /* Should probably fix this. */
434  friend class GlassFreeList;
435 
436  private:
439 
442 
443  void basic_open(const RootInfo * root_info,
445 
447  void do_open_to_read(const RootInfo * root_info,
449 
451  void do_open_to_write(const RootInfo * root_info,
453 
454  public:
468  GlassTable(const char* tablename_, std::string_view path_,
469  bool readonly_, bool lazy = false);
470 
471  GlassTable(const char * tablename_, int fd, off_t offset_,
472  bool readonly_, bool lazy = false);
473 
479  ~GlassTable();
480 
486  void close(bool permanent = false);
487 
488  bool readahead_key(std::string_view key) const;
489 
492  bool exists() const;
493 
505  void open(int flags_, const RootInfo & root_info,
507 
512  bool is_open() const { return handle >= 0; }
513 
515  bool is_writable() const { return writable; }
516 
522  void flush_db();
523 
539  void commit(glass_revision_number_t revision, RootInfo * root_info);
540 
541  bool sync() {
542  return (flags & Xapian::DB_NO_SYNC) ||
543  handle < 0 ||
544  io_sync(handle);
545  }
546 
552  void cancel(const RootInfo & root_info, glass_revision_number_t rev);
553 
568  bool get_exact_entry(std::string_view key, std::string& tag) const;
569 
581  bool key_exists(std::string_view key) const;
582 
591  bool read_tag(Glass::Cursor* C_,
592  std::string* tag,
593  bool keep_compressed) const;
594 
611  void add(std::string_view key,
612  std::string_view tag,
613  bool already_compressed = false);
614 
630  bool del(std::string_view key);
631 
632  int get_flags() const { return flags; }
633 
634  void set_flags(int new_flags) { flags = new_flags; }
635 
659  void create_and_open(int flags_, const RootInfo & root_info);
660 
661  void set_full_compaction(bool parity);
662 
672  return revision_number;
673  }
674 
685  return item_count;
686  }
687 
689  bool empty() const {
690  return (item_count == 0);
691  }
692 
698  GlassCursor * cursor_get() const;
699 
705  bool is_modified() const { return Btree_modified; }
706 
712  void set_max_item_size(size_t block_capacity) {
713  if (block_capacity > Glass::BLOCK_CAPACITY)
714  block_capacity = Glass::BLOCK_CAPACITY;
715  using Glass::DIR_START;
716  using Glass::D2;
717  max_item_size =
718  (block_size - DIR_START - block_capacity * D2) / block_capacity;
719  // Make sure we don't exceed the limit imposed by the format.
722  }
723 
729  void set_changes(GlassChanges * changes) {
730  changes_obj = changes;
731  }
732 
734  [[noreturn]]
735  static void throw_database_closed();
736 
737  string get_path() const {
738  return name + GLASS_TABLE_EXTENSION;
739  }
740 
741  protected:
742  bool find(Glass::Cursor *) const;
743  int delete_kt();
744  void read_block(uint4 n, uint8_t *p) const;
745  void write_block(uint4 n, const uint8_t *p,
746  bool appending = false) const;
747  [[noreturn]]
748  void throw_overwritten() const;
749  void block_to_cursor(Glass::Cursor *C_, int j, uint4 n) const;
750  void alter();
751  void compact(uint8_t *p);
753  Glass::LeafItem newitem);
754  void enter_key_above_branch(int j, Glass::BItem newitem);
755  int mid_point(uint8_t *p) const;
756  void add_item_to_leaf(uint8_t *p, Glass::LeafItem kt, int c);
757  void add_item_to_branch(uint8_t *p, Glass::BItem kt, int c);
759  void add_branch_item(Glass::BItem kt, int j);
760  void delete_leaf_item(bool repeatedly);
761  void delete_branch_item(int j);
762  int add_kt(bool found);
763  void read_root();
764  void split_root(uint4 split_n);
765  void form_key(std::string_view key) const;
766 
768  const char * tablename;
769 
772 
775 
777  unsigned int block_size;
778 
780  int flags;
781 
787 
792 
800  int handle;
801 
803  int level;
804 
807 
810 
812  uint8_t * buffer;
813 
816 
821  std::string name;
822 
827 
830 
834 
837 
839  mutable bool Btree_modified;
840 
843 
845  bool writable;
846 
849 
851  unsigned long cursor_version;
852 
858 
859  bool single_file() const {
860  return name.empty();
861  }
862 
863  /* B-tree navigation functions */
864  bool prev(Glass::Cursor *C_, int j) const {
865  if (sequential && !single_file())
866  return prev_for_sequential(C_, j);
867  return prev_default(C_, j);
868  }
869 
870  bool next(Glass::Cursor *C_, int j) const {
871  if (sequential) return next_for_sequential(C_, j);
872  return next_default(C_, j);
873  }
874 
875  /* Default implementations. */
876  bool prev_default(Glass::Cursor *C_, int j) const;
877  bool next_default(Glass::Cursor *C_, int j) const;
878 
879  /* Implementations for sequential mode. */
880  bool prev_for_sequential(Glass::Cursor *C_, int dummy) const;
881  bool next_for_sequential(Glass::Cursor *C_, int dummy) const;
882 
883  static int find_in_leaf(const uint8_t * p,
884  Glass::LeafItem item, int c, bool& exact);
885  static int find_in_branch(const uint8_t * p,
886  Glass::LeafItem item, int c);
887  static int find_in_branch(const uint8_t * p, Glass::BItem item, int c);
888 
892  static uint4 block_given_by(const uint8_t * p, int c);
893 
895 
901  uint8_t * split_p;
902 
905 
907 
909  bool lazy;
910 
913 
915  off_t offset;
916 
917  /* Debugging methods */
918 // void report_block_full(int m, int n, const uint8_t * p);
919 };
920 
921 namespace Glass {
922 
939 template<typename ITEM1, typename ITEM2>
940 int compare(ITEM1 a, ITEM2 b)
941 {
942  Key key1 = a.key();
943  Key key2 = b.key();
944  const uint8_t* p1 = key1.data();
945  const uint8_t* p2 = key2.data();
946  int key1_len = key1.length();
947  int key2_len = key2.length();
948  int k_smaller = (key2_len < key1_len ? key2_len : key1_len);
949 
950  // Compare the common part of the keys.
951  int diff = std::memcmp(p1, p2, k_smaller);
952  if (diff == 0) {
953  // If the common part matches, compare the lengths.
954  diff = key1_len - key2_len;
955  if (diff == 0) {
956  // If the strings match, compare component_of().
957  diff = a.component_of() - b.component_of();
958  }
959  }
960  return diff;
961 }
962 
968 inline int
970 {
971  Key key1 = a.key();
972  Key key2 = b.key();
973  const uint8_t* p1 = key1.data();
974  const uint8_t* p2 = key2.data();
975  int key1_len = key1.length();
976  int key2_len = key2.length();
977  if (key1_len == key2_len) {
978  // The keys are the same length, so we can compare the counts in the
979  // same operation since they're stored as 2 byte bigendian numbers.
980  int len = key1_len + X2;
981  return std::memcmp(p1, p2, len);
982  }
983 
984  int k_smaller = (key2_len < key1_len ? key2_len : key1_len);
985 
986  // Compare the common part of the keys.
987  int diff = std::memcmp(p1, p2, k_smaller);
988  if (diff == 0) {
989  // If the common part matches, compare the lengths.
990  diff = key1_len - key2_len;
991  // We dealt with the "same length" case above so we never need to check
992  // component_of here.
993  }
994  return diff;
995 }
996 
997 }
998 
999 #ifdef DISABLE_GPL_LIBXAPIAN
1000 # error GPL source we cannot relicense included in libxapian
1001 #endif
1002 
1003 #endif /* XAPIAN_INCLUDED_GLASS_TABLE_H */
bool decompress_chunk(const char *p, int len, std::string &buf)
Returns true if this was the final chunk.
A cursor pointing to a position in a Btree table, for reading several entries in order,...
Definition: glass_cursor.h:148
Class managing a Btree table in a Glass database.
Definition: glass_table.h:432
void block_to_cursor(Glass::Cursor *C_, int j, uint4 n) const
Definition: glass_table.cc:317
bool Btree_modified
Set to true the first time the B-tree is modified.
Definition: glass_table.h:839
uint4 changed_n
the last block to be changed by an addition
Definition: glass_table.h:829
void alter()
Btree::alter(); is called when the B-tree is to be altered.
Definition: glass_table.cc:380
bool next_for_sequential(Glass::Cursor *C_, int dummy) const
~GlassTable()
Close the Btree.
void compact(uint8_t *p)
compact(p) compact the block at p by shuffling all the items up to the end.
Definition: glass_table.cc:569
GlassFreeList free_list
List of free blocks.
Definition: glass_table.h:815
int seq_count
count of the number of successive instances of purely sequential addition, starting at SEQ_START_POIN...
Definition: glass_table.h:826
void create_and_open(int flags_, const RootInfo &root_info)
Create a new empty btree structure on disk and open it at the initial revision.
uint8_t * buffer
buffer of size block_size for reforming blocks
Definition: glass_table.h:812
CompressionStream comp_stream
Definition: glass_table.h:906
void throw_overwritten() const
Definition: glass_table.cc:296
bool key_exists(std::string_view key) const
Check if a key exists in the Btree.
bool next(Glass::Cursor *C_, int j) const
Definition: glass_table.h:870
void basic_open(const RootInfo *root_info, glass_revision_number_t rev)
bool sync()
Definition: glass_table.h:541
glass_tablesize_t item_count
keeps a count of the number of items in the B-tree.
Definition: glass_table.h:774
void delete_branch_item(int j)
GlassTable::delete_branch_item(j, repeatedly) is (almost) the converse of add_branch_item.
bool faked_root_block
true if the root block is faked (not written to disk).
Definition: glass_table.h:786
void commit(glass_revision_number_t revision, RootInfo *root_info)
Commit any outstanding changes to the table.
int changed_c
directory offset corresponding to last block to be changed by an addition
Definition: glass_table.h:833
bool next_default(Glass::Cursor *C_, int j) const
uint4 root
the root block of the B-tree
Definition: glass_table.h:806
void form_key(std::string_view key) const
uint4 last_readahead
Last block readahead_key() preread.
Definition: glass_table.h:912
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.
Definition: glass_table.cc:609
uint8_t * split_p
Buffer used when splitting a block.
Definition: glass_table.h:901
int add_kt(bool found)
add_kt(found) adds the item (key-tag pair) at B->kt into the B-tree, using cursor C.
void do_open_to_read(const RootInfo *root_info, glass_revision_number_t rev)
Perform the opening operation to read.
int level
number of levels, counting from 0
Definition: glass_table.h:803
bool exists() const
Determine whether the btree exists on disk.
GlassTable & operator=(const GlassTable &)
Assignment not allowed.
string get_path() const
Definition: glass_table.h:737
void enter_key_above_branch(int j, Glass::BItem newitem)
enter_key_above_branch(j, newkey) is called after a branch block split.
Definition: glass_table.cc:712
bool is_open() const
Return true if this table is open.
Definition: glass_table.h:512
void flush_db()
Flush any outstanding changes to the DB file of the table.
bool prev_default(Glass::Cursor *C_, int j) const
bool empty() const
Return true if there are no entries in the table.
Definition: glass_table.h:689
const char * tablename
The name of the table (used when writing changesets).
Definition: glass_table.h:768
bool writable
Set to true when the database is opened to write.
Definition: glass_table.h:845
void open(int flags_, const RootInfo &root_info, glass_revision_number_t rev)
Open the btree.
int delete_kt()
GlassTable(const GlassTable &)
Copying not allowed.
void enter_key_above_leaf(Glass::LeafItem previtem, Glass::LeafItem newitem)
enter_key_above_leaf(previtem, newitem) is called after a leaf block split.
Definition: glass_table.cc:656
bool find(Glass::Cursor *) const
find(C_) searches for the key of B->kt in the B-tree.
Definition: glass_table.cc:536
bool prev(Glass::Cursor *C_, int j) const
Definition: glass_table.h:864
bool read_tag(Glass::Cursor *C_, std::string *tag, bool keep_compressed) const
Read the tag value for the key pointed to by cursor C_.
bool is_modified() const
Determine whether the object contains uncommitted modifications.
Definition: glass_table.h:705
void write_block(uint4 n, const uint8_t *p, bool appending=false) const
write_block(n, p, appending) writes block n in the DB file from address p.
Definition: glass_table.cc:198
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 ...
Definition: glass_table.cc:743
void add_leaf_item(Glass::LeafItem kt)
GlassTable::add_leaf_item(kt_) adds item kt_ to the leaf block.
Definition: glass_table.cc:856
void set_changes(GlassChanges *changes)
Set the GlassChanges object to write changed blocks to.
Definition: glass_table.h:729
void read_block(uint4 n, uint8_t *p) const
read_block(n, p) reads block n of the DB file to address p.
Definition: glass_table.cc:167
unsigned int block_size
block size of the B tree in bytes
Definition: glass_table.h:777
GlassCursor * cursor_get() const
Get a cursor for reading from the table.
bool get_exact_entry(std::string_view key, std::string &tag) const
Read an entry from the table, if and only if it is exactly that being asked for.
bool cursor_created_since_last_modification
Flag for tracking when cursors need to rebuild.
Definition: glass_table.h:848
void set_full_compaction(bool parity)
size_t max_item_size
maximum size of an item (key-tag pair)
Definition: glass_table.h:836
unsigned long cursor_version
Version count for tracking when cursors need to rebuild.
Definition: glass_table.h:851
glass_tablesize_t get_entry_count() const
Return a count of the number of entries in the table.
Definition: glass_table.h:684
GlassChanges * changes_obj
The GlassChanges object to write block changes to.
Definition: glass_table.h:857
void add_item_to_branch(uint8_t *p, Glass::BItem kt, int c)
add_item_to_branch(p, kt_, c) adds item kt_ to the branch block at p.
Definition: glass_table.cc:820
std::string name
The path name of the B tree.
Definition: glass_table.h:821
bool lazy
If true, don't create the table until it's needed.
Definition: glass_table.h:909
bool single_file() const
Definition: glass_table.h:859
void add_branch_item(Glass::BItem kt, int j)
GlassTable::add_item(kt_, j) adds item kt_ to the block at cursor level C[j].
Definition: glass_table.cc:951
bool full_compaction
set to true when full compaction is to be achieved
Definition: glass_table.h:842
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...
static int find_in_branch(const uint8_t *p, Glass::LeafItem item, int c)
Definition: glass_table.cc:515
void close(bool permanent=false)
Close the Btree.
void delete_leaf_item(bool repeatedly)
GlassTable::delete_leaf_item(repeatedly) is (almost) the converse of add_leaf_item.
Glass::Cursor C[GLASS_BTREE_CURSOR_LEVELS]
Definition: glass_table.h:894
bool del(std::string_view key)
Delete an entry from the table.
int handle
File descriptor of the table.
Definition: glass_table.h:800
void cancel(const RootInfo &root_info, glass_revision_number_t rev)
Cancel any outstanding changes.
Glass::LeafItem_wr kt
buffer of size block_size for making up key-tag items
Definition: glass_table.h:809
bool is_writable() const
Return true if this table is writable.
Definition: glass_table.h:515
bool prev_for_sequential(Glass::Cursor *C_, int dummy) const
void add_item_to_leaf(uint8_t *p, Glass::LeafItem kt, int c)
add_item_to_leaf(p, kt_, c) adds item kt_ to the leaf block at p.
Definition: glass_table.cc:780
void do_open_to_write(const RootInfo *root_info, glass_revision_number_t rev=0)
Perform the opening operation to write.
void set_flags(int new_flags)
Definition: glass_table.h:634
static void throw_database_closed()
Throw an exception indicating that the database is closed.
uint4 compress_min
Minimum size tag to try compressing (0 for no compression).
Definition: glass_table.h:904
int get_flags() const
Definition: glass_table.h:632
bool sequential
true iff the data has been written in a single write in sequential order.
Definition: glass_table.h:791
int flags
Flags like DB_NO_SYNC and DB_DANGEROUS.
Definition: glass_table.h:780
off_t offset
offset to start of table in file.
Definition: glass_table.h:915
void add(std::string_view key, std::string_view tag, bool already_compressed=false)
Add a key/tag pair to the table, replacing any existing pair with the same key.
bool readahead_key(std::string_view key) const
void read_root()
static int find_in_leaf(const uint8_t *p, Glass::LeafItem item, int c, bool &exact)
find_in_leaf(p, key, c, exact) searches for the key in the leaf block at p.
Definition: glass_table.cc:424
glass_revision_number_t revision_number
revision number of the opened B-tree.
Definition: glass_table.h:771
glass_revision_number_t get_open_revision_number() const
Get the revision number at which this table is currently open.
Definition: glass_table.h:671
void set_max_item_size(size_t block_capacity)
Set the maximum item size given the block capacity.
Definition: glass_table.h:712
Key key() const
Definition: glass_table.h:329
BItem_base(T p_, int c)
Definition: glass_table.h:322
uint4 block_given_by() const
Get this item's tag as a block number (this block should not be at level 0).
Definition: glass_table.h:333
T get_address() const
Definition: glass_table.h:324
int component_of() const
Definition: glass_table.h:336
static int getX(const uint8_t *q, int c)
Definition: glass_table.h:319
int get_key_len() const
Definition: glass_table.h:312
static int getD(const uint8_t *q, int c)
Definition: glass_table.h:313
int size() const
SIZE in diagram above.
Definition: glass_table.h:326
void set_key_len(int x)
Definition: glass_table.h:349
void set_component_of(int i)
Definition: glass_table.h:359
void set_truncated_key_and_block(Key newkey, int new_comp, int truncate_size, uint4 n)
Definition: glass_table.h:370
BItem_wr(uint8_t *p_, int c)
Definition: glass_table.h:357
static void setX(uint8_t *q, int c, int x)
Definition: glass_table.h:354
void set_key_and_block(Key newkey, uint4 n)
Definition: glass_table.h:362
void form_null_key(uint4 n)
Form an item with a null key and with block number n in the tag.
Definition: glass_table.h:392
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).
Definition: glass_table.h:387
BItem_wr(uint8_t *p_)
Definition: glass_table.h:358
static void setD(uint8_t *q, int c, int x)
Definition: glass_table.h:398
BItem(const uint8_t *p_)
Definition: glass_table.h:345
BItem(const uint8_t *p_, int c)
Definition: glass_table.h:344
char operator[](size_t i) const
Definition: glass_table.h:154
const uint8_t * get_address() const
Definition: glass_table.h:146
const uint8_t * p
Definition: glass_table.h:143
const uint8_t * data() const
Definition: glass_table.h:147
int length() const
Definition: glass_table.h:151
Key(const uint8_t *p_)
Definition: glass_table.h:145
void read(std::string *key) const
Definition: glass_table.h:148
int size() const
SIZE in diagram above.
Definition: glass_table.h:184
bool first_component() const
Definition: glass_table.h:188
bool last_component() const
Definition: glass_table.h:189
int get_key_len() const
Definition: glass_table.h:165
LeafItem_base(T p_, int c)
Definition: glass_table.h:176
void append_chunk(std::string *tag) const
Definition: glass_table.h:195
static int getD(const uint8_t *q, int c)
Definition: glass_table.h:166
int component_of() const
Definition: glass_table.h:190
bool get_compressed() const
Definition: glass_table.h:187
void init(T p_, int c)
Definition: glass_table.h:179
bool decompress_chunk(CompressionStream &comp_stream, string &tag) const
Definition: glass_table.h:204
static int getX(const uint8_t *q, int c)
Definition: glass_table.h:173
void set_key_len(int x)
Definition: glass_table.h:225
LeafItem_wr(uint8_t *p_, int c)
Definition: glass_table.h:234
static void setX(uint8_t *q, int c, int x)
Definition: glass_table.h:231
void set_tag(int cd, const char *start, int len, bool compressed, int i, int m)
Definition: glass_table.h:268
void form_key(std::string_view key_)
Definition: glass_table.h:249
void set_size(int new_size)
Definition: glass_table.h:241
LeafItem_wr(uint8_t *p_)
Definition: glass_table.h:235
void setI(int x)
Definition: glass_table.h:230
void set_component_of(int i)
Definition: glass_table.h:236
static void setD(uint8_t *q, int c, int x)
Definition: glass_table.h:285
LeafItem(const uint8_t *p_)
Definition: glass_table.h:220
LeafItem(const uint8_t *p_, int c)
Definition: glass_table.h:218
DatabaseError indicates some sort of database related error.
Definition: error.h:355
InvalidArgumentError indicates an invalid parameter value was passed to the API.
Definition: error.h:229
class wrapper around zlib
#define rare(COND)
Definition: config.h:616
Constants in the Xapian namespace.
PositionList * p
Hierarchy of classes which Xapian can throw as exceptions.
#define DIR_START
Definition: glass_cursor.cc:52
Interface to Btree cursors.
Definitions, types, etc for use inside glass.
#define GLASS_BTREE_CURSOR_LEVELS
Allow for this many levels in the B-tree.
Definition: glass_defs.h:43
unsigned long long glass_tablesize_t
How many entries there are in a table.
Definition: glass_defs.h:71
uint4 glass_revision_number_t
The revision number of a glass database.
Definition: glass_defs.h:68
#define GLASS_TABLE_EXTENSION
Glass table extension.
Definition: glass_defs.h:27
Glass freelist.
#define GLASS_BTREE_MAX_KEY_LEN
The largest possible value of a key_len.
Definition: glass_table.h:56
uint32_t uint4
Definition: internaltypes.h:31
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.
Definition: io_utils.h:107
int DIR_END(const uint8_t *b)
Definition: glass_table.h:113
const int LEVEL_FREELIST
Freelist blocks have their level set to LEVEL_FREELIST.
Definition: glass_table.h:138
void SET_DIR_END(uint8_t *b, int x)
Definition: glass_table.h:123
int compare(ITEM1 a, ITEM2 b)
Compare two items by their keys.
Definition: glass_table.h:940
int TOTAL_FREE(const uint8_t *b)
Definition: glass_table.h:112
const int DIR_START
Definition: glass_table.h:114
const int I_LAST_BIT
Definition: glass_table.h:129
void SET_LEVEL(uint8_t *b, int x)
Definition: glass_table.h:117
int GET_LEVEL(const uint8_t *b)
Definition: glass_table.h:110
void SET_REVISION(uint8_t *b, uint4 rev)
Definition: glass_table.h:116
const size_t MAX_ITEM_SIZE
Definition: glass_table.h:135
const int I2
Definition: glass_table.h:72
int MAX_FREE(const uint8_t *b)
Definition: glass_table.h:111
const int D2
Definition: glass_table.h:73
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.
Definition: glass_table.h:49
const int BYTES_PER_BLOCK_NUMBER
Definition: glass_table.h:59
uint4 REVISION(const uint8_t *b)
Definition: glass_table.h:109
const int X2
Definition: glass_table.h:74
const int I_FIRST_BIT
Definition: glass_table.h:130
const int ITEM_SIZE_MASK
Definition: glass_table.h:134
void SET_TOTAL_FREE(uint8_t *b, int x)
Definition: glass_table.h:122
const int I_COMPRESSED_BIT
Definition: glass_table.h:128
void SET_MAX_FREE(uint8_t *b, int x)
Definition: glass_table.h:121
const int I_MASK
Definition: glass_table.h:132
const int K1
Definition: glass_table.h:71
string str(int value)
Convert int to std::string.
Definition: str.cc:91
int revision()
Report the revision of the library which the program is linked with.
Definition: xapian.h:146
XAPIAN_REVISION_TYPE rev
Revision number of a database.
Definition: types.h:106
const int DB_NO_SYNC
Don't attempt to ensure changes have hit disk.
Definition: constants.h:65
Various assertion macros.
#define AssertRel(A, REL, B)
Definition: omassert.h:123
#define Assert(COND)
Definition: omassert.h:122
Convert types to std::string.
Various handy string-related helpers.
#define STRINGIZE(X)
The STRINGIZE macro converts its parameter into a string constant.
Definition: stringutils.h:41
Definition: header.h:242
const char * dummy[]
Definition: version_h.cc:7
functions for reading and writing different width words
void aligned_write4(unsigned char *ptr, T value)
Definition: wordaccess.h:166
uint32_t unaligned_read4(const unsigned char *ptr)
Definition: wordaccess.h:147
void unaligned_write2(unsigned char *ptr, T value)
Definition: wordaccess.h:187
uint16_t unaligned_read2(const unsigned char *ptr)
Definition: wordaccess.h:159
void unaligned_write4(unsigned char *ptr, T value)
Definition: wordaccess.h:173
uint32_t aligned_read4(const unsigned char *ptr)
Definition: wordaccess.h:141