Example #1
0
 public static bool c4doc_resolveConflict(C4Document *doc, string winningRevID, string losingRevID, byte[] mergedBody, C4RevisionFlags mergedFlags, C4Error *error)
 {
     using (var winningRevID_ = new C4String(winningRevID))
         using (var losingRevID_ = new C4String(losingRevID))
             fixed(byte *mergedBody_ = mergedBody)
             {
                 return(NativeRaw.c4doc_resolveConflict(doc, winningRevID_.AsFLSlice(), losingRevID_.AsFLSlice(), new FLSlice(mergedBody_, mergedBody == null ? 0 : (ulong)mergedBody.Length), mergedFlags, error));
             }
 }
 /// <summary>
 /// Creates a CBForestHistoryEnumerator that enumerates all specified revisions
 /// of a document
 /// </summary>
 /// <param name="doc">The document to enumerate</param>
 /// <param name="onlyLeaf">If set to <c>true</c> only leaf revisions (i.e. revisions
 /// with no children) will be processed</param>
 /// <param name="owner">If set to <c>true</c>, the enumerator will free the document
 /// when finished</param>
 public CBForestHistoryEnumerator(C4Document *doc, bool onlyLeaf, bool owner)
 {
     _doc      = doc;
     _onlyLeaf = onlyLeaf;
     _owner    = owner;
     if (!_owner)
     {
         GC.SuppressFinalize(this);
     }
 }
Example #3
0
        protected override void Dispose(bool finalizing)
        {
            var native = _native;

            _native = null;
            if (native != null)
            {
                Native.c4doc_free(native);
            }
        }
 public static bool c4indexer_emit(C4Indexer *indexer,
                                   C4Document *document,
                                   uint viewNumber,
                                   C4Key *[] emittedKeys,
                                   C4Slice[] emittedValues,
                                   C4Error *outError)
 {
     return(c4indexer_emit(indexer, document, viewNumber, (uint)emittedKeys.Length, emittedKeys,
                           emittedValues, outError));
 }
Example #5
0
        private List <string> GetAllParentRevisions(C4Document *doc)
        {
            var history = new List <string>();

            do
            {
                history.Add(doc->selectedRev.revID.CreateString());
            } while (Native.c4doc_selectParentRevision(doc));

            return(history);
        }
Example #6
0
        private void VerifyRev(C4Document *doc, string[] history, string body)
        {
            doc->revID.CreateString().Should().Be(history[0]);
            doc->selectedRev.revID.CreateString().Should().Be(history[0]);
            doc->selectedRev.body.CreateString().Should().Be(body);

            var revs = GetAllParentRevisions(doc);

            revs.Count.Should().Be(history.Length);
            revs.SequenceEqual(history).Should().BeTrue();
        }
Example #7
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="doc">The document to retrieve information form.</param>
 /// <param name="owner">Whether or not the instance should own the
 /// document (i.e. free it when it is finished)</param>
 public CBForestDocStatus(C4Document *doc, bool owner)
 {
     DocumentInfo           = (C4DocumentInfo *)Marshal.AllocHGlobal(sizeof(C4DocumentInfo)).ToPointer();
     DocumentInfo->docID    = doc->docID;
     DocumentInfo->revID    = doc->revID;
     DocumentInfo->flags    = doc->flags;
     DocumentInfo->sequence = doc->sequence;
     _document = doc;
     _owner    = owner;
     Sequence  = (long)doc->sequence;
 }
Example #8
0
        private void VerifyRev(C4Document *doc, string[] history, FLSlice body)
        {
            doc->revID.CreateString().Should().Be(history[0]);
            doc->selectedRev.revID.CreateString().Should().Be(history[0]);
            Native.FLSlice_Equal(NativeRaw.c4doc_getRevisionBody(doc), body).Should().BeTrue();

            var revs = GetAllParentRevisions(doc);

            revs.Count.Should().Be(history.Length);
            revs.SequenceEqual(history).Should().BeTrue();
        }
        public CBForestDocStatus(C4Document *doc, bool owner)
        {
            Document = doc;
            _owner   = owner;
            if (!_owner)
            {
                GC.SuppressFinalize(this);
            }

            _docID = new Lazy <string>(() => (string)Document->docID);
            _revID = new Lazy <string>(() => (string)Document->revID);
        }
 public static bool c4indexer_emit(C4Indexer *indexer,
                                   C4Document *document,
                                   uint viewNumber,
                                   uint nKeys,
                                   C4Key *[] emittedKeys,
                                   C4Slice[] emittedValues,
                                   C4Error *outError)
 {
     fixed(C4Key **p = emittedKeys)
     {
         return(NativeRaw.c4indexer_emit(indexer, document, viewNumber, nKeys, p,
                                         emittedValues, outError));
     }
 }
        private void Dispose(bool disposing)
        {
            if (!_owner)
            {
                return;
            }

            var doc = _doc;

            _doc     = null;
            _current = null;
            if (doc != null)
            {
                Native.c4doc_free(doc);
            }
        }
