From 5f6fa8c04204888c4ff7ac6be1868d81ff4410a8 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 3 Sep 2013 16:10:20 -0700 Subject: [PATCH 1/5] Remember if last cursor op was a delete If so, don't advance cursor on next NEXT. Also, init xcursor on the next GET_CURRENT. --- libraries/liblmdb/mdb.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index f59fe51bc4..dc20b4fb5a 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -933,6 +933,7 @@ struct MDB_cursor { #define C_INITIALIZED 0x01 /**< cursor has been initialized and is valid */ #define C_EOF 0x02 /**< No more data */ #define C_SUB 0x04 /**< Cursor is a sub-cursor */ +#define C_DEL 0x08 /**< last op was a cursor_del */ #define C_SPLITTING 0x20 /**< Cursor is in page_split */ #define C_UNTRACK 0x40 /**< Un-track cursor when closing */ /** @} */ @@ -5006,6 +5007,8 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) } DPRINTF(("cursor_next: top page is %"Z"u in cursor %p", mp->mp_pgno, (void *) mc)); + if (mc->mc_flags & C_DEL) + goto skip; if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) { DPUTS("=====> move to next sibling page"); @@ -5018,6 +5021,7 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) } else mc->mc_ki[mc->mc_top]++; +skip: DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u", mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top])); @@ -5432,6 +5436,8 @@ mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_GET_KEY(leaf, key); if (data) { if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + if (mc->mc_flags & C_DEL) + mdb_xcursor_init1(mc, leaf); rc = mdb_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_GET_CURRENT); } else { rc = mdb_node_read(mc->mc_txn, leaf, data); @@ -5556,6 +5562,9 @@ fetchm: break; } + if (mc->mc_flags & C_DEL) + mc->mc_flags ^= C_DEL; + return rc; } @@ -6105,6 +6114,7 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags) } } mc->mc_db->md_entries--; + mc->mc_flags |= C_DEL; return rc; } /* otherwise fall thru and delete the sub-DB */ @@ -7280,12 +7290,16 @@ mdb_cursor_del0(MDB_cursor *mc, MDB_node *leaf) if (!(m2->mc_flags & C_INITIALIZED)) continue; if (m2->mc_pg[mc->mc_top] == mp) { - if (m2->mc_ki[mc->mc_top] > ki) - m2->mc_ki[mc->mc_top]--; + if (m2->mc_ki[mc->mc_top] >= ki) { + m2->mc_flags |= C_DEL; + if (m2->mc_ki[mc->mc_top] > ki) + m2->mc_ki[mc->mc_top]--; + } if (m2->mc_ki[mc->mc_top] >= nkeys) mdb_cursor_sibling(m2, 1); } } + mc->mc_flags |= C_DEL; } return rc; From 18a07eb7c2dc33372455a6040984cd6b699b41a5 Mon Sep 17 00:00:00 2001 From: Claude Brisson Date: Thu, 5 Sep 2013 12:58:18 +0200 Subject: [PATCH 2/5] ITS#7681 fix mdb_cursor_set behaviour for MDB_SET_RANGE --- libraries/liblmdb/mdb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index dc20b4fb5a..2b61adc5c9 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -5227,7 +5227,10 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, if (!mc->mc_top) { /* There are no other pages */ mc->mc_ki[mc->mc_top] = 0; - return MDB_NOTFOUND; + if (op == MDB_SET_RANGE) + goto set1; + else + return MDB_NOTFOUND; } } From 90c55178db46379c28a4ec7c2b36e36e992cd288 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 5 Sep 2013 06:02:07 -0700 Subject: [PATCH 3/5] More for 5f6fa8c04204888c4ff7ac6be1868d81ff4410a8 Reset delete flag in cursor_put(). --- libraries/liblmdb/mdb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 2b61adc5c9..16db71ecde 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -5688,6 +5688,9 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, return rc; } + if (mc->mc_flags & C_DEL) + mc->mc_flags ^= C_DEL; + /* Cursor is positioned, check for room in the dirty list */ if (!nospill) { if (flags & MDB_MULTIPLE) { From cfc13e2b4837f5cde8433251357ca82686e5b709 Mon Sep 17 00:00:00 2001 From: Salvador Ortiz Date: Thu, 5 Sep 2013 17:36:52 -0500 Subject: [PATCH 4/5] ITS#7682 In mdb_env_copy retry open if O_DIRECT fails --- libraries/liblmdb/mdb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 16db71ecde..9c5e7389de 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -4246,11 +4246,15 @@ mdb_env_copy(MDB_env *env, const char *path) newfd = CreateFile(lpath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL); #else - newfd = open(lpath, O_WRONLY|O_CREAT|O_EXCL #ifdef O_DIRECT - |O_DIRECT + /* The OS supports O_DIRECT, try with it */ + newfd = open(lpath, O_WRONLY|O_CREAT|O_EXCL|O_DIRECT, 0666); + /* But open can fail if O_DIRECT isn't supported by the file system + * so retry without the flag + */ + if (newfd == INVALID_HANDLE_VALUE && ErrCode() == EINVAL) #endif - , 0666); + newfd = open(lpath, O_WRONLY|O_CREAT|O_EXCL, 0666); #endif if (newfd == INVALID_HANDLE_VALUE) { rc = ErrCode(); From 7e58cc0fd39810c9bd0573ba62e3ac9c61b19f11 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 5 Sep 2013 16:23:49 -0700 Subject: [PATCH 5/5] updates --- libraries/liblmdb/CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/liblmdb/CHANGES b/libraries/liblmdb/CHANGES index d982caac6a..df8df44f3e 100644 --- a/libraries/liblmdb/CHANGES +++ b/libraries/liblmdb/CHANGES @@ -4,8 +4,11 @@ LMDB 0.9.8 Engineering Allow mdb_env_set_mapsize() on an open environment Fix mdb_dbi_flags() (ITS#7672) Fix mdb_page_unspill() in nested txns + Fix mdb_cursor_get(CURRENT|NEXT) after a delete Fix mdb_cursor_get(DUP) to always return key (ITS#7671) Fix mdb_cursor_del() to always advance to next item (ITS#7670) + Fix mdb_cursor_set(SET_RANGE) for tree with single page (ITS#7681) + Fix mdb_env_copy() retry open if O_DIRECT fails (ITS#7682) Tweak mdb_page_spill() to be less aggressive Documentation Update caveats since mdb_reader_check() added in 0.9.7