]> git.sur5r.net Git - openldap/blobdiff - libraries/liblmdb/mdb.c
Merge remote-tracking branch 'origin/mdb.master'
[openldap] / libraries / liblmdb / mdb.c
index 6284edccd13753a0dd6a8ffa415461d8c1d3410f..84477c428585303a5cd7edfdc63818f947ffd51f 100644 (file)
@@ -427,13 +427,14 @@ static txnid_t mdb_debug_start;
         *      Define this as 0 to compute the max from the page size.  511
         *      is default for backwards compat: liblmdb <= 0.9.10 can break
         *      when modifying a DB with keys/dupsort data bigger than its max.
+        *      #MDB_DEVEL sets the default to 0.
         *
         *      Data items in an #MDB_DUPSORT database are also limited to
         *      this size, since they're actually keys of a sub-DB.  Keys and
         *      #MDB_DUPSORT data items must fit on a node in a regular page.
         */
 #ifndef MDB_MAXKEYSIZE
-#define MDB_MAXKEYSIZE  511
+#define MDB_MAXKEYSIZE  ((MDB_DEVEL) ? 0 : 511)
 #endif
 
        /**     The maximum size of a key we can write to the environment. */
@@ -1073,8 +1074,6 @@ struct MDB_env {
        HANDLE          me_mfd;                 /**< just for writing the meta pages */
        /** Failed to update the meta page. Probably an I/O error. */
 #define        MDB_FATAL_ERROR 0x80000000U
-       /** We're explicitly changing the mapsize. */
-#define        MDB_RESIZING    0x40000000U
        /** Some fields are initialized. */
 #define        MDB_ENV_ACTIVE  0x20000000U
        /** me_txkey is set */
@@ -2536,9 +2535,7 @@ mdb_txn_renew0(MDB_txn *txn)
        }
        txn->mt_dbflags[0] = txn->mt_dbflags[1] = DB_VALID;
 
