public static RemoteSession Clone(RemoteSession source, CancellationTokenSource cts)
        {
            var retVal = new RemoteSession(source);

            retVal._cancellationTokenSource = cts;
            return(retVal);
        }
Exemple #2
0
        public static RemoteSession Clone(RemoteSession source)
        {
            if (!source.Disposed)
            {
                return(source);
            }

            return(new RemoteSession(source));
        }
Exemple #3
0
 private RemoteSession(RemoteSession source)
 {
     _workExecutor            = source._workExecutor;
     _cancellationTokenSource = source._cancellationTokenSource;
     _id            = source._id;
     _baseUrl       = source._baseUrl;
     Authenticator  = source.Authenticator;
     RequestHeaders = source.RequestHeaders;
     ServerType     = source.ServerType;
     CookieStore    = source.CookieStore;
 }
 private RemoteSession(RemoteSession source)
 {
     _workExecutor  = source._workExecutor;
     _id            = source._id;
     _baseUrl       = source._baseUrl;
     Authenticator  = source.Authenticator;
     RequestHeaders = source.RequestHeaders;
     ServerType     = source.ServerType;
     CookieStore    = source.CookieStore;
     ClientFactory  = source.ClientFactory;
 }
 protected ChangeTracker(ChangeTrackerOptions options)
 {
     options.Validate();
     Backoff           = new ChangeTrackerBackoff(options.RetryStrategy);
     DatabaseUrl       = options.DatabaseUri;
     Client            = options.Client;
     Mode              = options.Mode;
     Heartbeat         = DefaultHeartbeat;
     _includeConflicts = options.IncludeConflicts;
     LastSequenceId    = options.LastSequenceID;
     _workExecutor     = options.WorkExecutor ?? new TaskFactory(new SingleTaskThreadpoolScheduler());
     _remoteSession    = options.RemoteSession;
     _usePost          = options.UsePost;
 }
 private RemoteSession(RemoteSession source)
 {
     _workExecutor = source._workExecutor;
     _id = source._id;
     _baseUrl = source._baseUrl;
     Authenticator = source.Authenticator;
     RequestHeaders = source.RequestHeaders;
     ServerType = source.ServerType;
     CookieStore = source.CookieStore;
     ClientFactory = source.ClientFactory;
 }
 public static RemoteSession Clone(RemoteSession source, CancellationTokenSource cts)
 {
     var retVal = new RemoteSession(source);
     retVal._cancellationTokenSource = cts;
     return retVal;
 }
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="db">The local database to replicate to/from</param>
        /// <param name="remote">The remote Uri to sync with</param>
        /// <param name="continuous">If set to <c>true</c> continuous.</param>
        /// <param name="clientFactory">The client factory for instantiating the HttpClient used to create web requests</param>
        /// <param name="workExecutor">The TaskFactory to execute work on</param>
        internal Replication(Database db, Uri remote, bool continuous, IHttpClientFactory clientFactory, TaskFactory workExecutor)
        {
            sessionID = $"repl{ Interlocked.Increment(ref _lastSessionID):000}";
            var opts = new RemoteSessionContructorOptions {
                BaseUrl = remote,
                WorkExecutor = workExecutor,
                Id = _replicatorID,
                CancellationTokenSource = CancellationTokenSource
            };
            _remoteSession = new RemoteSession(opts);
            Username = remote.UserInfo;

            LocalDatabase = db;
            _eventContext = LocalDatabase.Manager.CapturedContext;
            Continuous = continuous;
            // NOTE: Consider running a separate scheduler for all http requests.
            WorkExecutor = workExecutor;
            RemoteUrl = remote;
#pragma warning disable 618
            Options = new ReplicationOptionsDictionary();
#pragma warning restore 618
            ReplicationOptions = new ReplicationOptions();

            if (RemoteUrl.Query != null && !StringEx.IsNullOrWhiteSpace(RemoteUrl.Query)) {
                Authenticator = AuthenticatorFactory.CreateFromUri(remote);

                // we need to remove the query from the URL, since it will cause problems when
                // communicating with sync gw / couchdb
                try {
                    RemoteUrl = new UriBuilder(remote.Scheme, remote.Host, remote.Port, remote.AbsolutePath).Uri;
                } catch (UriFormatException e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Sync, e, Tag,
                        "Invalid URI format for remote endpoint");
                }
            }

            Batcher = new Batcher<RevisionInternal>(workExecutor, INBOX_CAPACITY, ProcessorDelay, inbox =>
            {
                try {
                    Log.To.Sync.V(Tag, "*** {0} BEGIN ProcessInbox ({1} sequences)", this, inbox.Count);
                    if(Continuous) {
                        FireTrigger(ReplicationTrigger.Resume);
                    }

                    ProcessInbox (new RevisionList(inbox));

                    Log.To.Sync.V(Tag, "*** {0} END ProcessInbox (lastSequence={1})", this, LastSequence);
                } catch(Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Sync, e, Tag, 
                        "{0} ProcessInbox failed", this);
                }
            });

            ClientFactory = clientFactory;

            _stateMachine = new StateMachine<ReplicationState, ReplicationTrigger>(ReplicationState.Initial);
            InitializeStateMachine();
        }
        /// <summary>
        /// Starts the replicator when it transitions into a running state
        /// </summary>
        protected virtual void StartInternal()
        {
            Log.To.Sync.I(Tag, "Attempting to start {0} ({1})", IsPull ? "puller" : "pusher", _replicatorID);
            _remoteSession = RemoteSession.Clone (_remoteSession, CancellationTokenSource);
            _remoteSession.Setup (ReplicationOptions);

            if (!LocalDatabase.IsOpen) {
                Log.To.Sync.W(Tag, "Not starting because local database is not open.");
                FireTrigger(ReplicationTrigger.StopImmediate);
                return;
            }

            var authorizer = Authenticator as IAuthorizer;
            if (authorizer != null) {
                authorizer.RemoteUrl = RemoteUrl;
                authorizer.LocalUUID = LocalDatabase.PublicUUID ();
            }

            var reachabilityManager = LocalDatabase.Manager.NetworkReachabilityManager;
            reachabilityManager.StatusChanged += NetworkStatusChanged;

            if (!LocalDatabase.Manager.NetworkReachabilityManager.CanReach(RemoteUrl.AbsoluteUri, ReplicationOptions.RequestTimeout)) {
                Log.To.Sync.I(Tag, "Remote endpoint is not reachable, going offline...");
                LastError = LocalDatabase.Manager.NetworkReachabilityManager.LastError;
                FireTrigger(ReplicationTrigger.GoOffline);
                CheckOnlineLoop();
            }

            LocalDatabase.AddReplication(this);
            if(!LocalDatabase.AddActiveReplication(this)) {
#if DEBUG
                var activeReplicators = default(IList<Replication>);
                if(!LocalDatabase.ActiveReplicators.AcquireTemp(out activeReplicators)) {
                    Log.To.Sync.E(Tag, "Active replication list unavailable!");
                } else {
                    var existing = activeReplicators.FirstOrDefault(x => x.RemoteCheckpointDocID() == RemoteCheckpointDocID());
                    if(existing != null) {
                        Log.To.Sync.W(Tag, "Not starting because identical {0} already exists ({1})", IsPull ? "puller" : "pusher", existing._replicatorID);
                    } else {
                        Log.To.Sync.E(Tag, "Not starting {0} for unknown reasons", IsPull ? "puller" : "pusher");
                    }
                }
#else
                Log.To.Sync.W(Tag, "Not starting becuse identical {0} already exists", IsPull ? "puller" : "pusher");
#endif
                FireTrigger(ReplicationTrigger.StopImmediate);
                return;
            }

            _retryIfReadyTokenSource = CancellationTokenSource.CreateLinkedTokenSource(CancellationTokenSource.Token);
            if (ReplicationOptions.Reset) {
                LocalDatabase.SetLastSequence(null, RemoteCheckpointDocID());
            }

            _startTime = DateTime.UtcNow;
            SetupRevisionBodyTransformationFunction();

            Log.To.Sync.I(Tag, "Beginning replication process...");
            LastSequence = null;
            Login();
        }
 public RemoteLogin(Uri remoteUrl, string localUUID, RemoteSession session)
 {
     _remoteUrl = remoteUrl;
     _localUUID = localUUID;
     _session = session;
 }