]> git.sur5r.net Git - openldap/commitdiff
libmdb: Do not use the MDB_txbody.mtb_txnid field.
authorHallvard Furuseth <hallvard@openldap.org>
Thu, 12 Apr 2012 05:34:13 +0000 (07:34 +0200)
committerHallvard Furuseth <hallvard@openldap.org>
Thu, 12 Apr 2012 06:15:33 +0000 (08:15 +0200)
Get txn->mt_txnid from the meta page instead.  Otherwise it
and txn->mt_toggle could become inconsistent, since read-only
txns fetched both from MDB_txbody without mutex proteciton.

libraries/libmdb/mdb.c

index ba6ded3226810a2320d8b3d6ac5680bbfa2d5827..8280e22afbd63d13df0f42903ec7d16b6287e47b 100644 (file)
@@ -511,11 +511,17 @@ typedef struct MDB_txbody {
                 */
        pthread_mutex_t mtb_mutex;
 #endif
+#if MDB_VERSION == 1
                /**     The ID of the last transaction committed to the database.
                 *      This is recorded here only for convenience; the value can always
                 *      be determined by reading the main database meta pages.
+                *
+                *      Value is unused, but maintained for backwards compatibility.
+                *      Drop this or mtb_me_toggle when changing MDB_VERSION.
+                *      (Reading both should have been done atomically.)
                 */
        txnid_t         mtb_txnid;
+#endif
                /** The number of slots that have been used in the reader table.
                 *      This always records the maximum count, it is not decremented
                 *      when readers release their slots.
@@ -536,7 +542,9 @@ typedef struct MDB_txninfo {
 #define mti_version    mt1.mtb.mtb_version
 #define mti_mutex      mt1.mtb.mtb_mutex
 #define mti_rmname     mt1.mtb.mtb_rmname
+#if MDB_VERSION == 1
 #define mti_txnid      mt1.mtb.mtb_txnid
+#endif
 #define mti_numreaders mt1.mtb.mtb_numreaders
 #define mti_me_toggle  mt1.mtb.mtb_me_toggle
                char pad[(sizeof(MDB_txbody)+CACHELINE-1) & ~(CACHELINE-1)];
@@ -1565,18 +1573,19 @@ mdb_txn_renew0(MDB_txn *txn)
                        pthread_setspecific(env->me_txkey, r);
                }
                txn->mt_toggle = env->me_txns->mti_me_toggle;
-               txn->mt_txnid = env->me_txns->mti_txnid;
+               txn->mt_txnid = r->mr_txnid = env->me_metas[txn->mt_toggle]->mm_txnid;
+
                /* This happens if a different process was the
                 * last writer to the DB.
                 */
                if (env->me_wtxnid < txn->mt_txnid)
                        mt_dbflag = DB_STALE;
-               r->mr_txnid = txn->mt_txnid;
                txn->mt_u.reader = r;
        } else {
                LOCK_MUTEX_W(env);
 
-               txn->mt_txnid = env->me_txns->mti_txnid;
+               txn->mt_toggle = env->me_txns->mti_me_toggle;
+               txn->mt_txnid = env->me_metas[txn->mt_toggle]->mm_txnid;
                if (env->me_wtxnid < txn->mt_txnid)
                        mt_dbflag = DB_STALE;
                txn->mt_txnid++;
@@ -1584,7 +1593,6 @@ mdb_txn_renew0(MDB_txn *txn)
                if (txn->mt_txnid == mdb_debug_start)
                        mdb_debug = 1;
 #endif
-               txn->mt_toggle = env->me_txns->mti_me_toggle;
                txn->mt_u.dirty_list = env->me_dirty_list;
                txn->mt_u.dirty_list[0].mid = 0;
                txn->mt_free_pgs = env->me_free_pgs;