public RevisionInternal PutRevision(string inDocId, RevisionID inPrevRevId, IDictionary<string, object> properties, bool deleting, bool allowConflict, Uri source, StoreValidation validationBlock) { if(_config.HasFlag(C4DatabaseFlags.ReadOnly)) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.Forbidden, TAG, "Attempting to write to a readonly database (PutRevision)"); } var json = default(string); if(properties != null) { json = Manager.GetObjectMapper().WriteValueAsString(Database.StripDocumentJSON(properties), true); } else { json = "{}"; } if(inDocId == null) { inDocId = Misc.CreateGUID(); } C4Document* doc = null; var putRev = default(RevisionInternal); var change = default(DocumentChange); var success = RunInTransaction(() => { try { var docId = inDocId; var prevRevId = inPrevRevId; C4DocPutRequest rq = new C4DocPutRequest { body = json, docID = docId, deletion = deleting, hasAttachments = properties?.Get("_attachments") != null, existingRevision = false, allowConflict = allowConflict, history = prevRevId == null ? null : new[] { prevRevId.ToString() }, save = false }; UIntPtr commonAncestorIndex = UIntPtr.Zero; doc = (C4Document*)ForestDBBridge.Check(err => { UIntPtr tmp; var retVal = Native.c4doc_put(Forest, rq, &tmp, err); commonAncestorIndex = tmp; return retVal; }); if(docId == null) { docId = (string)doc->docID; } var newRevID = doc->selectedRev.revID.AsRevID(); Body body = null; if(properties != null) { properties.SetDocRevID(docId, newRevID); body = new Body(properties); } putRev = new RevisionInternal(docId, newRevID, deleting, body); if((uint)commonAncestorIndex == 0U) { return true; } if(validationBlock != null) { var prevRev = default(RevisionInternal); if(Native.c4doc_selectParentRevision(doc)) { prevRev = new ForestRevisionInternal(doc, false); } var status = validationBlock(putRev, prevRev, prevRev == null ? null : prevRev.RevID); if(status.IsError) { Log.To.Validation.I(TAG, "{0} ({1}) failed validation", new SecureLogString(docId, LogMessageSensitivity.PotentiallyInsecure), new SecureLogString(newRevID, LogMessageSensitivity.PotentiallyInsecure)); throw new CouchbaseLiteException("A document failed validation", status.Code); } } var isWinner = SaveDocument(doc, newRevID, properties); putRev.Sequence = (long)doc->sequence; change = ChangeWithNewRevision(putRev, isWinner, doc, null); return true; } finally { Native.c4doc_free(doc); } }); if(!success) { return null; } if(Delegate != null && change != null) { Delegate.DatabaseStorageChanged(change); } return putRev; }