xapian-core  2.0.0
honey_table.h
Go to the documentation of this file.
1 
4 /* Copyright (C) 2017,2018,2023,2024 Olly Betts
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see
18  * <https://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef XAPIAN_INCLUDED_HONEY_TABLE_H
22 #define XAPIAN_INCLUDED_HONEY_TABLE_H
23 
24 #ifndef PACKAGE
25 # error config.h must be included first in each C++ source file
26 #endif
27 
28 #define SSTINDEX_ARRAY
29 //#define SSTINDEX_BINARY_CHOP
30 //#define SSTINDEX_SKIPLIST
31 
32 #define SSTINDEX_BINARY_CHOP_KEY_SIZE 4
33 #define SSTINDEX_BINARY_CHOP_PTR_SIZE 4
34 #define SSTINDEX_BINARY_CHOP_ENTRY_SIZE \
35  (SSTINDEX_BINARY_CHOP_KEY_SIZE + SSTINDEX_BINARY_CHOP_PTR_SIZE)
36 
37 //#include "xapian/constants.h"
38 #include "xapian/error.h"
39 
40 #include <algorithm>
41 #include <string_view>
42 #if 0
43 #include <iostream> // FIXME
44 #endif
45 
46 #include <cstdio> // For EOF
47 #include <cstdlib> // std::abort()
48 #include <type_traits>
49 #ifdef HAVE_SYS_UIO_H
50 # include <sys/uio.h>
51 #endif
52 
53 #include <sys/types.h>
54 #include "safesysstat.h"
55 #include "safeunistd.h"
56 
57 #include "compression_stream.h"
58 #include "honey_defs.h"
59 #include "honey_version.h"
60 #include "internaltypes.h"
61 #include "io_utils.h"
62 #include "pack.h"
63 #include "str.h"
64 #include "stringutils.h"
65 #include "wordaccess.h"
66 
68 
69 #ifdef BLK_UNUSED
70 # undef BLK_UNUSED
71 #endif // FIXME: namespace it?
72 
73 const uint4 BLK_UNUSED = uint4(-1);
74 
76 
78  friend class BufferedFile;
79  int fd = -1;
80  unsigned _refs = 0;
81  off_t offset = 0;
82 
83  BufferedFileCommon(int fd_, off_t offset_)
84  : fd(fd_), _refs(1), offset(offset_) {}
85 
87 
89 };
90 
91 class BufferedFile {
93 
100  mutable off_t pos = 0;
101  bool read_only = true;
102 
104  mutable size_t buf_end = 0;
105  mutable char buf[4096];
106 
107  const int FORCED_CLOSE = -2;
108 
109  public:
111 
113  if (!o.read_only) std::abort();
114  if (common) ++common->_refs;
115 #if 0
116  if (o.buf_end) {
117  buf_end = o.buf_end;
118  std::memcpy(buf, o.buf, buf_end);
119  }
120 #endif
121  }
122 
123  BufferedFile(int fd_, off_t offset_, off_t pos_, bool read_only_)
124  : common(new BufferedFileCommon(fd_, offset_)),
125  pos(pos_), read_only(read_only_) {}
126 
128  if (common && --common->_refs == 0)
129  delete common;
130  }
131 
132  off_t get_offset() const { return common->offset; }
133 
134  void close(bool fd_owned) {
135  if (common && common->fd >= 0) {
136  if (fd_owned) ::close(common->fd);
137  common->fd = -1;
138  }
139  }
140 
141  void force_close(bool fd_owned) {
142  if (common) {
143  if (fd_owned && common->fd >= 0) ::close(common->fd);
145  }
146  }
147 
148  bool is_open() const { return common && common->fd >= 0; }
149 
150  bool was_forced_closed() const {
151  return common && common->fd == FORCED_CLOSE;
152  }
153 
154  bool open(const std::string& path, bool read_only_) {
155  if (common && --common->_refs == 0)
156  delete common;
157  common = nullptr;
158  read_only = read_only_;
159  int fd;
160  if (read_only) {
161  fd = io_open_stream_rd(path);
162  } else {
163  // FIXME: Always create anew for now...
164  fd = io_open_stream_wr(path, true);
165  }
166  if (fd < 0) return false;
167  common = new BufferedFileCommon(fd, 0);
168  return true;
169  }
170 
171  off_t get_pos() const {
172  return read_only ? pos - buf_end : pos + buf_end;
173  }
174 
175  void set_pos(off_t pos_) {
176  if (buf_end == 0) {
177  // No buffered data to flush or try to salvage.
178  } else if (!read_only) {
179  flush();
180  } else {
181  // Keep any buffered data we can.
182  size_t delta = size_t(pos_ - (pos - buf_end));
183  // Since delta is an unsigned type, `>` also checks for a
184  // "negative" delta.
185  if (delta > buf_end) {
186  buf_end = 0;
187  } else {
188  buf_end -= delta;
189  }
190  }
191  pos = pos_;
192  }
193 
194  void skip(size_t delta) const {
195  if (!read_only) std::abort();
196  // Keep any buffered data we can.
197  if (delta > buf_end) {
198  pos -= buf_end;
199  pos += delta;
200  buf_end = 0;
201  } else {
202  buf_end -= delta;
203  }
204  }
205 
206 #if 0
207  bool empty() const {
208  if (buf_end) return false;
209  struct stat sbuf;
210  if (fd == -1 || fstat(fd, &sbuf) < 0) return true;
211  return (sbuf.st_size == 0);
212  }
213 #endif
214 
215  void write(unsigned char ch) {
216  if (buf_end == sizeof(buf)) {
217  // writev()?
219  pos += buf_end;
220  buf_end = 0;
221  }
222  buf[buf_end++] = ch;
223  }
224 
225  void write(const char* p, size_t len) {
226  if (buf_end + len <= sizeof(buf)) {
227  memcpy(buf + buf_end, p, len);
228  buf_end += len;
229  return;
230  }
231 
232 #ifdef HAVE_WRITEV
233  pos += buf_end + len;
234  while (true) {
235  struct iovec iov[2];
236  iov[0].iov_base = buf;
237  iov[0].iov_len = buf_end;
238  iov[1].iov_base = const_cast<char*>(p);
239  iov[1].iov_len = len;
240  ssize_t n_ = writev(common->fd, iov, 2);
241  if (n_ < 0) std::abort();
242  size_t n = n_;
243  if (n == buf_end + len) {
244  // Wrote everything.
245  buf_end = 0;
246  return;
247  }
248  if (n >= buf_end) {
249  // Wrote all of buf.
250  n -= buf_end;
251  p += n;
252  len -= n;
253  io_write(common->fd, p, len);
254  buf_end = 0;
255  return;
256  }
257  buf_end -= n;
258  memmove(buf, buf + n, buf_end);
259  }
260 #else
262  pos += buf_end;
263  if (len >= sizeof(buf)) {
264  // If it's bigger than our buffer, just write it directly.
265  io_write(common->fd, p, len);
266  pos += len;
267  buf_end = 0;
268  return;
269  }
270  memcpy(buf, p, len);
271  buf_end = len;
272 #endif
273  }
274 
275  int read() const {
276  if (buf_end == 0) {
277  // The buffer is currently empty, so we need to read at least one
278  // byte.
279  size_t r = io_pread(common->fd, buf, sizeof(buf), pos, 0);
280  if (r < sizeof(buf)) {
281  if (r == 0) {
282  return EOF;
283  }
284  memmove(buf + sizeof(buf) - r, buf, r);
285  }
286  pos += r;
287  buf_end = r;
288  }
289  return static_cast<unsigned char>(buf[sizeof(buf) - buf_end--]);
290  }
291 
293  uint4 res = read() << 24;
294  res |= read() << 16;
295  res |= read() << 8;
296  res |= read();
297  return res;
298  }
299 
300  void read(char* p, size_t len) const {
301  if (buf_end != 0) {
302  if (len <= buf_end) {
303  memcpy(p, buf + sizeof(buf) - buf_end, len);
304  buf_end -= len;
305  return;
306  }
307  memcpy(p, buf + sizeof(buf) - buf_end, buf_end);
308  p += buf_end;
309  len -= buf_end;
310  buf_end = 0;
311  }
312  // FIXME: refill buffer if len < sizeof(buf)
313  size_t r = io_pread(common->fd, p, len, pos + common->offset, len);
314  // io_pread() should throw an exception if it read < len bytes.
315  AssertEq(r, len);
316  pos += r;
317  }
318 
319  void flush() {
320  if (!read_only && buf_end) {
322  pos += buf_end;
323  buf_end = 0;
324  }
325  }
326 
327  void sync() {
328  io_sync(common->fd);
329  }
330 
331  void rewind(off_t start) {
332  read_only = true;
333  pos = start;
334  buf_end = 0;
335  }
336 };
337 
338 class HoneyCursor;
339 
340 class SSTIndex {
341  std::string data;
342 #if defined SSTINDEX_BINARY_CHOP
343  size_t block = size_t(-1);
344 #elif defined SSTINDEX_SKIPLIST
345  size_t block = 0;
346 #endif
347 #if defined SSTINDEX_BINARY_CHOP || defined SSTINDEX_SKIPLIST
348  std::string last_index_key;
349 #endif
350  // Put an index entry every this much:
351  // FIXME: tune - seems 64K is common elsewhere
352  enum { INDEXBLOCK = 4096 };
354 
355 #ifdef SSTINDEX_ARRAY
356  unsigned char first, last = static_cast<unsigned char>(-1);
357  off_t* pointers = NULL;
358 #endif
359 
360  public:
362 #ifdef SSTINDEX_ARRAY
363  // Header added in write() method.
364 #elif defined SSTINDEX_BINARY_CHOP
365  data.assign(5, '\x01');
366 #elif defined SSTINDEX_SKIPLIST
367  data.assign(1, '\x02');
368 #else
369 # error SSTINDEX type not specified
370 #endif
371  }
372 
374 #ifdef SSTINDEX_ARRAY
375  delete [] pointers;
376 #endif
377  }
378 
379  void maybe_add_entry(std::string_view key, off_t ptr) {
380  Assert(!key.empty());
381 #ifdef SSTINDEX_ARRAY
382  unsigned char initial = key[0];
383  if (!pointers) {
384  pointers = new off_t[256]();
385  first = initial;
386  }
387  // We should only be called for valid index points.
388  AssertRel(int(initial), !=, last);
389 
390  while (++last != int(initial)) {
391  pointers[last] = ptr;
392  // FIXME: Perhaps record this differently so that an exact key
393  // search can return false?
394  }
395  pointers[initial] = ptr;
396  last = initial;
397 #elif defined SSTINDEX_BINARY_CHOP
398  // We store entries truncated to a maximum width (and trailing zeros
399  // are used to indicate keys shorter than that max width). These then
400  // point to the first key that maps to this truncated value.
401  //
402  // We need constant width entries to allow binary chop to work, but
403  // there are other ways to achieve this which could be explored. We
404  // could allow the full key width of 256 bytes, but that would take a
405  // lot more space. We could store a pointer (offset) to the key data,
406  // but that's more complex to read, and adds the pointer overhead. We
407  // could use a "SKO" - a fixed width entry which encodes variable
408  // length pointer and key with short keys in the entry and long keys
409  // pointed to (or prefix included and rest pointed to).
410  if (last_index_key.size() == SSTINDEX_BINARY_CHOP_KEY_SIZE) {
411  if (startswith(key, last_index_key)) {
412  return;
413  }
414  }
415 
416  // Ensure the truncated key doesn't end in a zero byte.
417  if (key.size() >= SSTINDEX_BINARY_CHOP_KEY_SIZE) {
418  // FIXME: Start from char N if we have N array index levels above.
419  last_index_key.assign(key, 0, SSTINDEX_BINARY_CHOP_KEY_SIZE);
420  if (key[SSTINDEX_BINARY_CHOP_KEY_SIZE - 1] == '\0')
421  return;
422  } else {
423  last_index_key = key;
424  if (key.back() == '\0')
425  return;
426  // Pad with zero bytes.
427  last_index_key.resize(SSTINDEX_BINARY_CHOP_KEY_SIZE);
428  }
429 
430  // Thin entries to at most one per INDEXBLOCK sized block.
431  size_t cur_block = ptr / INDEXBLOCK;
432  if (cur_block == block)
433  return;
434 
435 #if 0
436  {
437  std::string esc;
438  description_append(esc, last_index_key);
439  std::cout << "Adding «" << esc << "» -> file offset " << ptr
440  << std::endl;
441  }
442 #endif
443  data += last_index_key;
444  size_t c = data.size();
445  data.resize(c + 4);
446  unaligned_write4(reinterpret_cast<unsigned char*>(&data[c]), ptr);
447 
448  block = cur_block;
449 #elif defined SSTINDEX_SKIPLIST
450  size_t cur_block = ptr / INDEXBLOCK;
451  if (cur_block == block) return;
452 
453  size_t reuse = common_prefix_length(last_index_key, key);
454 
455  data += char(reuse);
456  data += char(key.size() - reuse);
457  data.append(key, reuse, key.size() - reuse);
458  pack_uint(data, static_cast<std::make_unsigned_t<off_t>>(ptr));
459 
460  block = cur_block;
461  // FIXME: deal with parent_index...
462 
463  last_index_key = key;
464 #else
465 # error SSTINDEX type not specified
466 #endif
467  }
468 
469  off_t write(BufferedFile& store) {
470  off_t root = store.get_pos();
471 
472 #ifdef SSTINDEX_ARRAY
473  if (!pointers) {
474  first = last = 0;
475  pointers = new off_t[1]();
476  }
477  data.resize(0);
478  data.resize(3 + (last - first + 1) * 4);
479  data[0] = 0;
480  data[1] = first;
481  data[2] = last - first;
482  for (unsigned ch = first; ch <= last; ++ch) {
483  size_t o = 3 + (ch - first) * 4;
484  // FIXME: Just make offsets 8 bytes? Or allow different widths?
485  off_t ptr = pointers[ch];
486  if (sizeof(off_t) > 4 && ptr > off_t(0xffffffff))
487  throw Xapian::DatabaseError("Index offset needs >4 bytes");
488  Assert(o + 4 <= data.size());
489  unaligned_write4(reinterpret_cast<unsigned char*>(&data[o]), ptr);
490  }
491  delete [] pointers;
492  pointers = NULL;
493 #elif defined SSTINDEX_BINARY_CHOP
494  if (last_index_key.size() == SSTINDEX_BINARY_CHOP_KEY_SIZE) {
495  // Increment final byte(s) to give a key which is definitely
496  // at or above any key which this could be truncated from.
497  size_t i = last_index_key.size();
498  unsigned char ch;
499  do {
500  if (i == 0) {
501  // We can't increment "\xff\xff\xff\xff" to give an upper
502  // bound - just skip adding one in this case as the table
503  // will handle it OK and there's not much to be gained by
504  // adding one as few keys are larger.
505  goto skip_adding_upper_bound;
506  }
507  --i;
508  ch = static_cast<unsigned char>(last_index_key[i]) + 1;
509  last_index_key[i] = ch;
510  } while (ch == 0);
511  } else {
512  // Pad with zeros, which gives an upper bound.
513  last_index_key.resize(SSTINDEX_BINARY_CHOP_KEY_SIZE);
514  }
515 
516  {
517  data += last_index_key;
518  size_t c = data.size();
519  data.resize(c + 4);
520  unaligned_write4(reinterpret_cast<unsigned char*>(&data[c]), root);
521  }
522 
523 skip_adding_upper_bound:
524  // Fill in bytes 1 to 4 with the number of entries.
525  size_t n_index = (data.size() - 5) / SSTINDEX_BINARY_CHOP_ENTRY_SIZE;
526  data[1] = n_index >> 24;
527  data[2] = n_index >> 16;
528  data[3] = n_index >> 8;
529  data[4] = n_index;
530 #elif defined SSTINDEX_SKIPLIST
531  // Already built in data.
532 #else
533 # error SSTINDEX type not specified
534 #endif
535 
536  store.write(data.data(), data.size());
537  // FIXME: parent stuff...
538  return root;
539  }
540 
541  size_t size() const {
542  // FIXME: For SSTINDEX_ARRAY, data.size() only correct after calling
543  // write().
544  size_t s = data.size();
545  if (parent_index) s += parent_index->size();
546  return s;
547  }
548 };
549 
550 class HoneyCursor;
551 class MutableHoneyCursor;
552 
553 class HoneyTable {
554  // FIXME cleaner way?
555  friend class HoneyCursor; // Allow access to store.
556  friend class MutableHoneyCursor; // Allow access to store.
557 
558  std::string path;
559  bool read_only;
560  int flags;
563  mutable std::string last_key;
565  off_t root = -1;
567  bool lazy;
568 
569  bool single_file() const { return path.empty(); }
570 
576  off_t offset = 0;
577 
578  bool get_exact_entry(std::string_view key, std::string* tag) const;
579 
580  bool read_key(std::string& key, size_t& val_size, bool& compressed) const;
581 
582  void read_val(std::string& val, size_t val_size) const;
583 
584  public:
585  HoneyTable(const char*, const std::string& path_, bool read_only_,
586  bool lazy_ = false)
587  : path(path_ + HONEY_TABLE_EXTENSION),
588  read_only(read_only_),
589  lazy(lazy_)
590  {
591  }
592 
593  HoneyTable(const char*, int fd, off_t offset_, bool read_only_,
594  bool lazy_ = false)
595  : read_only(read_only_),
596  store(fd, 0, offset_, read_only_),
597  lazy(lazy_),
598  offset(offset_)
599  {
600  }
601 
603 #if 0
604  size_t index_size = index.size();
605  if (index_size)
606  std::cout << "*** " << path << " - index " << index_size << " for "
607  << index.get_num_entries() << " entries" << std::endl;
608 #endif
609  bool fd_owned = !single_file();
610  store.close(fd_owned);
611  }
612 
613  bool is_writable() const { return !read_only; }
614 
615  int get_flags() const { return flags; }
616 
617  void create_and_open(int flags_, const Honey::RootInfo& root_info);
618 
619  void open(int flags_, const Honey::RootInfo& root_info,
621 
622  void close(bool permanent) {
623  bool fd_owned = !single_file();
624  if (permanent)
625  store.force_close(fd_owned);
626  else
627  store.close(fd_owned);
628  }
629 
630  const std::string& get_path() const { return path; }
631 
632  void add(std::string_view key,
633  const char* val,
634  size_t val_size,
635  bool compressed = false);
636 
637  void add(std::string_view key,
638  std::string_view val,
639  bool compressed = false) {
640  add(key, val.data(), val.size(), compressed);
641  }
642 
643  void flush_db() {
644  root = index.write(store);
645  store.flush();
646  }
647 
649  std::abort();
650  }
651 
653 
654  bool sync() {
655  store.sync();
656  return true;
657  }
658 
659  bool empty() const {
660  return num_entries == 0;
661  }
662 
663  bool get_exact_entry(std::string_view key, std::string& tag) const {
664  return get_exact_entry(key, &tag);
665  }
666 
667  bool key_exists(const std::string& key) const {
668  return get_exact_entry(key, NULL);
669  }
670 
671  bool del(const std::string&) {
672  std::abort();
673  }
674 
675  // readahead probably not useful? (FIXME)
676  bool readahead_key(const std::string&) const { return false; }
677 
678  bool is_modified() const { return !read_only && !empty(); }
679 
680  HoneyCursor* cursor_get() const;
681 
682  bool exists() const {
683  struct stat sbuf;
684  return stat(path.c_str(), &sbuf) == 0;
685  }
686 
687  bool is_open() const { return store.is_open(); }
688 
689  static void throw_database_closed() {
690  throw Xapian::DatabaseClosedError("Closed!");
691  }
692 
694 
700 
701  off_t get_root() const { return root; }
702 
703  off_t get_offset() const { return offset; }
704 };
705 
706 #endif // XAPIAN_INCLUDED_HONEY_TABLE_H
BufferedFileCommon & operator=(const BufferedFileCommon &)=delete
BufferedFileCommon(const BufferedFileCommon &)=delete
BufferedFileCommon(int fd_, off_t offset_)
Definition: honey_table.h:83
off_t get_pos() const
Definition: honey_table.h:171
void set_pos(off_t pos_)
Definition: honey_table.h:175
void skip(size_t delta) const
Definition: honey_table.h:194
void write(const char *p, size_t len)
Definition: honey_table.h:225
off_t pos
Offset in file.
Definition: honey_table.h:100
bool open(const std::string &path, bool read_only_)
Definition: honey_table.h:154
bool was_forced_closed() const
Definition: honey_table.h:150
void force_close(bool fd_owned)
Definition: honey_table.h:141
void read(char *p, size_t len) const
Definition: honey_table.h:300
void close(bool fd_owned)
Definition: honey_table.h:134
BufferedFile(int fd_, off_t offset_, off_t pos_, bool read_only_)
Definition: honey_table.h:123
BufferedFileCommon * common
Definition: honey_table.h:92
void write(unsigned char ch)
Definition: honey_table.h:215
size_t buf_end
Index into buf where buffered data ends.
Definition: honey_table.h:104
const int FORCED_CLOSE
Definition: honey_table.h:107
uint4 read_uint4_be() const
Definition: honey_table.h:292
bool is_open() const
Definition: honey_table.h:148
void rewind(off_t start)
Definition: honey_table.h:331
void flush()
Definition: honey_table.h:319
char buf[4096]
Definition: honey_table.h:105
int read() const
Definition: honey_table.h:275
off_t get_offset() const
Definition: honey_table.h:132
BufferedFile(const BufferedFile &o)
Definition: honey_table.h:112
size_t val_size
Definition: honey_cursor.h:44
HoneyCursor * cursor_get() const
Definition: honey_table.cc:454
HoneyTable(const char *, int fd, off_t offset_, bool read_only_, bool lazy_=false)
Definition: honey_table.h:593
bool get_exact_entry(std::string_view key, std::string *tag) const
Definition: honey_table.cc:247
honey_tablesize_t get_entry_count() const
Definition: honey_table.h:693
void close(bool permanent)
Definition: honey_table.h:622
void create_and_open(int flags_, const Honey::RootInfo &root_info)
Definition: honey_table.cc:43
void add(std::string_view key, const char *val, size_t val_size, bool compressed=false)
Definition: honey_table.cc:74
bool del(const std::string &)
Definition: honey_table.h:671
bool exists() const
Definition: honey_table.h:682
honey_tablesize_t get_approx_entry_count() const
Return an approximation of the number of entries in the table.
Definition: honey_table.h:699
void cancel(const Honey::RootInfo &, honey_revision_number_t)
Definition: honey_table.h:648
uint4 compress_min
Definition: honey_table.h:561
bool single_file() const
Definition: honey_table.h:569
bool is_open() const
Definition: honey_table.h:687
const std::string & get_path() const
Definition: honey_table.h:630
static void throw_database_closed()
Definition: honey_table.h:689
honey_tablesize_t num_entries
Definition: honey_table.h:566
BufferedFile store
Definition: honey_table.h:562
int get_flags() const
Definition: honey_table.h:615
SSTIndex index
Definition: honey_table.h:564
std::string last_key
Definition: honey_table.h:563
bool is_writable() const
Definition: honey_table.h:613
off_t offset
Offset to add to pointers in this table.
Definition: honey_table.h:576
bool read_key(std::string &key, size_t &val_size, bool &compressed) const
Definition: honey_table.cc:158
off_t root
Definition: honey_table.h:565
HoneyTable(const char *, const std::string &path_, bool read_only_, bool lazy_=false)
Definition: honey_table.h:585
bool get_exact_entry(std::string_view key, std::string &tag) const
Definition: honey_table.h:663
void read_val(std::string &val, size_t val_size) const
Definition: honey_table.cc:232
void commit(honey_revision_number_t, Honey::RootInfo *root_info)
Definition: honey_table.cc:141
off_t get_root() const
Definition: honey_table.h:701
std::string path
Definition: honey_table.h:558
bool is_modified() const
Definition: honey_table.h:678
void flush_db()
Definition: honey_table.h:643
bool key_exists(const std::string &key) const
Definition: honey_table.h:667
off_t get_offset() const
Definition: honey_table.h:703
bool read_only
Definition: honey_table.h:559
bool empty() const
Definition: honey_table.h:659
bool sync()
Definition: honey_table.h:654
void open(int flags_, const Honey::RootInfo &root_info, honey_revision_number_t)
Definition: honey_table.cc:58
void add(std::string_view key, std::string_view val, bool compressed=false)
Definition: honey_table.h:637
bool readahead_key(const std::string &) const
Definition: honey_table.h:676
unsigned char first
Definition: honey_table.h:356
SSTIndex * parent_index
Definition: honey_table.h:353
size_t size() const
Definition: honey_table.h:541
off_t write(BufferedFile &store)
Definition: honey_table.h:469
std::string data
Definition: honey_table.h:341
void maybe_add_entry(std::string_view key, off_t ptr)
Definition: honey_table.h:379
unsigned char last
Definition: honey_table.h:356
off_t * pointers
Definition: honey_table.h:357
Indicates an attempt to access a closed database.
Definition: error.h:1085
DatabaseError indicates some sort of database related error.
Definition: error.h:355
class wrapper around zlib
PositionList * p
Append a string to an object description, escaping invalid UTF-8.
Hierarchy of classes which Xapian can throw as exceptions.
Definitions, types, etc for use inside honey.
unsigned long long honey_tablesize_t
How many entries there are in a table.
Definition: honey_defs.h:107
#define HONEY_TABLE_EXTENSION
Honey table extension.
Definition: honey_defs.h:29
uint4 honey_revision_number_t
The revision number of a honey database.
Definition: honey_defs.h:104
#define SSTINDEX_BINARY_CHOP_ENTRY_SIZE
Definition: honey_table.h:34
#define SSTINDEX_BINARY_CHOP_KEY_SIZE
Definition: honey_table.h:32
const uint4 BLK_UNUSED
Definition: honey_table.h:73
HoneyVersion class.
Types used internally.
uint32_t uint4
Definition: internaltypes.h:31
void io_write(int fd, const char *p, size_t n)
Write n bytes from block pointed to by p to file descriptor fd.
Definition: io_utils.cc:263
int io_open_stream_wr(const char *filename, bool anew)
Open a stream-based file for writing.
Definition: io_utils.cc:231
size_t io_pread(int fd, char *p, size_t n, off_t o, size_t min)
Read n bytes (or until EOF) into block pointed to by p from file descriptor fd starting at position o...
Definition: io_utils.cc:277
Wrappers for low-level POSIX I/O routines.
int io_open_stream_rd(const char *filename)
Open a stream-based file for reading.
Definition: io_utils.h:72
bool io_sync(int fd)
Ensure all data previously written to file descriptor fd has been written to disk.
Definition: io_utils.h:107
#define AssertEq(A, B)
Definition: omassert.h:124
#define AssertRel(A, REL, B)
Definition: omassert.h:123
#define Assert(COND)
Definition: omassert.h:122
Pack types into strings and unpack them again.
void pack_uint(std::string &s, U value)
Append an encoded unsigned integer to a string.
Definition: pack.h:315
include <sys/stat.h> with portability enhancements
<unistd.h>, but with compat.
Convert types to std::string.
Various handy string-related helpers.
bool startswith(std::string_view s, char pfx)
Definition: stringutils.h:56
std::string::size_type common_prefix_length(std::string_view a, std::string_view b)
Definition: stringutils.h:128
void description_append(std::string &desc, std::string_view s)
Definition: unittest.cc:105
functions for reading and writing different width words
void unaligned_write4(unsigned char *ptr, T value)
Definition: wordaccess.h:173