private void RunReplication(ReplicatorConfiguration config, int expectedErrCode, C4ErrorDomain expectedErrDomain)
        {
            Misc.SafeSwap(ref _repl, new Replicator(config));
            _waitAssert = new WaitAssert();
            var token = _repl.AddChangeListener((sender, args) =>
            {
                _waitAssert.RunConditionalAssert(() =>
                {
                    VerifyChange(args, expectedErrCode, expectedErrDomain);
                    if (config.Continuous && args.Status.Activity == ReplicatorActivityLevel.Idle &&
                        args.Status.Progress.Completed == args.Status.Progress.Total)
                    {
                        ((Replicator)sender).Stop();
                    }

                    return(args.Status.Activity == ReplicatorActivityLevel.Stopped);
                });
            });

            _repl.Start();
            try {
                _waitAssert.WaitForResult(TimeSpan.FromSeconds(10));
            } catch {
                _repl.Stop();
                throw;
            } finally {
                _repl.RemoveChangeListener(token);
            }
        }
Example #2
0
 public void StopReplication()
 {
     if (_replicator != null)
     {
         _replicator.RemoveChangeListener(_replicatorListenerToken);
         _replicator.Stop();
     }
 }
Example #3
0
        private void RemoveReplicator()
        {
            if (IsStarted)
            {
                StopReplicator();
            }

            _repl?.RemoveChangeListener(_listenerToken);
            _repl?.Dispose();
        }
        public void TestStopContinuousReplicator()
        {
            var config = CreateConfig(true, false, true);

            using (var r = new Replicator(config)) {
                var stopWhen = new[]
                {
                    ReplicatorActivityLevel.Connecting, ReplicatorActivityLevel.Busy,
                    ReplicatorActivityLevel.Idle, ReplicatorActivityLevel.Idle
                };

                foreach (var when in stopWhen)
                {
                    var stopped    = 0;
                    var waitAssert = new WaitAssert();
                    var token      = r.AddChangeListener((sender, args) =>
                    {
                        waitAssert.RunConditionalAssert(() =>
                        {
                            VerifyChange(args, 0, 0);

                            // On Windows, at least, sometimes the connection is so fast that Connecting never gets called
                            if ((args.Status.Activity == when ||
                                 (when == ReplicatorActivityLevel.Connecting && args.Status.Activity > when)) &&
                                Interlocked.Exchange(ref stopped, 1) == 0)
                            {
                                WriteLine("***** Stop Replicator *****");
                                ((Replicator)sender).Stop();
                            }

                            if (args.Status.Activity == ReplicatorActivityLevel.Stopped)
                            {
                                WriteLine("Stopped!");
                            }

                            return(args.Status.Activity == ReplicatorActivityLevel.Stopped);
                        });
                    });

                    WriteLine("***** Start Replicator *****");
                    r.Start();
                    try {
                        waitAssert.WaitForResult(TimeSpan.FromSeconds(5));
                    } finally {
                        r.RemoveChangeListener(token);
                    }

                    Task.Delay(100).Wait();
                }
            }
        }
        private void Restart()
        {
            try
            {
                _replicator.RemoveChangeListener(_token);
                _replicator.Stop();
                _replicator = null;
                _replicator.Dispose();
            }
            catch (Exception)
            { }

            Connect();
        }
