From 5a4f5c964ac11c68e0788cac023ed210f65c26e4 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 9 Jun 2022 22:58:06 +0100 Subject: [PATCH 01/11] Fix spurious fallthru warning --- libraries/liblmdb/mdb_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/liblmdb/mdb_dump.c b/libraries/liblmdb/mdb_dump.c index 29ee02e031..36058df723 100644 --- a/libraries/liblmdb/mdb_dump.c +++ b/libraries/liblmdb/mdb_dump.c @@ -189,7 +189,7 @@ int main(int argc, char *argv[]) break; case 'l': list = 1; - /*FALLTHROUGH*/; + /*FALLTHROUGH*/ case 'a': if (subname) usage(prog); From 1b113f2c94940bedbe86332f0c802db031814749 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 13 Apr 2019 23:37:03 +0000 Subject: [PATCH 02/11] lmdb: catch non-LMDB negative errors before strerror That should hopefully shut coverity up --- libraries/liblmdb/mdb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 40728e716b..3b4652ec64 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -1752,6 +1752,8 @@ mdb_strerror(int err) NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE); return ptr; #else + if (err < 0) + return "Invalid error code"; return strerror(err); #endif } From a46d78e52098078786abfddd27908835efdde0df Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 6 Jun 2019 09:06:06 +0900 Subject: [PATCH 03/11] ITS#9030 - Use sys/cachectl.h rather than asm/cachectl.h on mips It also contains the cacheflush function declaration. --- libraries/liblmdb/mdb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 3b4652ec64..6fc2abdf0a 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -114,8 +114,7 @@ static NtCloseFunc *NtClose; #if defined(__mips) && defined(__linux) /* MIPS has cache coherency issues, requires explicit cache control */ -#include -extern int cacheflush(char *addr, int nbytes, int cache); +#include #define CACHEFLUSH(addr, bytes, cache) cacheflush(addr, bytes, cache) #else #define CACHEFLUSH(addr, bytes, cache) From b53474758f4fbcca2e76031017bbddfe92474e30 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Fri, 4 Feb 2022 08:48:06 +0900 Subject: [PATCH 04/11] ITS#9919 - Mark infrequently used functions as cold rather than manually putting them in a separate section --- libraries/liblmdb/mdb.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 6fc2abdf0a..fa01bb9bc5 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -248,15 +248,21 @@ union semun { # error "Two's complement, reasonably sized integer types, please" #endif -#ifdef __GNUC__ -/** Put infrequently used env functions in separate section */ -# ifdef __APPLE__ -# define ESECT __attribute__ ((section("__TEXT,text_env"))) +#if (((__clang_major__ << 8) | __clang_minor__) >= 0x0302) || (((__GNUC__ << 8) | __GNUC_MINOR__) >= 0x0403) +/** Mark infrequently used env functions as cold. This puts them in a separate + * section, and optimizes them for size */ +#define ESECT __attribute__ ((cold)) +#else +/* On older compilers, use a separate section */ +# ifdef __GNUC__ +# ifdef __APPLE__ +# define ESECT __attribute__ ((section("__TEXT,text_env"))) +# else +# define ESECT __attribute__ ((section("text_env"))) +# endif # else -# define ESECT __attribute__ ((section("text_env"))) +# define ESECT # endif -#else -#define ESECT #endif #ifdef _WIN32 From 6a1954d0ae6876b70f503121483a1c5107a910c2 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Mon, 28 Nov 2022 14:29:53 +0000 Subject: [PATCH 05/11] ITS#9806 LMDB page_split: key threshold depends on page size 32 was chosen for page size of 4KB. Not large nough for 16KB pages. --- libraries/liblmdb/mdb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index fa01bb9bc5..ec49ac06a4 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -9754,9 +9754,13 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno mc->mc_ki[mc->mc_top] = x; } } else { - int psize, nsize, k; + int psize, nsize, k, keythresh; + /* Maximum free space in an empty page */ pmax = env->me_psize - PAGEHDRSZ; + /* Threshold number of keys considered "small" */ + keythresh = env->me_psize >> 7; + if (IS_LEAF(mp)) nsize = mdb_leaf_size(env, newkey, newdata); else @@ -9797,7 +9801,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno * the split so the new page is emptier than the old page. * This yields better packing during sequential inserts. */ - if (nkeys < 32 || nsize > pmax/16 || newindx >= nkeys) { + if (nkeys < keythresh || nsize > pmax/16 || newindx >= nkeys) { /* Find split point */ psize = 0; if (newindx <= split_indx || newindx >= nkeys) { From 3947014aed7ffe39a79991fa7fb5b234da47ad1a Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 15 Nov 2022 15:33:48 +0000 Subject: [PATCH 06/11] ITS#9916 liblmdb: use alternate MDB_page2 struct for some accesses fakepage pointers are only guaranteed to be 2-byte aligned. Use a 2-byte aligned struct definition when referencing 2-byte page members if a page pointer possibly points to a fakepage. --- libraries/liblmdb/mdb.c | 135 +++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 58 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index ec49ac06a4..26b7cba01b 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -1008,9 +1008,26 @@ typedef struct MDB_page { } pb; uint32_t pb_pages; /**< number of overflow pages */ } mp_pb; - indx_t mp_ptrs[1]; /**< dynamic size */ + indx_t mp_ptrs[0]; /**< dynamic size */ } MDB_page; +/** Alternate page header, for 2-byte aligned access */ +typedef struct MDB_page2 { + uint16_t mp2_p[sizeof(pgno_t)/2]; + uint16_t mp2_pad; + uint16_t mp2_flags; + indx_t mp2_lower; + indx_t mp2_upper; + indx_t mp2_ptrs[0]; +} MDB_page2; + +#define MP_PGNO(p) (((MDB_page2 *)(void *)(p))->mp2_p) +#define MP_PAD(p) (((MDB_page2 *)(void *)(p))->mp2_pad) +#define MP_FLAGS(p) (((MDB_page2 *)(void *)(p))->mp2_flags) +#define MP_LOWER(p) (((MDB_page2 *)(void *)(p))->mp2_lower) +#define MP_UPPER(p) (((MDB_page2 *)(void *)(p))->mp2_upper) +#define MP_PTRS(p) (((MDB_page2 *)(void *)(p))->mp2_ptrs) + /** Size of the page header, excluding dynamic data at the end */ #define PAGEHDRSZ ((unsigned) offsetof(MDB_page, mp_ptrs)) @@ -1021,10 +1038,10 @@ typedef struct MDB_page { #define PAGEBASE ((MDB_DEVEL) ? PAGEHDRSZ : 0) /** Number of nodes on a page */ -#define NUMKEYS(p) (((p)->mp_lower - (PAGEHDRSZ-PAGEBASE)) >> 1) +#define NUMKEYS(p) ((MP_LOWER(p) - (PAGEHDRSZ-PAGEBASE)) >> 1) /** The amount of space remaining in the page */ -#define SIZELEFT(p) (indx_t)((p)->mp_upper - (p)->mp_lower) +#define SIZELEFT(p) (indx_t)(MP_UPPER(p) - MP_LOWER(p)) /** The percentage of space used in the page, in tenths of a percent. */ #define PAGEFILL(env, p) (1000L * ((env)->me_psize - PAGEHDRSZ - SIZELEFT(p)) / \ @@ -1035,15 +1052,15 @@ typedef struct MDB_page { #define FILL_THRESHOLD 250 /** Test if a page is a leaf page */ -#define IS_LEAF(p) F_ISSET((p)->mp_flags, P_LEAF) +#define IS_LEAF(p) F_ISSET(MP_FLAGS(p), P_LEAF) /** Test if a page is a LEAF2 page */ -#define IS_LEAF2(p) F_ISSET((p)->mp_flags, P_LEAF2) +#define IS_LEAF2(p) F_ISSET(MP_FLAGS(p), P_LEAF2) /** Test if a page is a branch page */ -#define IS_BRANCH(p) F_ISSET((p)->mp_flags, P_BRANCH) +#define IS_BRANCH(p) F_ISSET(MP_FLAGS(p), P_BRANCH) /** Test if a page is an overflow page */ -#define IS_OVERFLOW(p) F_ISSET((p)->mp_flags, P_OVERFLOW) +#define IS_OVERFLOW(p) F_ISSET(MP_FLAGS(p), P_OVERFLOW) /** Test if a page is a sub page */ -#define IS_SUBP(p) F_ISSET((p)->mp_flags, P_SUBP) +#define IS_SUBP(p) F_ISSET(MP_FLAGS(p), P_SUBP) /** The number of overflow pages needed to store the given size. */ #define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1) @@ -1111,7 +1128,7 @@ typedef struct MDB_node { #define LEAFSIZE(k, d) (NODESIZE + (k)->mv_size + (d)->mv_size) /** Address of node \b i in page \b p */ -#define NODEPTR(p, i) ((MDB_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEBASE)) +#define NODEPTR(p, i) ((MDB_node *)((char *)(p) + MP_PTRS(p)[i] + PAGEBASE)) /** Address of the key for the node */ #define NODEKEY(node) (void *)((node)->mn_data) @@ -1139,6 +1156,8 @@ typedef struct MDB_node { /** Copy a page number from src to dst */ #ifdef MISALIGNED_OK #define COPY_PGNO(dst,src) dst = src +#undef MP_PGNO +#define MP_PGNO(p) ((p)->mp_pgno) #else #if MDB_SIZE_MAX > 0xffffffffU #define COPY_PGNO(dst,src) do { \ @@ -1796,7 +1815,7 @@ static pgno_t mdb_dbg_pgno(MDB_page *mp) { pgno_t ret; - COPY_PGNO(ret, mp->mp_pgno); + COPY_PGNO(ret, MP_PGNO(mp)); return ret; } @@ -1843,13 +1862,13 @@ void mdb_page_list(MDB_page *mp) { pgno_t pgno = mdb_dbg_pgno(mp); - const char *type, *state = (mp->mp_flags & P_DIRTY) ? ", dirty" : ""; + const char *type, *state = (MP_FLAGS(mp) & P_DIRTY) ? ", dirty" : ""; MDB_node *node; unsigned int i, nkeys, nsize, total = 0; MDB_val key; DKBUF; - switch (mp->mp_flags & (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP)) { + switch (MP_FLAGS(mp) & (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP)) { case P_BRANCH: type = "Branch page"; break; case P_LEAF: type = "Leaf page"; break; case P_LEAF|P_SUBP: type = "Sub-page"; break; @@ -1864,7 +1883,7 @@ mdb_page_list(MDB_page *mp) pgno, ((MDB_meta *)METADATA(mp))->mm_txnid); return; default: - fprintf(stderr, "Bad page %"Yu" flags 0x%X\n", pgno, mp->mp_flags); + fprintf(stderr, "Bad page %"Yu" flags 0x%X\n", pgno, MP_FLAGS(mp)); return; } @@ -1900,7 +1919,7 @@ mdb_page_list(MDB_page *mp) total = EVEN(total); } fprintf(stderr, "Total: header %d + contents %d + unused %d\n", - IS_LEAF2(mp) ? PAGEHDRSZ : PAGEBASE + mp->mp_lower, total, SIZELEFT(mp)); + IS_LEAF2(mp) ? PAGEHDRSZ : PAGEBASE + MP_LOWER(mp), total, SIZELEFT(mp)); } void @@ -2730,7 +2749,7 @@ mdb_page_touch(MDB_cursor *mc) pgno_t pgno; int rc; - if (!F_ISSET(mp->mp_flags, P_DIRTY)) { + if (!F_ISSET(MP_FLAGS(mp), P_DIRTY)) { if (txn->mt_flags & MDB_TXN_SPILLS) { np = NULL; rc = mdb_page_unspill(txn, mp, &np); @@ -7079,7 +7098,7 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, mc->mc_ki[mc->mc_top] = 0; return MDB_NOTFOUND; } - if (mp->mp_flags & P_LEAF2) { + if (MP_FLAGS(mp) & P_LEAF2) { nodekey.mv_size = mc->mc_db->md_pad; nodekey.mv_data = LEAF2KEY(mp, 0, nodekey.mv_size); } else { @@ -7100,7 +7119,7 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int i; unsigned int nkeys = NUMKEYS(mp); if (nkeys > 1) { - if (mp->mp_flags & P_LEAF2) { + if (MP_FLAGS(mp) & P_LEAF2) { nodekey.mv_data = LEAF2KEY(mp, nkeys-1, nodekey.mv_size); } else { @@ -7118,7 +7137,7 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, if (rc < 0) { if (mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) { /* This is definitely the right page, skip search_page */ - if (mp->mp_flags & P_LEAF2) { + if (MP_FLAGS(mp) & P_LEAF2) { nodekey.mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], nodekey.mv_size); } else { @@ -7684,7 +7703,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, *mc->mc_dbflag |= DB_DIRTY; if ((mc->mc_db->md_flags & (MDB_DUPSORT|MDB_DUPFIXED)) == MDB_DUPFIXED) - np->mp_flags |= P_LEAF2; + MP_FLAGS(np) |= P_LEAF2; mc->mc_flags |= C_INITIALIZED; } else { /* make sure all cursor pages are writable */ @@ -7706,7 +7725,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, fp_flags = P_LEAF|P_DIRTY; fp = env->me_pbuf; fp->mp_pad = data->mv_size; /* used if MDB_DUPFIXED */ - fp->mp_lower = fp->mp_upper = (PAGEHDRSZ-PAGEBASE); + MP_LOWER(fp) = MP_UPPER(fp) = (PAGEHDRSZ-PAGEBASE); olddata.mv_size = PAGEHDRSZ; goto prep_subDB; } @@ -7780,18 +7799,18 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, dkey.mv_data = memcpy(fp+1, olddata.mv_data, olddata.mv_size); /* Make sub-page header for the dup items, with dummy body */ - fp->mp_flags = P_LEAF|P_DIRTY|P_SUBP; - fp->mp_lower = (PAGEHDRSZ-PAGEBASE); + MP_FLAGS(fp) = P_LEAF|P_DIRTY|P_SUBP; + MP_LOWER(fp) = (PAGEHDRSZ-PAGEBASE); xdata.mv_size = PAGEHDRSZ + dkey.mv_size + data->mv_size; if (mc->mc_db->md_flags & MDB_DUPFIXED) { - fp->mp_flags |= P_LEAF2; + MP_FLAGS(fp) |= P_LEAF2; fp->mp_pad = data->mv_size; xdata.mv_size += 2 * data->mv_size; /* leave space for 2 more */ } else { xdata.mv_size += 2 * (sizeof(indx_t) + NODESIZE) + (dkey.mv_size & 1) + (data->mv_size & 1); } - fp->mp_upper = xdata.mv_size - PAGEBASE; + MP_UPPER(fp) = xdata.mv_size - PAGEBASE; olddata.mv_size = xdata.mv_size; /* pretend olddata is fp */ } else if (leaf->mn_flags & F_SUBDATA) { /* Data is on sub-DB, just store it */ @@ -7814,8 +7833,8 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, } /* FALLTHRU */ /* Big enough MDB_DUPFIXED sub-page */ case MDB_CURRENT: - fp->mp_flags |= P_DIRTY; - COPY_PGNO(fp->mp_pgno, mp->mp_pgno); + MP_FLAGS(fp) |= P_DIRTY; + COPY_PGNO(MP_PGNO(fp), MP_PGNO(mp)); mc->mc_xcursor->mx_cursor.mc_pg[0] = fp; flags |= F_DUPDATA; goto put_sub; @@ -7823,7 +7842,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, xdata.mv_size = olddata.mv_size + offset; } - fp_flags = fp->mp_flags; + fp_flags = MP_FLAGS(fp); if (NODESIZE + NODEKSZ(leaf) + xdata.mv_size > env->me_nodemax) { /* Too big for a sub-page, convert to sub-DB */ fp_flags &= ~P_SUBP; @@ -7853,16 +7872,16 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, sub_root = mp; } if (mp != fp) { - mp->mp_flags = fp_flags | P_DIRTY; - mp->mp_pad = fp->mp_pad; - mp->mp_lower = fp->mp_lower; - mp->mp_upper = fp->mp_upper + offset; + MP_FLAGS(mp) = fp_flags | P_DIRTY; + MP_PAD(mp) = MP_PAD(fp); + MP_LOWER(mp) = MP_LOWER(fp); + MP_UPPER(mp) = MP_UPPER(fp) + offset; if (fp_flags & P_LEAF2) { memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad); } else { - memcpy((char *)mp + mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper + PAGEBASE, - olddata.mv_size - fp->mp_upper - PAGEBASE); - memcpy((char *)(&mp->mp_ptrs), (char *)(&fp->mp_ptrs), NUMKEYS(fp) * sizeof(mp->mp_ptrs[0])); + memcpy((char *)mp + MP_UPPER(mp) + PAGEBASE, (char *)fp + MP_UPPER(fp) + PAGEBASE, + olddata.mv_size - MP_UPPER(fp) - PAGEBASE); + memcpy((char *)MP_PTRS(mp), (char *)MP_PTRS(fp), NUMKEYS(fp) * sizeof(mp->mp_ptrs[0])); for (i=0; imp_ptrs[i] += offset; } @@ -8310,7 +8329,7 @@ mdb_node_add(MDB_cursor *mc, indx_t indx, void *ndata; DKBUF; - mdb_cassert(mc, mp->mp_upper >= mp->mp_lower); + mdb_cassert(mc, MP_UPPER(mp) >= MP_LOWER(mp)); DPRINTF(("add to %s %spage %"Yu" index %i, data size %"Z"u key size %"Z"u [%s]", IS_LEAF(mp) ? "leaf" : "branch", @@ -8329,8 +8348,8 @@ mdb_node_add(MDB_cursor *mc, indx_t indx, memcpy(ptr, key->mv_data, ksize); /* Just using these for counting */ - mp->mp_lower += sizeof(indx_t); - mp->mp_upper -= ksize - sizeof(indx_t); + MP_LOWER(mp) += sizeof(indx_t); + MP_UPPER(mp) -= ksize - sizeof(indx_t); return MDB_SUCCESS; } @@ -8367,14 +8386,14 @@ mdb_node_add(MDB_cursor *mc, indx_t indx, update: /* Move higher pointers up one slot. */ for (i = NUMKEYS(mp); i > indx; i--) - mp->mp_ptrs[i] = mp->mp_ptrs[i - 1]; + MP_PTRS(mp)[i] = MP_PTRS(mp)[i - 1]; /* Adjust free space offsets. */ - ofs = mp->mp_upper - node_size; - mdb_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t)); - mp->mp_ptrs[indx] = ofs; - mp->mp_upper = ofs; - mp->mp_lower += sizeof(indx_t); + ofs = MP_UPPER(mp) - node_size; + mdb_cassert(mc, ofs >= MP_LOWER(mp) + sizeof(indx_t)); + MP_PTRS(mp)[indx] = ofs; + MP_UPPER(mp) = ofs; + MP_LOWER(mp) += sizeof(indx_t); /* Write the node data. */ node = NODEPTR(mp, indx); @@ -8412,7 +8431,7 @@ mdb_node_add(MDB_cursor *mc, indx_t indx, full: DPRINTF(("not enough room in page %"Yu", got %u ptrs", mdb_dbg_pgno(mp), NUMKEYS(mp))); - DPRINTF(("upper-lower = %u - %u = %"Z"d", mp->mp_upper,mp->mp_lower,room)); + DPRINTF(("upper-lower = %u - %u = %"Z"d", MP_UPPER(mp),MP_LOWER(mp),room)); DPRINTF(("node size = %"Z"u", node_size)); mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return MDB_PAGE_FULL; @@ -8443,8 +8462,8 @@ mdb_node_del(MDB_cursor *mc, int ksize) base = LEAF2KEY(mp, indx, ksize); if (x) memmove(base, base + ksize, x * ksize); - mp->mp_lower -= sizeof(indx_t); - mp->mp_upper += ksize - sizeof(indx_t); + MP_LOWER(mp) -= sizeof(indx_t); + MP_UPPER(mp) += ksize - sizeof(indx_t); return; } @@ -8458,21 +8477,21 @@ mdb_node_del(MDB_cursor *mc, int ksize) } sz = EVEN(sz); - ptr = mp->mp_ptrs[indx]; + ptr = MP_PTRS(mp)[indx]; for (i = j = 0; i < numkeys; i++) { if (i != indx) { - mp->mp_ptrs[j] = mp->mp_ptrs[i]; - if (mp->mp_ptrs[i] < ptr) - mp->mp_ptrs[j] += sz; + MP_PTRS(mp)[j] = MP_PTRS(mp)[i]; + if (MP_PTRS(mp)[i] < ptr) + MP_PTRS(mp)[j] += sz; j++; } } - base = (char *)mp + mp->mp_upper + PAGEBASE; - memmove(base + sz, base, ptr - mp->mp_upper); + base = (char *)mp + MP_UPPER(mp) + PAGEBASE; + memmove(base + sz, base, ptr - MP_UPPER(mp)); - mp->mp_lower -= sizeof(indx_t); - mp->mp_upper += sz; + MP_LOWER(mp) -= sizeof(indx_t); + MP_UPPER(mp) += sz; } /** Compact the main page after deleting a node on a subpage. @@ -8501,11 +8520,11 @@ mdb_node_shrink(MDB_page *mp, indx_t indx) } else { xp = (MDB_page *)((char *)sp + delta); /* destination subpage */ for (i = NUMKEYS(sp); --i >= 0; ) - xp->mp_ptrs[i] = sp->mp_ptrs[i] - delta; + MP_PTRS(xp)[i] = MP_PTRS(sp)[i] - delta; len = PAGEHDRSZ; } - sp->mp_upper = sp->mp_lower; - COPY_PGNO(sp->mp_pgno, mp->mp_pgno); + MP_UPPER(sp) = MP_LOWER(sp); + COPY_PGNO(MP_PGNO(sp), mp->mp_pgno); SETDSZ(node, nsize); /* Shift upward */ @@ -8577,7 +8596,7 @@ mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node) mx->mx_db.md_leaf_pages = 1; mx->mx_db.md_overflow_pages = 0; mx->mx_db.md_entries = NUMKEYS(fp); - COPY_PGNO(mx->mx_db.md_root, fp->mp_pgno); + COPY_PGNO(mx->mx_db.md_root, MP_PGNO(fp)); mx->mx_cursor.mc_snum = 1; mx->mx_cursor.mc_top = 0; mx->mx_cursor.mc_flags |= C_INITIALIZED; From 02baafbc54678a255126dc9422795dc6eb0946eb Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 15 Dec 2022 09:36:58 +0000 Subject: [PATCH 07/11] ITS#9961 LMDB: fix MSVC error --- libraries/liblmdb/mdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 26b7cba01b..e76f09b71a 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -7946,7 +7946,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, * Copy end of page, adjusting alignment so * compiler may copy words instead of bytes. */ - off = (PAGEHDRSZ + data->mv_size) & -sizeof(size_t); + off = (PAGEHDRSZ + data->mv_size) & -(int)sizeof(size_t); memcpy((size_t *)((char *)np + off), (size_t *)((char *)omp + off), sz - off); sz = PAGEHDRSZ; From c7b3cc4df6dfe8f0772fb509bdc74777667caa43 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Mon, 6 Mar 2023 16:47:44 +0000 Subject: [PATCH 08/11] ITS#8447 fix cursor_put(MDB_CURRENT) on DUPSORT DB with different-sized data --- libraries/liblmdb/mdb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index e76f09b71a..6e4c4d04bf 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -7974,11 +7974,14 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, else if (!(mc->mc_flags & C_SUB)) memcpy(olddata.mv_data, data->mv_data, data->mv_size); else { + if (key->mv_size != NODEKSZ(leaf)) + goto new_ksize; memcpy(NODEKEY(leaf), key->mv_data, key->mv_size); goto fix_parent; } return MDB_SUCCESS; } +new_ksize: mdb_node_del(mc, 0); } From 3dde6c46e6c55458eadaf7f81492c822414be2c7 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sun, 27 Aug 2023 15:37:34 +0100 Subject: [PATCH 09/11] ITS#10095 partial revert of ITS#9278 2fd44e325195ae81664eb5dc36e7d265927c5ebc The patch was incorrect and introduced numerous race conditions. The original problem was a FreeBSD bug, subsequently fixed: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=269277 --- libraries/liblmdb/mdb.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 6e4c4d04bf..965ba2a2b8 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -5824,17 +5824,6 @@ mdb_env_close0(MDB_env *env, int excl) if (excl > 0) semctl(env->me_rmutex->semid, 0, IPC_RMID); } -#elif defined(MDB_ROBUST_SUPPORTED) - /* If we have the filelock: If we are the - * only remaining user, clean up robust - * mutexes. - */ - if (excl == 0) - mdb_env_excl_lock(env, &excl); - if (excl > 0) { - pthread_mutex_destroy(env->me_txns->mti_rmutex); - pthread_mutex_destroy(env->me_txns->mti_wmutex); - } #endif munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo)); } From c07884d1142f15bd3049bc9c2b62f1ef84992725 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sun, 5 Nov 2023 17:34:03 +0000 Subject: [PATCH 10/11] ITS#10125 mdb_load: fix cursor reinit in Append mode --- libraries/liblmdb/mdb_load.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/liblmdb/mdb_load.c b/libraries/liblmdb/mdb_load.c index 6f6dddc9e6..23f67a5fe3 100644 --- a/libraries/liblmdb/mdb_load.c +++ b/libraries/liblmdb/mdb_load.c @@ -445,7 +445,7 @@ int main(int argc, char *argv[]) if (rc == MDB_KEYEXIST && putflags) continue; if (rc) { - fprintf(stderr, "mdb_cursor_put failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "%s: line %"Yu": mdb_cursor_put failed, error %d %s\n", prog, lineno, rc, mdb_strerror(rc)); goto txn_abort; } batch++; @@ -466,9 +466,11 @@ int main(int argc, char *argv[]) fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } - if (appflag & MDB_APPENDDUP) { + if (append) { MDB_val k, d; mdb_cursor_get(mc, &k, &d, MDB_LAST); + memcpy(prevk.mv_data, k.mv_data, k.mv_size); + prevk.mv_size = k.mv_size; } batch = 0; } From 30288c72573ceac719627183f1058cad1dd08b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Mon, 27 Nov 2023 10:35:15 +0100 Subject: [PATCH 11/11] ITS#10137 LMDB: Allow users to define MDB_IDL_LOGN --- libraries/liblmdb/midl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/liblmdb/midl.h b/libraries/liblmdb/midl.h index 1035c01e14..400877e1bc 100644 --- a/libraries/liblmdb/midl.h +++ b/libraries/liblmdb/midl.h @@ -56,7 +56,9 @@ typedef MDB_ID *MDB_IDL; /* IDL sizes - likely should be even bigger * limiting factors: sizeof(ID), thread stack size */ +#ifndef MDB_IDL_LOGN #define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */ +#endif #define MDB_IDL_DB_SIZE (1<