53 if (!store.open(path, read_only))
65 if (!single_file() && !store.open(path, read_only)) {
70 store.set_pos(offset);
79 if (
rare(val_size == 0))
81 if (store.was_forced_closed())
83 if (!compressed && compress_min > 0 && val_size > compress_min) {
84 size_t compressed_size = val_size;
86 const char*
p = comp_stream.
compress(val, &compressed_size);
88 add(key,
p, compressed_size,
true);
102 #ifdef SSTINDEX_ARRAY
104 index.maybe_add_entry(key, store.get_pos());
106 #elif defined SSTINDEX_BINARY_CHOP
110 index.maybe_add_entry(key, store.get_pos());
111 #elif defined SSTINDEX_SKIPLIST
114 # error SSTINDEX type not specified
117 store.write(
static_cast<unsigned char>(reuse));
118 store.write(
static_cast<unsigned char>(key.size() - reuse));
119 store.write(key.data() + reuse, key.size() - reuse);
122 #ifdef SSTINDEX_SKIPLIST
125 index.maybe_add_entry(key, store.get_pos());
131 size_t val_size_enc = (val_size << 1) |
size_t{compressed};
135 store.write(val_len.data(), val_len.size());
136 store.write(val, val_size);
153 store.rewind(offset);
160 bool& compressed)
const
166 cerr <<
"HoneyTable::read_key(" << desc <<
", ...) for path=" << path
175 if (store.get_pos() >= root) {
179 int ch = store.read();
180 if (ch == EOF)
return false;
183 if (reuse > last_key.size()) {
191 size_t key_size = ch;
193 store.read(buf, key_size);
194 key.assign(last_key, 0, reuse);
195 key.append(buf, key_size);
202 std::cout <<
"K:" << esc << std::endl;
210 for (
int i = 0; i < 8; ++i) {
211 int ch2 = store.read();
216 if (ch2 < 128)
break;
221 const char* end =
p + r;
225 compressed = val_size & 1;
234 AssertRel(store.get_pos() + val_size, <=,
size_t(root));
235 val.resize(val_size);
236 store.read(&(val[0]), val_size);
241 std::cout <<
"V:" << esc << std::endl;
249 if (!read_only) std::abort();
250 if (
rare(!store.is_open())) {
251 if (store.was_forced_closed())
256 if (
rare(key.empty()))
258 bool exact_match =
false;
259 bool compressed =
false;
261 int index_type = store.read();
262 switch (index_type) {
266 unsigned char first =
267 static_cast<unsigned char>(key[0] - store.read());
268 unsigned char range = store.read();
271 store.skip(first * 4);
272 off_t jump = store.read_uint4_be();
281 size_t j = store.read_uint4_be();
284 off_t base = store.get_pos();
289 size_t k = i + (j - i) / 2;
293 while (kkey_len > 0 && kkey[kkey_len - 1] ==
'\0') --kkey_len;
308 while (kkey_len > 0 && kkey[kkey_len - 1] ==
'\0') --kkey_len;
309 off_t jump = store.read_uint4_be();
314 last_key.assign(kkey, jump == 0 ? 0 : kkey_len);
321 string index_key, prev_index_key;
322 make_unsigned_t<off_t> ptr = 0;
325 int reuse = store.read();
326 if (reuse == EOF)
break;
327 int len = store.read();
328 if (len == EOF) abort();
329 index_key.resize(reuse + len);
330 store.read(&index_key[reuse], len);
336 cerr <<
"Index key: " << desc << endl;
340 cmp0 = index_key.compare(key);
342 index_key = prev_index_key;
348 int b = store.read();
350 if ((b & 0x80) == 0)
break;
356 cerr <<
" -> " << ptr << endl;
361 prev_index_key = index_key;
365 cerr <<
" cmp0 = " << cmp0 <<
", going to " << ptr << endl;
371 last_key = index_key;
377 for (
int i = 0; i < 8; ++i) {
378 int ch2 = store.read();
383 if (ch2 < 128)
break;
388 const char* end =
p + r;
392 compressed = val_size & 1;
408 cerr <<
"Dropped to data layer on key: " << desc << endl;
415 string m =
"HoneyTable: Unknown index type ";
416 m +=
str(index_type);
427 store.skip(val_size);
430 if (!read_key(k, val_size, compressed))
return false;
431 cmp = k.compare(key);
433 if (cmp > 0)
return false;
438 read_val(v, val_size);
447 read_val(*tag, val_size);
456 if (
rare(!store.is_open())) {
457 if (store.was_forced_closed())
bool decompress_chunk(const char *p, int len, std::string &buf)
Returns true if this was the final chunk.
const char * compress(const char *buf, size_t *p_size)
HoneyCursor * cursor_get() const
bool get_exact_entry(std::string_view key, std::string *tag) const
void create_and_open(int flags_, const Honey::RootInfo &root_info)
void add(std::string_view key, const char *val, size_t val_size, bool compressed=false)
bool read_key(std::string &key, size_t &val_size, bool &compressed) const
void read_val(std::string &val, size_t val_size) const
void commit(honey_revision_number_t, Honey::RootInfo *root_info)
void open(int flags_, const Honey::RootInfo &root_info, honey_revision_number_t)
void set_num_entries(honey_tablesize_t n)
uint4 get_compress_min() const
honey_tablesize_t get_num_entries() const
void set_root(off_t root_)
DatabaseCorruptError indicates database corruption was detected.
DatabaseError indicates some sort of database related error.
DatabaseOpeningError indicates failure to open a database.
InvalidArgumentError indicates an invalid parameter value was passed to the API.
InvalidOperationError indicates the API was used in an invalid way.
Append a string to an object description, escaping invalid UTF-8.
#define HONEY_MAX_KEY_LENGTH
Maximum key length.
uint4 honey_revision_number_t
The revision number of a honey database.
#define SSTINDEX_BINARY_CHOP_ENTRY_SIZE
#define SSTINDEX_BINARY_CHOP_KEY_SIZE
string str(int value)
Convert int to std::string.
#define AssertRel(A, REL, B)
bool unpack_uint(const char **p, const char *end, U *result)
Decode an unsigned integer from a string.
void pack_uint(std::string &s, U value)
Append an encoded unsigned integer to a string.
static void throw_database_closed()
Various handy string-related helpers.
std::string::size_type common_prefix_length(std::string_view a, std::string_view b)
void description_append(std::string &desc, std::string_view s)