* BerkeleyDB API, but much simplified.
*/
/*
- * Copyright 2011-2015 Howard Chu, Symas Corp.
+ * Copyright 2011-2016 Howard Chu, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
-#ifdef MDB_VL32
+#if defined(MDB_VL32) || defined(__WIN64__)
#define _FILE_OFFSET_BITS 64
#endif
#ifdef _WIN32
pgno_t md_branch_pages; /**< number of internal pages */
pgno_t md_leaf_pages; /**< number of leaf pages */
pgno_t md_overflow_pages; /**< number of overflow pages */
- pgno_t md_entries; /**< number of data items */
+ mdb_size_t md_entries; /**< number of data items */
pgno_t md_root; /**< the root page of this tree */
} MDB_db;
* This works as long as no function between the call to mdb_strerror
* and the actual use of the message uses more than 4K of stack.
*/
- char pad[4096];
- char buf[1024], *ptr = buf;
+#define MSGSIZE 1024
+#define PADSIZE 4096
+ char buf[MSGSIZE+PADSIZE], *ptr = buf;
#endif
int i;
if (!err)
buf[0] = 0;
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, err, 0, ptr, sizeof(buf), (va_list *)pad);
+ NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE);
return ptr;
#else
return strerror(err);
rc = MDB_MAP_FULL;
goto fail;
}
-#ifdef _WIN32
- if (env->me_flags & MDB_WRITEMAP) {
+#if defined(_WIN32) && !defined(MDB_VL32)
+ if (!(env->me_flags & MDB_RDONLY)) {
void *p;
p = (MDB_page *)(env->me_map + env->me_psize * pgno);
p = VirtualAlloc(p, env->me_psize * num, MEM_COMMIT,
return MDB_SUCCESS;
}
+#ifdef _WIN32
+/** @brief Map a result from an NTAPI call to WIN32. */
+static DWORD
+mdb_nt2win32(NTSTATUS st)
+{
+ OVERLAPPED o = {0};
+ DWORD br;
+ o.Internal = st;
+ GetOverlappedResult(NULL, &o, &br, FALSE);
+ return GetLastError();
+}
+#endif
+
static int ESECT
mdb_env_map(MDB_env *env, void *addr)
{
rc = NtCreateSection(&mh, access, NULL, NULL, secprot, SEC_RESERVE, env->me_fd);
if (rc)
- return rc;
+ return mdb_nt2win32(rc);
map = addr;
#ifdef MDB_VL32
msize = NUM_METAS * env->me_psize;
NtClose(mh);
#endif
if (rc)
- return rc;
+ return mdb_nt2win32(rc);
env->me_map = map;
#else
#ifdef MDB_VL32
size = meta->mm_mapsize;
{
/* Silently round up to minimum if the size is too small */
- size_t minsize = (meta->mm_last_pg + 1) * env->me_psize;
+ mdb_size_t minsize = (meta->mm_last_pg + 1) * env->me_psize;
if (size < minsize)
size = minsize;
}
#define MAP(rc,env,addr,len,off) \
addr = NULL; \
rc = NtMapViewOfSection(env->me_fmh, GetCurrentProcess(), &addr, 0, \
- len, &off, &len, ViewUnmap, (env->me_flags & MDB_RDONLY) ? 0 : MEM_RESERVE, PAGE_READONLY)
+ len, &off, &len, ViewUnmap, (env->me_flags & MDB_RDONLY) ? 0 : MEM_RESERVE, PAGE_READONLY); \
+ if (rc) rc = mdb_nt2win32(rc)
#else
off_t off;
size_t len;
if (rc)
goto fail;
if (!el[x].mref) {
- munmap(el[x].mptr, el[x].mcnt);
+ munmap(el[x].mptr, env->me_psize * el[x].mcnt);
el[x].mptr = id3.mptr;
el[x].mcnt = id3.mcnt;
} else {
pthread_mutex_unlock(&env->me_rpmutex);
return rc;
}
- /* If this page is far enough from the end of the env, scan for
- * any overflow pages that would spill onto another block.
- * Note we must compare against mt_last_pgno, the last written
- * page in the environment. Not mt_next_pgno, which increases
- * for every newly allocated (but not yet written) page. If
- * we scanned beyond the last written page we'd get a bus error.
- */
- if (pgno + MDB_RPAGE_CHUNK <= txn->mt_last_pgno) {
- int i;
- char *cp = (char *)id3.mptr + rem * env->me_psize;
- for (i=rem; i<MDB_RPAGE_CHUNK;) {
- p = (MDB_page *)cp;
- if (IS_OVERFLOW(p)) {
- int nop = p->mp_pages;
- if (nop + i > MDB_RPAGE_CHUNK) {
- munmap(id3.mptr, len);
- id3.mcnt = nop + i;
- len = id3.mcnt * env->me_psize;
- MAP(rc, env, id3.mptr, len, off);
- if (rc)
- goto fail;
- break;
- }
- i += nop;
- cp += nop * env->me_psize;
- } else {
- i++;
- cp += env->me_psize;
- }
- }
+ /* check for overflow size */
+ p = (MDB_page *)((char *)id3.mptr + rem * env->me_psize);
+ if (IS_OVERFLOW(p) && p->mp_pages + rem > id3.mcnt) {
+ id3.mcnt = p->mp_pages + rem;
+ munmap(id3.mptr, len);
+ len = id3.mcnt * env->me_psize;
+ MAP(rc, env, id3.mptr, len, off);
+ if (rc)
+ goto fail;
}
mdb_mid3l_insert(el, &id3);
pthread_mutex_unlock(&env->me_rpmutex);
DPRINTF(("cursor_next: top page is %"Y"u in cursor %p",
mdb_dbg_pgno(mp), (void *) mc));
- if (mc->mc_flags & C_DEL)
+ if (mc->mc_flags & C_DEL) {
+ mc->mc_flags ^= C_DEL;
goto skip;
+ }
if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) {
DPUTS("=====> move to next sibling page");
DPRINTF(("cursor_prev: top page is %"Y"u in cursor %p",
mdb_dbg_pgno(mp), (void *) mc));
+ mc->mc_flags &= ~(C_EOF|C_DEL);
+
if (mc->mc_ki[mc->mc_top] == 0) {
DPUTS("=====> move to prev sibling page");
if ((rc = mdb_cursor_sibling(mc, 0)) != MDB_SUCCESS) {
break;
}
if (!(mc->mc_flags & C_INITIALIZED))
- rc = mdb_cursor_first(mc, key, data);
- else {
+ rc = mdb_cursor_last(mc, key, data);
+ else
+ rc = MDB_SUCCESS;
+ if (rc == MDB_SUCCESS) {
MDB_cursor *mx = &mc->mc_xcursor->mx_cursor;
if (mx->mc_flags & C_INITIALIZED) {
rc = mdb_cursor_sibling(mx, 0);
*/
if (do_sub) {
int xflags, new_dupdata;
- size_t ecount;
+ mdb_size_t ecount;
put_sub:
xdata.mv_size = 0;
xdata.mv_data = "";
/* Return the count of duplicate data items for the current key */
int
-mdb_cursor_count(MDB_cursor *mc, size_t *countp)
+mdb_cursor_count(MDB_cursor *mc, mdb_size_t *countp)
{
MDB_node *leaf;
#ifdef _WIN32
rc = utf8_to_utf16(lpath, -1, &wpath, NULL);
if (rc)
- return rc;
+ goto leave;
newfd = CreateFileW(wpath, GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL);
free(wpath);