]> 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>
Sat, 10 Oct 2020 12:04:50 +0000 (13:04 +0100)
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 3a6be034a4a0f1b15957476868fd80a7e297e4d9..f9f847f1ce300119697996c74bb8702f79da9082 100644 (file)
@@ -354,8 +354,8 @@ typedef void (MDB_enc_func)(const MDB_val *src, MDB_val *dst, const MDB_val *key
 #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
        /** don't use a single mmap, remap individual chunks (needs MDB_RPAGE_CACHE) */
 #define MDB_REMAP_CHUNKS       0x4000000
 /** @} */
@@ -672,10 +672,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 217e2038397e1527a53e226a345dd1d7cbc4f629..4b774588067742d2a5b5625920223a65b530b766 100644 (file)
@@ -4047,6 +4047,8 @@ done:
        return MDB_SUCCESS;
 }
 
+static int ESECT mdb_env_share_locks(MDB_env *env, int *excl);
+
 int
 mdb_txn_commit(MDB_txn *txn)
 {
@@ -4274,6 +4276,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);
@@ -4564,7 +4575,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
@@ -5139,6 +5151,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);
@@ -5238,9 +5253,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
        {
@@ -5684,7 +5696,7 @@ mdb_env_envflags(MDB_env *env)
                /*f*/ MDB_FIXEDMAP, /*h*/ MDB_NORDAHEAD,    /*i*/ MDB_NOMEMINIT,
                /*l*/ MDB_NOLOCK,   /*m*/ MDB_NOMETASYNC,   /*n*/ MDB_NOSUBDIR,
                /*r*/ MDB_RDONLY,   /*s*/ MDB_NOSYNC,       /*t*/ MDB_NOTLS,
-               /*v*/ MDB_PREVMETA, /*w*/ MDB_WRITEMAP,
+               /*v*/ MDB_PREVSNAPSHOT, /*w*/ MDB_WRITEMAP,
        };
        unsigned flags = 0;
        const char *s, *opts = getenv("LMDB_FLAGS");
@@ -5724,7 +5736,7 @@ mdb_env_envflags(MDB_env *env)
         */
 #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_REMAP_CHUNKS)
+       MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD|MDB_PREVSNAPSHOT|MDB_REMAP_CHUNKS)
 #define EXPOSED                (CHANGEABLE|CHANGELESS | MDB_ENCRYPT)
 
 #if VALID_FLAGS & PERSISTENT_FLAGS & EXPOSED
@@ -5823,6 +5835,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,
@@ -5837,7 +5853,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.
@@ -5847,7 +5863,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 f156a545bdba8909e9149821a4f64dc742d53fff..fd7268dc4d8853a49699a098a26aeb71636e5b48 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 05402bc18d5d143e4da6e1eb1e4b0e72a3f16864..77c2a5a3583b6294d8942846223458c5461de7b3 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 15145b8456050d49c32a9cb7ff9d2528b425cd13..c67ed6021adc93c83740dee02d4d17f132c10cf1 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++;