xapian-core  2.0.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:
469  GlassTable(const char* tablename_, std::string_view path_,
470  bool readonly_, bool lazy = false);
471 
472  GlassTable(const char * tablename_, int fd, off_t offset_,
473  bool readonly_, bool lazy = false);
474 
480  ~GlassTable();
481 
487  void close(bool permanent = false);
488 
489  bool readahead_key(std::string_view key) const;
490 
493  bool exists() const;
494 
506  void open(int flags_, const RootInfo & root_info,
508 
513  bool is_open() const { return handle >= 0; }
514 
516  bool is_writable() const { return writable; }
517 
523  void flush_db();
524 
540  void commit(glass_revision_number_t revision, RootInfo * root_info);
541 
542  bool sync() {
543  return (flags & Xapian::DB_NO_SYNC) ||
544  handle < 0 ||
545  io_sync(handle);
546  }
547 
553  void cancel(const RootInfo & root_info, glass_revision_number_t rev);
554 
569  bool get_exact_entry(std::string_view key, std::string& tag) const;
570 
582  bool key_exists(std::string_view key) const;
583 
592  bool read_tag(Glass::Cursor* C_,
593  std::string* tag,
594  bool keep_compressed) const;
595 
612  void add(std::string_view key,
613  std::string_view tag,
614  bool already_compressed = false);
615 
631  bool del(std::string_view key);
632 
633  int get_flags() const { return flags; }
634 
635  void set_flags(int new_flags) { flags = new_flags; }
636 
660  void create_and_open(int flags_, const RootInfo & root_info);
661 
662  void set_full_compaction(bool parity);
663 
673  return revision_number;
674  }
675 
686  return item_count;
687  }
688 
690  bool empty() const {
691  return (item_count == 0);
692  }
693 
699  GlassCursor * cursor_get() const;
700 
706  bool is_modified() const { return Btree_modified; }
707 
713  void set_max_item_size(size_t block_capacity) {
714  if (block_capacity > Glass::BLOCK_CAPACITY)
715  block_capacity = Glass::BLOCK_CAPACITY;
716  using Glass::DIR_START;
717  using Glass::D2;
718  max_item_size =
719  (block_size - DIR_START - block_capacity * D2) / block_capacity;
720  // Make sure we don't exceed the limit imposed by the format.
723  }
724 
730  void set_changes(GlassChanges * changes) {
731  changes_obj = changes;
732  }
733 
735  [[noreturn]]
736  static void throw_database_closed();
737 
738  string get_path() const {
739  return name + GLASS_TABLE_EXTENSION;
740  }
741 
742  protected:
743  bool find(Glass::Cursor *) const;
744  int delete_kt();
745  void read_block(uint4 n, uint8_t *p) const;
746  void write_block(uint4 n, const uint8_t *p,
747  bool appending = false) const;
748  [[noreturn]]
749  void throw_overwritten() const;
750  void block_to_cursor(Glass::Cursor *C_, int j, uint4 n) const;
751  void alter();
752  void compact(uint8_t *p);
754  Glass::LeafItem newitem);
755  void enter_key_above_branch(int j, Glass::BItem newitem);
756  int mid_point(uint8_t *p) const;
757  void add_item_to_leaf(uint8_t *p, Glass::LeafItem kt, int c);
758  void add_item_to_branch(uint8_t *p, Glass::BItem kt, int c);
760  void add_branch_item(Glass::BItem kt, int j);
761  void delete_leaf_item(bool repeatedly);
762  void delete_branch_item(int j);
763  int add_kt(bool found);
764  void read_root();
765  void split_root(uint4 split_n);
766  void form_key(std::string_view key) const;
767 
769  const char * tablename;
770 
773 
776 
778  unsigned int block_size;
779 
781  int flags;
782 
788 
793 
801  int handle;
802 
804  int level;
805 
808 
811 
813  uint8_t * buffer;
814 
817 
822  std::string name;
823 
828 
831 
835 
838 
840  mutable bool Btree_modified;
841 
844 
846  bool writable;
847 
850 
852  unsigned long cursor_version;
853 
859 
860  bool single_file() const {
861  return name.empty();
862  }
863 
864  /* B-tree navigation functions */
865  bool prev(Glass::Cursor *C_, int j) const {
866  if (sequential && !single_file())
867  return prev_for_sequential(C_, j);
868  return prev_default(C_, j);
869  }
870 
871  bool next(Glass::Cursor *C_, int j) const {
872  if (sequential) return next_for_sequential(C_, j);
873  return next_default(C_, j);
874  }
875 
876  /* Default implementations. */
877  bool prev_default(Glass::Cursor *C_, int j) const;
878  bool next_default(Glass::Cursor *C_, int j) const;
879 
880  /* Implementations for sequential mode. */
881  bool prev_for_sequential(Glass::Cursor *C_, int dummy) const;
882  bool next_for_sequential(Glass::Cursor *C_, int dummy) const;
883 
884  static int find_in_leaf(const uint8_t * p,
885  Glass::LeafItem item, int c, bool& exact);
886  static int find_in_branch(const uint8_t * p,
887  Glass::LeafItem item, int c);
888  static int find_in_branch(const uint8_t * p, Glass::BItem item, int c);
889 
893  static uint4 block_given_by(const uint8_t * p, int c);
894 
896 
902  uint8_t * split_p;
903 
906 
908 
910  bool lazy;
911 
914 
916  off_t offset;
917 
918  /* Debugging methods */
919 // void report_block_full(int m, int n, const uint8_t * p);
920 };
921 
922 namespace Glass {
923 
940 template<typename ITEM1, typename ITEM2>
941 int compare(ITEM1 a, ITEM2 b)
942 {
943  Key key1 = a.key();
944  Key key2 = b.key();
945  const uint8_t* p1 = key1.data();
946  const uint8_t* p2 = key2.data();
947  int key1_len = key1.length();
948  int key2_len = key2.length();
949  int k_smaller = (key2_len < key1_len ? key2_len : key1_len);
950 
951  // Compare the common part of the keys.
952  int diff = std::memcmp(p1, p2, k_smaller);
953  if (diff == 0) {
954  // If the common part matches, compare the lengths.
955  diff = key1_len - key2_len;
956  if (diff == 0) {
957  // If the strings match, compare component_of().
958  diff = a.component_of() - b.component_of();
959  }
960  }
961  return diff;
962 }
963 
969 inline int
971 {
972  Key key1 = a.key();
973  Key key2 = b.key();
974  const uint8_t* p1 = key1.data();
975  const uint8_t* p2 = key2.data();
976  int key1_len = key1.length();
977  int key2_len = key2.length();
978  if (key1_len == key2_len) {
979  // The keys are the same length, so we can compare the counts in the
980  // same operation since they're stored as 2 byte bigendian numbers.
981  int len = key1_len + X2;
982  return std::memcmp(p1, p2, len);
983  }
984 
985  int k_smaller = (key2_len < key1_len ? key2_len : key1_len);
986 
987  // Compare the common part of the keys.
988  int diff = std::memcmp(p1, p2, k_smaller);
989  if (diff == 0) {
990  // If the common part matches, compare the lengths.
991  diff = key1_len - key2_len;
992  // We dealt with the "same length" case above so we never need to check
993  // component_of here.
994  }
995  return diff;
996 }
997 
998 }
999 
1000 #ifdef DISABLE_GPL_LIBXAPIAN
1001 # error GPL source we cannot relicense included in libxapian
1002 #endif
1003 
1004 #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:840
uint4 changed_n
the last block to be changed by an addition
Definition: glass_table.h:830
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:816
int seq_count
count of the number of successive instances of purely sequential addition, starting at SEQ_START_POIN...
Definition: glass_table.h:827
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:813
CompressionStream comp_stream
Definition: glass_table.h:907
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:871
void basic_open(const RootInfo *root_info, glass_revision_number_t rev)
bool sync()
Definition: glass_table.h:542
glass_tablesize_t item_count
keeps a count of the number of items in the B-tree.
Definition: glass_table.h:775
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:787
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:834
bool next_default(Glass::Cursor *C_, int j) const
uint4 root
the root block of the B-tree
Definition: glass_table.h:807
void form_key(std::string_view key) const
uint4 last_readahead
Last block readahead_key() preread.
Definition: glass_table.h:913
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:902
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:804
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:738
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:513
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:690
const char * tablename
The name of the table (used when writing changesets).
Definition: glass_table.h:769
bool writable
Set to true when the database is opened to write.
Definition: glass_table.h:846
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:865
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:706
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:730
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:778
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:849
void set_full_compaction(bool parity)
size_t max_item_size
maximum size of an item (key-tag pair)
Definition: glass_table.h:837
unsigned long cursor_version
Version count for tracking when cursors need to rebuild.
Definition: glass_table.h:852
glass_tablesize_t get_entry_count() const
Return a count of the number of entries in the table.
Definition: glass_table.h:685
GlassChanges * changes_obj
The GlassChanges object to write block changes to.
Definition: glass_table.h:858
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:822
bool lazy
If true, don't create the table until it's needed.
Definition: glass_table.h:910
bool single_file() const
Definition: glass_table.h:860
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:843
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:895
bool del(std::string_view key)
Delete an entry from the table.
int handle
File descriptor of the table.
Definition: glass_table.h:801
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:810
bool is_writable() const
Return true if this table is writable.
Definition: glass_table.h:516
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:635
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:905
int get_flags() const
Definition: glass_table.h:633
bool sequential
true iff the data has been written in a single write in sequential order.
Definition: glass_table.h:792
int flags
Flags like DB_NO_SYNC and DB_DANGEROUS.
Definition: glass_table.h:781
off_t offset
offset to start of table in file.
Definition: glass_table.h:916
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:772
glass_revision_number_t get_open_revision_number() const
Get the revision number at which this table is currently open.
Definition: glass_table.h:672
void set_max_item_size(size_t block_capacity)
Set the maximum item size given the block capacity.
Definition: glass_table.h:713
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:607
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:941
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:108
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:215
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