Esempio n. 1
0
        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);
        }
Esempio n. 3
0
        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();
        }
Esempio n. 4
0
        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;
        }
Esempio n. 5
0
        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;
                            }
                        }
                    }
                }
        }