]> git.sur5r.net Git - openldap/blobdiff - libraries/liblmdb/mdb.c
ITS#8756 remove loose pg from dirty list in freelist_save
[openldap] / libraries / liblmdb / mdb.c
index f5f99a59019b79afc632ffbc584e69fbbd42cc53..63872c92bff93943dcfa360e772e264c694f29a0 100644 (file)
@@ -5,7 +5,7 @@
  *     BerkeleyDB API, but much simplified.
  */
 /*
- * Copyright 2011-2017 Howard Chu, Symas Corp.
+ * Copyright 2011-2018 Howard Chu, Symas Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * the full size. These APIs are defined in <wdm.h> and <ntifs.h>
  * but those headers are meant for driver-level development and
  * conflict with the regular user-level headers, so we explicitly
- * declare them here. Using these APIs also means we must link to
- * ntdll.dll, which is not linked by default in user code.
+ * declare them here. We get pointers to these functions from
+ * NTDLL.DLL at runtime, to avoid buildtime dependencies on any
+ * NTDLL import libraries.
  */
-NTSTATUS WINAPI
-NtCreateSection(OUT PHANDLE sh, IN ACCESS_MASK acc,
+typedef NTSTATUS WINAPI (NtCreateSectionFunc)
+  (OUT PHANDLE sh, IN ACCESS_MASK acc,
   IN void * oa OPTIONAL,
   IN PLARGE_INTEGER ms OPTIONAL,
   IN ULONG pp, IN ULONG aa, IN HANDLE fh OPTIONAL);
 
+static NtCreateSectionFunc *NtCreateSection;
+
 typedef enum _SECTION_INHERIT {
        ViewShare = 1,
        ViewUnmap = 2
 } SECTION_INHERIT;
 
-NTSTATUS WINAPI
-NtMapViewOfSection(IN PHANDLE sh, IN HANDLE ph,
+typedef NTSTATUS WINAPI (NtMapViewOfSectionFunc)
+  (IN PHANDLE sh, IN HANDLE ph,
   IN OUT PVOID *addr, IN ULONG_PTR zbits,
   IN SIZE_T cs, IN OUT PLARGE_INTEGER off OPTIONAL,
   IN OUT PSIZE_T vs, IN SECTION_INHERIT ih,
   IN ULONG at, IN ULONG pp);
 
-NTSTATUS WINAPI
-NtClose(HANDLE h);
+static NtMapViewOfSectionFunc *NtMapViewOfSection;
+
+typedef NTSTATUS WINAPI (NtCloseFunc)(HANDLE h);
+
+static NtCloseFunc *NtClose;
 
 /** getpid() returns int; MinGW defines pid_t but MinGW64 typedefs it
  *  as int64 which is wrong. MSVC doesn't define it at all, so just
@@ -3438,10 +3444,41 @@ mdb_freelist_save(MDB_txn *txn)
                 * we may be unable to return them to me_pghead.
                 */
                MDB_page *mp = txn->mt_loose_pgs;
+               MDB_ID2 *dl = txn->mt_u.dirty_list;
+               unsigned x;
                if ((rc = mdb_midl_need(&txn->mt_free_pgs, txn->mt_loose_count)) != 0)
                        return rc;
-               for (; mp; mp = NEXT_LOOSE_PAGE(mp))
+               for (; mp; mp = NEXT_LOOSE_PAGE(mp)) {
                        mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
+                       /* must also remove from dirty list */
+                       if (txn->mt_flags & MDB_TXN_WRITEMAP) {
+                               for (x=1; x<=dl[0].mid; x++)
+                                       if (dl[x].mid == mp->mp_pgno)
+                                               break;
+                               mdb_tassert(txn, x <= dl[0].mid);
+                       } else {
+                               x = mdb_mid2l_search(dl, mp->mp_pgno);
+                               mdb_tassert(txn, dl[x].mid == mp->mp_pgno);
+                       }
+                       dl[x].mptr = NULL;
+                       mdb_dpage_free(env, mp);
+               }
+               {
+                       /* squash freed slots out of the dirty list */
+                       unsigned y;
+                       for (y=1; dl[y].mptr && y <= dl[0].mid; y++);
+                       if (y <= dl[0].mid) {
+                               for(x=y, y++;;) {
+                                       while (!dl[y].mptr && y <= dl[0].mid) y++;
+                                       if (y > dl[0].mid) break;
+                                       dl[x++] = dl[y++];
+                               }
+                               dl[0].mid = x-1;
+                       } else {
+                               /* all slots freed */
+                               dl[0].mid = 0;
+                       }
+               }
                txn->mt_loose_pgs = NULL;
                txn->mt_loose_count = 0;
        }
@@ -4690,6 +4727,21 @@ mdb_env_open2(MDB_env *env, int prev)
                env->me_pidquery = MDB_PROCESS_QUERY_LIMITED_INFORMATION;
        else
                env->me_pidquery = PROCESS_QUERY_INFORMATION;
+       /* Grab functions we need from NTDLL */
+       if (!NtCreateSection) {
+               HMODULE h = GetModuleHandle("NTDLL.DLL");
+               if (!h)
+                       return MDB_PROBLEM;
+               NtClose = (NtCloseFunc *)GetProcAddress(h, "NtClose");
+               if (!NtClose)
+                       return MDB_PROBLEM;
+               NtMapViewOfSection = (NtMapViewOfSectionFunc *)GetProcAddress(h, "NtMapViewOfSection");
+               if (!NtMapViewOfSection)
+                       return MDB_PROBLEM;
+               NtCreateSection = (NtCreateSectionFunc *)GetProcAddress(h, "NtCreateSection");
+               if (!NtCreateSection)
+                       return MDB_PROBLEM;
+       }
 #endif /* _WIN32 */
 
 #ifdef BROKEN_FDATASYNC
@@ -5553,7 +5605,7 @@ mdb_env_close0(MDB_env *env, int excl)
        if (env->me_fd != INVALID_HANDLE_VALUE)
                (void) close(env->me_fd);
        if (env->me_txns) {
-               MDB_PID_T pid = env->me_pid;
+               MDB_PID_T pid = getpid();
                /* Clearing readers is done in this function because
                 * me_txkey with its destructor must be disabled first.
                 *
@@ -7648,8 +7700,9 @@ prep_subDB:
                                } else {
                                        memcpy((char *)mp + mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper + PAGEBASE,
                                                olddata.mv_size - fp->mp_upper - PAGEBASE);
+                                       memcpy((char *)(&mp->mp_ptrs), (char *)(&fp->mp_ptrs), NUMKEYS(fp) * sizeof(mp->mp_ptrs[0]));
                                        for (i=0; i<NUMKEYS(fp); i++)
-                                               mp->mp_ptrs[i] = fp->mp_ptrs[i] + offset;
+                                               mp->mp_ptrs[i] += offset;
                                }
                        }