Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package lmdb for openSUSE:Factory checked in at 2026-03-19 17:35:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/lmdb (Old) and /work/SRC/openSUSE:Factory/.lmdb.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "lmdb" Thu Mar 19 17:35:33 2026 rev:22 rq:1340760 version:0.9.35 Changes: -------- --- /work/SRC/openSUSE:Factory/lmdb/lmdb.changes 2024-03-03 20:19:54.711112284 +0100 +++ /work/SRC/openSUSE:Factory/.lmdb.new.8177/lmdb.changes 2026-03-19 17:36:27.255515127 +0100 @@ -1,0 +2,31 @@ +Sun Mar 15 18:50:22 UTC 2026 - Mia Herkt <[email protected]> + +- Enable tests +- Update to 0.9.35: + * fix race condition freeing spilled pages at end of transaction + * Update mdb_dump(1) and mdb_load(1) man pages for append (-a) + option + * mdb_load: add -Q option to use NOSYNC + * fix memleak in mdb_txn_begin for nested txns + * fix mdb_env_copy2 with values > (2GB-16) + * fix mplay build on musl + * fix mdb_cursor_del0 with multiple DUPSORT cursors + * mdb_load: check for malicious input +- 0.9.33 Release (2024/05/21) + * mdb_page_search: fix error code when DBI record is missing + * Fix meta page usage by read only tools +- 0.9.32 Release (2024/01/29) + * Add ability to replay log and replay log tool + * mdb_load: fix cursor reinit in Append mode + * Allow users to define MDB_IDL_LOGN +- 0.9.31 Release (2023/07/10) + * Fix cursor_put(MDB_CURRENT) on DUPSORT DB with different sized + data +- Refresh patches: + * 0001-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch + -> 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch + Merge with liblmdb-implicit-decl.patch + * Makefile-build-use-shared-lib.patch + -> 0001-Makefile-use-shared-library.patch + +------------------------------------------------------------------- Old: ---- 0001-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch Makefile-build-use-shared-lib.patch liblmdb-implicit-decl.patch openldap-LMDB_0.9.30.tar.gz New: ---- 0001-Makefile-use-shared-library.patch 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch openldap-LMDB_0.9.35.tar.gz ----------(Old B)---------- Old:- Refresh patches: * 0001-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch -> 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch Old: Merge with liblmdb-implicit-decl.patch * Makefile-build-use-shared-lib.patch -> 0001-Makefile-use-shared-library.patch Old: -> 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch Merge with liblmdb-implicit-decl.patch * Makefile-build-use-shared-lib.patch ----------(Old E)---------- ----------(New B)---------- New: * Makefile-build-use-shared-lib.patch -> 0001-Makefile-use-shared-library.patch New: * 0001-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch -> 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch Merge with liblmdb-implicit-decl.patch ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ lmdb.spec ++++++ --- /var/tmp/diff_new_pack.wHl1zt/_old 2026-03-19 17:36:29.739618042 +0100 +++ /var/tmp/diff_new_pack.wHl1zt/_new 2026-03-19 17:36:29.739618042 +0100 @@ -1,7 +1,7 @@ # # spec file for package lmdb # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,26 +16,20 @@ # +%define lname liblmdb-0_9_35 Name: lmdb +Version: 0.9.35 +Release: 0 Summary: Lightning Memory-Mapped Database Manager License: OLDAP-2.8 -Group: Productivity/Databases/Tools -%define lname liblmdb-0_9_30 -Version: 0.9.30 -Release: 0 URL: https://symas.com/mdb/ Source: https://git.openldap.org/openldap/openldap/-/archive/LMDB_%{version}/openldap-LMDB_%{version}.tar.gz Source1: lmdb.pc.in Source99: baselibs.conf - -# PATCH-FIX-UPSTREAM - debugging tools (https://github.com/kacfengine/lmdb) -Patch1: 0001-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch -# PATCH-FIX-OPENSUSE - Implicit declaration of atol() -Patch2: liblmdb-implicit-decl.patch # PATCH-FIX-OPENSUSE - Build and link to shared library -Patch3: Makefile-build-use-shared-lib.patch - -BuildRoot: %{_tmppath}/%{name}-%{version}-build +Patch1: 0001-Makefile-use-shared-library.patch +# PATCH-FIX-UPSTREAM - debugging tools (https://github.com/kacfengine/lmdb) +Patch2: 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch %if 0%{?rhel_version} == 700 BuildRequires: perl-Exporter %endif @@ -49,11 +43,10 @@ the need for any recovery procedures. The database is exposed in a memory map, requiring no page cache layer of its own. -%package -n %lname +%package -n %{lname} Summary: Shared library for Lightning Memory-Mapped Database (LMDB) -Group: System/Libraries -%description -n %lname +%description -n %{lname} LMDB is a Btree-based database management library with an API similar to BerkeleyDB. The library is thread-aware and supports concurrent read/write access from multiple processes and threads. The DB @@ -66,8 +59,7 @@ %package devel Summary: Development package for lmdb -Group: Development/Libraries/C and C++ -Requires: %lname = %version +Requires: %{lname} = %{version} %description devel LMDB is a Btree-based database management library with an API similar @@ -82,15 +74,15 @@ the liblmdb library. %prep -%autosetup -p1 -n openldap-LMDB_%version +%autosetup -p1 -n openldap-LMDB_%{version} %build cd libraries/liblmdb -make %{?_smp_mflags} V=1 SOVERSION=%{version} CFLAGS="%{optflags}" +%make_build SOVERSION=%{version} CFLAGS="%{optflags}" %install cd libraries/liblmdb -make install DESTDIR="%buildroot" SOVERSION=%{version} \ +make install DESTDIR=%{buildroot} SOVERSION=%{version} \ bindir=%{_bindir} \ libdir=%{_libdir} \ mandir=%{_mandir} \ @@ -107,21 +99,26 @@ %{SOURCE1} >lmdb.pc install -Dpm 0644 -t %{buildroot}%{_libdir}/pkgconfig lmdb.pc -%post -n %lname -p /sbin/ldconfig -%postun -n %lname -p /sbin/ldconfig +%check +cd libraries/liblmdb +LD_LIBRARY_PATH=%{buildroot}%{_libdir} %{make_build} test + +%post -n %{lname} -p /sbin/ldconfig +%postun -n %{lname} -p /sbin/ldconfig %files %doc libraries/liblmdb/CHANGES %doc libraries/liblmdb/COPYRIGHT %license libraries/liblmdb/LICENSE -%{_bindir}/* -%doc %{_mandir}/man1/*.1.gz +%{_bindir}/lm* +%{_bindir}/mdb_* +%{_mandir}/man1/*.1%{?ext_man} -%files -n %lname -%_libdir/liblmdb-%version.so +%files -n %{lname} +%{_libdir}/liblmdb-%{version}.so %files devel -%_includedir/* -%_libdir/liblmdb.so -%_libdir/pkgconfig/lmdb.pc +%{_includedir}/lmdb.h +%{_libdir}/liblmdb.so +%{_libdir}/pkgconfig/lmdb.pc ++++++ 0001-Makefile-use-shared-library.patch ++++++ >From 2c2332bd4c39539df9717514e699e531d52739d3 Mon Sep 17 00:00:00 2001 From: Mia Herkt <[email protected]> Date: Sun, 15 Mar 2026 20:21:38 +0100 Subject: [PATCH 1/2] Makefile: use shared library --- libraries/liblmdb/Makefile | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/libraries/liblmdb/Makefile b/libraries/liblmdb/Makefile index 000f1f9..cf2a92e 100644 --- a/libraries/liblmdb/Makefile +++ b/libraries/liblmdb/Makefile @@ -38,7 +38,7 @@ mandir = $(datarootdir)/man ######################################################################## IHDRS = lmdb.h -ILIBS = liblmdb.a liblmdb$(SOEXT) +ILIBS = liblmdb-$(SOVERSION)$(SOEXT) IPROGS = mdb_stat mdb_copy mdb_dump mdb_load IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1 PROGS = $(IPROGS) mtest mtest2 mtest3 mtest4 mtest5 @@ -64,21 +64,21 @@ test: all liblmdb.a: mdb.o midl.o $(AR) rs $@ mdb.o midl.o -liblmdb$(SOEXT): mdb.lo midl.lo +liblmdb-$(SOVERSION)$(SOEXT): mdb.lo midl.lo # $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS) - $(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS) - -mdb_stat: mdb_stat.o liblmdb.a -mdb_copy: mdb_copy.o liblmdb.a -mdb_dump: mdb_dump.o liblmdb.a -mdb_load: mdb_load.o liblmdb.a -mtest: mtest.o liblmdb.a -mtest2: mtest2.o liblmdb.a -mtest3: mtest3.o liblmdb.a -mtest4: mtest4.o liblmdb.a -mtest5: mtest5.o liblmdb.a -mtest6: mtest6.o liblmdb.a -mplay: mplay.o liblmdb.a + $(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS) -Wl,-soname -Wl,liblmdb-$(SOVERSION).so + +mdb_stat: mdb_stat.o +mdb_copy: mdb_copy.o +mdb_dump: mdb_dump.o +mdb_load: mdb_load.o +mtest: mtest.o +mtest2: mtest2.o +mtest3: mtest3.o +mtest4: mtest4.o +mtest5: mtest5.o +mtest6: mtest6.o +mplay: mplay.o mdb.o: mdb.c lmdb.h midl.h $(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c @@ -92,8 +92,8 @@ mdb.lo: mdb.c lmdb.h midl.h midl.lo: midl.c midl.h $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c midl.c -o $@ -%: %.o - $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ +%: %.o | liblmdb-$(SOVERSION)$(SOEXT) + $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -L. -llmdb-$(SOVERSION) -o $@ %.o: %.c lmdb.h $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -- 2.53.0 ++++++ 0001-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch -> 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch ++++++ --- /work/SRC/openSUSE:Factory/lmdb/0001-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch 2023-02-07 18:47:39.578671998 +0100 +++ /work/SRC/openSUSE:Factory/.lmdb.new.8177/0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch 2026-03-19 17:36:27.239514463 +0100 @@ -1,19 +1,40 @@ -From 1701892d066c626bbd82c9340d6b442f733c33a1 Mon Sep 17 00:00:00 2001 +From 7d3450e5c1dada32b8130b8469821210e5910387 Mon Sep 17 00:00:00 2001 From: Kristian Amlie <[email protected]> Date: Mon, 28 Jul 2014 11:28:38 +0200 -Subject: [PATCH 1/4] Add extra tools and CFEngine modifications for LMDB. +Subject: [PATCH 2/2] Add extra tools and CFEngine modifications for LMDB. --- - libraries/liblmdb/lmdump.c | 128 +++++++++++++++++++++++++++ - libraries/liblmdb/lmmgr.c | 201 +++++++++++++++++++++++++++++++++++++++++++ - libraries/liblmdb/mdb_copy.c | 2 +- - 3 files changed, 330 insertions(+), 1 deletion(-) + libraries/liblmdb/Makefile | 3 + + libraries/liblmdb/lmdump.c | 128 +++++++++++++++++++++++ + libraries/liblmdb/lmmgr.c | 202 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 333 insertions(+) create mode 100644 libraries/liblmdb/lmdump.c create mode 100644 libraries/liblmdb/lmmgr.c +diff --git a/libraries/liblmdb/Makefile b/libraries/liblmdb/Makefile +index cf2a92e..cbbbd23 100644 +--- a/libraries/liblmdb/Makefile ++++ b/libraries/liblmdb/Makefile +@@ -40,6 +40,7 @@ mandir = $(datarootdir)/man + IHDRS = lmdb.h + ILIBS = liblmdb-$(SOVERSION)$(SOEXT) + IPROGS = mdb_stat mdb_copy mdb_dump mdb_load ++IPROGS += lmdump lmmgr + IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1 + PROGS = $(IPROGS) mtest mtest2 mtest3 mtest4 mtest5 + all: $(ILIBS) $(PROGS) +@@ -79,6 +80,8 @@ mtest4: mtest4.o + mtest5: mtest5.o + mtest6: mtest6.o + mplay: mplay.o ++lmmgr: lmmgr.o ++lmdump: lmdump.o + + mdb.o: mdb.c lmdb.h midl.h + $(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c diff --git a/libraries/liblmdb/lmdump.c b/libraries/liblmdb/lmdump.c new file mode 100644 -index 000000000000..0e3ee4bb61c2 +index 0000000..c957ae5 --- /dev/null +++ b/libraries/liblmdb/lmdump.c @@ -0,0 +1,128 @@ @@ -32,7 +53,7 @@ +#include <string.h> +#include "lmdb.h" + -+static void print_hex(char *s, int len) ++static void print_hex(char *s, int len) +{ + int i = 0; + for (i=0; i<len; i++) @@ -41,7 +62,7 @@ + } +} + -+static void print_usage(void) ++static void print_usage(void) +{ + printf("Lmdb database dumper\n"); + printf("Usage: dump -d|-x|-a|-A filename\n\n"); @@ -52,9 +73,9 @@ + printf(" -d : print only the size of keys and values\n"); +} + -+static int report_error(int rc) ++static int report_error(int rc) +{ -+ printf("err(%d): %s\n", rc, mdb_strerror(rc)); ++ printf("err(%d): %s\n", rc, mdb_strerror(rc)); + return rc; +} + @@ -147,20 +168,21 @@ +} diff --git a/libraries/liblmdb/lmmgr.c b/libraries/liblmdb/lmmgr.c new file mode 100644 -index 000000000000..1137d8dc388a +index 0000000..d8c76c0 --- /dev/null +++ b/libraries/liblmdb/lmmgr.c -@@ -0,0 +1,201 @@ +@@ -0,0 +1,202 @@ +/* +lmmgr.c : Add, remove or manage the maxreaders value of a given database file +*/ +#include <stdio.h> +#include <string.h> ++#include <stdlib.h> +#include "lmdb.h" + -+static int report_error(int rc) ++static int report_error(int rc) +{ -+ printf("err(%d): %s\n", rc, mdb_strerror(rc)); ++ printf("err(%d): %s\n", rc, mdb_strerror(rc)); + return rc; +} + @@ -352,3 +374,6 @@ + + return 1; +} +-- +2.53.0 + ++++++ baselibs.conf ++++++ --- /var/tmp/diff_new_pack.wHl1zt/_old 2026-03-19 17:36:29.811621025 +0100 +++ /var/tmp/diff_new_pack.wHl1zt/_new 2026-03-19 17:36:29.811621025 +0100 @@ -1,2 +1,2 @@ -liblmdb-0_9_30 +liblmdb-0_9_35 ++++++ openldap-LMDB_0.9.30.tar.gz -> openldap-LMDB_0.9.35.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/.gitignore new/openldap-LMDB_0.9.35/libraries/liblmdb/.gitignore --- old/openldap-LMDB_0.9.30/libraries/liblmdb/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/.gitignore 2026-01-29 22:51:48.000000000 +0100 @@ -0,0 +1,23 @@ +mtest +mtest[23456] +testdb +mdb_copy +mdb_stat +mdb_dump +mdb_load +*.lo +*.[ao] +*.so +*.exe +*[~#] +*.bak +*.orig +*.rej +*.gcov +*.gcda +*.gcno +core +core.* +valgrind.* +man/ +html/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/CHANGES new/openldap-LMDB_0.9.35/libraries/liblmdb/CHANGES --- old/openldap-LMDB_0.9.30/libraries/liblmdb/CHANGES 2023-02-08 19:41:37.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/CHANGES 2026-01-29 22:51:48.000000000 +0100 @@ -1,5 +1,35 @@ LMDB 0.9 Change Log +LMDB 0.9.35 Release (2026/01/27) + ITS#10434 - Fix typo affecting Mac OSX + +LMDB 0.9.34 Release (2026/01/26) + ITS#9564 - fix race condition freeing spilled pages at end of transaction + ITS#10222 - Update mdb_dump(1) and mdb_load(1) man pages for append (-a) option + ITS#10275 - mdb_load: add -Q option to use NOSYNC + ITS#10296 - fix fdatasync on MacOS + ITS#10342 - fix memleak in mdb_txn_begin for nested txns + ITS#10346 - fix mdb_env_copy2 with values > (2GB-16) + ITS#10355 - fix mplay build on musl + ITS#10396 - fix mdb_cursor_del0 with multiple DUPSORT cursors + ITS#10419 - add support for NetBSD + ITS#10420 - add support for Haiku + ITS#10421 - mdb_load: check for malicious input + +LMDB 0.9.33 Release (2024/05/21) + ITS#9037 mdb_page_search: fix error code when DBI record is missing + ITS#10198 For win32, stop passing ignored parameter + ITS#10212 Fix meta page usage by read only tools + +LMDB 0.9.32 Release (2024/01/29) + ITS#9378 - Add ability to replay log and replay log tool + ITS#10095 - partial revert of ITS#9278. The patch was incorrect and introduced numerous race conditions. + ITS#10125 - mdb_load: fix cursor reinit in Append mode + ITS#10137 - Allow users to define MDB_IDL_LOGN + +LMDB 0.9.31 Release (2023/07/10) + ITS#8447 - Fix cursor_put(MDB_CURRENT) on DUPSORT DB with different sized data + LMDB 0.9.30 Release (2023/02/08) ITS#9806 - LMDB page_split: key threshold depends on page size ITS#9916 - avoid gcc optimization bug on sparc64 linux diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/Makefile new/openldap-LMDB_0.9.35/libraries/liblmdb/Makefile --- old/openldap-LMDB_0.9.30/libraries/liblmdb/Makefile 2023-02-08 19:41:37.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/Makefile 2026-01-29 22:51:48.000000000 +0100 @@ -78,6 +78,7 @@ mtest4: mtest4.o liblmdb.a mtest5: mtest5.o liblmdb.a mtest6: mtest6.o liblmdb.a +mplay: mplay.o liblmdb.a mdb.o: mdb.c lmdb.h midl.h $(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/lmdb.h new/openldap-LMDB_0.9.35/libraries/liblmdb/lmdb.h --- old/openldap-LMDB_0.9.30/libraries/liblmdb/lmdb.h 2023-02-08 19:41:37.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/lmdb.h 2026-01-29 22:51:48.000000000 +0100 @@ -200,7 +200,7 @@ /** Library minor version */ #define MDB_VERSION_MINOR 9 /** Library patch version */ -#define MDB_VERSION_PATCH 30 +#define MDB_VERSION_PATCH 35 /** Combine args a,b,c into a single integer for easy version comparisons */ #define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c)) @@ -210,7 +210,7 @@ MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH) /** The release date of this library version */ -#define MDB_VERSION_DATE "February 8, 2023" +#define MDB_VERSION_DATE "Jan 27, 2026" /** A stringifier for the version info */ #define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/mdb.c new/openldap-LMDB_0.9.35/libraries/liblmdb/mdb.c --- old/openldap-LMDB_0.9.30/libraries/liblmdb/mdb.c 2023-02-08 19:41:37.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/mdb.c 2026-01-29 22:51:48.000000000 +0100 @@ -128,9 +128,21 @@ # define MDB_USE_ROBUST 1 #elif defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__) # define MDB_USE_POSIX_SEM 1 -# define MDB_FDATASYNC fsync +# if defined(__APPLE__) +# define MDB_FDATASYNC(fd) fcntl(fd, F_FULLFSYNC) +# else +# define MDB_FDATASYNC fsync +# endif #elif defined(ANDROID) # define MDB_FDATASYNC fsync +#elif defined(__HAIKU__) +# define MDB_USE_POSIX_SEM 1 +# define MDB_FDATASYNC fsync +#endif + +/* NetBSD does not define union semun in sys/sem.h */ +#if defined(__NetBSD__) && !defined(_SEM_SEMUN_UNDEFINED) +# define _SEM_SEMUN_UNDEFINED 1 #endif #ifndef _WIN32 @@ -481,18 +493,26 @@ #define MDB_DEBUG 0 #endif +#define MDB_DBG_INFO 1 +#define MDB_DBG_TRACE 2 + #if MDB_DEBUG -static int mdb_debug; +static int mdb_debug = MDB_DBG_TRACE; static txnid_t mdb_debug_start; /** Print a debug message with printf formatting. * Requires double parenthesis around 2 or more args. */ -# define DPRINTF(args) ((void) ((mdb_debug) && DPRINTF0 args)) +# define DPRINTF(args) ((void) ((mdb_debug & MDB_DBG_INFO) && DPRINTF0 args)) # define DPRINTF0(fmt, ...) \ fprintf(stderr, "%s:%d " fmt "\n", mdb_func_, __LINE__, __VA_ARGS__) + /** Trace info for replaying */ +# define MDB_TRACE(args) ((void) ((mdb_debug & MDB_DBG_TRACE) && DPRINTF1 args)) +# define DPRINTF1(fmt, ...) \ + fprintf(stderr, ">%d:%s: " fmt "\n", getpid(), mdb_func_, __VA_ARGS__) #else # define DPRINTF(args) ((void) 0) +# define MDB_TRACE(args) ((void) 0) #endif /** Print a debug string. * The string is printed literally, with no format processing. @@ -589,6 +609,11 @@ * This is used for printing a hex dump of a key's contents. */ #define DKBUF char kbuf[DKBUF_MAXKEYSIZE*2+1] + /** A data value buffer. + * @ingroup debug + * This is used for printing a hex dump of a #MDB_DUPSORT value's contents. + */ +#define DDBUF char dbuf[DKBUF_MAXKEYSIZE*2+1+2] /** Display a key in hex. * @ingroup debug * Invoke a function to display a key in hex. @@ -596,6 +621,7 @@ #define DKEY(x) mdb_dkey(x, kbuf) #else #define DKBUF +#define DDBUF #define DKEY(x) 0 #endif @@ -1423,6 +1449,9 @@ static void mdb_cursor_pop(MDB_cursor *mc); static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp); +static int _mdb_cursor_del(MDB_cursor *mc, unsigned int flags); +static int _mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int flags); + static int mdb_cursor_del0(MDB_cursor *mc); static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags); static int mdb_cursor_sibling(MDB_cursor *mc, int move_right); @@ -1538,7 +1567,7 @@ buf[0] = 0; FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE); + NULL, err, 0, ptr, MSGSIZE, NULL); return ptr; #else if (err < 0) @@ -1614,6 +1643,18 @@ return buf; } +static char * +mdb_dval(MDB_txn *txn, MDB_dbi dbi, MDB_val *data, char *buf) +{ + if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) { + mdb_dkey(data, buf+1); + *buf = '['; + strcpy(buf + data->mv_size * 2 + 1, "]"); + } else + *buf = '\0'; + return buf; +} + static const char * mdb_leafnode_type(MDB_node *n) { @@ -2544,7 +2585,7 @@ ? MS_ASYNC : MS_SYNC; if (MDB_MSYNC(env->me_map, env->me_mapsize, flags)) rc = ErrCode(); -#ifdef _WIN32 +#if defined(_WIN32) || defined(__APPLE__) else if (flags == MS_SYNC && MDB_FDATASYNC(env->me_fd)) rc = ErrCode(); #endif @@ -2767,9 +2808,14 @@ do /* LY: Retry on a race, ITS#7970. */ r->mr_txnid = ti->mti_txnid; while(r->mr_txnid != ti->mti_txnid); + if (!r->mr_txnid && (env->me_flags & MDB_RDONLY)) { + meta = mdb_env_pick_meta(env); + r->mr_txnid = meta->mm_txnid; + } else { + meta = env->me_metas[r->mr_txnid & 1]; + } txn->mt_txnid = r->mr_txnid; txn->mt_u.reader = r; - meta = env->me_metas[txn->mt_txnid & 1]; } } else { @@ -2786,7 +2832,7 @@ txn->mt_txnid++; #if MDB_DEBUG if (txn->mt_txnid == mdb_debug_start) - mdb_debug = 1; + mdb_debug = MDB_DBG_INFO; #endif txn->mt_child = NULL; txn->mt_loose_pgs = NULL; @@ -2936,8 +2982,10 @@ rc = mdb_txn_renew0(txn); } if (rc) { - if (txn != env->me_txn0) + if (txn != env->me_txn0) { + free(txn->mt_u.dirty_list); free(txn); + } } else { txn->mt_flags |= flags; /* could not change txn=me_txn0 earlier */ *ret = txn; @@ -2945,6 +2993,7 @@ txn->mt_txnid, (flags & MDB_RDONLY) ? 'r' : 'w', (void *) txn, (void *) env, txn->mt_dbs[MAIN_DBI].md_root)); } + MDB_TRACE(("%p, %p, %u = %p", env, parent, flags, txn)); return rc; } @@ -3037,6 +3086,7 @@ txn->mt_numdbs = 0; txn->mt_flags = MDB_TXN_FINISHED; + mdb_midl_free(txn->mt_spill_pgs); if (!txn->mt_parent) { mdb_midl_shrink(&txn->mt_free_pgs); @@ -3058,7 +3108,6 @@ mdb_midl_free(txn->mt_free_pgs); free(txn->mt_u.dirty_list); } - mdb_midl_free(txn->mt_spill_pgs); mdb_midl_free(pghead); } @@ -3080,18 +3129,25 @@ mdb_txn_end(txn, MDB_END_RESET); } -void -mdb_txn_abort(MDB_txn *txn) +static void +_mdb_txn_abort(MDB_txn *txn) { if (txn == NULL) return; if (txn->mt_child) - mdb_txn_abort(txn->mt_child); + _mdb_txn_abort(txn->mt_child); mdb_txn_end(txn, MDB_END_ABORT|MDB_END_SLOT|MDB_END_FREE); } +void +mdb_txn_abort(MDB_txn *txn) +{ + MDB_TRACE(("%p", txn)); + _mdb_txn_abort(txn); +} + /** Save the freelist as of this transaction to the freeDB. * This changes the freelist. Keep trying until it stabilizes. */ @@ -3182,7 +3238,7 @@ pglast = head_id = *(txnid_t *)key.mv_data; total_room = head_room = 0; mdb_tassert(txn, pglast <= env->me_pglast); - rc = mdb_cursor_del(&mc, 0); + rc = _mdb_cursor_del(&mc, 0); if (rc) return rc; } @@ -3202,7 +3258,7 @@ do { freecnt = free_pgs[0]; data.mv_size = MDB_IDL_SIZEOF(free_pgs); - rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); + rc = _mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); if (rc) return rc; /* Retry if mt_free_pgs[] grew during the Put() */ @@ -3251,7 +3307,7 @@ key.mv_size = sizeof(head_id); key.mv_data = &head_id; data.mv_size = (head_room + 1) * sizeof(pgno_t); - rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); + rc = _mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); if (rc) return rc; /* IDL is initially empty, zero out at least the length */ @@ -3306,7 +3362,7 @@ data.mv_data = mop -= len; save = mop[0]; mop[0] = len; - rc = mdb_cursor_put(&mc, &key, &data, MDB_CURRENT); + rc = _mdb_cursor_put(&mc, &key, &data, MDB_CURRENT); mop[0] = save; if (rc || !(mop_len -= len)) break; @@ -3467,8 +3523,8 @@ return MDB_SUCCESS; } -int -mdb_txn_commit(MDB_txn *txn) +static int +_mdb_txn_commit(MDB_txn *txn) { int rc; unsigned int i, end_mode; @@ -3481,7 +3537,7 @@ end_mode = MDB_END_EMPTY_COMMIT|MDB_END_UPDATE|MDB_END_SLOT|MDB_END_FREE; if (txn->mt_child) { - rc = mdb_txn_commit(txn->mt_child); + rc = _mdb_txn_commit(txn->mt_child); if (rc) goto fail; } @@ -3661,7 +3717,7 @@ goto fail; } data.mv_data = &txn->mt_dbs[i]; - rc = mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data, + rc = _mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data, F_SUBDATA); if (rc) goto fail; @@ -3692,10 +3748,17 @@ return MDB_SUCCESS; fail: - mdb_txn_abort(txn); + _mdb_txn_abort(txn); return rc; } +int +mdb_txn_commit(MDB_txn *txn) +{ + MDB_TRACE(("%p", txn)); + return _mdb_txn_commit(txn); +} + /** Read the environment parameters of a DB environment before * mapping it into memory. * @param[in] env the environment handle @@ -3992,6 +4055,7 @@ GET_PAGESIZE(e->me_os_psize); VGMEMP_CREATE(e,0,0); *env = e; + MDB_TRACE(("%p", e)); return MDB_SUCCESS; } @@ -4115,6 +4179,7 @@ env->me_mapsize = size; if (env->me_psize) env->me_maxpg = env->me_mapsize / env->me_psize; + MDB_TRACE(("%p, %"Yu"", env, size)); return MDB_SUCCESS; } @@ -4124,6 +4189,7 @@ if (env->me_map) return EINVAL; env->me_maxdbs = dbs + CORE_DBS; + MDB_TRACE(("%p, %u", env, dbs)); return MDB_SUCCESS; } @@ -4133,6 +4199,7 @@ if (env->me_map || readers < 1) return EINVAL; env->me_maxreaders = readers; + MDB_TRACE(("%p, %u", env, readers)); return MDB_SUCCESS; } @@ -5076,6 +5143,7 @@ } leave: + MDB_TRACE(("%p, %s, %u, %04o", env, path, flags & (CHANGEABLE|CHANGELESS), mode)); if (rc) { mdb_env_close0(env, excl); } @@ -5162,17 +5230,6 @@ sem_unlink(env->me_txns->mti_wmname); } } -#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)); } @@ -5199,6 +5256,7 @@ if (env == NULL) return; + MDB_TRACE(("%p", env)); VGMEMP_DESTROY(env); while ((dp = env->me_dpages) != NULL) { VGMEMP_DEFINED(&dp->mp_next, sizeof(dp->mp_next)); @@ -5662,7 +5720,7 @@ MDB_node *leaf = mdb_node_search(&mc2, &mc->mc_dbx->md_name, &exact); if (!exact) - return MDB_NOTFOUND; + return MDB_BAD_DBI; if ((leaf->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA) return MDB_INCOMPATIBLE; /* not a named DB */ rc = mdb_node_read(&mc2, leaf, &data); @@ -6570,8 +6628,8 @@ /** Do not spill pages to disk if txn is getting full, may fail instead */ #define MDB_NOSPILL 0x8000 -int -mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, +static int +_mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int flags) { MDB_env *env; @@ -6963,11 +7021,14 @@ 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); } @@ -7031,7 +7092,7 @@ new_dupdata = (int)dkey.mv_size; /* converted, write the original data first */ if (dkey.mv_size) { - rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags); + rc = _mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags); if (rc) goto bad_sub; /* we've done our job */ @@ -7059,7 +7120,7 @@ ecount = mc->mc_xcursor->mx_db.md_entries; if (flags & MDB_APPENDDUP) xflags |= MDB_APPEND; - rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags); + rc = _mdb_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags); if (flags & F_SUBDATA) { void *db = NODEDATA(leaf); memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db)); @@ -7100,7 +7161,20 @@ } int -mdb_cursor_del(MDB_cursor *mc, unsigned int flags) +mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, + unsigned int flags) +{ + DKBUF; + DDBUF; + int rc = _mdb_cursor_put(mc, key, data, flags); + MDB_TRACE(("%p, %"Z"u[%s], %"Z"u%s, %u", + mc, key ? key->mv_size:0, DKEY(key), data ? data->mv_size:0, + data ? mdb_dval(mc->mc_txn, mc->mc_dbi, data, dbuf):"", flags)); + return rc; +} + +static int +_mdb_cursor_del(MDB_cursor *mc, unsigned int flags) { MDB_node *leaf; MDB_page *mp; @@ -7138,7 +7212,7 @@ if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) { mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); } - rc = mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL); + rc = _mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL); if (rc) return rc; /* If sub-DB still has entries, we're done */ @@ -7202,6 +7276,14 @@ return rc; } +int +mdb_cursor_del(MDB_cursor *mc, unsigned int flags) +{ + MDB_TRACE(("%p, %u", + mc, flags)); + return _mdb_cursor_del(mc, flags); +} + /** Allocate and initialize new pages for a database. * Set #MDB_TXN_ERROR on failure. * @param[in] mc a cursor on the database being added to. @@ -7695,6 +7777,7 @@ return ENOMEM; } + MDB_TRACE(("%p, %u = %p", txn, dbi, mc)); *ret = mc; return MDB_SUCCESS; @@ -7758,6 +7841,7 @@ void mdb_cursor_close(MDB_cursor *mc) { + MDB_TRACE(("%p", mc)); if (mc && !mc->mc_backup) { /* remove from txn, if tracked */ if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) { @@ -8532,7 +8616,7 @@ goto fail; } if (m3->mc_xcursor && !(m3->mc_flags & C_EOF)) { - MDB_node *node = NODEPTR(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]); + MDB_node *node = NODEPTR(m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]); /* If this node has dupdata, it may need to be reinited * because its data has moved. * If the xcursor was not initd it must be reinited. @@ -8567,6 +8651,8 @@ mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data) { + DKBUF; + DDBUF; if (!key || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) return EINVAL; @@ -8578,6 +8664,9 @@ data = NULL; } + MDB_TRACE(("%p, %u, %"Z"u[%s], %"Z"u%s", + txn, dbi, key ? key->mv_size:0, DKEY(key), data ? data->mv_size:0, + data ? mdb_dval(txn, dbi, data, dbuf):"")); return mdb_del0(txn, dbi, key, data, 0); } @@ -8618,7 +8707,7 @@ mc.mc_flags |= C_UNTRACK; mc.mc_next = txn->mt_cursors[dbi]; txn->mt_cursors[dbi] = &mc; - rc = mdb_cursor_del(&mc, flags); + rc = _mdb_cursor_del(&mc, flags); txn->mt_cursors[dbi] = mc.mc_next; } return rc; @@ -9060,6 +9149,8 @@ MDB_cursor mc; MDB_xcursor mx; int rc; + DKBUF; + DDBUF; if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) return EINVAL; @@ -9070,10 +9161,12 @@ if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED)) return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; + MDB_TRACE(("%p, %u, %"Z"u[%s], %"Z"u%s, %u", + txn, dbi, key ? key->mv_size:0, DKEY(key), data->mv_size, mdb_dval(txn, dbi, data, dbuf), flags)); mdb_cursor_init(&mc, txn, dbi, &mx); mc.mc_next = txn->mt_cursors[dbi]; txn->mt_cursors[dbi] = &mc; - rc = mdb_cursor_put(&mc, key, data, flags); + rc = _mdb_cursor_put(&mc, key, data, flags); txn->mt_cursors[dbi] = mc.mc_next; return rc; } @@ -9091,8 +9184,8 @@ pthread_cond_t mc_cond; /**< Condition variable for #mc_new */ char *mc_wbuf[2]; char *mc_over[2]; - int mc_wlen[2]; - int mc_olen[2]; + size_t mc_wlen[2]; + size_t mc_olen[2]; pgno_t mc_next_pgno; HANDLE mc_fd; int mc_toggle; /**< Buffer number in provider */ @@ -9109,7 +9202,8 @@ { mdb_copy *my = arg; char *ptr; - int toggle = 0, wsize, rc; + int toggle = 0, rc; + size_t wsize; #ifdef _WIN32 DWORD len; #define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL) @@ -9476,7 +9570,7 @@ my.mc_error = rc; mdb_env_cthr_toggle(&my, 1 | MDB_EOF); rc = THREAD_FINISH(thr); - mdb_txn_abort(txn); + _mdb_txn_abort(txn); done: #ifdef _WIN32 @@ -9588,7 +9682,7 @@ } leave: - mdb_txn_abort(txn); + _mdb_txn_abort(txn); return rc; } @@ -9803,6 +9897,7 @@ } } mdb_default_cmp(txn, MAIN_DBI); + MDB_TRACE(("%p, (null), %u = %u", txn, flags, MAIN_DBI)); return MDB_SUCCESS; } @@ -9864,7 +9959,7 @@ dummy.md_root = P_INVALID; dummy.md_flags = flags & PERSISTENT_FLAGS; WITH_CURSOR_TRACKING(mc, - rc = mdb_cursor_put(&mc, &key, &data, F_SUBDATA)); + rc = _mdb_cursor_put(&mc, &key, &data, F_SUBDATA)); dbflag |= DB_DIRTY; } @@ -9889,6 +9984,7 @@ if (!unused) { txn->mt_numdbs++; } + MDB_TRACE(("%p, %s, %u = %u", txn, name, flags, slot)); } return rc; @@ -9920,6 +10016,7 @@ ptr = env->me_dbxs[dbi].md_name.mv_data; /* If there was no name, this was already closed */ if (ptr) { + MDB_TRACE(("%p, %u", env, dbi)); env->me_dbxs[dbi].md_name.mv_data = NULL; env->me_dbxs[dbi].md_name.mv_size = 0; env->me_dbflags[dbi] = 0; @@ -10054,6 +10151,7 @@ if (rc) return rc; + MDB_TRACE(("%u, %d", dbi, del)); rc = mdb_drop0(mc, mc->mc_db->md_flags & MDB_DUPSORT); /* Invalidate the dropped DB's cursors */ for (m2 = txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/mdb_dump.1 new/openldap-LMDB_0.9.35/libraries/liblmdb/mdb_dump.1 --- old/openldap-LMDB_0.9.30/libraries/liblmdb/mdb_dump.1 2023-02-08 19:41:37.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/mdb_dump.1 2026-01-29 22:51:48.000000000 +0100 @@ -61,14 +61,14 @@ Errors result in a non-zero exit status and a diagnostic message being written to standard error. -Dumping and reloading databases that use user-defined comparison functions -will result in new databases that use the default comparison functions. -\fBIn this case it is quite likely that the reloaded database will be -damaged beyond repair permitting neither record storage nor retrieval.\fP +Dumping databases that use user-defined comparison functions will output +records with the ordering imposed by those comparison functions. If +.B mdb_load +is invoked without including the +.B -a +option when reloading those records, the new databases will likely be +damaged beyond repair, permitting neither record storage nor retrieval. -The only available workaround is to modify the source for the -.BR mdb_load (1) -utility to load the database using the correct comparison functions. .SH "SEE ALSO" .BR mdb_load (1) .SH AUTHOR diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/mdb_load.1 new/openldap-LMDB_0.9.35/libraries/liblmdb/mdb_load.1 --- old/openldap-LMDB_0.9.30/libraries/liblmdb/mdb_load.1 2023-02-08 19:41:37.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/mdb_load.1 2026-01-29 22:51:48.000000000 +0100 @@ -8,6 +8,8 @@ [\c .BR \-V ] [\c +.BR \-a ] +[\c .BI \-f \ file\fR] [\c .BR \-n ] @@ -16,6 +18,8 @@ [\c .BR \-N ] [\c +.BR \-Q ] +[\c .BR \-T ] .BR \ envpath .SH DESCRIPTION @@ -56,6 +60,9 @@ .BR \-N Don't overwrite existing records when loading into an already existing database; just skip them. .TP +.BR \-Q +Quick mode, uses MDB_NOSYNC for faster loading. Forces sync with mdb_env_sync() before exiting. +.TP .BR \-T Load data from simple text files. The input must be paired lines of text, where the first line of the pair is the key item, and the second line of the pair is its corresponding diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/mdb_load.c new/openldap-LMDB_0.9.35/libraries/liblmdb/mdb_load.c --- old/openldap-LMDB_0.9.30/libraries/liblmdb/mdb_load.c 2023-02-08 19:41:37.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/mdb_load.c 2026-01-29 22:51:48.000000000 +0100 @@ -208,6 +208,12 @@ c1 = buf->mv_data; len = strlen((char *)c1); + if (!len) { + /* This can only happen with an intentionally invalid input + * with a NUL byte after the leading SPACE + */ + goto badend; + } l2 = len; /* Is buffer too short? */ @@ -311,10 +317,11 @@ * -n: use NOSUBDIR flag on env_open * -s: load into named subDB * -N: use NOOVERWRITE on puts + * -Q: quick mode using NOSYNC * -T: read plaintext * -V: print version and exit */ - while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) { + while ((i = getopt(argc, argv, "af:ns:NQTV")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); @@ -339,6 +346,9 @@ case 'N': putflags = MDB_NOOVERWRITE|MDB_NODUPDATA; break; + case 'Q': + envflags |= MDB_NOSYNC; + break; case 'T': mode |= NOHDR | PRINT; break; @@ -403,9 +413,9 @@ goto env_close; } - rc = mdb_open(txn, subname, flags|MDB_CREATE, &dbi); + rc = mdb_dbi_open(txn, subname, flags|MDB_CREATE, &dbi); if (rc) { - fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); + fprintf(stderr, "mdb_dbi_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } prevk.mv_size = 0; @@ -449,7 +459,7 @@ 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 %" Z "d: mdb_cursor_put failed, error %d %s\n", prog, lineno, rc, mdb_strerror(rc)); goto txn_abort; } batch++; @@ -470,9 +480,11 @@ 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; } @@ -484,6 +496,13 @@ prog, lineno, mdb_strerror(rc)); goto env_close; } + if (envflags & MDB_NOSYNC) { + rc = mdb_env_sync(env, 1); + if (rc) { + fprintf(stderr, "mdb_env_sync failed, error %d %s\n", rc, mdb_strerror(rc)); + goto env_close; + } + } mdb_dbi_close(env, dbi); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/midl.h new/openldap-LMDB_0.9.35/libraries/liblmdb/midl.h --- old/openldap-LMDB_0.9.30/libraries/liblmdb/midl.h 2023-02-08 19:41:37.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/midl.h 2026-01-29 22:51:48.000000000 +0100 @@ -56,7 +56,9 @@ /* 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<<MDB_IDL_LOGN) #define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openldap-LMDB_0.9.30/libraries/liblmdb/mplay.c new/openldap-LMDB_0.9.35/libraries/liblmdb/mplay.c --- old/openldap-LMDB_0.9.30/libraries/liblmdb/mplay.c 1970-01-01 01:00:00.000000000 +0100 +++ new/openldap-LMDB_0.9.35/libraries/liblmdb/mplay.c 2026-01-29 22:51:48.000000000 +0100 @@ -0,0 +1,580 @@ +/* mplay.c - memory-mapped database log replay */ +/* + * Copyright 2011-2023 Howard Chu, Symas Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "lmdb.h" + +#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) +#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) +#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ + "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) + +#define MDB_SCNy(t) "z" #t + +#define SCMP(s) s, (sizeof(s)-1) +char inbuf[8192]; +char *dbuf, *kbuf; +size_t dbufsize; +int maxkey; + +#define SOFF(s) (sizeof(s)+1) + +#define MAXENVS 16 +#define MAXTXNS 16 +#define MAXCRSS 16 + +#define MAXPIDS 16 + +typedef struct crspair { + void *tcrs; /* scanned text pointer */ + MDB_cursor *rcrs; +} crspair; + +typedef struct txnpair { + void *ttxn; /* scanned text pointer */ + MDB_txn *rtxn; + crspair cursors[MAXCRSS]; + int ncursors; +} txnpair; + +typedef struct envpair { + void *tenv; + MDB_env *renv; + txnpair txns[MAXTXNS]; + int ntxns; +} envpair; + +envpair envs[MAXENVS]; +int nenvs; + +envpair *lastenv; +txnpair *lasttxn; +crspair *lastcrs; + +typedef struct pidpair { + int tpid; + pid_t rpid; + int fdout, fdin; +} pidpair; + +pidpair *lastpid; + +pidpair pids[MAXPIDS]; +int npids; + +unsigned long lcount; + +static int unhex(unsigned char *c2) +{ + int x, c; + x = *c2++ & 0x4f; + if (x & 0x40) + x -= 55; + c = x << 4; + x = *c2 & 0x4f; + if (x & 0x40) + x -= 55; + c |= x; + return c; +} + +int inhex(char *in, char *out) +{ + char *c2 = out; + while (isxdigit(*in)) { + *c2++ = unhex((unsigned char *)in); + in += 2; + } + return c2 - out; +} + +static void addenv(void *tenv, MDB_env *renv) +{ + assert(nenvs < MAXENVS); + envs[nenvs].tenv = tenv; + envs[nenvs].renv = renv; + envs[nenvs].ntxns = 0; + lastenv = envs+nenvs; + nenvs++; +} + +static envpair *findenv(void *tenv) +{ + int i; + if (!lastenv || lastenv->tenv != tenv) { + for (i=0; i<nenvs; i++) + if (envs[i].tenv == tenv) + break; + assert(i < nenvs); + lastenv = &envs[i]; + } + return lastenv; +} + +static void delenv(envpair *ep) +{ + int i = ep - envs; + for (; i<nenvs-1; i++) + envs[i] = envs[i+1]; + nenvs--; + lastenv = NULL; +} + +static void addtxn(void *tenv, void *ttxn, MDB_txn *rtxn) +{ + envpair *ep; + txnpair *tp; + + ep = findenv(tenv); + assert(ep->ntxns < MAXTXNS); + tp = ep->txns+ep->ntxns; + tp->ttxn = ttxn; + tp->rtxn = rtxn; + tp->ncursors = 0; + ep->ntxns++; + lasttxn = tp; +} + +static txnpair *findtxn(void *ttxn) +{ + int i, j; + if (lasttxn && lasttxn->ttxn == ttxn) + return lasttxn; + if (lastenv) { + for (i=0; i<lastenv->ntxns; i++) { + if (lastenv->txns[i].ttxn == ttxn) { + lasttxn = lastenv->txns+i; + return lasttxn; + } + } + } + for (i=0; i<nenvs; i++) { + if (envs+i == lastenv) continue; + for (j=0; j<envs[i].ntxns; j++) { + if (envs[i].txns[j].ttxn == ttxn) { + lastenv = envs+i; + lasttxn = envs[i].txns+j; + return lasttxn; + } + } + } + assert(0); /* should have found it */ +} + +static void deltxn(txnpair *tp) +{ + int i = tp - lastenv->txns; + for (; i<lastenv->ntxns-1; i++) + lastenv->txns[i] = lastenv->txns[i+1]; + lastenv->ntxns--; + lasttxn = NULL; +} + +static void addcrs(txnpair *tp, void *tcrs, MDB_cursor *rcrs) +{ + int j = tp->ncursors; + assert(tp->ncursors < MAXCRSS); + + tp->cursors[j].tcrs = tcrs; + tp->cursors[j].rcrs = rcrs; + tp->ncursors++; + lastcrs = tp->cursors+j; +} + +static crspair *findcrs(void *tcrs) +{ + int i, j, k; + envpair *ep; + txnpair *tp; + crspair *cp; + if (lastcrs && lastcrs->tcrs == tcrs) + return lastcrs; + if (lasttxn) { + for (k=0, cp=lasttxn->cursors; k<lasttxn->ncursors; k++, cp++) { + if (cp->tcrs == tcrs) { + lastcrs = cp; + return lastcrs; + } + } + } + if (lastenv) { + for (j=0, tp=lastenv->txns; j<lastenv->ntxns; j++, tp++){ + if (tp == lasttxn) + continue; + for (k=0, cp = tp->cursors; k<tp->ncursors; k++, cp++) { + if (cp->tcrs == tcrs) { + lastcrs = cp; + lasttxn = tp; + return lastcrs; + } + } + } + } + for (i=0, ep=envs; i<nenvs; i++, ep++) { + for (j=0, tp=ep->txns; j<ep->ntxns; j++, tp++) { + if (tp == lasttxn) + continue; + for (k=0, cp = tp->cursors; k<tp->ncursors; k++, cp++) { + if (cp->tcrs == tcrs) { + lastcrs = cp; + lasttxn = tp; + lastenv = ep; + return lastcrs; + } + } + } + } + assert(0); /* should have found it already */ +} + +static void delcrs(void *tcrs) +{ + int i; + crspair *cp = findcrs(tcrs); + mdb_cursor_close(cp->rcrs); + for (i = cp - lasttxn->cursors; i<lasttxn->ncursors-1; i++) + lasttxn->cursors[i] = lasttxn->cursors[i+1]; + lasttxn->ncursors--; + lastcrs = NULL; +} + +void child() +{ + int rc; + MDB_val key, data; + char *ptr; + + while (fgets(inbuf, sizeof(inbuf), stdin)) { + ptr = inbuf; + if (!strncmp(ptr, SCMP("exit"))) + break; + + if (!strncmp(ptr, SCMP("mdb_env_create"))) { + void *tenv; + MDB_env *renv; + sscanf(ptr+SOFF("mdb_env_create"), "%p", &tenv); + E(mdb_env_create(&renv)); + addenv(tenv, renv); + } else if (!strncmp(ptr, SCMP("mdb_env_set_maxdbs"))) { + void *tenv; + envpair *ep; + unsigned int maxdbs; + sscanf(ptr+SOFF("mdb_env_set_maxdbs"), "%p, %u", &tenv, &maxdbs); + ep = findenv(tenv); + E(mdb_env_set_maxdbs(ep->renv, maxdbs)); + } else if (!strncmp(ptr, SCMP("mdb_env_set_mapsize"))) { + void *tenv; + envpair *ep; + size_t mapsize; + sscanf(ptr+SOFF("mdb_env_set_mapsize"), "%p, %"MDB_SCNy(u), &tenv, &mapsize); + ep = findenv(tenv); + E(mdb_env_set_mapsize(ep->renv, mapsize)); + } else if (!strncmp(ptr, SCMP("mdb_env_open"))) { + void *tenv; + envpair *ep; + char *path; + int len; + unsigned int flags, mode; + sscanf(ptr+SOFF("mdb_env_open"), "%p, %n", &tenv, &len); + path = ptr+SOFF("mdb_env_open")+len; + ptr = strchr(path, ','); + *ptr++ = '\0'; + sscanf(ptr, "%u, %o", &flags, &mode); + ep = findenv(tenv); + E(mdb_env_open(ep->renv, path, flags, mode)); + if (!maxkey) { + maxkey = mdb_env_get_maxkeysize(ep->renv); + kbuf = malloc(maxkey+2); + dbuf = malloc(maxkey+2); + dbufsize = maxkey; + } + } else if (!strncmp(ptr, SCMP("mdb_env_close"))) { + void *tenv; + envpair *ep; + sscanf(ptr+SOFF("mdb_env_close"), "%p", &tenv); + ep = findenv(tenv); + mdb_env_close(ep->renv); + delenv(ep); + if (!nenvs) /* if no other envs left, this process is done */ + break; + } else if (!strncmp(ptr, SCMP("mdb_txn_begin"))) { + unsigned int flags; + void *tenv, *ttxn; + envpair *ep; + MDB_txn *rtxn; + sscanf(ptr+SOFF("mdb_txn_begin"), "%p, %*p, %u = %p", &tenv, &flags, &ttxn); + ep = findenv(tenv); + E(mdb_txn_begin(ep->renv, NULL, flags, &rtxn)); + addtxn(tenv, ttxn, rtxn); + } else if (!strncmp(ptr, SCMP("mdb_txn_commit"))) { + void *ttxn; + txnpair *tp; + sscanf(ptr+SOFF("mdb_txn_commit"), "%p", &ttxn); + tp = findtxn(ttxn); + E(mdb_txn_commit(tp->rtxn)); + deltxn(tp); + } else if (!strncmp(ptr, SCMP("mdb_txn_abort"))) { + void *ttxn; + txnpair *tp; + sscanf(ptr+SOFF("mdb_txn_abort"), "%p", &ttxn); + tp = findtxn(ttxn); + mdb_txn_abort(tp->rtxn); + deltxn(tp); + } else if (!strncmp(ptr, SCMP("mdb_dbi_open"))) { + void *ttxn; + txnpair *tp; + char *dbname; + unsigned int flags; + unsigned int tdbi; + MDB_dbi dbi; + sscanf(ptr+SOFF("mdb_dbi_open"), "%p, ", &ttxn); + dbname = strchr(ptr+SOFF("mdb_dbi_open"), ','); + dbname += 2; + ptr = strchr(dbname, ','); + *ptr++ = '\0'; + if (!strcmp(dbname, "(null)")) + dbname = NULL; + sscanf(ptr, "%u = %u", &flags, &tdbi); + tp = findtxn(ttxn); + E(mdb_dbi_open(tp->rtxn, dbname, flags, &dbi)); + } else if (!strncmp(ptr, SCMP("mdb_dbi_close"))) { + void *tenv; + envpair *ep; + unsigned int tdbi; + sscanf(ptr+SOFF("mdb_dbi_close"), "%p, %u", &tenv, &tdbi); + ep = findenv(tenv); + mdb_dbi_close(ep->renv, tdbi); + } else if (!strncmp(ptr, SCMP("mdb_cursor_open"))) { + void *ttxn, *tcrs; + txnpair *tp; + MDB_cursor *rcrs; + unsigned int tdbi; + sscanf(ptr+SOFF("mdb_cursor_open"), "%p, %u = %p", &ttxn, &tdbi, &tcrs); + tp = findtxn(ttxn); + E(mdb_cursor_open(tp->rtxn, tdbi, &rcrs)); + addcrs(tp, tcrs, rcrs); + } else if (!strncmp(ptr, SCMP("mdb_cursor_close"))) { + void *tcrs; + sscanf(ptr+SOFF("mdb_cursor_close"), "%p", &tcrs); + delcrs(tcrs); + } else if (!strncmp(ptr, SCMP("mdb_cursor_put"))) { + void *tcrs; + crspair *cp; + unsigned int flags; + int len; + sscanf(ptr+SOFF("mdb_cursor_put"), "%p, ", &tcrs); + cp = findcrs(tcrs); + ptr = strchr(ptr+SOFF("mdb_cursor_put"), ','); + sscanf(ptr+1, "%"MDB_SCNy(u)",", &key.mv_size); + if (key.mv_size) { + ptr = strchr(ptr, '['); + inhex(ptr+1, kbuf); + key.mv_data = kbuf; + ptr += key.mv_size * 2 + 2; + } + ptr = strchr(ptr+1, ','); + sscanf(ptr+1, "%"MDB_SCNy(u)"%n", &data.mv_size, &len); + if (data.mv_size > dbufsize) { + dbuf = realloc(dbuf, data.mv_size+2); + assert(dbuf != NULL); + dbufsize = data.mv_size; + } + ptr += len+1; + if (*ptr == '[') { + inhex(ptr+1, dbuf); + data.mv_data = dbuf; + ptr += data.mv_size * 2 + 2; + } else { + sprintf(dbuf, "%09ld", (long)mdb_txn_id(lasttxn->rtxn)); + } + sscanf(ptr+1, "%u", &flags); + E(mdb_cursor_put(cp->rcrs, &key, &data, flags)); + } else if (!strncmp(ptr, SCMP("mdb_cursor_del"))) { + void *tcrs; + crspair *cp; + unsigned int flags; + sscanf(ptr+SOFF("mdb_cursor_del"), "%p, %u", &tcrs, &flags); + cp = findcrs(tcrs); + E(mdb_cursor_del(cp->rcrs, flags)); + } else if (!strncmp(ptr, SCMP("mdb_put"))) { + void *ttxn; + txnpair *tp; + unsigned int tdbi, flags; + int len; + sscanf(ptr+SOFF("mdb_put"),"%p, %u, %"MDB_SCNy(u), &ttxn, &tdbi, &key.mv_size); + tp = findtxn(ttxn); + ptr = strchr(ptr+SOFF("mdb_put"), '['); + inhex(ptr+1, kbuf); + key.mv_data = kbuf; + ptr += key.mv_size * 2 + 2; + sscanf(ptr+1, "%"MDB_SCNy(u)"%n", &data.mv_size, &len); + if (data.mv_size > dbufsize) { + dbuf = realloc(dbuf, data.mv_size+2); + assert(dbuf != NULL); + dbufsize = data.mv_size; + } + ptr += len+1; + if (*ptr == '[') { + inhex(ptr+1, dbuf); + ptr += data.mv_size * 2 + 2; + } else { + sprintf(dbuf, "%09ld", (long)mdb_txn_id(tp->rtxn)); + } + data.mv_data = dbuf; + sscanf(ptr+1, "%u", &flags); + RES(MDB_KEYEXIST,mdb_put(tp->rtxn, tdbi, &key, &data, flags)); + } else if (!strncmp(ptr, SCMP("mdb_del"))) { + void *ttxn; + txnpair *tp; + unsigned int tdbi; + int len; + sscanf(ptr+SOFF("mdb_del"),"%p, %u, %"MDB_SCNy(u), &ttxn, &tdbi, &key.mv_size); + tp = findtxn(ttxn); + ptr = strchr(ptr+SOFF("mdb_del"), '['); + inhex(ptr+1, kbuf); + key.mv_data = kbuf; + ptr += key.mv_size * 2 + 2; + sscanf(ptr+1, "%"MDB_SCNy(u)"%n", &data.mv_size, &len); + if (data.mv_size > dbufsize) { + dbuf = realloc(dbuf, data.mv_size+2); + assert(dbuf != NULL); + dbufsize = data.mv_size; + } + ptr += len+1; + if (*ptr == '[') { + inhex(ptr+1, dbuf); + } else { + sprintf(dbuf, "%09ld", (long)mdb_txn_id(tp->rtxn)); + } + data.mv_data = dbuf; + RES(MDB_NOTFOUND,mdb_del(tp->rtxn, tdbi, &key, &data)); + } + write(1, "\n", 1); + } + exit(0); +} + +static pidpair *addpid(int tpid) +{ + int fdout[2], fdin[2]; + pid_t pid; + assert(npids < MAXPIDS); + pids[npids].tpid = tpid; + pipe(fdout); + pipe(fdin); + if ((pid = fork()) == 0) { + /* child */ + fflush(stdin); + fflush(stdout); + dup2(fdout[0], 0); + dup2(fdin[1], 1); + child(); + return 0; /* NOTREACHED */ + } else { + pids[npids].rpid = pid; + pids[npids].fdout = fdout[1]; + pids[npids].fdin = fdin[0]; + lastpid = pids+npids; + npids++; + return lastpid; + } +} + +static pidpair *findpid(int tpid) +{ + int i; + if (!lastpid || lastpid->tpid != tpid) { + for (i=0; i<npids; i++) + if (pids[i].tpid == tpid) + break; + if (i == npids) + return NULL; + lastpid = &pids[i]; + } + return lastpid; +} + +volatile pid_t killpid; + +static void delpid(int tpid) +{ + pidpair *pp = findpid(tpid); + if (pp) { + pid_t kpid = pp->rpid; + killpid = kpid; + write(pp->fdout, "exit\n", sizeof("exit")); + while (killpid == kpid) + usleep(10000); + } +} + +static void reaper(int sig) +{ + int status, i; + pid_t pid = waitpid(-1, &status, 0); + if (pid > 0) { + fprintf(stderr, "# %s %d\n", WIFEXITED(status) ? "exited" : "killed", pid); + for (i=0; i<npids; i++) + if (pids[i].rpid == pid) + break; + assert(i < npids); + close(pids[i].fdout); + close(pids[i].fdin); + for (;i<npids-1; i++) + pids[i] = pids[i+1]; + npids--; + killpid = 0; + } +} + +int main(int argc,char * argv[]) +{ + signal(SIGCHLD, reaper); + + while (fgets(inbuf, sizeof(inbuf), stdin)) { + pidpair *pp; + int tpid, len; + char c, *ptr; + lcount++; + + if (inbuf[0] == '#' && !strncmp(inbuf+1, SCMP(" killed"))) { + sscanf(inbuf+SOFF("killed"),"%d", &tpid); + delpid(tpid); + continue; + } + + if (inbuf[0] != '>') + continue; + ptr = inbuf+1; + sscanf(ptr, "%d:%n", &tpid, &len); + pp = findpid(tpid); + if (!pp) + pp = addpid(tpid); /* new process */ + + ptr = inbuf+len+1; + len = strlen(ptr); + write(pp->fdout, ptr, len); /* send command and wait for ack */ + read(pp->fdin, &c, 1); + } + while (npids) + delpid(pids[0].tpid); +}
