public void AckRequest(string host, AcknowledgeDto acknowledgeDto)
 {
     using (var cf = GetChannelFactory(host))
     {
         cf.CreateChannel().AckRequest(acknowledgeDto);
     }
 }
예제 #2
0
        private void ConfirmPendingUpdate(Document document, AcknowledgeDto dto)
        {
            var result = _diffMatchPatch.patch_apply(document.PendingUpdate.Patch, document.Content);

            if (CheckResultIsValidOtherwiseReOpen(result, dto.DocumentId))
            {
                document.PendingUpdate.NewRevisionId = dto.NewRevisionId;
                document.PendingUpdate.NewHash       = dto.NewHash;
                UpdateDocument(document, document.PendingUpdate, result);
            }
            var currentText = _editor.GetText(dto.DocumentId);

            if (document.Content != currentText)
            {
                //send next update
                var updateDto = CreateUpdateDto(document, currentText);
                document.PendingUpdate = updateDto;

                SendUpdateToDocumentOwner(document, updateDto);
            }
            else
            {
                document.PendingUpdate = null;
            }
        }
예제 #3
0
 public void AckRequest(string host, AcknowledgeDto acknowledgeDto)
 {
     using (var cf = GetChannelFactory(host))
     {
         cf.CreateChannel().AckRequest(acknowledgeDto);
     }
 }
예제 #4
0
 public void AckRequest(AcknowledgeDto dto)
 {
     //do we know the document?
     if (_documents.ContainsKey(dto.DocumentId))
     {
         var document = _documents[dto.DocumentId];
         if (document.Owner != _memberName && document.PendingUpdate != null)
         {
             if (document.PendingUpdate.PreviousRevisionId == dto.PreviousRevisionId && document.PendingUpdate.PreviousHash.SequenceEqual(dto.PreviousHash))
             {
                 ConfirmPendingUpdate(document, dto);
             }
             else if (document.OutOfSyncAcknowledge != null)
             {
                 document.OutOfSyncAcknowledge = dto;
             }
             else
             {
                 ReOpenDocument(document.Id);
             }
         }
     }
 }
 public void AckRequest(AcknowledgeDto dto)
 {
     //do we know the document?
     if (_documents.ContainsKey(dto.DocumentId))
     {
         var document = _documents[dto.DocumentId];
         if (document.Owner != _memberName && document.PendingUpdate != null)
         {
             if (document.PendingUpdate.PreviousRevisionId == dto.PreviousRevisionId && document.PendingUpdate.PreviousHash.SequenceEqual(dto.PreviousHash))
             {
                 ConfirmPendingUpdate(document, dto);
             }
             else if (document.OutOfSyncAcknowledge != null)
             {
                 document.OutOfSyncAcknowledge = dto;
             }
             else
             {
                 ReOpenDocument(document.Id);
             }
         }
     }
 }
