public void MoveWithRMW(string home, string name) { paramEnv = null; paramDB = null; // Open the environment. DatabaseEnvironmentConfig envCfg = new DatabaseEnvironmentConfig(); envCfg.Create = true; envCfg.FreeThreaded = true; envCfg.UseLocking = true; envCfg.UseLogging = true; envCfg.UseMPool = true; envCfg.UseTxns = true; paramEnv = DatabaseEnvironment.Open(home, envCfg); // Open database in transaction. Transaction openTxn = paramEnv.BeginTransaction(); BTreeDatabaseConfig cfg = new BTreeDatabaseConfig(); cfg.Creation = CreatePolicy.ALWAYS; cfg.Env = paramEnv; cfg.FreeThreaded = true; cfg.PageSize = 4096; // Use record number. cfg.UseRecordNumbers = true; paramDB = BTreeDatabase.Open(name + ".db", cfg, openTxn); openTxn.Commit(); /* * Put 10 different, 2 duplicate and another different * records into database. */ Transaction txn = paramEnv.BeginTransaction(); for (int i = 0; i < 13; i++) { DatabaseEntry key, data; if (i == 10 || i == 11) { key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")); data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")); } else { key = new DatabaseEntry(BitConverter.GetBytes(i)); data = new DatabaseEntry(BitConverter.GetBytes(i)); } paramDB.Put(key, data, txn); } txn.Commit(); // Get a event wait handle. signal = new EventWaitHandle(false, EventResetMode.ManualReset); /* * Start RdMfWt() in two threads. RdMfWt() reads * and writes data into database. */ Thread t1 = new Thread(new ThreadStart(RdMfWt)); Thread t2 = new Thread(new ThreadStart(RdMfWt)); t1.Start(); t2.Start(); // Give both threads time to read before signalling them to write. Thread.Sleep(1000); // Invoke the write operation in both threads. signal.Set(); // Return the number of deadlocks. while (t1.IsAlive || t2.IsAlive) { /* * Give both threads time to write before * counting the number of deadlocks. */ Thread.Sleep(1000); uint deadlocks = paramEnv.DetectDeadlocks(DeadlockPolicy.DEFAULT); // Confirm that there won't be any deadlock. Assert.AreEqual(0, deadlocks); } t1.Join(); t2.Join(); paramDB.Close(); paramEnv.Close(); }
public void TestSnapshotIsolation() { BTreeDatabaseConfig dbConfig; DatabaseEntry key, data; DatabaseEnvironmentConfig envConfig; Thread readThread, updateThread; Transaction txn; updateTxn = null; readTxn = null; paramDB = null; paramEnv = null; testName = "TestSnapshotIsolation"; testHome = testFixtureHome + "/" + testName; Configuration.ClearDir(testHome); /* * Open environment with DB_MULTIVERSION * which is required by DB_TXN_SNAPSHOT. */ envConfig = new DatabaseEnvironmentConfig(); envConfig.Create = true; envConfig.UseMVCC = true; envConfig.UseTxns = true; envConfig.UseMPool = true; envConfig.UseLocking = true; envConfig.TxnTimeout = 1000; paramEnv = DatabaseEnvironment.Open( testHome, envConfig); paramEnv.DetectDeadlocks(DeadlockPolicy.YOUNGEST); /* * Open a transactional database and put 1000 records * into it within transaction. */ txn = paramEnv.BeginTransaction(); dbConfig = new BTreeDatabaseConfig(); dbConfig.Creation = CreatePolicy.IF_NEEDED; dbConfig.UseMVCC = true; dbConfig.Env = paramEnv; paramDB = BTreeDatabase.Open( testName + ".db", dbConfig, txn); for (int i = 0; i < 256; i++) { key = new DatabaseEntry( BitConverter.GetBytes(i)); data = new DatabaseEntry( BitConverter.GetBytes(i)); paramDB.Put(key, data, txn); } txn.Commit(); /* * Begin two threads, read and update thread. * The update thread runs a update transaction * using full read/write locking. The read thread * set DB_TXN_SNAPSHOT on read-only cursor. */ readThread = new Thread(new ThreadStart(ReadTxn)); updateThread = new Thread(new ThreadStart(UpdateTxn)); updateThread.Start(); Thread.Sleep(1000); readThread.Start(); readThread.Join(); updateThread.Join(); // Commit transacion in both two threads. if (updateTxn != null) { updateTxn.Commit(); } if (readTxn != null) { readTxn.Commit(); } /* * Confirm that the overwrite operation works. */ ConfirmOverwrite(); paramDB.Close(); paramEnv.Close(); }