]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#8704 Fix PREVMETA, rename to PREVSNAPSHOT
authorHoward Chu <hyc@openldap.org>
Sat, 12 Aug 2017 10:16:45 +0000 (11:16 +0100)
committerHoward Chu <hyc@openldap.org>
Thu, 17 Jan 2019 19:02:39 +0000 (19:02 +0000)
and enforce exclusive access to environment. Also fix txn_begin/pick_meta
to use correct meta page, and reset the flag after successful commit.

libraries/liblmdb/lmdb.h
libraries/liblmdb/mdb.c
libraries/liblmdb/mdb_copy.c
libraries/liblmdb/mdb_dump.c
libraries/liblmdb/mdb_stat.c

index 9e51b551755f1779befa79f6252ec87ba5ac6582..1f4736ce2be743100b8a53dba02dbe66391942f1 100644 (file)
@@ -332,8 +332,8 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
 #define MDB_NORDAHEAD  0x800000
        /** don't initialize malloc'd memory before writing to datafile */
 #define MDB_NOMEMINIT  0x1000000
-       /** use the previous meta page rather than the latest one */
-#define MDB_PREVMETA   0x2000000
+       /** use the previous snapshot rather than the latest one */
+#define MDB_PREVSNAPSHOT       0x2000000
 /** @} */
 
 /**    @defgroup       mdb_dbi_open    Database Flags
@@ -648,10 +648,12 @@ int  mdb_env_create(MDB_env **env);
         *              caller is expected to overwrite all of the memory that was
         *              reserved in that case.
         *              This flag may be changed at any time using #mdb_env_set_flags().
-        *      <li>#MDB_PREVMETA
-        *              Open the environment with the previous meta page rather than the latest
+        *      <li>#MDB_PREVSNAPSHOT
+        *              Open the environment with the previous snapshot rather than the latest
         *              one. This loses the latest transaction, but may help work around some
-        *              types of corruption.
+        *              types of corruption. If opened with write access, this must be the
+        *              only process using the environment. This flag is automatically reset
+        *              after a write transaction is successfully committed.
         * </ul>
         * @param[in] mode The UNIX permissions to set on created files and semaphores.
         * This parameter is ignored on Windows.
index 433fe505574f258f37fda68e7024c194b40bb6fb..fb57a72a33cf17802e3e1bcc6c665bf4fc7e2f2f 100644 (file)
@@ -3793,6 +3793,8 @@ done:
        return MDB_SUCCESS;
 }
 
+static int ESECT mdb_env_share_locks(MDB_env *env, int *excl);
+
 int
 mdb_txn_commit(MDB_txn *txn)
 {
@@ -4015,6 +4017,15 @@ mdb_txn_commit(MDB_txn *txn)
        if ((rc = mdb_env_write_meta(txn)))
                goto fail;
        end_mode = MDB_END_COMMITTED|MDB_END_UPDATE;
+       if (env->me_flags & MDB_PREVSNAPSHOT) {
+               if (!(env->me_flags & MDB_NOLOCK)) {
+                       int excl;
+                       rc = mdb_env_share_locks(env, &excl);
+                       if (rc)
+                               goto fail;
+               }
+               env->me_flags ^= MDB_PREVSNAPSHOT;
+       }
 
 done:
        mdb_txn_end(txn, end_mode);
@@ -4296,7 +4307,8 @@ static MDB_meta *
 mdb_env_pick_meta(const MDB_env *env)
 {
        MDB_meta *const *metas = env->me_metas;
-       return metas[ metas[0]->mm_txnid < metas[1]->mm_txnid ];
+       return metas[ (metas[0]->mm_txnid < metas[1]->mm_txnid) ^
+               ((env->me_flags & MDB_PREVSNAPSHOT) != 0) ];
 }
 
 int ESECT
@@ -4868,6 +4880,9 @@ mdb_env_open2(MDB_env *env, int prev)
 #endif
        env->me_maxpg = env->me_mapsize / env->me_psize;
 
+       if (env->me_txns)
+               env->me_txns->mti_txnid = meta.mm_txnid;
+
 #if MDB_DEBUG
        {
                MDB_meta *meta = mdb_env_pick_meta(env);
@@ -4967,9 +4982,6 @@ static int ESECT
 mdb_env_share_locks(MDB_env *env, int *excl)
 {
        int rc = 0;
-       MDB_meta *meta = mdb_env_pick_meta(env);
-
-       env->me_txns->mti_txnid = meta->mm_txnid;
 
 #ifdef _WIN32
        {
@@ -5391,7 +5403,7 @@ fail:
         */
 #define        CHANGEABLE      (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT)
 #define        CHANGELESS      (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY| \
