Ejemplo n.º 1
0
        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()}");
            });
        }
Ejemplo n.º 2
0
        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));
                });
            }
        }