/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> public virtual void TestRevTree() { RevisionInternal rev = new RevisionInternal("MyDocId", "4-foxy", false, database); IDictionary<string, object> revProperties = new Dictionary<string, object>(); revProperties.Put("_id", rev.GetDocId()); revProperties.Put("_rev", rev.GetRevId()); revProperties.Put("message", "hi"); rev.SetProperties(revProperties); IList<string> revHistory = new AList<string>(); revHistory.AddItem(rev.GetRevId()); revHistory.AddItem("3-thrice"); revHistory.AddItem("2-too"); revHistory.AddItem("1-won"); database.ForceInsert(rev, revHistory, null); NUnit.Framework.Assert.AreEqual(1, database.GetDocumentCount()); VerifyHistory(database, rev, revHistory); RevisionInternal conflict = new RevisionInternal("MyDocId", "5-epsilon", false, database ); IDictionary<string, object> conflictProperties = new Dictionary<string, object>(); conflictProperties.Put("_id", conflict.GetDocId()); conflictProperties.Put("_rev", conflict.GetRevId()); conflictProperties.Put("message", "yo"); conflict.SetProperties(conflictProperties); IList<string> conflictHistory = new AList<string>(); conflictHistory.AddItem(conflict.GetRevId()); conflictHistory.AddItem("4-delta"); conflictHistory.AddItem("3-gamma"); conflictHistory.AddItem("2-too"); conflictHistory.AddItem("1-won"); IList wasInConflict = new ArrayList(); Database.ChangeListener listener = new _ChangeListener_84(wasInConflict); database.AddChangeListener(listener); database.ForceInsert(conflict, conflictHistory, null); NUnit.Framework.Assert.IsTrue(wasInConflict.Count > 0); database.RemoveChangeListener(listener); NUnit.Framework.Assert.AreEqual(1, database.GetDocumentCount()); VerifyHistory(database, conflict, conflictHistory); // Add an unrelated document: RevisionInternal other = new RevisionInternal("AnotherDocID", "1-ichi", false, database ); IDictionary<string, object> otherProperties = new Dictionary<string, object>(); otherProperties.Put("language", "jp"); other.SetProperties(otherProperties); IList<string> otherHistory = new AList<string>(); otherHistory.AddItem(other.GetRevId()); database.ForceInsert(other, otherHistory, null); // Fetch one of those phantom revisions with no body: RevisionInternal rev2 = database.GetDocumentWithIDAndRev(rev.GetDocId(), "2-too", EnumSet.NoneOf<Database.TDContentOptions>()); NUnit.Framework.Assert.AreEqual(rev.GetDocId(), rev2.GetDocId()); NUnit.Framework.Assert.AreEqual("2-too", rev2.GetRevId()); //Assert.assertNull(rev2.getContent()); // Make sure no duplicate rows were inserted for the common revisions: NUnit.Framework.Assert.AreEqual(8, database.GetLastSequenceNumber()); // Make sure the revision with the higher revID wins the conflict: RevisionInternal current = database.GetDocumentWithIDAndRev(rev.GetDocId(), null, EnumSet.NoneOf<Database.TDContentOptions>()); NUnit.Framework.Assert.AreEqual(conflict, current); // Get the _changes feed and verify only the winner is in it: ChangesOptions options = new ChangesOptions(); RevisionList changes = database.ChangesSince(0, options, null); RevisionList expectedChanges = new RevisionList(); expectedChanges.AddItem(conflict); expectedChanges.AddItem(other); NUnit.Framework.Assert.AreEqual(changes, expectedChanges); options.SetIncludeConflicts(true); changes = database.ChangesSince(0, options, null); expectedChanges = new RevisionList(); expectedChanges.AddItem(rev); expectedChanges.AddItem(conflict); expectedChanges.AddItem(other); NUnit.Framework.Assert.AreEqual(changes, expectedChanges); }
internal IEnumerable<QueryRow> GetAllDocs(QueryOptions options) { // For regular all-docs, let storage do it all: if (options == null || options.AllDocsMode != AllDocsMode.BySequence) { return Storage.GetAllDocs(options); } if (options.Descending) { throw new CouchbaseLiteException("Descending all docs not implemented", StatusCode.NotImplemented); } ChangesOptions changesOpts = new ChangesOptions(); changesOpts.SetLimit(options.Limit); changesOpts.SetIncludeDocs(options.IncludeDocs); changesOpts.SetIncludeConflicts(true); changesOpts.SetSortBySequence(true); long startSeq = KeyToSequence(options.StartKey, 1); long endSeq = KeyToSequence(options.EndKey, long.MaxValue); if (!options.InclusiveStart) { ++startSeq; } if (!options.InclusiveEnd) { --endSeq; } long minSeq = startSeq, maxSeq = endSeq; if (minSeq > maxSeq) { return null; // empty result } RevisionList revs = Storage.ChangesSince(minSeq - 1, changesOpts, null); if (revs == null) { return null; } var result = new List<QueryRow>(); var revEnum = options.Descending ? revs.Reverse<RevisionInternal>() : revs; foreach (var rev in revEnum) { long seq = rev.GetSequence(); if (seq < minSeq || seq > maxSeq) { break; } var value = new NonNullDictionary<string, object> { { "rev", rev.GetRevId() }, { "deleted", rev.IsDeleted() ? (object)true : null } }; result.Add(new QueryRow(rev.GetDocId(), seq, rev.GetDocId(), value, rev, null)); } return result; }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> public virtual void TestRevTree() { RevisionInternal rev = new RevisionInternal("MyDocId", "4-foxy", false, database); IDictionary <string, object> revProperties = new Dictionary <string, object>(); revProperties.Put("_id", rev.GetDocId()); revProperties.Put("_rev", rev.GetRevId()); revProperties["message"] = "hi"; rev.SetProperties(revProperties); IList <string> revHistory = new AList <string>(); revHistory.AddItem(rev.GetRevId()); revHistory.AddItem("3-thrice"); revHistory.AddItem("2-too"); revHistory.AddItem("1-won"); database.ForceInsert(rev, revHistory, null); NUnit.Framework.Assert.AreEqual(1, database.DocumentCount); VerifyHistory(database, rev, revHistory); RevisionInternal conflict = new RevisionInternal("MyDocId", "5-epsilon", false, database ); IDictionary <string, object> conflictProperties = new Dictionary <string, object>(); conflictProperties.Put("_id", conflict.GetDocId()); conflictProperties.Put("_rev", conflict.GetRevId()); conflictProperties["message"] = "yo"; conflict.SetProperties(conflictProperties); IList <string> conflictHistory = new AList <string>(); conflictHistory.AddItem(conflict.GetRevId()); conflictHistory.AddItem("4-delta"); conflictHistory.AddItem("3-gamma"); conflictHistory.AddItem("2-too"); conflictHistory.AddItem("1-won"); database.ForceInsert(conflict, conflictHistory, null); NUnit.Framework.Assert.AreEqual(1, database.DocumentCount); VerifyHistory(database, conflict, conflictHistory); // Add an unrelated document: RevisionInternal other = new RevisionInternal("AnotherDocID", "1-ichi", false, database ); IDictionary <string, object> otherProperties = new Dictionary <string, object>(); otherProperties["language"] = "jp"; other.SetProperties(otherProperties); IList <string> otherHistory = new AList <string>(); otherHistory.AddItem(other.GetRevId()); database.ForceInsert(other, otherHistory, null); // Fetch one of those phantom revisions with no body: RevisionInternal rev2 = database.GetDocumentWithIDAndRev(rev.GetDocId(), "2-too", EnumSet.NoneOf <TDContentOptions>()); NUnit.Framework.Assert.AreEqual(rev.GetDocId(), rev2.GetDocId()); NUnit.Framework.Assert.AreEqual("2-too", rev2.GetRevId()); //Assert.assertNull(rev2.getContent()); // Make sure no duplicate rows were inserted for the common revisions: NUnit.Framework.Assert.AreEqual(8, database.GetLastSequenceNumber()); // Make sure the revision with the higher revID wins the conflict: RevisionInternal current = database.GetDocumentWithIDAndRev(rev.GetDocId(), null, EnumSet.NoneOf <TDContentOptions>()); NUnit.Framework.Assert.AreEqual(conflict, current); // Get the _changes feed and verify only the winner is in it: ChangesOptions options = new ChangesOptions(); RevisionList changes = database.ChangesSince(0, options, null); RevisionList expectedChanges = new RevisionList(); expectedChanges.AddItem(conflict); expectedChanges.AddItem(other); NUnit.Framework.Assert.AreEqual(changes, expectedChanges); options.SetIncludeConflicts(true); changes = database.ChangesSince(0, options, null); expectedChanges = new RevisionList(); expectedChanges.AddItem(rev); expectedChanges.AddItem(conflict); expectedChanges.AddItem(other); NUnit.Framework.Assert.AreEqual(changes, expectedChanges); }
public void TestRevTree() { var rev = new RevisionInternal("MyDocId", "4-foxy", false, database); var revProperties = new Dictionary<string, object>(); revProperties.Put("_id", rev.GetDocId()); revProperties.Put("_rev", rev.GetRevId()); revProperties["message"] = "hi"; rev.SetProperties(revProperties); var revHistory = new AList<string>(); revHistory.AddItem(rev.GetRevId()); revHistory.AddItem("3-thrice"); revHistory.AddItem("2-too"); revHistory.AddItem("1-won"); database.ForceInsert(rev, revHistory, null); Assert.AreEqual(1, database.DocumentCount); VerifyHistory(database, rev, revHistory); var conflict = new RevisionInternal("MyDocId", "5-epsilon", false, database); var conflictProperties = new Dictionary<string, object>(); conflictProperties.Put("_id", conflict.GetDocId()); conflictProperties.Put("_rev", conflict.GetRevId()); conflictProperties["message"] = "yo"; conflict.SetProperties(conflictProperties); var conflictHistory = new AList<string>(); conflictHistory.AddItem(conflict.GetRevId()); conflictHistory.AddItem("4-delta"); conflictHistory.AddItem("3-gamma"); conflictHistory.AddItem("2-too"); conflictHistory.AddItem("1-won"); database.ForceInsert(conflict, conflictHistory, null); Assert.AreEqual(1, database.DocumentCount); VerifyHistory(database, conflict, conflictHistory); // Add an unrelated document: var other = new RevisionInternal("AnotherDocID", "1-ichi", false, database); var otherProperties = new Dictionary<string, object>(); otherProperties["language"] = "jp"; other.SetProperties(otherProperties); var otherHistory = new AList<string>(); otherHistory.AddItem(other.GetRevId()); database.ForceInsert(other, otherHistory, null); // Fetch one of those phantom revisions with no body: var rev2 = database.GetDocumentWithIDAndRev(rev.GetDocId(), "2-too", DocumentContentOptions.None); Assert.AreEqual(rev.GetDocId(), rev2.GetDocId()); Assert.AreEqual("2-too", rev2.GetRevId()); // Make sure no duplicate rows were inserted for the common revisions: Assert.AreEqual(8, database.GetLastSequenceNumber()); // Make sure the revision with the higher revID wins the conflict: var current = database.GetDocumentWithIDAndRev(rev.GetDocId(), null, DocumentContentOptions.None); Assert.AreEqual(conflict, current); // Get the _changes feed and verify only the winner is in it: var options = new ChangesOptions(); var changes = database.ChangesSince(0, options, null); var expectedChanges = new RevisionList(); expectedChanges.AddItem(conflict); expectedChanges.AddItem(other); Assert.AreEqual(changes, expectedChanges); options.SetIncludeConflicts(true); changes = database.ChangesSince(0, options, null); expectedChanges = new RevisionList(); expectedChanges.AddItem(rev); expectedChanges.AddItem(conflict); expectedChanges.AddItem(other); Assert.AreEqual(changes, expectedChanges); }
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", e); _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); } // 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 = new ChangesOptions(); options.SetIncludeConflicts(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); } } }
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 SortedSet<long>(); 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); } 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; } }
public 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.) Log.D(Database.Tag, this + "|" + Sharpen.Thread.CurrentThread() + ": beginReplicating() called" ); if (creatingTarget) { Log.D(Database.Tag, this + "|" + Sharpen.Thread.CurrentThread() + ": creatingTarget == true, doing nothing" ); return; } else { Log.D(Database.Tag, this + "|" + Sharpen.Thread.CurrentThread() + ": creatingTarget != true, continuing" ); } if (filterName != null) { filter = db.GetFilter(filterName); } if (filterName != null && filter == null) { Log.W(Database.Tag, string.Format("%s: No ReplicationFilter registered for filter '%s'; ignoring" , this, filterName)); } // Process existing changes since the last push: long lastSequenceLong = 0; if (lastSequence != null) { lastSequenceLong = long.Parse(lastSequence); } ChangesOptions options = new ChangesOptions(); options.SetIncludeConflicts(true); RevisionList changes = db.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; db.AddChangeListener(this); Log.D(Database.Tag, this + "|" + Sharpen.Thread.CurrentThread() + ": pusher.beginReplicating() calling asyncTaskStarted()" ); AsyncTaskStarted(); } }
public override void BeginReplicating() { Log.D(Log.TagSync, "%s: beginReplicating() called", this); // 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(Log.TagSync, "%s: creatingTarget == true, doing nothing", this); return; } pendingSequences = Sharpen.Collections.SynchronizedSortedSet(new TreeSet<long>()); try { maxPendingSequence = long.Parse(lastSequence); } catch (FormatException) { Log.W(Log.TagSync, "Error converting lastSequence: %s to long. Using 0", lastSequence ); maxPendingSequence = System.Convert.ToInt64(0); } if (filterName != null) { filter = db.GetFilter(filterName); } if (filterName != null && filter == null) { Log.W(Log.TagSync, "%s: No ReplicationFilter registered for filter '%s'; ignoring" , this, filterName); } // Process existing changes since the last push: long lastSequenceLong = 0; if (lastSequence != null) { lastSequenceLong = long.Parse(lastSequence); } ChangesOptions options = new ChangesOptions(); options.SetIncludeConflicts(true); RevisionList changes = db.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; db.AddChangeListener(this); } }
public void TestRevTree() { var rev = new RevisionInternal("MyDocId", "4-foxy", false); var revProperties = new Dictionary <string, object>(); revProperties.Put("_id", rev.GetDocId()); revProperties.Put("_rev", rev.GetRevId()); revProperties["message"] = "hi"; rev.SetProperties(revProperties); var revHistory = new List <string>(); revHistory.AddItem(rev.GetRevId()); revHistory.AddItem("3-thrice"); revHistory.AddItem("2-too"); revHistory.AddItem("1-won"); database.ForceInsert(rev, revHistory, null); Assert.AreEqual(1, database.DocumentCount); VerifyHistory(database, rev, revHistory); var conflict = new RevisionInternal("MyDocId", "5-epsilon", false); var conflictProperties = new Dictionary <string, object>(); conflictProperties.Put("_id", conflict.GetDocId()); conflictProperties.Put("_rev", conflict.GetRevId()); conflictProperties["message"] = "yo"; conflict.SetProperties(conflictProperties); var conflictHistory = new List <string>(); conflictHistory.AddItem(conflict.GetRevId()); conflictHistory.AddItem("4-delta"); conflictHistory.AddItem("3-gamma"); conflictHistory.AddItem("2-too"); conflictHistory.AddItem("1-won"); database.ForceInsert(conflict, conflictHistory, null); Assert.AreEqual(1, database.DocumentCount); VerifyHistory(database, conflict, conflictHistory); // Add an unrelated document: var other = new RevisionInternal("AnotherDocID", "1-ichi", false); var otherProperties = new Dictionary <string, object>(); otherProperties["language"] = "jp"; other.SetProperties(otherProperties); var otherHistory = new List <string>(); otherHistory.AddItem(other.GetRevId()); database.ForceInsert(other, otherHistory, null); // Fetch one of those phantom revisions with no body: var rev2 = database.GetDocument(rev.GetDocId(), "2-too", true); Assert.IsNull(rev2); // Make sure no duplicate rows were inserted for the common revisions: Assert.AreEqual(8, database.LastSequenceNumber); // Make sure the revision with the higher revID wins the conflict: var current = database.GetDocument(rev.GetDocId(), null, true); Assert.AreEqual(conflict, current); // Get the _changes feed and verify only the winner is in it: var options = new ChangesOptions(); var changes = database.ChangesSince(0, options, null, null); var expectedChanges = new RevisionList(); expectedChanges.AddItem(conflict); expectedChanges.AddItem(other); Assert.AreEqual(expectedChanges, changes); options.SetIncludeConflicts(true); changes = database.ChangesSince(0, options, null, null); expectedChanges = new RevisionList(); expectedChanges.AddItem(rev); expectedChanges.AddItem(conflict); expectedChanges.AddItem(other); var expectedChangesAlt = new RevisionList(); expectedChangesAlt.AddItem(conflict); expectedChangesAlt.AddItem(rev); expectedChangesAlt.AddItem(other); Assert.IsTrue(expectedChanges.SequenceEqual(changes) || expectedChangesAlt.SequenceEqual(changes)); }