private void StartChangeTracker() { Log.D(TAG, "starting ChangeTracker with since = " + LastSequence); var mode = Continuous ? ChangeTrackerMode.LongPoll : ChangeTrackerMode.OneShot; _changeTracker = new ChangeTracker(RemoteUrl, mode, LastSequence, true, this, WorkExecutor); _changeTracker.Authenticator = Authenticator; if (DocIds != null) { if (ServerType != null && ServerType.Name == "CouchDB") { _changeTracker.SetDocIDs(DocIds.ToList()); } else { Log.W(TAG, "DocIds parameter only supported on CouchDB"); } } if (Filter != null) { _changeTracker.SetFilterName(Filter); if (FilterParams != null) { _changeTracker.SetFilterParams(FilterParams.ToDictionary(kvp => kvp.Key, kvp => kvp.Value)); } } _changeTracker.UsePost = CheckServerCompatVersion("0.93"); _changeTracker.Start(); }
private void StartChangeTracker() { var mode = ChangeTrackerMode.OneShot; var pollInterval = ReplicationOptions.PollInterval; if (Continuous && pollInterval == TimeSpan.Zero && ReplicationOptions.UseWebSocket) { mode = ChangeTrackerMode.WebSocket; } Log.To.Sync.V(TAG, "{0} starting ChangeTracker: mode={0} since={1}", this, mode, LastSequence); var initialSync = LocalDatabase.IsOpen && LocalDatabase.GetDocumentCount() == 0; var changeTrackerOptions = new ChangeTrackerOptions { DatabaseUri = RemoteUrl, Mode = mode, IncludeConflicts = true, LastSequenceID = LastSequence, Client = this, RetryStrategy = ReplicationOptions.RetryStrategy, WorkExecutor = WorkExecutor, }; _changeTracker = ChangeTrackerFactory.Create(changeTrackerOptions); _changeTracker.ActiveOnly = initialSync; _changeTracker.Authenticator = Authenticator; _changeTracker.Continuous = Continuous; _changeTracker.PollInterval = pollInterval; _changeTracker.Heartbeat = ReplicationOptions.Heartbeat; if (DocIds != null) { if (ServerType != null && ServerType.Name == "CouchDB") { _changeTracker.DocIDs = DocIds.ToList(); } else { Log.To.Sync.W(TAG, "DocIds parameter only supported on CouchDB"); } } if (Filter != null) { _changeTracker.FilterName = Filter; if (FilterParams != null) { _changeTracker.FilterParameters = FilterParams.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } } if (ServerType != null) { _changeTracker.ServerType = ServerType; } _changeTracker.Start(); }
private void StartChangeTracker() { var mode = ChangeTrackerMode.OneShot; var pollInterval = ReplicationOptions.PollInterval; if (Continuous && pollInterval == TimeSpan.Zero && ReplicationOptions.UseWebSocket) { mode = ChangeTrackerMode.WebSocket; } _canBulkGet = mode == ChangeTrackerMode.WebSocket; Log.To.Sync.V(TAG, "{0} starting ChangeTracker: mode={0} since={1}", this, mode, LastSequence); var initialSync = LocalDatabase.IsOpen && LocalDatabase.GetDocumentCount() == 0; var changeTrackerOptions = new ChangeTrackerOptions { DatabaseUri = RemoteUrl, Mode = mode, IncludeConflicts = true, LastSequenceID = LastSequence, Client = this, RemoteSession = _remoteSession, RetryStrategy = ReplicationOptions.RetryStrategy, WorkExecutor = WorkExecutor, UsePost = CheckServerCompatVersion("0.9.3") }; _changeTracker = ChangeTrackerFactory.Create(changeTrackerOptions); _changeTracker.ActiveOnly = initialSync; _changeTracker.Continuous = Continuous; _changeTracker.PollInterval = pollInterval; _changeTracker.Heartbeat = ReplicationOptions.Heartbeat; _changeTracker.DocIDs = DocIds?.ToList(); if (Filter != null) { _changeTracker.FilterName = Filter; if (FilterParams != null) { _changeTracker.FilterParameters = FilterParams.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } } _changeTracker.Start(); }
internal override void BeginReplicating() { // If we're still waiting to create the remote db, do nothing now. (This method will be // re-invoked after that request finishes; see maybeCreateRemoteDB() above.) if (_creatingTarget) { Log.To.Sync.D(TAG, "creatingTarget == true, doing nothing"); return; } _pendingSequences = new SortedDictionary <long, int>(); if (!Int64.TryParse(LastSequence, out _maxPendingSequence)) { Log.To.Sync.W(TAG, "{0} is not a valid last sequence, using 0", LastSequence); _maxPendingSequence = 0; } if (Filter != null) { _filter = LocalDatabase.GetFilter(Filter); } else { // If not filter function was provided, but DocIds were // specified, then only push the documents listed in the // DocIds property. It is assumed that if the users // specified both a filter name and doc ids that their // custom filter function will handle that. This is // consistent with the iOS behavior. if (DocIds != null && DocIds.Any()) { _filter = (rev, filterParams) => DocIds.Contains(rev.Document.Id); } } if (Filter != null && _filter == null) { Log.To.Sync.W(TAG, "{0}: No ReplicationFilter registered for filter '{1}'; ignoring", this, Filter); } // Process existing changes since the last push: long lastSequenceLong = 0; if (LastSequence != null) { lastSequenceLong = long.Parse(LastSequence); } if (ReplicationOptions.PurgePushed) { _purgeQueue = new Batcher <RevisionInternal>(WorkExecutor, EphemeralPurgeBatchSize, EphemeralPurgeDelay, (revs) => { Log.To.Sync.I(TAG, "Purging {0} docs ('purgePushed' option)", revs.Count); var toPurge = new Dictionary <string, IList <string> >(); foreach (var rev in revs) { toPurge[rev.DocID] = new List <string> { rev.RevID }; } var localDb = LocalDatabase; if (localDb != null && localDb.IsOpen) { var storage = localDb.Storage; if (storage != null && storage.IsOpen) { storage.PurgeRevisions(toPurge); } else { Log.To.Sync.W(TAG, "{0} storage is closed, cannot purge...", localDb); } } else { Log.To.Sync.W(TAG, "Local database is closed or null, cannot purge..."); } }, CancellationTokenSource); } // Now listen for future changes (in continuous mode): // Note: This needs to happen before adding the observer // or else there is a race condition. // A document could be added between the call to // ChangesSince and adding the observer, which would result // in a document being skipped if (Continuous) { _observing = true; LocalDatabase.Changed += OnChanged; } var options = ChangesOptions.Default; options.IncludeConflicts = true; var changes = LocalDatabase.ChangesSince(lastSequenceLong, options, _filter, FilterParams); if (changes.Count > 0) { Batcher.QueueObjects(changes); Batcher.Flush(); } if (Continuous) { if (changes.Count == 0) { Log.To.Sync.V(TAG, "No changes to push, switching to idle..."); FireTrigger(ReplicationTrigger.WaitingForChanges); } } else { if (changes.Count == 0) { Log.To.Sync.V(TAG, "No changes to push, firing StopGraceful..."); FireTrigger(ReplicationTrigger.StopGraceful); } } }
internal override void BeginReplicating() { Log.D(Tag, "beginReplicating() called"); // If we're still waiting to create the remote db, do nothing now. (This method will be // re-invoked after that request finishes; see maybeCreateRemoteDB() above.) if (creatingTarget) { Log.D(Tag, "creatingTarget == true, doing nothing"); return; } pendingSequences = new SortedDictionary <long, int>(); try { maxPendingSequence = Int64.Parse(LastSequence); } catch (Exception e) { Log.W(Tag, "Error converting lastSequence: " + LastSequence + " to long. Using 0"); maxPendingSequence = 0; } if (Filter != null) { filter = LocalDatabase.GetFilter(Filter); } else { // If not filter function was provided, but DocIds were // specified, then only push the documents listed in the // DocIds property. It is assumed that if the users // specified both a filter name and doc ids that their // custom filter function will handle that. This is // consistent with the iOS behavior. if (DocIds != null && DocIds.Any()) { filter = (rev, filterParams) => DocIds.Contains(rev.Document.Id); } } if (Filter != null && filter == null) { Log.W(Tag, string.Format("{0}: No ReplicationFilter registered for filter '{1}'; ignoring", this, Filter)); } // Process existing changes since the last push: long lastSequenceLong = 0; if (LastSequence != null) { lastSequenceLong = long.Parse(LastSequence); } var options = new ChangesOptions(); options.SetIncludeConflicts(true); var changes = LocalDatabase.ChangesSince(lastSequenceLong, options, filter); if (changes.Count > 0) { Batcher.QueueObjects(changes); Batcher.Flush(); } // Now listen for future changes (in continuous mode): if (continuous) { observing = true; LocalDatabase.Changed += OnChanged; } }
internal override void BeginReplicating() { // If we're still waiting to create the remote db, do nothing now. (This method will be // re-invoked after that request finishes; see maybeCreateRemoteDB() above.) if (_creatingTarget) { Log.To.Sync.D(TAG, "creatingTarget == true, doing nothing"); return; } _pendingSequences = new SortedDictionary <long, int>(); if (!Int64.TryParse(LastSequence, out _maxPendingSequence)) { Log.To.Sync.W(TAG, "{0} is not a valid last sequence, using 0", LastSequence); _maxPendingSequence = 0; } if (Filter != null) { _filter = LocalDatabase.GetFilter(Filter); } else { // If not filter function was provided, but DocIds were // specified, then only push the documents listed in the // DocIds property. It is assumed that if the users // specified both a filter name and doc ids that their // custom filter function will handle that. This is // consistent with the iOS behavior. if (DocIds != null && DocIds.Any()) { _filter = (rev, filterParams) => DocIds.Contains(rev.Document.Id); } } if (Filter != null && _filter == null) { Log.To.Sync.W(TAG, "{0}: No ReplicationFilter registered for filter '{1}'; ignoring", this, Filter); } // Process existing changes since the last push: long lastSequenceLong = 0; if (LastSequence != null) { lastSequenceLong = long.Parse(LastSequence); } // Now listen for future changes (in continuous mode): // Note: This needs to happen before adding the observer // or else there is a race condition. // A document could be added between the call to // ChangesSince and adding the observer, which would result // in a document being skipped if (Continuous) { _observing = true; LocalDatabase.Changed += OnChanged; } var options = ChangesOptions.Default; options.IncludeConflicts = true; var changes = LocalDatabase.ChangesSince(lastSequenceLong, options, _filter, FilterParams); if (changes.Count > 0) { Batcher.QueueObjects(changes); Batcher.Flush(); } if (Continuous) { if (changes.Count == 0) { FireTrigger(ReplicationTrigger.WaitingForChanges); } } else { if (changes.Count == 0) { FireTrigger(ReplicationTrigger.StopGraceful); } } }