Example #12
0
        private bool SaveDocument(C4Document *doc, string revId, IDictionary <string, object> properties)
        {
            // Is the new revision the winner?
            Native.c4doc_selectCurrentRevision(doc);
            bool isWinner = (string)doc->selectedRev.revID == revId;

            // Update the documentType:
            if (isWinner)
            {
                var type = properties == null ? null : properties.GetCast <string>("type");
                ForestDBBridge.Check(err => Native.c4doc_setType(doc, type, err));
            }

            // Save:
            ForestDBBridge.Check(err => Native.c4doc_save(doc, (uint)MaxRevTreeDepth, err));
            return(isWinner);
        }
Example #13
0
        internal static LiteCoreDocument Get(C4Database *parent, C4SequenceNumber seq)
        {
            C4Error     err;
            C4Document *native = Native.c4doc_getBySequence(parent, seq, &err);

            if (native == null)
            {
                if (err.Code != 0)
                {
                    throw new LiteCoreException(err);
                }

                return(null);
            }

            return(new LiteCoreDocument(native));
        }
Example #14
0
        internal static LiteCoreDocument Get(C4Database *parent, string docID, bool mustExist)
        {
            C4Error     err;
            C4Document *native = Native.c4doc_get(parent, docID, mustExist, &err);

            if (native == null)
            {
                if (err.Code != 0)
                {
                    throw new LiteCoreException(err);
                }

                return(null);
            }

            return(new LiteCoreDocument(native));
        }
Example #15
0
        private List <string> GetRevisionHistory(C4Document *doc, bool onlyCurrent, bool includeDeleted)
        {
            var history = new List <string>();

            do
            {
                if (onlyCurrent && !doc->selectedRev.flags.HasFlag(C4RevisionFlags.Leaf))
                {
                    continue;
                }

                if (!includeDeleted && doc->selectedRev.flags.HasFlag(C4RevisionFlags.Deleted))
                {
                    continue;
                }

                history.Add(doc->selectedRev.revID.CreateString());
            } while (Native.c4doc_selectNextRevision(doc));

            return(history);
        }
Example #16
0
 public static int c4doc_purgeRevision(C4Document *doc, string revID, C4Error *outError)
 {
     using (var revID_ = new C4String(revID)) {
         return(NativeRaw.c4doc_purgeRevision(doc, revID_.AsFLSlice(), outError));
     }
 }
