]> git.sur5r.net Git - openldap/blobdiff - libraries/liblmdb/mdb.c
Tweak MDB_PREV_MULTIPLE for uninit'd cursor
[openldap] / libraries / liblmdb / mdb.c
index be36d4967e6df0dc6505158e436d1d0383dc8444..a366b40245f6f83e70440abc460489280b87c6fa 100644 (file)
@@ -5,7 +5,7 @@
  *     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
@@ -1075,7 +1075,7 @@ typedef struct MDB_db {
        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;
 
@@ -1572,8 +1572,9 @@ mdb_strerror(int err)
         *      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)
@@ -1605,7 +1606,7 @@ mdb_strerror(int 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);
@@ -4159,6 +4160,19 @@ mdb_env_create(MDB_env **env)
        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)
 {
@@ -4188,7 +4202,7 @@ 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;
@@ -4200,7 +4214,7 @@ mdb_env_map(MDB_env *env, void *addr)
        NtClose(mh);
 #endif
        if (rc)
-               return rc;
+               return mdb_nt2win32(rc);
        env->me_map = map;
 #else
 #ifdef MDB_VL32
@@ -4272,7 +4286,7 @@ mdb_env_set_mapsize(MDB_env *env, mdb_size_t size)
                        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;
                }
@@ -5692,7 +5706,8 @@ mdb_rpage_get(MDB_txn *txn, pgno_t pg0, MDB_page **ret)
 #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;
@@ -5830,7 +5845,7 @@ retry:
                                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 {
@@ -5882,36 +5897,15 @@ fail:
                        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);
@@ -7013,8 +7007,10 @@ fetchm:
                        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);
@@ -7566,7 +7562,7 @@ new_sub:
                 */
                if (do_sub) {
                        int xflags, new_dupdata;
-                       size_t ecount;
+                       mdb_size_t ecount;
 put_sub:
                        xdata.mv_size = 0;
                        xdata.mv_data = "";
@@ -8281,7 +8277,7 @@ mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc)
 
 /* 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;
 
@@ -10141,7 +10137,7 @@ mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags)
 #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);