internal void RevisionAdded(DocumentChange documentChange) { RevisionInternal rev = documentChange.GetWinningRevision(); if (rev == null) { return; } // current revision didn't change if (currentRevision != null && !rev.GetRevId().Equals(currentRevision.GetId())) { if (!rev.IsDeleted()) { currentRevision = new SavedRevision(this, rev); } else { currentRevision = null; } } foreach (Document.ChangeListener listener in changeListeners) { listener.Changed(new Document.ChangeEvent(this, documentChange)); } }
public void TestRevisionWithNull() { RevisionInternal revisionWitDeletedNull = new RevisionInternal(new Dictionary <string, Object> { { "_id", Guid.NewGuid().ToString() }, { "_rev", "1-23243234" }, { "_deleted", null } }); RevisionInternal revisionWithDeletedFalse = new RevisionInternal(new Dictionary <string, Object> { { "_id", Guid.NewGuid().ToString() }, { "_rev", "1-23243234" }, { "_deleted", false } }); RevisionInternal revisionWithDeletedTrue = new RevisionInternal(new Dictionary <string, Object> { { "_id", Guid.NewGuid().ToString() }, { "_rev", "1-23243234" }, { "_deleted", true } }); RevisionInternal revisionWithDeletedString = new RevisionInternal(new Dictionary <string, Object> { { "_id", Guid.NewGuid().ToString() }, { "_rev", "1-23243234" }, { "_deleted", "foo" } }); Assert.IsFalse(revisionWitDeletedNull.IsDeleted()); Assert.IsFalse(revisionWithDeletedFalse.IsDeleted()); Assert.IsFalse(revisionWithDeletedString.IsDeleted()); Assert.IsTrue(revisionWithDeletedTrue.IsDeleted()); }
public RevisionInternal PutLocalRevision(RevisionInternal revision, string prevRevId, bool obeyMVCC) { var docId = revision.GetDocId(); if (!docId.StartsWith("_local/")) { throw new CouchbaseLiteException("Local revision IDs must start with _local/", StatusCode.BadId); } if (revision.IsDeleted()) { DeleteLocalRevision(docId, prevRevId, obeyMVCC); return(revision); } var result = default(RevisionInternal); RunInTransaction(() => { var json = Manager.GetObjectMapper().WriteValueAsString(revision.GetProperties(), true); WithC4Raw(docId, "_local", doc => { var generation = RevisionInternal.GenerationFromRevID(prevRevId); if (obeyMVCC) { if (prevRevId != null) { if (prevRevId != (doc != null ? (string)doc->meta : null)) { throw new CouchbaseLiteException(StatusCode.Conflict); } if (generation == 0) { throw new CouchbaseLiteException(StatusCode.BadId); } } else if (doc != null) { throw new CouchbaseLiteException(StatusCode.Conflict); } } var newRevId = String.Format("{0}-local", ++generation); ForestDBBridge.Check(err => Native.c4raw_put(Forest, "_local", docId, newRevId, json, err)); result = revision.CopyWithDocID(docId, newRevId); }); return(true); }); return(result); }
/// <summary> /// Creates a dictionary of metadata for one specific revision /// </summary> /// <returns>The metadata dictionary</returns> /// <param name="rev">The revision to examine</param> /// <param name="responseState">The current response state</param> public static IDictionary <string, object> ChangesDictForRev(RevisionInternal rev, DBMonitorCouchbaseResponseState responseState) { return(new NonNullDictionary <string, object> { { "seq", rev.GetSequence() }, { "id", rev.GetDocId() }, { "changes", new List <object> { new Dictionary <string, object> { { "rev", rev.GetRevId() } } } }, { "deleted", rev.IsDeleted() ? (object)true : null }, { "doc", responseState.ChangesIncludeDocs ? rev.GetProperties() : null } }); }
/// <summary>Add a revision to the appropriate queue of revs to individually GET</summary> internal void QueueRemoteRevision(RevisionInternal rev) { if (rev.IsDeleted()) { if (deletedRevsToPull == null) { deletedRevsToPull = new List <RevisionInternal>(100); } deletedRevsToPull.AddItem(rev); } else { if (revsToPull == null) { revsToPull = new List <RevisionInternal>(100); } revsToPull.AddItem(rev); } }
private static void VerifyHistory(Database db, RevisionInternal rev, IList <string > history) { RevisionInternal gotRev = db.GetDocumentWithIDAndRev(rev.GetDocId(), null, EnumSet .NoneOf <TDContentOptions>()); NUnit.Framework.Assert.AreEqual(rev, gotRev); NUnit.Framework.Assert.AreEqual(rev.Properties, gotRev.Properties); IList <RevisionInternal> revHistory = db.GetRevisionHistory(gotRev); NUnit.Framework.Assert.AreEqual(history.Count, revHistory.Count); for (int i = 0; i < history.Count; i++) { RevisionInternal hrev = revHistory[i]; NUnit.Framework.Assert.AreEqual(rev.GetDocId(), hrev.GetDocId()); NUnit.Framework.Assert.AreEqual(history[i], hrev.GetRevId()); NUnit.Framework.Assert.IsFalse(rev.IsDeleted()); } }
private void VerifyHistory(Database db, RevisionInternal rev, IList <string> history) { var gotRev = db.GetDocumentWithIDAndRev(rev.GetDocId(), null, DocumentContentOptions.None); Assert.AreEqual(rev, gotRev); AssertPropertiesAreEqual(rev.GetProperties(), gotRev.GetProperties()); var revHistory = db.GetRevisionHistory(gotRev); Assert.AreEqual(history.Count, revHistory.Count); for (int i = 0; i < history.Count; i++) { RevisionInternal hrev = revHistory[i]; Assert.AreEqual(rev.GetDocId(), hrev.GetDocId()); Assert.AreEqual(history[i], hrev.GetRevId()); Assert.IsFalse(rev.IsDeleted()); } }
private void QueueRemoteRevision(RevisionInternal rev) { if (rev.IsDeleted()) { if (_deletedRevsToPull == null) { _deletedRevsToPull = new List <RevisionInternal>(100); } _deletedRevsToPull.AddItem(rev); } else { if (_revsToPull == null) { _revsToPull = new List <RevisionInternal>(100); } _revsToPull.AddItem(rev); } }
/// <summary> /// Creates a dictionary of metadata for one specific revision /// </summary> /// <returns>The metadata dictionary</returns> /// <param name="rev">The revision to examine</param> /// <param name="responseState">The current response state</param> public static IDictionary <string, object> ChangesDictForRev(RevisionInternal rev, DBMonitorCouchbaseResponseState responseState) { if (responseState.ChangesIncludeDocs) { var status = new Status(); var rev2 = DocumentMethods.ApplyOptions(responseState.ContentOptions, rev, responseState.Context, responseState.Db, status); if (rev2 != null) { rev2.SetSequence(rev.GetSequence()); rev = rev2; } } return(new NonNullDictionary <string, object> { { "seq", rev.GetSequence() }, { "id", rev.GetDocId() }, { "changes", new List <object> { new Dictionary <string, object> { { "rev", rev.GetRevId() } } } }, { "deleted", rev.IsDeleted() ? (object)true : null }, { "doc", responseState.ChangesIncludeDocs ? rev.GetProperties() : null } }); }
public void ForceInsert(RevisionInternal inRev, IList <string> revHistory, StoreValidation validationBlock, Uri source) { if (_config.HasFlag(C4DatabaseFlags.ReadOnly)) { throw new CouchbaseLiteException("Attempting to write to a readonly database", StatusCode.Forbidden); } var json = Manager.GetObjectMapper().WriteValueAsString(inRev.GetProperties(), true); var change = default(DocumentChange); RunInTransaction(() => { // First get the CBForest doc: WithC4Document(inRev.GetDocId(), null, false, true, doc => { ForestDBBridge.Check(err => Native.c4doc_insertRevisionWithHistory(doc, json, inRev.IsDeleted(), inRev.GetAttachments() != null, revHistory.ToArray(), err)); // Save updated doc back to the database: var isWinner = SaveDocument(doc, revHistory[0], inRev.GetProperties()); inRev.SetSequence((long)doc->sequence); change = ChangeWithNewRevision(inRev, isWinner, doc, source); }); return(true); }); if (change != null && Delegate != null) { Delegate.DatabaseStorageChanged(change); } }
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception> public virtual void TestValidations() { Validator validator = new _Validator_19(this); database.SetValidation("hoopy", validator); // POST a valid new document: IDictionary <string, object> props = new Dictionary <string, object>(); props.Put("name", "Zaphod Beeblebrox"); props.Put("towel", "velvet"); RevisionInternal rev = new RevisionInternal(props, database); Status status = new Status(); validationCalled = false; rev = database.PutRevision(rev, null, false, status); NUnit.Framework.Assert.IsTrue(validationCalled); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); // PUT a valid update: props.Put("head_count", 3); rev.SetProperties(props); validationCalled = false; rev = database.PutRevision(rev, rev.GetRevId(), false, status); NUnit.Framework.Assert.IsTrue(validationCalled); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); // PUT an invalid update: Sharpen.Collections.Remove(props, "towel"); rev.SetProperties(props); validationCalled = false; bool gotExpectedError = false; try { rev = database.PutRevision(rev, rev.GetRevId(), false, status); } catch (CouchbaseLiteException e) { gotExpectedError = (e.GetCBLStatus().GetCode() == Status.Forbidden); } NUnit.Framework.Assert.IsTrue(validationCalled); NUnit.Framework.Assert.IsTrue(gotExpectedError); // POST an invalid new document: props = new Dictionary <string, object>(); props.Put("name", "Vogon"); props.Put("poetry", true); rev = new RevisionInternal(props, database); validationCalled = false; gotExpectedError = false; try { rev = database.PutRevision(rev, null, false, status); } catch (CouchbaseLiteException e) { gotExpectedError = (e.GetCBLStatus().GetCode() == Status.Forbidden); } NUnit.Framework.Assert.IsTrue(validationCalled); NUnit.Framework.Assert.IsTrue(gotExpectedError); // PUT a valid new document with an ID: props = new Dictionary <string, object>(); props.Put("_id", "ford"); props.Put("name", "Ford Prefect"); props.Put("towel", "terrycloth"); rev = new RevisionInternal(props, database); validationCalled = false; rev = database.PutRevision(rev, null, false, status); NUnit.Framework.Assert.IsTrue(validationCalled); NUnit.Framework.Assert.AreEqual("ford", rev.GetDocId()); // DELETE a document: rev = new RevisionInternal(rev.GetDocId(), rev.GetRevId(), true, database); NUnit.Framework.Assert.IsTrue(rev.IsDeleted()); validationCalled = false; rev = database.PutRevision(rev, rev.GetRevId(), false, status); NUnit.Framework.Assert.IsTrue(validationCalled); // PUT an invalid new document: props = new Dictionary <string, object>(); props.Put("_id", "petunias"); props.Put("name", "Pot of Petunias"); rev = new RevisionInternal(props, database); validationCalled = false; gotExpectedError = false; try { rev = database.PutRevision(rev, null, false, status); } catch (CouchbaseLiteException e) { gotExpectedError = (e.GetCBLStatus().GetCode() == Status.Forbidden); } NUnit.Framework.Assert.IsTrue(validationCalled); NUnit.Framework.Assert.IsTrue(gotExpectedError); }
public void TestValidations() { ValidateDelegate validator = (newRevision, context) => { Assert.IsNotNull(newRevision); Assert.IsNotNull(context); Assert.IsTrue(newRevision.Properties != null || newRevision.IsDeletion); validationCalled = true; bool hoopy = newRevision.IsDeletion || (newRevision.Properties.Get("towel") != null); Log.V(ValidationsTest.Tag, string.Format("--- Validating {0} --> {1}", newRevision.Properties, hoopy)); if (!hoopy) { context.Reject("Where's your towel?"); } return(hoopy); }; database.SetValidation("hoopy", validator); // POST a valid new document: IDictionary <string, object> props = new Dictionary <string, object>(); props["name"] = "Zaphod Beeblebrox"; props["towel"] = "velvet"; RevisionInternal rev = new RevisionInternal(props, database); Status status = new Status(); validationCalled = false; rev = database.PutRevision(rev, null, false, status); Assert.IsTrue(validationCalled); Assert.AreEqual(StatusCode.Created, status.GetCode()); // PUT a valid update: props["head_count"] = 3; rev.SetProperties(props); validationCalled = false; rev = database.PutRevision(rev, rev.GetRevId(), false, status); Assert.IsTrue(validationCalled); Assert.AreEqual(StatusCode.Created, status.GetCode()); // PUT an invalid update: Sharpen.Collections.Remove(props, "towel"); rev.SetProperties(props); validationCalled = false; bool gotExpectedError = false; try { rev = database.PutRevision(rev, rev.GetRevId(), false, status); } catch (CouchbaseLiteException e) { gotExpectedError = (e.GetCBLStatus().GetCode() == StatusCode.Forbidden); } Assert.IsTrue(validationCalled); Assert.IsTrue(gotExpectedError); // POST an invalid new document: props = new Dictionary <string, object>(); props["name"] = "Vogon"; props["poetry"] = true; rev = new RevisionInternal(props, database); validationCalled = false; gotExpectedError = false; try { rev = database.PutRevision(rev, null, false, status); } catch (CouchbaseLiteException e) { gotExpectedError = (e.GetCBLStatus().GetCode() == StatusCode.Forbidden); } Assert.IsTrue(validationCalled); Assert.IsTrue(gotExpectedError); // PUT a valid new document with an ID: props = new Dictionary <string, object>(); props["_id"] = "ford"; props["name"] = "Ford Prefect"; props["towel"] = "terrycloth"; rev = new RevisionInternal(props, database); validationCalled = false; rev = database.PutRevision(rev, null, false, status); Assert.IsTrue(validationCalled); Assert.AreEqual("ford", rev.GetDocId()); // DELETE a document: rev = new RevisionInternal(rev.GetDocId(), rev.GetRevId(), true, database); Assert.IsTrue(rev.IsDeleted()); validationCalled = false; rev = database.PutRevision(rev, rev.GetRevId(), false, status); Assert.IsTrue(validationCalled); // PUT an invalid new document: props = new Dictionary <string, object>(); props["_id"] = "petunias"; props["name"] = "Pot of Petunias"; rev = new RevisionInternal(props, database); validationCalled = false; gotExpectedError = false; try { rev = database.PutRevision(rev, null, false, status); } catch (CouchbaseLiteException e) { gotExpectedError = (e.GetCBLStatus().GetCode() == StatusCode.Forbidden); } Assert.IsTrue(validationCalled); Assert.IsTrue(gotExpectedError); }
public override bool IsDeletion() { return(revisionInternal.IsDeleted()); }