Example #17
0
        public void TestCreateVersionedDoc()
        {
            RunTestVariants(() => {
                // Try reading doc with mustExist=true, which should fail:
                C4Error error;
                C4Document *doc = NativeRaw.c4doc_get(Db, DocID, true, &error);
                ((long)doc).Should().Be(0, "because the document does not exist");
                error.domain.Should().Be(C4ErrorDomain.LiteCoreDomain);
                error.code.Should().Be((int)C4ErrorCode.NotFound);
                Native.c4doc_free(doc);

                // Now get the doc with mustExist=false, which returns an empty doc:
                doc = (C4Document *)LiteCoreBridge.Check(err => NativeRaw.c4doc_get(Db, DocID, false, err));
                ((int)doc->flags).Should().Be(0, "because the document is empty");
                doc->docID.Equals(DocID).Should().BeTrue("because the doc ID should match what was stored");
                ((long)doc->revID.buf).Should().Be(0, "because the doc has no revision ID yet");
                ((long)doc->selectedRev.revID.buf).Should().Be(0, "because the doc has no revision ID yet");
                Native.c4doc_free(doc);

                LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                try {
                    var tmp = RevID;
                    var rq  = new C4DocPutRequest {
                        existingRevision = true,
                        docID            = DocID,
                        history          = &tmp,
                        historyCount     = 1,
                        body             = Body,
                        save             = true
                    };

                    doc = (C4Document *)LiteCoreBridge.Check(err => {
                        var localRq = rq;
                        return(Native.c4doc_put(Db, &localRq, null, err));
                    });
                    doc->revID.Equals(RevID).Should().BeTrue("because the doc should have the stored revID");
                    doc->selectedRev.revID.Equals(RevID).Should().BeTrue("because the doc should have the stored revID");
                    doc->selectedRev.flags.Should().Be(C4RevisionFlags.Leaf, "because this is a leaf revision");
                    doc->selectedRev.body.Equals(Body).Should().BeTrue("because the body should be stored correctly");
                    Native.c4doc_free(doc);
                } finally {
                    LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                }

                // Reload the doc:
                doc = (C4Document *)LiteCoreBridge.Check(err => NativeRaw.c4doc_get(Db, DocID, true, err));
                doc->flags.Should().Be(C4DocumentFlags.DocExists, "because this is an existing document");
                doc->docID.Equals(DocID).Should().BeTrue("because the doc should have the stored doc ID");
                doc->revID.Equals(RevID).Should().BeTrue("because the doc should have the stored rev ID");
                doc->selectedRev.revID.Equals(RevID).Should().BeTrue("because the doc should have the stored rev ID");
                doc->selectedRev.sequence.Should().Be(1, "because it is the first stored document");
                doc->selectedRev.body.Equals(Body).Should().BeTrue("because the doc should have the stored body");
                Native.c4doc_free(doc);

                // Get the doc by its sequence
                doc = (C4Document *)LiteCoreBridge.Check(err => Native.c4doc_getBySequence(Db, 1, err));
                doc->flags.Should().Be(C4DocumentFlags.DocExists, "because this is an existing document");
                doc->docID.Equals(DocID).Should().BeTrue("because the doc should have the stored doc ID");
                doc->revID.Equals(RevID).Should().BeTrue("because the doc should have the stored rev ID");
                doc->selectedRev.revID.Equals(RevID).Should().BeTrue("because the doc should have the stored rev ID");
                doc->selectedRev.sequence.Should().Be(1, "because it is the first stored document");
                doc->selectedRev.body.Equals(Body).Should().BeTrue("because the doc should have the stored body");
                Native.c4doc_free(doc);
            });
        }
Example #18
0
 public static extern bool c4doc_selectNextRevision(C4Document *doc);
Example #19
0
 public static extern bool c4doc_selectNextLeafRevision(C4Document *doc, [MarshalAs(UnmanagedType.U1)] bool includeDeleted, [MarshalAs(UnmanagedType.U1)] bool withBody, C4Error *outError);
Example #20
0
 public static extern bool c4doc_hasRevisionBody(C4Document *doc);
Example #21
0
 public static byte[] c4doc_getRevisionBody(C4Document *doc)
 {
     return(NativeRaw.c4doc_getRevisionBody(doc).ToArrayFast());
 }
Example #22
0
 public static bool c4doc_selectRevision(C4Document *doc, string revID, bool withBody, C4Error *outError)
 {
     using (var revID_ = new C4String(revID)) {
         return(NativeRaw.c4doc_selectRevision(doc, revID_.AsFLSlice(), withBody, outError));
     }
 }
Example #23
0
 public static extern bool c4doc_loadRevisionBody(C4Document *doc, C4Error *outError);
Example #24
0
 public static extern bool c4doc_save(C4Document *doc, uint maxRevTreeDepth, C4Error *outError);
Example #25
0
 public static extern C4Document *c4doc_update(C4Document *doc, FLSlice revisionBody, C4RevisionFlags revisionFlags, C4Error *error);
Example #26
0
 public static extern bool c4doc_resolveConflict(C4Document *doc, FLSlice winningRevID, FLSlice losingRevID, FLSlice mergedBody, C4RevisionFlags mergedFlags, C4Error *error);
Example #27
0
 public static extern int c4doc_purgeRevision(C4Document *doc, FLSlice revID, C4Error *outError);
