public void StartReplication(string sessionId, string[] channels, ReplicatorType replicationType = ReplicatorType.PushAndPull, bool continuous = true) { var targetUrlEndpoint = new URLEndpoint(new Uri(_remoteSyncUrl, _databaseName)); var configuration = new ReplicatorConfiguration(Database, targetUrlEndpoint) { ReplicatorType = replicationType, Continuous = continuous, Authenticator = new SessionAuthenticator(sessionId), Channels = channels }; _replicator = new Replicator(configuration); _replicatorListenerToken = _replicator.AddChangeListener(OnReplicatorUpdate); _replicator.Start(); }
// Two replicators, replicates docs to the listener; validates connection status private void ValidateMultipleReplicationsTo(ReplicatorType replicatorType) { ulong maxConnectionCount = 0UL; ulong maxActiveCount = 0UL; var existingDocsInListener = _listener.Config.Database.Count; existingDocsInListener.Should().Be(1); using (var doc1 = new MutableDocument()) { Db.Save(doc1); } var target = _listener.LocalEndpoint(); var serverCert = _listener.TlsIdentity.Certs[0]; var config1 = CreateConfig(target, replicatorType, true, serverCert: serverCert, sourceDb: Db); var repl1 = new Replicator(config1); Database.Delete("urlepTestDb", Directory); var urlepTestDb = OpenDB("urlepTestDb"); using (var doc2 = new MutableDocument()) { urlepTestDb.Save(doc2); } var config2 = CreateConfig(target, replicatorType, true, serverCert: serverCert, sourceDb: urlepTestDb); var repl2 = new Replicator(config2); var wait1 = new ManualResetEventSlim(); var wait2 = new ManualResetEventSlim(); EventHandler <ReplicatorStatusChangedEventArgs> changeListener = (sender, args) => { maxConnectionCount = Math.Max(maxConnectionCount, _listener.Status.ConnectionCount); maxActiveCount = Math.Max(maxActiveCount, _listener.Status.ActiveConnectionCount); if (args.Status.Activity == ReplicatorActivityLevel.Idle && args.Status.Progress.Completed == args.Status.Progress.Total) { if ((replicatorType == ReplicatorType.PushAndPull && OtherDb.Count == 3 && Db.Count == 3 && urlepTestDb.Count == 3) || (replicatorType == ReplicatorType.Pull && OtherDb.Count == 1 && Db.Count == 2 && urlepTestDb.Count == 2)) { ((Replicator)sender).Stop(); } } else if (args.Status.Activity == ReplicatorActivityLevel.Stopped) { if (sender == repl1) { wait1.Set(); } else { wait2.Set(); } } }; var token1 = repl1.AddChangeListener(changeListener); var token2 = repl2.AddChangeListener(changeListener); repl1.Start(); repl2.Start(); while (repl1.Status.Activity != ReplicatorActivityLevel.Busy || repl2.Status.Activity != ReplicatorActivityLevel.Busy) { Thread.Sleep(100); } // For some reason running on mac throws off the timing enough so that the active connection count // of 1 is never seen. So record the value right after it becomes busy. maxConnectionCount = Math.Max(maxConnectionCount, _listener.Status.ConnectionCount); maxActiveCount = Math.Max(maxActiveCount, _listener.Status.ActiveConnectionCount); WaitHandle.WaitAll(new[] { wait1.WaitHandle, wait2.WaitHandle }, TimeSpan.FromSeconds(30)) .Should().BeTrue(); maxConnectionCount.Should().Be(2); maxActiveCount.Should().Be(2); // all data are transferred to/from if (replicatorType == ReplicatorType.PushAndPull) { _listener.Config.Database.Count.Should().Be(existingDocsInListener + 2UL); Db.Count.Should().Be(existingDocsInListener + 2UL); urlepTestDb.Count.Should().Be(existingDocsInListener + 2UL); } else if (replicatorType == ReplicatorType.Pull) { _listener.Config.Database.Count.Should().Be(1); Db.Count.Should().Be(existingDocsInListener + 1UL); urlepTestDb.Count.Should().Be(existingDocsInListener + 1UL); } repl1.RemoveChangeListener(token1); repl2.RemoveChangeListener(token2); repl1.Dispose(); repl2.Dispose(); wait1.Dispose(); wait2.Dispose(); urlepTestDb.Delete(); _listener.Stop(); Thread.Sleep(500); }
private void RunTwoStepContinuous(ReplicatorType type, string uid) { var listener = new MessageEndpointListener(new MessageEndpointListenerConfiguration(_otherDB, ProtocolType.ByteStream)); var server = new MockServerConnection(listener, ProtocolType.ByteStream); var config = new ReplicatorConfiguration(Db, new MessageEndpoint(uid, server, ProtocolType.ByteStream, new MockConnectionFactory(null))) { ReplicatorType = type, Continuous = true }; var replicator = new Replicator(config); replicator.Start(); Database firstSource = null; Database secondSource = null; Database firstTarget = null; Database secondTarget = null; if (type == ReplicatorType.Push) { firstSource = Db; secondSource = Db; firstTarget = _otherDB; secondTarget = _otherDB; } else if (type == ReplicatorType.Pull) { firstSource = _otherDB; secondSource = _otherDB; firstTarget = Db; secondTarget = Db; } else { firstSource = Db; secondSource = _otherDB; firstTarget = _otherDB; secondTarget = Db; } using (var mdoc = new MutableDocument("livesindb")) { mdoc.SetString("name", "db"); mdoc.SetInt("version", 1); firstSource.Save(mdoc); } var count = 0; while (replicator.Status.Progress.Completed == 0 || replicator.Status.Activity != ReplicatorActivityLevel.Idle) { Thread.Sleep(500); count++; count.Should().BeLessThan(10, "because otherwise the replicator did not advance"); } var previousCompleted = replicator.Status.Progress.Completed; firstTarget.Count.Should().Be(1); using (var savedDoc = secondSource.GetDocument("livesindb")) using (var mdoc = savedDoc.ToMutable()) { mdoc.SetInt("version", 2); secondSource.Save(mdoc); } count = 0; while (replicator.Status.Progress.Completed == previousCompleted || replicator.Status.Activity != ReplicatorActivityLevel.Idle) { Thread.Sleep(500); count++; count.Should().BeLessThan(10, "because otherwise the replicator did not advance"); } using (var savedDoc = secondTarget.GetDocument("livesindb")) { savedDoc.GetInt("version").Should().Be(2); } replicator.Stop(); while (replicator.Status.Activity != ReplicatorActivityLevel.Stopped) { Thread.Sleep(100); } replicator.Dispose(); }
public void Setup(ReplicatorType replicatorType = ReplicatorType.LevelInstance, ReplicatorCHType channelType = ReplicatorCHType.GameOrderCritical, S defaultState = null) { if (DoneSetup) { throw new ArgumentException("This replicator already has been setup"); } //Convert Type to LifeTime eSNetReplicatorLifeTime lifeTime; switch (replicatorType) { case ReplicatorType.LevelInstance: lifeTime = eSNetReplicatorLifeTime.DestroyedOnLevelReset; break; case ReplicatorType.Manager: lifeTime = eSNetReplicatorLifeTime.NeverDestroyed; break; default: throw new ArgumentException("Argument: replicatorType is Invalid!"); } //Convert Managed ChannelType into SNet_ChannelType SNet_ChannelType snet_channelType; switch (channelType) { case ReplicatorCHType.SessionOrderCritical: snet_channelType = SNet_ChannelType.SessionOrderCritical; break; case ReplicatorCHType.GameReceiveCritical: snet_channelType = SNet_ChannelType.GameReceiveCritical; break; case ReplicatorCHType.GameOrderCritical: snet_channelType = SNet_ChannelType.GameOrderCritical; break; case ReplicatorCHType.GameNonCritical: snet_channelType = SNet_ChannelType.GameNonCritical; break; default: throw new ArgumentException("Argument: channelType is Invalid!"); } //Create stuffs var guid = Guid.NewGuid().ToString() + "_CustomReplicator_" + UnityEngine.Random.Range(000, 999); var syncObj = new GameObject(guid); var syncInstance = syncObj.AddComponent <LG_Door_Sync>(); //Make object not be Destroy On Loaded if (lifeTime == eSNetReplicatorLifeTime.NeverDestroyed) { GameObject.DontDestroyOnLoad(syncObj); } //Cast Door_Sync to Provider SyncProvider = syncInstance; var provider = SyncProvider.Cast <ComplexStateReplicatorProvider>(); //Create Replicator var defaultStateStruct = defaultState?.ToOriginal() ?? default; OriginalReplicator = ComplexStateReplicator.Create(provider, lifeTime, defaultStateStruct, snet_channelType); InnerReplicator = OriginalReplicator.Replicator.Cast <SNet_Replicator>(); InnerIReplicator = OriginalReplicator.Replicator; //Remove Replicator from Official Manager Class var oldKey = InnerIReplicator.Key; switch (InnerIReplicator.Type) { case SNet_ReplicatorType.Manager: SNet_Replication.s_replicatorSlots[oldKey] = null; SNet_Replication.s_highestSlotUsed_Manager--; break; case SNet_ReplicatorType.SelfManaged: SNet_Replication.s_replicatorSlots[oldKey] = null; SNet_Replication.s_highestSlotUsed_SelfManaged--; break; } SNet.Replication.RemoveFromAssignedList(InnerIReplicator); //Register Replicator to Custom Manager CustomReplicatorManager.RegisterReplicator(InnerIReplicator, guid, OnStateChange_Cast, out var newKey); InnerReplicator.Key = newKey; InnerIReplicator.Key = newKey; //Set Packet ID to Custom Area SetPacketBytes(OriginalReplicator.m_statePacket, InnerIReplicator.KeyBytes); SetPacketBytes(OriginalReplicator.m_statePacket_Recall, InnerIReplicator.KeyBytes); SetPacketBytes(OriginalReplicator.m_interactionPacket, InnerIReplicator.KeyBytes); SyncProvider.m_stateReplicator = OriginalReplicator; SyncProvider.m_syncStruct = OriginalReplicator.GetProviderSyncStruct(); //Set Default Value State.FromOriginal(OriginalReplicator.State); SendState.FromOriginal(OriginalReplicator.State); DoneSetup = true; }
private void RunTwoStepContinuous(ReplicatorType type, string uid) { using (var OtherDb1 = OpenDB(OtherDb.Name)) using (var Db1 = OpenDB(Db.Name)) { var listener = new MessageEndpointListener(new MessageEndpointListenerConfiguration(OtherDb1, ProtocolType.ByteStream)); var server = new MockServerConnection(listener, ProtocolType.ByteStream); var config = new ReplicatorConfiguration(Db1, new MessageEndpoint(uid, server, ProtocolType.ByteStream, new MockConnectionFactory(null))) { ReplicatorType = type, Continuous = true }; using (var replicator = new Replicator(config)) { Database firstSource = null; Database secondSource = null; Database firstTarget = null; Database secondTarget = null; if (type == ReplicatorType.Push) { firstSource = Db1; secondSource = Db1; firstTarget = OtherDb1; secondTarget = OtherDb1; } else if (type == ReplicatorType.Pull) { firstSource = OtherDb1; secondSource = OtherDb1; firstTarget = Db1; secondTarget = Db1; } else { firstSource = Db1; secondSource = OtherDb1; firstTarget = OtherDb1; secondTarget = Db1; } replicator.Start(); using (var mdoc = new MutableDocument("livesindb")) { mdoc.SetString("name", "db"); mdoc.SetInt("version", 1); firstSource.Save(mdoc); } var count = 0; if (type != ReplicatorType.Push) { while (true) { count++; Thread.Sleep(1000); if (replicator.Status.Progress.Completed > 0 && replicator.Status.Activity == ReplicatorActivityLevel.Idle) { break; } } count.Should().BeLessThan(10, "because otherwise the replicator did not advance"); } else //when both doc updates happens on local side with push only, replicator.Status.Progress value wipe out too fast, so skip while loop { Thread.Sleep(1000); } var previousCompleted = replicator.Status.Progress.Completed; firstTarget.Count.Should().Be(1); using (var savedDoc = secondSource.GetDocument("livesindb")) using (var mdoc = savedDoc.ToMutable()) { mdoc.SetInt("version", 2); secondSource.Save(mdoc); } count = 0; if (type != ReplicatorType.Push) { while (true) { count++; Thread.Sleep(1000); if (replicator.Status.Progress.Completed > previousCompleted && replicator.Status.Activity == ReplicatorActivityLevel.Idle) { break; } } count.Should().BeLessThan(10, "because otherwise the replicator did not advance"); } else //when both doc updates happens on local side with push only, replicator.Status.Progress value wipe out too fast, so skip while loop { Thread.Sleep(1000); } using (var savedDoc = secondTarget.GetDocument("livesindb")) { savedDoc.GetInt("version").Should().Be(2); } replicator.Stop(); Thread.Sleep(100); while (true) { if (replicator.Status.Activity == ReplicatorActivityLevel.Stopped) { break; } } } } }