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);
+}

Reply via email to