Example #28
0
        public void TestPurge()
        {
            RunTestVariants(() => {
                var body2 = C4Slice.Constant("{\"ok\":\"go\"}");
                var body3 = C4Slice.Constant("{\"ubu\":\"roi\"}");
                CreateRev(DocID.CreateString(), RevID, Body);
                CreateRev(DocID.CreateString(), Rev2ID, body2);
                CreateRev(DocID.CreateString(), Rev3ID, body3);

                var history = new[] { C4Slice.Constant("3-ababab"), Rev2ID };
                fixed(C4Slice * history_ = history)
                {
                    var rq = new C4DocPutRequest
                    {
                        existingRevision = true,
                        docID            = DocID,
                        history          = history_,
                        historyCount     = 2,
                        body             = body3,
                        save             = true
                    };

                    C4Error error;
                    C4Document *doc = null;
                    LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                    try {
                        doc = Native.c4doc_put(Db, &rq, null, &error);
                        ((IntPtr)doc).Should().NotBe(IntPtr.Zero);
                        Native.c4doc_free(doc);
                    } finally {
                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                    }

                    LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                    try {
                        LiteCoreBridge.Check(err => NativeRaw.c4db_purgeDoc(Db, DocID, err));
                    } finally {
                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                    }

                    Native.c4db_getDocumentCount(Db).Should().Be(0UL);

                    CreateRev(DocID.CreateString(), RevID, Body);
                    CreateRev(DocID.CreateString(), Rev2ID, body2);
                    CreateRev(DocID.CreateString(), Rev3ID, body3);

                    LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                    try {
                        doc = Native.c4doc_put(Db, &rq, null, &error);
                        ((IntPtr)doc).Should().NotBe(IntPtr.Zero);
                    } finally {
                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                    }

                    LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                    try {
                        LiteCoreBridge.Check(err => Native.c4doc_purgeRevision(doc, null, err));
                        LiteCoreBridge.Check(err => Native.c4doc_save(doc, 0, err));
                    } finally {
                        Native.c4doc_free(doc);
                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                    }

                    Native.c4db_getDocumentCount(Db).Should().Be(0UL);
                }
            });
        }
Example #29
0
        public void TestUpdate()
        {
            RunTestVariants(() =>
            {
                WriteLine("Begin test");
                C4Document *doc = null;
                LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                try {
                    WriteLine("Begin create");
                    doc = (C4Document *)LiteCoreBridge.Check(err => NativeRaw.c4doc_create(Db, DocID, Body, 0, err));
                } finally {
                    LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                }

                WriteLine("After save");
                var expectedRevID = IsRevTrees()
                    ? C4Slice.Constant("1-c10c25442d9fe14fa3ca0db4322d7f1e43140fab")
                    : C4Slice.Constant("1@*");

                doc->revID.Equals(expectedRevID).Should().BeTrue();
                doc->flags.Should().Be(C4DocumentFlags.DocExists, "because the document was saved");
                doc->selectedRev.revID.Equals(expectedRevID).Should().BeTrue();
                doc->docID.Equals(DocID).Should().BeTrue("because that is the document ID that it was saved with");

                // Read the doc into another C4Document
                var doc2 = (C4Document *)LiteCoreBridge.Check(err => NativeRaw.c4doc_get(Db, DocID, false, err));
                doc->revID.Equals(expectedRevID).Should()
                .BeTrue("because the other reference should have the same rev ID");

                LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                try {
                    WriteLine("Begin 2nd save");
                    var updatedDoc =
                        (C4Document *)LiteCoreBridge.Check(
                            err => Native.c4doc_update(doc, Encoding.UTF8.GetBytes("{\"ok\":\"go\"}"), 0, err));
                    doc->selectedRev.revID.Equals(expectedRevID).Should().BeTrue();
                    doc->revID.Equals(expectedRevID).Should().BeTrue();
                    Native.c4doc_free(doc);
                    doc = updatedDoc;
                }
                finally {
                    LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                }

                WriteLine("After 2nd save");
                var expectedRev2ID = IsRevTrees()
                    ? C4Slice.Constant("2-32c711b29ea3297e27f3c28c8b066a68e1bb3f7b")
                    : C4Slice.Constant("2@*");
                doc->revID.Equals(expectedRev2ID).Should().BeTrue();
                doc->selectedRev.revID.Equals(expectedRev2ID).Should().BeTrue();

                LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                try {
                    WriteLine("Begin conflicting save");
                    C4Error error;
                    ((long)Native.c4doc_update(doc2, Encoding.UTF8.GetBytes("{\"ok\":\"no way\"}"), 0, &error)).Should().Be(0, "because this is a conflict");
                    error.code.Should().Be((int)C4ErrorCode.Conflict);
                    error.domain.Should().Be(C4ErrorDomain.LiteCoreDomain);
                }
                finally {
                    LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                }

                LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                try {
                    WriteLine("Begin conflicting create");
                    C4Error error;
                    ((long)NativeRaw.c4doc_create(Db, DocID, C4Slice.Constant("{\"ok\":\"no way\"}"), 0, &error)).Should().Be(0, "because this is a conflict");
                    error.code.Should().Be((int)C4ErrorCode.Conflict);
                    error.domain.Should().Be(C4ErrorDomain.LiteCoreDomain);
                }
                finally {
                    LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                }

                Native.c4doc_free(doc);
                Native.c4doc_free(doc2);
            });
        }
Example #30
0
 public static extern bool c4doc_selectCommonAncestorRevision(C4Document *doc, FLSlice rev1ID, FLSlice rev2ID);