* 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
* 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;
}
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
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.
*
} 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;
}
}