1edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep"""TestCases for distributed transactions.
2edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep"""
3edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
4edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport os
5edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport unittest
6edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
7edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom test_all import db, test_support, get_new_environment_path, \
8edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        get_new_database_path
9edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
10edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom test_all import verbose
11edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
12edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#----------------------------------------------------------------------
13edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
14edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass DBTxn_distributed(unittest.TestCase):
15edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    num_txns=1234
16edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    nosync=True
17edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    must_open_db=False
18edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def _create_env(self, must_open_db) :
19edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.dbenv = db.DBEnv()
20edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.dbenv.set_tx_max(self.num_txns)
21edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.dbenv.set_lk_max_lockers(self.num_txns*2)
22edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.dbenv.set_lk_max_locks(self.num_txns*2)
23edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.dbenv.set_lk_max_objects(self.num_txns*2)
24edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if self.nosync :
25edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.dbenv.set_flags(db.DB_TXN_NOSYNC,True)
26edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.dbenv.open(self.homeDir, db.DB_CREATE | db.DB_THREAD |
27edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                db.DB_RECOVER |
28edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                db.DB_INIT_TXN | db.DB_INIT_LOG | db.DB_INIT_MPOOL |
29edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                db.DB_INIT_LOCK, 0666)
30edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.db = db.DB(self.dbenv)
31edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.db.set_re_len(db.DB_GID_SIZE)
32edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if must_open_db :
33edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            txn=self.dbenv.txn_begin()
34edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.db.open(self.filename,
35edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                    db.DB_QUEUE, db.DB_CREATE | db.DB_THREAD, 0666,
36edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                    txn=txn)
37edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            txn.commit()
38edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
39edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def setUp(self) :
40edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.homeDir = get_new_environment_path()
41edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.filename = "test"
42edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return self._create_env(must_open_db=True)
43edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
44edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def _destroy_env(self):
45edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if self.nosync or (db.version()[:2] == (4,6)):  # Known bug
46edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.dbenv.log_flush()
47edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.db.close()
48edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.dbenv.close()
49edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
50edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def tearDown(self):
51edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._destroy_env()
52edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        test_support.rmtree(self.homeDir)
53edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
54edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def _recreate_env(self,must_open_db) :
55edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._destroy_env()
56edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._create_env(must_open_db)
57edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
58edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def test01_distributed_transactions(self) :
59edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        txns=set()
60edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        adapt = lambda x : x
61edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        import sys
62edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if sys.version_info[0] >= 3 :
63edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            adapt = lambda x : bytes(x, "ascii")
64edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # Create transactions, "prepare" them, and
65edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # let them be garbage collected.
66edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        for i in xrange(self.num_txns) :
67edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            txn = self.dbenv.txn_begin()
68edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            gid = "%%%dd" %db.DB_GID_SIZE
69edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            gid = adapt(gid %i)
70edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.db.put(i, gid, txn=txn, flags=db.DB_APPEND)
71edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            txns.add(gid)
72edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            txn.prepare(gid)
73edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        del txn
74edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
75edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._recreate_env(self.must_open_db)
76edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
77edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # Get "to be recovered" transactions but
78edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # let them be garbage collected.
79edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        recovered_txns=self.dbenv.txn_recover()
80edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.assertEqual(self.num_txns,len(recovered_txns))
81edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        for gid,txn in recovered_txns :
82edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.assertTrue(gid in txns)
83edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        del txn
84edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        del recovered_txns
85edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
86edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._recreate_env(self.must_open_db)
87edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
88edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # Get "to be recovered" transactions. Commit, abort and
89edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # discard them.
90edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        recovered_txns=self.dbenv.txn_recover()
91edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.assertEqual(self.num_txns,len(recovered_txns))
92edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        discard_txns=set()
93edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        committed_txns=set()
94edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        state=0
95edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        for gid,txn in recovered_txns :
96edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            if state==0 or state==1:
97edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                committed_txns.add(gid)
98edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                txn.commit()
99edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            elif state==2 :
100edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                txn.abort()
101edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            elif state==3 :
102edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                txn.discard()
103edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                discard_txns.add(gid)
104edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                state=-1
105edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            state+=1
106edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        del txn
107edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        del recovered_txns
108edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
109edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._recreate_env(self.must_open_db)
110edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
111edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # Verify the discarded transactions are still
112edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # around, and dispose them.
113edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        recovered_txns=self.dbenv.txn_recover()
114edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.assertEqual(len(discard_txns),len(recovered_txns))
115edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        for gid,txn in recovered_txns :
116edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            txn.abort()
117edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        del txn
118edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        del recovered_txns
119edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
120edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._recreate_env(must_open_db=True)
121edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
122edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # Be sure there are not pending transactions.
123edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # Check also database size.
124edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        recovered_txns=self.dbenv.txn_recover()
125edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.assertTrue(len(recovered_txns)==0)
126edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.assertEqual(len(committed_txns),self.db.stat()["nkeys"])
127edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
128edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass DBTxn_distributedSYNC(DBTxn_distributed):
129edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    nosync=False
130edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
131edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass DBTxn_distributed_must_open_db(DBTxn_distributed):
132edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    must_open_db=True
133edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
134edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass DBTxn_distributedSYNC_must_open_db(DBTxn_distributed):
135edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    nosync=False
136edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    must_open_db=True
137edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
138edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#----------------------------------------------------------------------
139edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
140edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef test_suite():
141edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    suite = unittest.TestSuite()
142edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if db.version() >= (4,5) :
143edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        suite.addTest(unittest.makeSuite(DBTxn_distributed))
144edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        suite.addTest(unittest.makeSuite(DBTxn_distributedSYNC))
145edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if db.version() >= (4,6) :
146edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        suite.addTest(unittest.makeSuite(DBTxn_distributed_must_open_db))
147edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        suite.addTest(unittest.makeSuite(DBTxn_distributedSYNC_must_open_db))
148edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return suite
149edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
150edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
151edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepif __name__ == '__main__':
152edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    unittest.main(defaultTest='test_suite')
153