<!DOCTYPE html><html><head><title></title><style type="text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style></head><body><div style="font-family:Arial;">Hi,<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">This is a fun one!  I've been playing with the following pattern:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">* multiple read-only databases being compacted into one.<br></div><div style="font-family:Arial;">* combined metadata to add to the destination database which needs to be calculated (language counts and indexer versions)<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">This is in cyrus imapd.  Existing code is here:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"><a href="https://github.com/cyrusimap/cyrus-imapd/blob/4376a87773f709516105b84e3cf12b7d55775a55/imap/xapian_wrap.cpp#L522">https://github.com/cyrusimap/cyrus-imapd/blob/4376a87773f709516105b84e3cf12b7d55775a55/imap/xapian_wrap.cpp#L522</a><br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">It does the compact, then opens the target database to fiddle the metadata.  Obviously, this isn't allowed with Honey, so I decided to do the following instead:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">* create a new WritableDatabase and write in the metadata I want with a magic prefix on it.<br></div><div style="font-family:Arial;">* update the Xapian::Compactor subclass with the magic to pick the value with the prefix and return that (including empty to remove it).  That code is here:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"><a href="https://github.com/cyrusimap/cyrus-imapd/commit/5ff26ec64197efa568c56fc2189f3f05647b8db2">https://github.com/cyrusimap/cyrus-imapd/commit/5ff26ec64197efa568c56fc2189f3f05647b8db2</a><br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">It works fine still when writing to Glass, but is crashes when writing to Honey:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">Program received signal SIGSEGV, Segmentation fault.<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">Glass::LeafItem_wr::form_key (key_="", this=0x5555555d9308) at backends/glass/glass_table.h:255<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">255              set_key_len(key_len);<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">(gdb) bt<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#0  Glass::LeafItem_wr::form_key (key_="", this=0x5555555d9308) at backends/glass/glass_table.h:255<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#1  GlassTable::form_key (this=this@entry=0x5555555d92d8, key="") at backends/glass/glass_table.cc:1250<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#2  0x00007ffff733bfdb in GlassCursor::find_entry_ge (this=this@entry=0x55555558fea0, key="") at backends/glass/glass_cursor.cc:257<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#3  0x00007ffff73810e8 in GlassCursor::rewind (this=0x55555558fea0) at /usr/include/c++/9/bits/char_traits.h:300<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#4  HoneyCompact::PositionCursor<GlassTable const&>::PositionCursor (offset_=<optimised out>, in=0x5555555d92d8, this=0x55555558fea0)<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    at backends/honey/honey_compact.cc:1662<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#5  HoneyCompact::merge_positions<HoneyTable, GlassTable const> (out=0x5555555b31c0, inputs=std::vector of length 2, capacity 2 = {...},<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    offset=std::vector of length 2, capacity 2 = {...}) at backends/honey/honey_compact.cc:1747<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#6  0x00007ffff737367b in HoneyDatabase::compact (compactor=0x7ffff7fc8828 <xapian_compact_dbs::comp>,<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    destdir=0x5555555905e0 "/tmpfs/cas/1027490101/search2/c/user/cassandane/xapian.NEW", fd=-1, source_backend=<optimised out>,<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    sources=std::vector of length 2, capacity 2 = {...}, offset=std::vector of length 2, capacity 2 = {...}, compaction=Xapian::Compactor::FULLER,<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    flags=<optimised out>, last_docid=<optimised out>) at backends/honey/honey_compact.cc:2325<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#7  0x00007ffff72ac649 in Xapian::Database::compact_ (this=this@entry=0x7fffffffddf0, output_ptr=output_ptr@entry=0x7fffffffdf60, fd=fd@entry=0, flags=<optimised out>,<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    flags@entry=1290, block_size=block_size@entry=0, compactor=compactor@entry=0x7ffff7fc8828 <xapian_compact_dbs::comp>) at /usr/include/c++/9/bits/basic_string.h:2300<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">#8  0x00007ffff7f6884a in Xapian::Database::compact (compactor=..., block_size=0, flags=1290, output="/tmpfs/cas/1027490101/search2/c/user/cassandane/xapian.NEW",<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    this=0x7fffffffddf0) at /usr/local/cyruslibs-v33/include/xapian-1.5/xapian/database.h:818</span><br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">The issue is, 'p' is NULL:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">(gdb) p in<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">$4 = (const GlassTable *) 0x5555555d92d8<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">(gdb) p *in<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">$5 = {tablename = 0x7ffff74b33e9 "position", revision_number = 1, item_count = 0, block_size = 8192, flags = -1, faked_root_block = true, sequential = true,<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">  handle = -1, level = 0, root = 0, kt = {<Glass::LeafItem_base<unsigned char*>> = {p = 0x0}, <No data fields>}, buffer = 0x0, free_list = {revision = 0,<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    first_unused_block = 0, fl = {n = 0, c = 0}, fl_end = {n = 0, c = 0}, flw = {n = 0, c = 0}, flw_appending = false, p = 0x0, pw = 0x0},<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">  name = "/tmpfs/cas/1027490101/search2/c/user/cassandane/</span><a href="http://xapian.NEW.META/position"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">xapian.NEW.META/position</span></a><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">.", seq_count = 0, changed_n = 0, changed_c = 0, max_item_size = 0,<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">  Btree_modified = false, full_compaction = false, writable = false, cursor_created_since_last_modification = true, cursor_version = 0, changes_obj = 0x0, C = {{<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">      data = 0x0, c = -1, rewrite = false}, {data = 0x0, c = -1, rewrite = false}, {data = 0x0, c = -1, rewrite = false}, {data = 0x0, c = -1, rewrite = false}, {<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">      data = 0x0, c = -1, rewrite = false}, {data = 0x0, c = -1, rewrite = false}, {data = 0x0, c = -1, rewrite = false}, {data = 0x0, c = -1, rewrite = false}, {<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">      data = 0x0, c = -1, rewrite = false}, {data = 0x0, c = -1, rewrite = false}}, split_p = 0x0, compress_min = 0, comp_stream = {compress_strategy = 0, out_len = 0,<br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">    out = 0x0, deflate_zstream = 0x0, inflate_zstream = 0x0}, lazy = true, last_readahead = 4294967295, offset = 0}</span><br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">Because the position table is empty!  I'm not sure why 'kt' isn't being initialised.  I patched around it on my testbed as follows:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">diff --git a/xapian-core/backends/glass/glass_cursor.cc b/xapian-core/backends/glass/glass_cursor.cc</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">index c20ff1ab04f8..07c2a58cb7c8 100644</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">--- a/xapian-core/backends/glass/glass_cursor.cc</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+++ b/xapian-core/backends/glass/glass_cursor.cc</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">@@ -106,6 +106,10 @@ bool</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">GlassCursor::next()</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">{</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     LOGCALL(DB, bool, "GlassCursor::next", NO_ARGS);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    if (B->empty()) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+     is_after_end = true;</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+ RETURN(false);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    }</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     Assert(!is_after_end);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     if (B->cursor_version != version) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">// find_entry() will call rebuild().</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">@@ -144,6 +148,10 @@ bool</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">GlassCursor::find_entry(const string &key)</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">{</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     LOGCALL(DB, bool, "GlassCursor::find_entry", key);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    if (B->empty()) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+        is_after_end = true;</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+        RETURN(false);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    }</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     if (B->cursor_version != version) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">rebuild();</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     }</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">@@ -190,6 +198,10 @@ void</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">GlassCursor::find_entry_lt(const string &key)</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">{</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     LOGCALL_VOID(DB, "GlassCursor::find_entry_lt", key);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    if (B->empty()) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+        is_after_end = true;</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+        return;</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    }</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     if (!find_entry(key)) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">// The entry wasn't found, so find_entry() left us on the entry before</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">// the one we asked for and we're done.</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">@@ -213,6 +225,10 @@ bool</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">GlassCursor::find_exact(const string &key)</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">{</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     LOGCALL(DB, bool, "GlassCursor::find_exact", key);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    if (B->empty()) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+        is_after_end = true;</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+        RETURN(false);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    }</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     is_after_end = false;</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     is_positioned = false;</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     if (rare(key.size() > GLASS_BTREE_MAX_KEY_LEN)) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">@@ -238,6 +254,10 @@ bool</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">GlassCursor::find_entry_ge(const string &key)</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">{</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     LOGCALL(DB, bool, "GlassCursor::find_entry_ge", key);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    if (B->empty()) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+        is_after_end = true;</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+        RETURN(false);</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">+    }</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     if (B->cursor_version != version) {</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">rebuild();</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;">     }</span><span class="font" style="font-family:menlo, consolas, monospace, sans-serif;"><br></span></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">But I'm not sure if the right approach is to patch the cursor to not try and build a key if there's no data, or if kt should be initialised.<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">Or indeed, if the Honey compactor should check for empty tables and just skip them without trying to create a cursor!<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">What I think I would really like is an API to pass a hash of key/value metadata items into db.compact rather than having to do this workaround, but either way it's bad if we crash on an empty database!</div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">Cheers,<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">Bron.</div><div style="font-family:Arial;"><br></div><div id="sig56629417"><div>--<br></div><div>  Bron Gondwana, CEO, Fastmail Pty Ltd<br></div><div>  brong@fastmailteam.com<br></div><div><br></div></div><div style="font-family:Arial;"><br></div></body></html>