예제 #6
0
        private void CreatePatchForUpdate(Document document, UpdateDto updateDto)
        {
            var currentRevision = document.GetCurrentRevision();
            var lastUpdate      = currentRevision.UpdateDto;
            //non existing revision - used as null object
            var secondLastUpdate = new UpdateDto {
                NewRevisionId = -1
            };

            if (document.CurrentRevisionId > FIRST_VALID_REVISON_ID)
            {
                secondLastUpdate = document.GetRevision(document.CurrentRevisionId - 1).UpdateDto;
            }

            bool creationSucessfull = false;

            //update is either based on current version
            //or on previous version where
            //   - the member which initialised the previous version was the owner itself
            //   - or a member with a lower member name (and thus the given update will be applied afterwards)
            //)
            if (IsFirstPreviousOfSecond(lastUpdate, updateDto) ||
                (IsFirstPreviousOfSecond(secondLastUpdate, updateDto) &&
                 MemberOfFirstUpdateIsOwnerOrLowerMember(lastUpdate, updateDto)
                )
                )
            {
                var result = _diffMatchPatch.patch_apply(updateDto.Patch, document.Content);
                if (result.Item2.All(x => x))
                {
                    document.Content   = result.Item1;
                    creationSucessfull = true;
                }
                else
                {
                    HandleErrorOnUpdate(updateDto);
                }
            }
            else
            {
                var revision = document.GetRevision(updateDto.PreviousRevisionId);
                if (revision.Id + SUPPORTED_NUM_OF_REACTIVE_UPDATES >= currentRevision.Id)
                {
                    var nextRevision = document.GetRevision(revision.Id + 1);
                    //move to next revision as long as
                    while (
                        nextRevision.UpdateDto.PreviousHash.SequenceEqual(updateDto.PreviousHash) &&
                        MemberOfFirstUpdateIsNotOwnerAndHigherMember(updateDto, nextRevision.UpdateDto) &&
                        nextRevision.Id < currentRevision.Id)
                    {
                        revision     = nextRevision;
                        nextRevision = document.GetRevision(nextRevision.Id + 1);
                    }

                    var content     = revision.Content;
                    var tmpRevision = revision;
                    var patch       = updateDto.Patch;

                    //apply all patches on top of the found revision
                    while (tmpRevision.Id <= currentRevision.Id)
                    {
                        var result = _diffMatchPatch.patch_apply(patch, content);
                        if (result.Item2.All(x => x))
                        {
                            content = result.Item1;
                            if (tmpRevision.Id == currentRevision.Id)
                            {
                                break;
                            }
                            tmpRevision = document.GetRevision(tmpRevision.Id + 1);
                            patch       = tmpRevision.UpdateDto.Patch;
                        }
                        else
                        {
                            HandleErrorOnUpdate(updateDto);
                        }
                    }
                    document.Content   = content;
                    updateDto.Patch    = _diffMatchPatch.patch_make(currentRevision.Content, content);
                    creationSucessfull = true;
                }
            }

            if (creationSucessfull)
            {
                document.CurrentRevisionId = currentRevision.Id + 1;
                document.CurrentHash       = GetHash(document.Content);
                updateDto.NewRevisionId    = document.CurrentRevisionId;
                updateDto.NewHash          = document.CurrentHash;
                document.AddRevision(new Revision
                {
                    Id        = document.CurrentRevisionId,
                    Content   = document.Content,
                    UpdateDto = updateDto
                });

                if (IsNotOwnUpdate(updateDto))
                {
                    _editor.UpdateText(updateDto.DocumentId, document.Content);

                    var acknowledgeDto = new AcknowledgeDto
                    {
                        PreviousRevisionId = updateDto.PreviousRevisionId,
                        PreviousHash       = updateDto.PreviousHash,
                        NewRevisionId      = updateDto.NewRevisionId,
                        NewHash            = updateDto.NewHash,
                        DocumentId         = document.Id
                    };

                    _communication.AckRequest(updateDto.MemberHost, acknowledgeDto);
                }

                var newUpdateDto = new UpdateDto
                {
                    DocumentId         = document.Id,
                    MemberName         = updateDto.MemberName,
                    MemberHost         = _serverHost,
                    PreviousRevisionId = updateDto.PreviousRevisionId,
                    PreviousHash       = updateDto.PreviousHash,
                    NewRevisionId      = updateDto.NewRevisionId,
                    NewHash            = updateDto.NewHash,
                    Patch       = updateDto.Patch,
                    EditorCount = document.EditorCount
                };

                foreach (var editorHost in document.Editors().Values)
                {
                    if (updateDto.MemberHost != editorHost)
                    {
                        try
                        {
                            _communication.UpdateRequest(editorHost, newUpdateDto);
                        }
                        catch (EndpointNotFoundException)
                        {
                            document.Editors().Remove(editorHost);
                        }
                    }
                }
            }
            else if (IsNotOwnUpdate(updateDto))
            {
                HandleErrorOnUpdate(updateDto);
            }
        }
        private void CreatePatchForUpdate(Document document, UpdateDto updateDto)
        {
            var currentRevision = document.GetCurrentRevision();
            var lastUpdate = currentRevision.UpdateDto;
            //non existing revision - used as null object
            var secondLastUpdate = new UpdateDto {NewRevisionId = -1};
            if (document.CurrentRevisionId > FIRST_VALID_REVISON_ID)
            {
                secondLastUpdate=document.GetRevision(document.CurrentRevisionId - 1).UpdateDto;
            }

            bool creationSucessfull = false;

            //update is either based on current version
            //or on previous version where
            //   - the member which initialised the previous version was the owner itself
            //   - or a member with a lower member name (and thus the given update will be applied afterwards)
            //)
            if (IsFirstPreviousOfSecond(lastUpdate, updateDto) ||
                (IsFirstPreviousOfSecond(secondLastUpdate, updateDto)
                   && MemberOfFirstUpdateIsOwnerOrLowerMember(lastUpdate, updateDto)
                )
            )
            {
                var result = _diffMatchPatch.patch_apply(updateDto.Patch, document.Content);
                if (result.Item2.All(x => x))
                {
                    document.Content = result.Item1;
                    creationSucessfull = true;
                }else
                {
                   HandleErrorOnUpdate(updateDto);
                }
            }
            else
            {
                var revision = document.GetRevision(updateDto.PreviousRevisionId);
                if (revision.Id + SUPPORTED_NUM_OF_REACTIVE_UPDATES >= currentRevision.Id)
                {
                    var nextRevision = document.GetRevision(revision.Id + 1);
                    //move to next revision as long as
                    while (
                        nextRevision.UpdateDto.PreviousHash.SequenceEqual(updateDto.PreviousHash)
                        && MemberOfFirstUpdateIsNotOwnerAndHigherMember(updateDto, nextRevision.UpdateDto)
                        && nextRevision.Id < currentRevision.Id)
                    {
                        revision = nextRevision;
                        nextRevision = document.GetRevision(nextRevision.Id + 1);
                    }

                    var content = revision.Content;
                    var tmpRevision = revision;
                    var patch = updateDto.Patch;

                    //apply all patches on top of the found revision
                    while (tmpRevision.Id <= currentRevision.Id)
                    {
                        var result = _diffMatchPatch.patch_apply(patch, content);
                        if (result.Item2.All(x => x))
                        {
                            content = result.Item1;
                            if (tmpRevision.Id == currentRevision.Id)
                            {
                                break;
                            }
                            tmpRevision = document.GetRevision(tmpRevision.Id + 1);
                            patch = tmpRevision.UpdateDto.Patch;
                        }
                        else
                        {
                            HandleErrorOnUpdate(updateDto);
                        }
                    }
                    document.Content = content;
                    updateDto.Patch = _diffMatchPatch.patch_make(currentRevision.Content, content);
                    creationSucessfull = true;
                }
            }

            if (creationSucessfull)
            {

                document.CurrentRevisionId = currentRevision.Id + 1;
                document.CurrentHash = GetHash(document.Content);
                updateDto.NewRevisionId = document.CurrentRevisionId;
                updateDto.NewHash = document.CurrentHash;
                document.AddRevision(new Revision
                {
                    Id = document.CurrentRevisionId,
                    Content = document.Content,
                    UpdateDto = updateDto
                });

                if (IsNotOwnUpdate(updateDto))
                {
                    _editor.UpdateText(updateDto.DocumentId, document.Content);

                    var acknowledgeDto = new AcknowledgeDto
                    {
                        PreviousRevisionId = updateDto.PreviousRevisionId,
                        PreviousHash = updateDto.PreviousHash,
                        NewRevisionId = updateDto.NewRevisionId,
                        NewHash = updateDto.NewHash,
                        DocumentId = document.Id
                    };

                    _communication.AckRequest(updateDto.MemberHost, acknowledgeDto);
                }

                var newUpdateDto = new UpdateDto
                {
                    DocumentId = document.Id,
                    MemberName = updateDto.MemberName,
                    MemberHost = _serverHost,
                    PreviousRevisionId = updateDto.PreviousRevisionId,
                    PreviousHash = updateDto.PreviousHash,
                    NewRevisionId = updateDto.NewRevisionId,
                    NewHash = updateDto.NewHash,
                    Patch = updateDto.Patch,
                    EditorCount = document.EditorCount
                };

                foreach (var editorHost in document.Editors().Values)
                {
                    if (updateDto.MemberHost != editorHost)
                    {
                        try
                        {
                            _communication.UpdateRequest(editorHost, newUpdateDto);
                        }
                        catch (EndpointNotFoundException)
                        {
                            document.Editors().Remove(editorHost);
                        }
                    }
                }
            }
            else if (IsNotOwnUpdate(updateDto))
            {
                HandleErrorOnUpdate(updateDto);
            }
        }
        private void ConfirmPendingUpdate(Document document, AcknowledgeDto dto)
        {
            var result = _diffMatchPatch.patch_apply(document.PendingUpdate.Patch, document.Content);
            if (CheckResultIsValidOtherwiseReOpen(result, dto.DocumentId))
            {
                document.PendingUpdate.NewRevisionId = dto.NewRevisionId;
                document.PendingUpdate.NewHash = dto.NewHash;
                UpdateDocument(document, document.PendingUpdate, result);
            }
            var currentText = _editor.GetText(dto.DocumentId);
            if (document.Content != currentText)
            {
                //send next update
                var updateDto = CreateUpdateDto(document, currentText);
                document.PendingUpdate = updateDto;

                SendUpdateToDocumentOwner(document, updateDto);
            }
            else
            {
                document.PendingUpdate = null;
            }
        }