private void SaveResolvedDocument([NotNull] Document resolved, [NotNull] Conflict conflict) { InBatch(() => { var doc = conflict.Mine; var otherDoc = conflict.Theirs; // Figure out what revision to delete and what if anything to add string winningRevID, losingRevID; byte[] mergedBody = null; if (ReferenceEquals(resolved, otherDoc)) { winningRevID = otherDoc.RevID; losingRevID = doc.RevID; } else { winningRevID = doc.RevID; losingRevID = otherDoc.RevID; if (!ReferenceEquals(resolved, doc)) { resolved.Database = this; mergedBody = resolved.Encode(); } } // Tell LiteCore to do the resolution: var rawDoc = doc.c4Doc?.HasValue == true ? doc.c4Doc.RawDoc : null; LiteCoreBridge.Check(err => Native.c4doc_resolveConflict(rawDoc, winningRevID, losingRevID, mergedBody, err)); LiteCoreBridge.Check(err => Native.c4doc_save(rawDoc, 0, err)); var logID = new SecureLogString(doc.Id, LogMessageSensitivity.PotentiallyInsecure); Log.To.Database.I(Tag, $"Conflict resolved as doc '{logID}' rev {rawDoc->revID.CreateString()}"); }); }
private void Save([NotNull] Document doc, C4Document **outDoc, C4Document *baseDoc, bool deletion) { var revFlags = (C4RevisionFlags)0; if (deletion) { revFlags = C4RevisionFlags.Deleted; } byte[] body = null; if (!deletion && !doc.IsEmpty) { body = doc.Encode(); var root = Native.FLValue_FromTrustedData(body); if (root == null) { Log.To.Database.E(Tag, "Failed to encode document body properly. Aborting save of document!"); return; } var rootDict = Native.FLValue_AsDict(root); if (rootDict == null) { Log.To.Database.E(Tag, "Failed to encode document body properly. Aborting save of document!"); return; } ThreadSafety.DoLocked(() => { if (Native.c4doc_dictContainsBlobs(rootDict, SharedStrings.SharedKeys)) { revFlags |= C4RevisionFlags.HasAttachments; } }); } else if (doc.IsEmpty) { FLEncoder *encoder = SharedEncoder; Native.FLEncoder_BeginDict(encoder, 0); Native.FLEncoder_EndDict(encoder); body = Native.FLEncoder_Finish(encoder, null); Native.FLEncoder_Reset(encoder); } var rawDoc = baseDoc != null ? baseDoc : doc.c4Doc?.HasValue == true ? doc.c4Doc.RawDoc : null; if (rawDoc != null) { doc.ThreadSafety.DoLocked(() => { ThreadSafety.DoLocked(() => { *outDoc = (C4Document *)NativeHandler.Create() .AllowError((int)C4ErrorCode.Conflict, C4ErrorDomain.LiteCoreDomain).Execute( err => Native.c4doc_update(rawDoc, body, revFlags, err)); }); }); } else { ThreadSafety.DoLocked(() => { *outDoc = (C4Document *)NativeHandler.Create() .AllowError((int)C4ErrorCode.Conflict, C4ErrorDomain.LiteCoreDomain).Execute( err => Native.c4doc_create(_c4db, doc.Id, body, revFlags, err)); }); } }