-       MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD|MDB_PREVMETA)
+       MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD|MDB_PREVSNAPSHOT)
 
 #if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS)
 # error "Persistent DB flags & env flags overlap, but both go in mm_flags"
@@ -5477,6 +5489,10 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
                rc = mdb_env_setup_locks(env, &fname, mode, &excl);
                if (rc)
                        goto leave;
+               if ((flags & MDB_PREVSNAPSHOT) && !excl) {
+                       rc = EAGAIN;
+                       goto leave;
+               }
        }
 
        rc = mdb_fopen(env, &fname,
@@ -5491,7 +5507,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
                        goto leave;
        }
 
-       if ((rc = mdb_env_open2(env, flags & MDB_PREVMETA)) == MDB_SUCCESS) {
+       if ((rc = mdb_env_open2(env, flags & MDB_PREVSNAPSHOT)) == MDB_SUCCESS) {
                if (!(flags & (MDB_RDONLY|MDB_WRITEMAP))) {
                        /* Synchronous fd for meta writes. Needed even with
                         * MDB_NOSYNC/MDB_NOMETASYNC, in case these get reset.
@@ -5501,7 +5517,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
                                goto leave;
                }
                DPRINTF(("opened dbenv %p", (void *) env));
-               if (excl > 0) {
+               if (excl > 0 && !(flags & MDB_PREVSNAPSHOT)) {
                        rc = mdb_env_share_locks(env, &excl);
                        if (rc)
                                goto leave;
index 98df57aedc7adc048f8393081a084376326d0979..23be815062164404e57a0b8bf597c7d2b5e671f1 100644 (file)
@@ -39,7 +39,7 @@ int main(int argc,char * argv[])
                if (argv[1][1] == 'n' && argv[1][2] == '\0')
                        flags |= MDB_NOSUBDIR;
                else if (argv[1][1] == 'v' && argv[1][2] == '\0')
-                       flags |= MDB_PREVMETA;
+                       flags |= MDB_PREVSNAPSHOT;
                else if (argv[1][1] == 'c' && argv[1][2] == '\0')
                        cpflags |= MDB_CP_COMPACT;
                else if (argv[1][1] == 'V' && argv[1][2] == '\0') {
index 8ba688d922872d5bf7925931df82a484f53be321..b7737f12de16e9d1e8edd068ad1518cc7522633d 100644 (file)
@@ -175,7 +175,7 @@ int main(int argc, char *argv[])
         * -n: use NOSUBDIR flag on env_open
         * -p: use printable characters
         * -f: write to file instead of stdout
-        * -v: use previous metapage
+        * -v: use previous snapshot
         * -V: print version and exit
         * (default) dump only the main DB
         */
@@ -204,7 +204,7 @@ int main(int argc, char *argv[])
                        envflags |= MDB_NOSUBDIR;
                        break;
                case 'v':
-                       envflags |= MDB_PREVMETA;
+                       envflags |= MDB_PREVSNAPSHOT;
                        break;
                case 'p':
                        mode |= PRINT;
index 1ec1042170c6182d02f7087d016715ebfe39e0da..08f30befd6606cf77880c421dc0a322d608d03db 100644 (file)
@@ -61,7 +61,7 @@ int main(int argc, char *argv[])
         * -f: print freelist info
         * -r: print reader info
         * -n: use NOSUBDIR flag on env_open
-        * -v: use previous metapage
+        * -v: use previous snapshot
         * -V: print version and exit
         * (default) print stat of only the main DB
         */
@@ -86,7 +86,7 @@ int main(int argc, char *argv[])
                        envflags |= MDB_NOSUBDIR;
                        break;
                case 'v':
-                       envflags |= MDB_PREVMETA;
+                       envflags |= MDB_PREVSNAPSHOT;
                        break;
                case 'r':
                        rdrinfo++;