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); } }
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)); }
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); }
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(); }
/// <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; }
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); } }
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); }
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)); }
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)); }
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); }
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)); } }
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); }); }
public static extern bool c4doc_selectNextRevision(C4Document *doc);
public static extern bool c4doc_selectNextLeafRevision(C4Document *doc, [MarshalAs(UnmanagedType.U1)] bool includeDeleted, [MarshalAs(UnmanagedType.U1)] bool withBody, C4Error *outError);
public static extern bool c4doc_hasRevisionBody(C4Document *doc);
public static byte[] c4doc_getRevisionBody(C4Document *doc) { return(NativeRaw.c4doc_getRevisionBody(doc).ToArrayFast()); }
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)); } }
public static extern bool c4doc_loadRevisionBody(C4Document *doc, C4Error *outError);
public static extern bool c4doc_save(C4Document *doc, uint maxRevTreeDepth, C4Error *outError);
public static extern C4Document *c4doc_update(C4Document *doc, FLSlice revisionBody, C4RevisionFlags revisionFlags, C4Error *error);
public static extern bool c4doc_resolveConflict(C4Document *doc, FLSlice winningRevID, FLSlice losingRevID, FLSlice mergedBody, C4RevisionFlags mergedFlags, C4Error *error);
public static extern int c4doc_purgeRevision(C4Document *doc, FLSlice revID, C4Error *outError);
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); } }); }
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); }); }
public static extern bool c4doc_selectCommonAncestorRevision(C4Document *doc, FLSlice rev1ID, FLSlice rev2ID);