Example #6
0
        private void Restart(ReplicatorStatusMessage obj)
        {
            try
            {
                _replicator.RemoveChangeListener(_token);
                _replicator.Stop();
                _replicator.Dispose();
                _replicator = null;

                Connect();
            }
            catch (Exception e)
            {
#if DEBUG
#endif
            }
        }
        public void TestReplicatorAndListenerOnSameDatabase()
        {
            using (var doc = new MutableDocument()) {
                OtherDb.Save(doc);
            }

            CreateListener();
            using (var doc1 = new MutableDocument()) {
                Db.Save(doc1);
            }

            var target  = new DatabaseEndpoint(Db);
            var config1 = CreateConfig(target, ReplicatorType.PushAndPull, true, sourceDb: OtherDb);
            var repl1   = new Replicator(config1);

            Database.Delete("urlepTestDb", Directory);
            var urlepTestDb = OpenDB("urlepTestDb");

            using (var doc2 = new MutableDocument()) {
                urlepTestDb.Save(doc2);
            }

            var config2 = CreateConfig(_listener.LocalEndpoint(), ReplicatorType.PushAndPull, true,
                                       serverCert: _listener.TlsIdentity.Certs[0], sourceDb: urlepTestDb);
            var repl2 = new Replicator(config2);

            var wait1 = new ManualResetEventSlim();
            var wait2 = new ManualResetEventSlim();
            EventHandler <ReplicatorStatusChangedEventArgs> changeListener = (sender, args) =>
            {
                if (args.Status.Activity == ReplicatorActivityLevel.Idle && args.Status.Progress.Completed ==
                    args.Status.Progress.Total)
                {
                    if (OtherDb.Count == 3 && Db.Count == 3 && urlepTestDb.Count == 3)
                    {
                        ((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();
            WaitHandle.WaitAll(new[] { wait1.WaitHandle, wait2.WaitHandle }, TimeSpan.FromSeconds(20))
            .Should().BeTrue();

            repl1.RemoveChangeListener(token1);
            repl2.RemoveChangeListener(token2);

            Db.Count.Should().Be(3, "because otherwise not all docs were received into Db");
            OtherDb.Count.Should().Be(3, "because otherwise not all docs were received into OtherDb");
            urlepTestDb.Count.Should().Be(3, "because otherwise not all docs were received into urlepTestDb");

            repl1.Dispose();
            repl2.Dispose();
            wait1.Dispose();
            wait2.Dispose();
            urlepTestDb.Delete();

            _listener.Stop();

            Thread.Sleep(500); // wait for everything to stop
        }
        public void TestStatus()
        {
            ulong maxConnectionCount = 0UL;
            ulong maxActiveCount     = 0UL;

            //init and start a listener
            _listener = CreateListener(false);

            //listener is started at this point
            _listener.Status.ConnectionCount.Should().Be(0, "Listener's connection count should be 0 because no client connection has been established.");
            _listener.Status.ActiveConnectionCount.Should().Be(0, "Listener's active connection count should be 0 because no client connection has been established.");

            using (var doc1 = new MutableDocument())
                using (var doc2 = new MutableDocument()) {
                    doc1.SetString("name", "Sam");
                    Db.Save(doc1);
                    doc2.SetString("name", "Mary");
                    OtherDb.Save(doc2);
                }

            var targetEndpoint = _listener.LocalEndpoint();
            var config         = new ReplicatorConfiguration(Db, targetEndpoint);

            using (var repl = new Replicator(config)) {
                var waitAssert = new WaitAssert();
                var token      = repl.AddChangeListener((sender, args) =>
                {
                    WriteLine($"Yeehaw {_listener.Status.ConnectionCount} / {_listener.Status.ActiveConnectionCount}");

                    maxConnectionCount = Math.Max(maxConnectionCount, _listener.Status.ConnectionCount);
                    maxActiveCount     = Math.Max(maxActiveCount, _listener.Status.ActiveConnectionCount);

                    waitAssert.RunConditionalAssert(() =>
                    {
                        return(args.Status.Activity == ReplicatorActivityLevel.Stopped);
                    });
                });

                repl.Start();
                while (repl.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);

                try {
                    waitAssert.WaitForResult(TimeSpan.FromSeconds(100));
                } finally {
                    repl.RemoveChangeListener(token);
                }
            }

            maxConnectionCount.Should().Be(1);
            maxActiveCount.Should().Be(1);

            //stop the listener
            _listener.Stop();
            _listener.Status.ConnectionCount.Should().Be(0, "Listener's connection count should be 0 because the connection is stopped.");
            _listener.Status.ActiveConnectionCount.Should().Be(0, "Listener's active connection count should be 0 because the connection is stopped.");
        }
        // 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);
        }