summaryrefslogtreecommitdiff
path: root/db-4.8.30/test/scr037/ReplicationTest.cs
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
committerJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
commit54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch)
tree18147b92b969d25ffbe61935fb63035cac820dd0 /db-4.8.30/test/scr037/ReplicationTest.cs
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/test/scr037/ReplicationTest.cs')
-rw-r--r--db-4.8.30/test/scr037/ReplicationTest.cs748
1 files changed, 748 insertions, 0 deletions
diff --git a/db-4.8.30/test/scr037/ReplicationTest.cs b/db-4.8.30/test/scr037/ReplicationTest.cs
new file mode 100644
index 0000000..938689b
--- /dev/null
+++ b/db-4.8.30/test/scr037/ReplicationTest.cs
@@ -0,0 +1,748 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class ReplicationTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ private EventWaitHandle clientStartSignal;
+ private EventWaitHandle masterCloseSignal;
+
+ private EventWaitHandle client1StartSignal;
+ private EventWaitHandle client1ReadySignal;
+ private EventWaitHandle client2StartSignal;
+ private EventWaitHandle client2ReadySignal;
+ private EventWaitHandle client3StartSignal;
+ private EventWaitHandle client3ReadySignal;
+ private EventWaitHandle masterLeaveSignal;
+
+ [TestFixtureSetUp]
+ public void SetUp()
+ {
+ testFixtureName = "ReplicationTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ try
+ {
+ Configuration.ClearDir(testFixtureHome);
+ }
+ catch (Exception)
+ {
+ throw new TestException("Please clean the directory");
+ }
+ }
+
+ [Test]
+ public void TestRepMgr()
+ {
+ testName = "TestRepMgr";
+ testHome = testFixtureHome + "/" + testName;
+
+ clientStartSignal = new AutoResetEvent(false);
+ masterCloseSignal = new AutoResetEvent(false);
+
+ Thread thread1 = new Thread(new ThreadStart(Master));
+ Thread thread2 = new Thread(new ThreadStart(Client));
+
+ // Start master thread before client thread.
+ thread1.Start();
+ Thread.Sleep(1000);
+ thread2.Start();
+ thread2.Join();
+ thread1.Join();
+
+ clientStartSignal.Close();
+ masterCloseSignal.Close();
+ }
+
+ public void Master()
+ {
+ string home = testHome + "/Master";
+ string dbName = "rep.db";
+ Configuration.ClearDir(home);
+
+ /*
+ * Configure and open environment with replication
+ * application.
+ */
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 8870);
+ cfg.RepSystemCfg.Priority = 100;
+ cfg.RepSystemCfg.NSites = 2;
+ cfg.RepSystemCfg.BulkTransfer = true;
+ cfg.RepSystemCfg.AckTimeout = 2000;
+ cfg.RepSystemCfg.BulkTransfer = true;
+ cfg.RepSystemCfg.CheckpointDelay = 1500;
+ cfg.RepSystemCfg.Clockskew(102, 100);
+ cfg.RepSystemCfg.ConnectionRetry = 10;
+ cfg.RepSystemCfg.DelayClientSync = false;
+ cfg.RepSystemCfg.ElectionRetry = 5;
+ cfg.RepSystemCfg.ElectionTimeout = 3000;
+ cfg.RepSystemCfg.FullElectionTimeout = 5000;
+ cfg.RepSystemCfg.HeartbeatMonitor = 100;
+ cfg.RepSystemCfg.HeartbeatSend = 10;
+ cfg.RepSystemCfg.LeaseTimeout = 1300;
+ cfg.RepSystemCfg.NoAutoInit = false;
+ cfg.RepSystemCfg.NoBlocking = false;
+ cfg.RepSystemCfg.RepMgrAckPolicy =
+ AckPolicy.ALL_PEERS;
+ cfg.RepSystemCfg.RetransmissionRequest(10, 100);
+ cfg.RepSystemCfg.Strict2Site = true;
+ cfg.RepSystemCfg.UseMasterLeases = false;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+
+ // Get initial replication stats.
+ ReplicationStats repStats = env.ReplicationSystemStats();
+ env.PrintReplicationSystemStats();
+ Assert.AreEqual(100, repStats.EnvPriority);
+ Assert.AreEqual(1,
+ repStats.CurrentElectionGenerationNumber);
+ Assert.AreEqual(0, repStats.CurrentGenerationNumber);
+ Assert.AreEqual(0, repStats.AppliedTransactions);
+
+ // Start a master site with replication manager.
+ env.RepMgrStartMaster(3);
+
+ // Open a btree database and write some data.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.AutoCommit = true;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 512;
+ BTreeDatabase db = BTreeDatabase.Open(dbName,
+ dbConfig);
+ for (int i = 0; i < 5; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+
+ Console.WriteLine(
+ "Master: Finished initialization and data#1.");
+
+ // Client site could enter now.
+ clientStartSignal.Set();
+ Console.WriteLine(
+ "Master: Wait for Client to join and get #1.");
+
+ Console.WriteLine("...");
+
+ // Put some new data into master site.
+ for (int i = 10; i < 15; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+ Console.WriteLine(
+ "Master: Write something new, data #2.");
+ Console.WriteLine("Master: Wait for client to read #2...");
+
+ // Get the stats.
+ repStats = env.ReplicationSystemStats(true);
+ env.PrintReplicationSystemStats();
+ Assert.LessOrEqual(0, repStats.AppliedTransactions);
+ Assert.LessOrEqual(0, repStats.AwaitedLSN.LogFileNumber);
+ Assert.LessOrEqual(0, repStats.AwaitedLSN.Offset);
+ Assert.LessOrEqual(0, repStats.AwaitedPage);
+ Assert.LessOrEqual(0, repStats.BadGenerationMessages);
+ Assert.LessOrEqual(0, repStats.BulkBufferFills);
+ Assert.LessOrEqual(0, repStats.BulkBufferOverflows);
+ Assert.LessOrEqual(0, repStats.BulkBufferTransfers);
+ Assert.LessOrEqual(0, repStats.BulkRecordsStored);
+ Assert.LessOrEqual(0, repStats.ClientServiceRequests);
+ Assert.LessOrEqual(0, repStats.ClientServiceRequestsMissing);
+ Assert.IsInstanceOfType(typeof(bool), repStats.ClientStartupComplete);
+ Assert.AreEqual(2, repStats.CurrentElectionGenerationNumber);
+ Assert.AreEqual(1, repStats.CurrentGenerationNumber);
+ Assert.LessOrEqual(0, repStats.CurrentQueuedLogRecords);
+ Assert.LessOrEqual(0, repStats.CurrentWinner);
+ Assert.LessOrEqual(0, repStats.CurrentWinnerMaxLSN.LogFileNumber);
+ Assert.LessOrEqual(0, repStats.CurrentWinnerMaxLSN.Offset);
+ Assert.LessOrEqual(0, repStats.DuplicateLogRecords);
+ Assert.LessOrEqual(0, repStats.DuplicatePages);
+ Assert.LessOrEqual(0, repStats.DupMasters);
+ Assert.LessOrEqual(0, repStats.ElectionGenerationNumber);
+ Assert.LessOrEqual(0, repStats.ElectionPriority);
+ Assert.LessOrEqual(0, repStats.Elections);
+ Assert.LessOrEqual(0, repStats.ElectionStatus);
+ Assert.LessOrEqual(0, repStats.ElectionsWon);
+ Assert.LessOrEqual(0, repStats.ElectionTiebreaker);
+ Assert.LessOrEqual(0, repStats.ElectionTimeSec);
+ Assert.LessOrEqual(0, repStats.ElectionTimeUSec);
+ Assert.AreEqual(repStats.EnvID, repStats.MasterEnvID);
+ Assert.LessOrEqual(0, repStats.EnvPriority);
+ Assert.LessOrEqual(0, repStats.FailedMessageSends);
+ Assert.LessOrEqual(0, repStats.ForcedRerequests);
+ Assert.LessOrEqual(0, repStats.IgnoredMessages);
+ Assert.LessOrEqual(0, repStats.MasterChanges);
+ Assert.LessOrEqual(0, repStats.MasterEnvID);
+ Assert.LessOrEqual(0, repStats.MaxLeaseSec);
+ Assert.LessOrEqual(0, repStats.MaxLeaseUSec);
+ Assert.LessOrEqual(0, repStats.MaxPermanentLSN.Offset);
+ Assert.LessOrEqual(0, repStats.MaxQueuedLogRecords);
+ Assert.LessOrEqual(0, repStats.MessagesSent);
+ Assert.LessOrEqual(0, repStats.MissedLogRecords);
+ Assert.LessOrEqual(0, repStats.MissedPages);
+ Assert.LessOrEqual(0, repStats.NewSiteMessages);
+ Assert.LessOrEqual(repStats.MaxPermanentLSN.LogFileNumber,
+ repStats.NextLSN.LogFileNumber);
+ if (repStats.MaxPermanentLSN.LogFileNumber ==
+ repStats.NextLSN.LogFileNumber)
+ Assert.Less(repStats.MaxPermanentLSN.Offset,
+ repStats.NextLSN.Offset);
+ Assert.LessOrEqual(0, repStats.NextPage);
+ Assert.LessOrEqual(0, repStats.Outdated);
+ Assert.LessOrEqual(0, repStats.QueuedLogRecords);
+ Assert.LessOrEqual(0, repStats.ReceivedLogRecords);
+ Assert.LessOrEqual(0, repStats.ReceivedMessages);
+ Assert.LessOrEqual(0, repStats.ReceivedPages);
+ Assert.LessOrEqual(0, repStats.RegisteredSites);
+ Assert.LessOrEqual(0, repStats.RegisteredSitesNeeded);
+ Assert.LessOrEqual(0, repStats.Sites);
+ Assert.LessOrEqual(0, repStats.StartSyncMessagesDelayed);
+ Assert.AreEqual(2, repStats.Status);
+ Assert.LessOrEqual(0, repStats.Throttled);
+ Assert.LessOrEqual(0, repStats.Votes);
+
+ // Get replication manager statistics.
+ RepMgrStats repMgrStats = env.RepMgrSystemStats(true);
+ Assert.LessOrEqual(0, repMgrStats.DroppedConnections);
+ Assert.LessOrEqual(0, repMgrStats.DroppedMessages);
+ Assert.LessOrEqual(0, repMgrStats.FailedConnections);
+ Assert.LessOrEqual(0, repMgrStats.FailedMessages);
+ Assert.LessOrEqual(0, repMgrStats.QueuedMessages);
+
+ // Print them out.
+ env.PrintRepMgrSystemStats();
+
+ // Wait until client has finished reading.
+ masterCloseSignal.WaitOne();
+ Console.WriteLine("Master: Leave as well.");
+
+ // Close all.
+ db.Close(false);
+ env.LogFlush();
+ env.Close();
+ }
+
+ public void Client()
+ {
+ string home = testHome + "/Client";
+ Configuration.ClearDir(home);
+
+ clientStartSignal.WaitOne();
+ Console.WriteLine("Client: Join the replication");
+
+ // Open a environment.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.LockTimeout = 50000;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 6870);
+ cfg.RepSystemCfg.Priority = 10;
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 8870), false);
+ cfg.RepSystemCfg.NSites = 2;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+
+ // Start a client site with replication manager.
+ env.RepMgrStartClient(3, false);
+
+ // Leave enough time to sync.
+ Thread.Sleep(20000);
+
+ // Open database.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.NEVER;
+ dbConfig.AutoCommit = true;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 512;
+ BTreeDatabase db = BTreeDatabase.Open("rep.db",
+ dbConfig);
+
+ // Write data into database.
+ Console.WriteLine("Client: Start reading data #1.");
+ for (int i = 0; i < 5; i++)
+ db.GetBoth(new DatabaseEntry(
+ BitConverter.GetBytes(i)), new DatabaseEntry(
+ BitConverter.GetBytes(i)));
+
+ // Leave sometime for client to read new data from master.
+ Thread.Sleep(20000);
+
+ /*
+ * Read the data. All data exists in master site should
+ * appear in the client site.
+ */
+ Console.WriteLine("Client: Start reading data #2.");
+ for (int i = 10; i < 15; i++)
+ db.GetBoth(new DatabaseEntry(
+ BitConverter.GetBytes(i)), new DatabaseEntry(
+ BitConverter.GetBytes(i)));
+
+ // Get the latest replication subsystem statistics.
+ ReplicationStats repStats = env.ReplicationSystemStats();
+ Assert.IsTrue(repStats.ClientStartupComplete);
+ Assert.AreEqual(1, repStats.DuplicateLogRecords);
+ Assert.LessOrEqual(0, repStats.EnvID);
+ Assert.LessOrEqual(0, repStats.NextPage);
+ Assert.LessOrEqual(0, repStats.ReceivedPages);
+ Assert.AreEqual(1, repStats.Status);
+
+ // Close all.
+ db.Close(false);
+ env.LogFlush();
+ env.Close();
+ Console.WriteLine(
+ "Client: All data is read. Leaving the replication");
+
+ // The master is closed after client's close.
+ masterCloseSignal.Set();
+ }
+
+ private void stuffHappened(NotificationEvent eventCode, byte[] info)
+ {
+ switch (eventCode)
+ {
+ case NotificationEvent.REP_CLIENT:
+ Console.WriteLine("CLIENT");
+ break;
+ case NotificationEvent.REP_MASTER:
+ Console.WriteLine("MASTER");
+ break;
+ case NotificationEvent.REP_NEWMASTER:
+ Console.WriteLine("NEWMASTER");
+ break;
+ case NotificationEvent.REP_STARTUPDONE:
+ /* We don't care about these */
+ break;
+ case NotificationEvent.REP_PERM_FAILED:
+ Console.WriteLine("Insufficient Acks.");
+ break;
+ default:
+ Console.WriteLine("Event: {0}", eventCode);
+ break;
+ }
+ }
+
+ [Test]
+ public void TestElection()
+ {
+ testName = "TestElection";
+ testHome = testFixtureHome + "/" + testName;
+
+ client1StartSignal = new AutoResetEvent(false);
+ client2StartSignal = new AutoResetEvent(false);
+ client1ReadySignal = new AutoResetEvent(false);
+ client2ReadySignal = new AutoResetEvent(false);
+ client3StartSignal = new AutoResetEvent(false);
+ client3ReadySignal = new AutoResetEvent(false);
+ masterLeaveSignal = new AutoResetEvent(false);
+
+ Thread thread1 = new Thread(
+ new ThreadStart(UnstableMaster));
+ Thread thread2 = new Thread(
+ new ThreadStart(StableClient1));
+ Thread thread3 = new Thread(
+ new ThreadStart(StableClient2));
+ Thread thread4 = new Thread(
+ new ThreadStart(StableClient3));
+
+ thread1.Start();
+ Thread.Sleep(1000);
+ thread2.Start();
+ thread3.Start();
+ thread4.Start();
+
+ thread4.Join();
+ thread3.Join();
+ thread2.Join();
+ thread1.Join();
+
+ client1StartSignal.Close();
+ client2StartSignal.Close();
+ client1ReadySignal.Close();
+ client2ReadySignal.Close();
+ client3ReadySignal.Close();
+ client3StartSignal.Close();
+ masterLeaveSignal.Close();
+ }
+
+ public void UnstableMaster()
+ {
+ string home = testHome + "/UnstableMaster";
+ Configuration.ClearDir(home);
+
+ // Open environment with replication configuration.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 8888);
+ cfg.RepSystemCfg.Priority = 200;
+ cfg.RepSystemCfg.NSites = 4;
+ cfg.RepSystemCfg.ElectionRetry = 10;
+ cfg.RepSystemCfg.RepMgrAckPolicy = AckPolicy.ALL;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+ env.DeadlockResolution = DeadlockPolicy.DEFAULT;
+
+ // Start as master site.
+ env.RepMgrStartMaster(3);
+
+ Console.WriteLine("Master: Finish initialization");
+
+ // Notify clients to join.
+ client1StartSignal.Set();
+ client2StartSignal.Set();
+ client3StartSignal.Set();
+
+ // Wait for initialization of all clients.
+ client1ReadySignal.WaitOne();
+ client2ReadySignal.WaitOne();
+ client3ReadySignal.WaitOne();
+
+ List<uint> ports = new List<uint>();
+ ports.Add(5888);
+ ports.Add(6888);
+ ports.Add(7888);
+ foreach (RepMgrSite site in env.RepMgrRemoteSites)
+ {
+ Assert.AreEqual("127.0.0.1", site.Address.Host);
+ Assert.IsTrue(ports.Contains(site.Address.Port));
+ Assert.Greater(4, site.EId);
+ Assert.IsTrue(site.isConnected);
+ }
+
+ // After all of them are ready, close the current master.
+ Console.WriteLine("Master: Unexpected leave.");
+ env.LogFlush();
+ env.Close();
+ masterLeaveSignal.Set();
+ }
+
+ public void StableClient1()
+ {
+ string home = testHome + "/StableClient1";
+ Configuration.ClearDir(home);
+
+ // Get notification from master and start the #1 client.
+ client1StartSignal.WaitOne();
+ Console.WriteLine("Client1: Join the replication");
+
+ // Open the environment.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.LockTimeout = 50000;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 7888);
+ cfg.RepSystemCfg.Priority = 10;
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 8888), false);
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 5888), true);
+ cfg.RepSystemCfg.NSites = 4;
+ cfg.RepSystemCfg.ElectionRetry = 10;
+ cfg.RepSystemCfg.RepMgrAckPolicy = AckPolicy.NONE;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+ env.DeadlockResolution = DeadlockPolicy.DEFAULT;
+
+ // Start the client who won't raise any election.
+ env.RepMgrStartClient(3, false);
+
+ // Leave enough time to sync.
+ Thread.Sleep(20000);
+
+ // The current client site is fully initialized.
+ client1ReadySignal.Set();
+
+ // Wait for master's leave signal.
+ masterLeaveSignal.WaitOne();
+
+ /*
+ * Set the master's leave signal so that other clients
+ * could be informed.
+ */
+ masterLeaveSignal.Set();
+
+ // Leave sometime for client to hold election.
+ Thread.Sleep(10000);
+
+ env.LogFlush();
+ env.Close();
+ Console.WriteLine("Client1: Leaving the replication");
+ }
+
+
+ public void StableClient2()
+ {
+ string home = testHome + "/StableClient2";
+ Configuration.ClearDir(home);
+
+ client2StartSignal.WaitOne();
+ Console.WriteLine("Client2: Join the replication");
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.LockTimeout = 50000;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 6888);
+ cfg.RepSystemCfg.Priority = 20;
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 8888), false);
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 7888), true);
+ cfg.RepSystemCfg.NSites = 4;
+ cfg.RepSystemCfg.ElectionRetry = 10;
+ cfg.RepSystemCfg.RepMgrAckPolicy =
+ AckPolicy.ONE_PEER;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+ env.DeadlockResolution = DeadlockPolicy.DEFAULT;
+
+ // Start the client who will raise election if no master.
+ env.RepMgrStartClient(3, true);
+
+ // Leave enough time to sync.
+ Thread.Sleep(20000);
+
+ // The current client site is fully initialized.
+ client2ReadySignal.Set();
+
+ // Wait for master's leave signal.
+ masterLeaveSignal.WaitOne();
+
+ /*
+ * Set the master's leave signal so that other clients
+ * could be informed.
+ */
+ masterLeaveSignal.Set();
+
+ // Leave sometime for client to hold election.
+ Thread.Sleep(5000);
+
+ env.LogFlush();
+ env.Close();
+ Console.WriteLine("Client2: Leaving the replication");
+ }
+
+ public void StableClient3()
+ {
+ string home = testHome + "/StableClient3";
+ Configuration.ClearDir(home);
+
+ client3StartSignal.WaitOne();
+ Console.WriteLine("Client3: Join the replication");
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.LockTimeout = 50000;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 5888);
+ cfg.RepSystemCfg.Priority = 80;
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 8888), false);
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 6888), true);
+ cfg.RepSystemCfg.NSites = 4;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ cfg.RepSystemCfg.ElectionRetry = 10;
+ cfg.RepSystemCfg.RepMgrAckPolicy = AckPolicy.QUORUM;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+ env.DeadlockResolution = DeadlockPolicy.DEFAULT;
+
+ env.RepMgrStartClient(3, false);
+
+ // Leave enough time to sync with master.
+ Thread.Sleep(20000);
+
+ // The current client site is fully initialized.
+ client3ReadySignal.Set();
+
+ // Wait for master's leave signal.
+ masterLeaveSignal.WaitOne();
+
+ /*
+ * Set the master's leave signal so that other clients
+ * could be informed.
+ */
+ masterLeaveSignal.Set();
+
+ /*
+ * Master will leave the replication after all clients'
+ * initialization. Leave sometime for master to leave
+ * and for clients elect.
+ */
+ Thread.Sleep(5000);
+
+ ReplicationStats repStats = env.ReplicationSystemStats();
+ Assert.LessOrEqual(0, repStats.Elections);
+ Assert.LessOrEqual(0, repStats.ElectionTiebreaker);
+ Assert.LessOrEqual(0,
+ repStats.ElectionTimeSec + repStats.ElectionTimeUSec);
+ Assert.LessOrEqual(0, repStats.MasterChanges);
+ Assert.LessOrEqual(0, repStats.NewSiteMessages);
+ Assert.LessOrEqual(0, repStats.ReceivedLogRecords);
+ Assert.LessOrEqual(0, repStats.ReceivedMessages);
+ Assert.LessOrEqual(0, repStats.ReceivedPages);
+ Assert.GreaterOrEqual(4, repStats.RegisteredSitesNeeded);
+ Assert.LessOrEqual(0, repStats.Sites);
+
+ /*
+ * Client 3 will be the new master. The Elected master should wait
+ * until all other clients leave.
+ */
+ Thread.Sleep(10000);
+
+ env.LogFlush();
+ env.Close();
+ Console.WriteLine("Client3: Leaving the replication");
+ }
+
+ [Test]
+ public void TestAckPolicy()
+ {
+ testName = "TestAckPolicy";
+ testHome = testFixtureHome + "/" + testName;
+
+ SetRepMgrAckPolicy(testHome + "_ALL", AckPolicy.ALL);
+ SetRepMgrAckPolicy(testHome + "_ALL_PEERS",
+ AckPolicy.ALL_PEERS);
+ SetRepMgrAckPolicy(testHome + "_NONE",
+ AckPolicy.NONE);
+ SetRepMgrAckPolicy(testHome + "_ONE",
+ AckPolicy.ONE);
+ SetRepMgrAckPolicy(testHome + "_ONE_PEER",
+ AckPolicy.ONE_PEER);
+ SetRepMgrAckPolicy(testHome + "_QUORUM",
+ AckPolicy.QUORUM);
+ SetRepMgrAckPolicy(testHome + "_NULL", null);
+ }
+
+ public void SetRepMgrAckPolicy(string home, AckPolicy policy)
+ {
+ Configuration.ClearDir(home);
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLocking = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseReplication = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+ if (policy != null)
+ {
+ env.RepMgrAckPolicy = policy;
+ Assert.AreEqual(policy, env.RepMgrAckPolicy);
+ }
+ env.Close();
+ }
+ }
+}