-       /* If we didn't ask for a resize, but the size grew, fail */
-       if (!(env->me_flags & MDB_RESIZING)
-               && env->me_mapsize < meta->mm_mapsize) {
+       if (env->me_maxpg < txn->mt_next_pgno) {
                mdb_txn_reset0(txn, "renew0-mapfail");
                if (new_notls) {
                        txn->mt_u.reader->mr_pid = 0;
@@ -3276,13 +3273,8 @@ mdb_txn_commit(MDB_txn *txn)
        mdb_cursors_close(txn, 0);
 
        if (!txn->mt_u.dirty_list[0].mid &&
-               !(txn->mt_flags & (MDB_TXN_DIRTY|MDB_TXN_SPILLS))) {
-               if ((env->me_flags & MDB_RESIZING)
-                       && (rc = mdb_env_write_meta(txn))) {
-                       goto fail;
-               }
+               !(txn->mt_flags & (MDB_TXN_DIRTY|MDB_TXN_SPILLS)))
                goto done;
-       }
 
        DPRINTF(("committing txn %"Z"u %p on mdbenv %p, root page %"Z"u",
            txn->mt_txnid, (void*)txn, (void*)env, txn->mt_dbs[MAIN_DBI].md_root));
@@ -3323,6 +3315,7 @@ mdb_txn_commit(MDB_txn *txn)
 #endif
 
        if ((rc = mdb_page_flush(txn, 0)) ||
+               (rc = mdb_env_sync(env, 0)) ||
                (rc = mdb_env_write_meta(txn)))
                goto fail;
 
@@ -3479,8 +3472,9 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
 static int
 mdb_env_write_meta(MDB_txn *txn)
 {
-       MDB_env *env = txn->mt_env;
+       MDB_env *env;
        MDB_meta        meta, metab, *mp;
+       size_t mapsize;
        off_t off;
        int rc, len, toggle;
        char *ptr;
@@ -3491,22 +3485,19 @@ mdb_env_write_meta(MDB_txn *txn)
        int r2;
 #endif
 
-       /* Sync data and previous metapage before writing a new metapage */
-       if ((rc = mdb_env_sync(env, 0)) != MDB_SUCCESS)
-               return rc;
-
        toggle = txn->mt_txnid & 1;
        DPRINTF(("writing meta page %d for root page %"Z"u",
                toggle, txn->mt_dbs[MAIN_DBI].md_root));
 
+       env = txn->mt_env;
        mp = env->me_metas[toggle];
+       mapsize = env->me_metas[toggle ^ 1]->mm_mapsize;
+       /* Persist any increases of mapsize config */
+       if (mapsize < env->me_mapsize)
+               mapsize = env->me_mapsize;
 
        if (env->me_flags & MDB_WRITEMAP) {
-               /* Persist any changes of mapsize config */
-               if (env->me_flags & MDB_RESIZING) {
-                       mp->mm_mapsize = env->me_mapsize;
-                       env->me_flags ^= MDB_RESIZING;
-               }
+               mp->mm_mapsize = mapsize;
                mp->mm_dbs[0] = txn->mt_dbs[0];
                mp->mm_dbs[1] = txn->mt_dbs[1];
                mp->mm_last_pg = txn->mt_next_pgno - 1;
@@ -3533,23 +3524,15 @@ mdb_env_write_meta(MDB_txn *txn)
        metab.mm_txnid = env->me_metas[toggle]->mm_txnid;
        metab.mm_last_pg = env->me_metas[toggle]->mm_last_pg;
 
-       ptr = (char *)&meta;
-       if (env->me_flags & MDB_RESIZING) {
-               /* Persist any changes of mapsize config */
-               meta.mm_mapsize = env->me_mapsize;
-               off = offsetof(MDB_meta, mm_mapsize);
-               env->me_flags ^= MDB_RESIZING;
-       } else {
-               off = offsetof(MDB_meta, mm_dbs[0].md_depth);
-       }
-       len = sizeof(MDB_meta) - off;
-
-       ptr += off;
+       meta.mm_mapsize = mapsize;
        meta.mm_dbs[0] = txn->mt_dbs[0];
        meta.mm_dbs[1] = txn->mt_dbs[1];
        meta.mm_last_pg = txn->mt_next_pgno - 1;
        meta.mm_txnid = txn->mt_txnid;
 
+       off = offsetof(MDB_meta, mm_mapsize);
+       ptr = (char *)&meta + off;
+       len = sizeof(MDB_meta) - off;
        if (toggle)
                off += env->me_psize;
        off += PAGEHDRSZ;
@@ -3727,25 +3710,19 @@ mdb_env_set_mapsize(MDB_env *env, size_t size)
         * sure there are no active txns.
         */
        if (env->me_map) {
-               int rc, change = 0;
+               int rc;
                void *old;
                if (env->me_txn)
                        return EINVAL;
                if (!size)
                        size = env->me_metas[mdb_env_pick_meta(env)]->mm_mapsize;
-               else {
-                       if (size < env->me_mapsize) {
-                               /* If the configured size is smaller, make sure it's
-                                * still big enough. Silently round up to minimum if not.
-                                */
-                               size_t minsize = (env->me_metas[mdb_env_pick_meta(env)]->mm_last_pg + 1) * env->me_psize;
-                               if (size < minsize)
-                                       size = minsize;
-                       }
-                       /* nothing actually changed */
-                       if (size == env->me_mapsize)
-                               return MDB_SUCCESS;
-                       change = 1;
+               else if (size < env->me_mapsize) {
+                       /* If the configured size is smaller, make sure it's
+                        * still big enough. Silently round up to minimum if not.
+                        */
+                       size_t minsize = (env->me_metas[mdb_env_pick_meta(env)]->mm_last_pg + 1) * env->me_psize;
+                       if (size < minsize)
+                               size = minsize;
                }
                munmap(env->me_map, env->me_mapsize);
                env->me_mapsize = size;
@@ -3753,8 +3730,6 @@ mdb_env_set_mapsize(MDB_env *env, size_t size)
                rc = mdb_env_map(env, old);
                if (rc)
                        return rc;
-               if (change)
-                       env->me_flags |= MDB_RESIZING;
        }
        env->me_mapsize = size;
        if (env->me_psize)
@@ -3827,20 +3802,16 @@ mdb_env_open2(MDB_env *env)
                 * else use the size recorded in the existing env.
                 */
                env->me_mapsize = newenv ? DEFAULT_MAPSIZE : meta.mm_mapsize;
-       } else {
-               if (env->me_mapsize < meta.mm_mapsize) {
-                       /* If the configured size is smaller, make sure it's
-                        * still big enough. Silently round up to minimum if not.
-                        */
-                       size_t minsize = (meta.mm_last_pg + 1) * meta.mm_psize;
-                       if (env->me_mapsize < minsize)
-                               env->me_mapsize = minsize;
-               }
-               if (env->me_mapsize != meta.mm_mapsize)
-                       env->me_flags |= MDB_RESIZING;
+       } else if (env->me_mapsize < meta.mm_mapsize) {
+               /* If the configured size is smaller, make sure it's
+                * still big enough. Silently round up to minimum if not.
+                */
+               size_t minsize = (meta.mm_last_pg + 1) * meta.mm_psize;
+               if (env->me_mapsize < minsize)
+                       env->me_mapsize = minsize;
        }
 
-       rc = mdb_env_map(env, meta.mm_address);
+       rc = mdb_env_map(env, (flags & MDB_FIXEDMAP) ? meta.mm_address : NULL);
        if (rc)
                return rc;
 
@@ -6988,6 +6959,12 @@ mdb_cursor_count(MDB_cursor *mc, size_t *countp)
        if (mc->mc_txn->mt_flags & MDB_TXN_ERROR)
                return MDB_BAD_TXN;
 
+       if (!(mc->mc_flags & C_INITIALIZED))
+               return EINVAL;
+
+       if (!mc->mc_snum || (mc->mc_flags & C_EOF))
+               return MDB_NOTFOUND;
+
        leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
        if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
                *countp = 1;
@@ -7658,6 +7635,8 @@ mdb_cursor_del0(MDB_cursor *mc)
                                        m3->mc_flags |= C_DEL;
                                        if (m3->mc_ki[mc->mc_top] > ki)
                                                m3->mc_ki[mc->mc_top]--;
+                                       else if (mc->mc_db->md_flags & MDB_DUPSORT)
+                                               m3->mc_xcursor->mx_cursor.mc_flags |= C_EOF;
                                }
                                if (m3->mc_ki[mc->mc_top] >= nkeys) {
                                        rc = mdb_cursor_sibling(m3, 1);
@@ -8434,16 +8413,17 @@ mdb_env_copyfd1(MDB_env *env, HANDLE fd)
 #ifdef _WIN32
        my.mc_mutex = CreateMutex(NULL, FALSE, NULL);
        my.mc_cond = CreateEvent(NULL, FALSE, FALSE, NULL);
-       my.mc_wbuf[0] = _aligned_malloc(MDB_WBUF*2, env->me_psize);
+       my.mc_wbuf[0] = _aligned_malloc(MDB_WBUF*2, env->me_os_psize);
        if (my.mc_wbuf[0] == NULL)
                return errno;
 #else
        pthread_mutex_init(&my.mc_mutex, NULL);
        pthread_cond_init(&my.mc_cond, NULL);
-       rc = posix_memalign((void **)&my.mc_wbuf[0], env->me_psize, MDB_WBUF*2);
+       rc = posix_memalign((void **)&my.mc_wbuf[0], env->me_os_psize, MDB_WBUF*2);
        if (rc)
                return rc;
 #endif
+       memset(my.mc_wbuf[0], 0, MDB_WBUF*2);
        my.mc_wbuf[1] = my.mc_wbuf[0] + MDB_WBUF;
        my.mc_wlen[0] = 0;
        my.mc_wlen[1] = 0;
@@ -8677,6 +8657,7 @@ mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags)
                goto leave;
        }
 
+       if (env->me_psize >= env->me_os_psize) {
 #ifdef O_DIRECT
        /* Set O_DIRECT if the file system supports it */
        if ((rc = fcntl(newfd, F_GETFL)) != -1)
@@ -8689,6 +8670,7 @@ mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags)
                goto leave;
        }
 #endif
+       }
 
        rc = mdb_env_copyfd2(env, newfd, flags);