Beispiel #1
0
        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());
        }
Beispiel #3
0
        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 }
     });
 }
Beispiel #5
0
 /// <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);
     }
 }
Beispiel #6
0
        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());
            }
        }
Beispiel #8
0
        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);
            }
        }
Beispiel #9
0
 /// <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 }
     });
 }
Beispiel #10
0
        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);
            }
        }
Beispiel #11
0
        /// <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());
 }