예제 #1
0
        private async Task <SynchronizationReport> ApplyConflictOnDestinationAsync(ConflictItem conflict, RavenJObject remoteMetadata, ISynchronizationServerClient synchronizationServerClient, string localServerUrl, ILog log)
        {
            if (log.IsDebugEnabled)
            {
                log.Debug("File '{0}' is in conflict with destination version from {1}. Applying conflict on destination", FileName, synchronizationServerClient.BaseUrl);
            }

            try
            {
                var version  = conflict.RemoteHistory.Last().Version;
                var serverId = conflict.RemoteHistory.Last().ServerId;
                var history  = new List <HistoryItem>(conflict.RemoteHistory);
                history.RemoveAt(conflict.RemoteHistory.Count - 1);

                await synchronizationServerClient.ApplyConflictAsync(FileName, version, serverId, remoteMetadata, localServerUrl).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                log.WarnException(string.Format("Failed to apply conflict on {0} for file '{1}'", synchronizationServerClient, FileName), ex);
            }

            return(new SynchronizationReport(FileName, FileETag, SynchronizationType)
            {
                Exception = new SynchronizationException(string.Format("File {0} is conflicted", FileName)),
            });
        }
예제 #2
0
        void ExtractSubItems(Item[] items, CancellationToken cancellationToken)
        {
            try
            {
                operationItems.Clear();
                foreach (var item in items.Where(n => n.Kind == Kind.File))
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        throw new CancelledException();
                    }
                    operationItems.Add(ConflictItem.CreateConflictFileItem(item));
                }
                var dirs = items.Where(n => n.Kind == Kind.Directory).Select(n => ConflictItem.CreateConflictDirectoryItem(n.Name, null));
                foreach (var item in dirs)
                {
                    var odi = ConflictItem.CreateConflictDirectoryItem(item.Name, null);

                    sourceProcessor.ExtractSubItems(operationItems, odi, cancellationToken);
                }
            }
            catch (CancelledException)
            {
                throw;
            }
            catch (Exception e)
            {
                var var = e;
            }
        }
 ConflictItem[] RefreshDirectories(DirectoryInfo directoryInfo, string subPath)
 {
     return(directoryInfo.SafeGetDirectories()
            .Where(n => Show(n.Attributes))
            .OrderBy(n => n.Name)
            .Select(n => ConflictItem.CreateConflictDirectoryItem(n.Name, CombineSubPath(subPath, directoryInfo.Name))).ToArray());
 }
예제 #4
0
        public async Task <HttpResponseMessage> ApplyConflict(string filename, long remoteVersion, string remoteServerId, string remoteServerUrl)
        {
            var canonicalFilename = FileHeader.Canonize(filename);

            var localMetadata = Synchronizations.GetLocalMetadata(canonicalFilename);

            if (localMetadata == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            var contentStream = await Request.Content.ReadAsStreamAsync().ConfigureAwait(false);

            var current = new HistoryItem
            {
                ServerId = Storage.Id.ToString(),
                Version  = localMetadata.Value <long>(SynchronizationConstants.RavenSynchronizationVersion)
            };

            var currentConflictHistory = Historian.DeserializeHistory(localMetadata);

            currentConflictHistory.Add(current);

            var remote = new HistoryItem
            {
                ServerId = remoteServerId,
                Version  = remoteVersion
            };

            var remoteMetadata = RavenJObject.Load(new JsonTextReader(new StreamReader(contentStream)));

            var remoteConflictHistory = Historian.DeserializeHistory(remoteMetadata);

            remoteConflictHistory.Add(remote);

            var conflict = new ConflictItem
            {
                CurrentHistory  = currentConflictHistory,
                RemoteHistory   = remoteConflictHistory,
                FileName        = canonicalFilename,
                RemoteServerUrl = Uri.UnescapeDataString(remoteServerUrl)
            };

            ConflictArtifactManager.Create(canonicalFilename, conflict);

            Publisher.Publish(new ConflictNotification
            {
                FileName         = filename,
                SourceServerUrl  = remoteServerUrl,
                Status           = ConflictStatus.Detected,
                RemoteFileHeader = new FileHeader(canonicalFilename, remoteMetadata)
            });

            if (Log.IsDebugEnabled)
            {
                Log.Debug("Conflict applied for a file '{0}' (remote version: {1}, remote server id: {2}).", filename, remoteVersion, remoteServerId);
            }

            return(GetEmptyMessage(HttpStatusCode.NoContent));
        }
예제 #5
0
        protected async Task <SynchronizationReport> ApplyConflictOnDestinationAsync(ConflictItem conflict, RavenJObject remoteMetadata, IAsyncFilesSynchronizationCommands destination, string localServerUrl, ILog log)
        {
            var commands = (IAsyncFilesCommandsImpl)destination.Commands;

            log.Debug("File '{0}' is in conflict with destination version from {1}. Applying conflict on destination", FileName, commands.UrlFor());

            try
            {
                var version  = conflict.RemoteHistory.Last().Version;
                var serverId = conflict.RemoteHistory.Last().ServerId;
                var history  = new List <HistoryItem>(conflict.RemoteHistory);
                history.RemoveAt(conflict.RemoteHistory.Count - 1);

                await destination.ApplyConflictAsync(FileName, version, serverId, remoteMetadata, localServerUrl);
            }
            catch (Exception ex)
            {
                log.WarnException(string.Format("Failed to apply conflict on {0} for file '{1}'", destination, FileName), ex);
            }

            return(new SynchronizationReport(FileName, FileETag, SynchronizationType)
            {
                Exception = new SynchronizationException(string.Format("File {0} is conflicted", FileName)),
            });
        }
예제 #6
0
        public void ApplyRemoteStrategy(string fileName, ConflictItem conflict, RavenJObject localMetadata)
        {
            var conflictResolution = new ConflictResolution
            {
                Strategy       = ConflictResolutionStrategy.RemoteVersion,
                RemoteServerId = conflict.RemoteHistory.Last().ServerId,
                Version        = conflict.RemoteHistory.Last().Version,
            };

            localMetadata[SynchronizationConstants.RavenSynchronizationConflictResolution] = JsonExtensions.ToJObject(conflictResolution);
        }
예제 #7
0
        public void ApplyCurrentStrategy(string fileName, ConflictItem conflict, RavenJObject localMetadata)
        {
            var localHistory = Historian.DeserializeHistory(localMetadata);

            // incorporate remote version history into local
            foreach (var remoteHistoryItem in conflict.RemoteHistory.Where(remoteHistoryItem => !localHistory.Contains(remoteHistoryItem)))
            {
                localHistory.Add(remoteHistoryItem);
            }

            localMetadata[SynchronizationConstants.RavenSynchronizationHistory] = Historian.SerializeHistory(localHistory);
        }
        public override void ExtractSubItems(List <ConflictItem> operationItems, ConflictItem directoryItem, CancellationToken cancellationToken)
        {
            var directoryInfo = new DirectoryInfo(Path.Combine(Directory, directoryItem.NameWithSubPath));

            RefreshFiles(operationItems, directoryInfo, directoryItem.SubPath, cancellationToken);
            var subDirs = RefreshDirectories(directoryInfo, directoryItem.SubPath);

            foreach (var subDir in subDirs)
            {
                ExtractSubItems(operationItems, subDir, cancellationToken);
            }
        }
예제 #9
0
        public bool IsResolved(RavenJObject destinationMetadata, ConflictItem conflict)
        {
            var conflictResolutionMetadata = destinationMetadata[SynchronizationConstants.RavenSynchronizationConflictResolution] as RavenJObject;

            if (conflictResolutionMetadata == null)
            {
                return(false);
            }

            var conflictResolution = JsonExtensions.JsonDeserialization <ConflictResolution>(conflictResolutionMetadata);

            return(conflictResolution.Strategy == ConflictResolutionStrategy.RemoteVersion && conflictResolution.RemoteServerId == conflict.RemoteHistory.Last().ServerId);
        }
        void RefreshFiles(List <ConflictItem> operationItems, DirectoryInfo directoryInfo, string subPath, CancellationToken cancellationToken)
        {
            var files = directoryInfo.SafeGetFiles()
                        .Where(n => Show(n.Attributes))
                        .Select(n => ConflictItem.CreateConflictFileItem(n.Name, n.Extension, n.FullName, n.Length,
                                                                         n.LastWriteTime, CombineSubPath(subPath, directoryInfo.Name)));

            foreach (var file in files)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    throw new CancelledException();
                }
                operationItems.Add(file);
            }
        }
예제 #11
0
        public void Create(string fileName, ConflictItem conflict)
        {
            RavenJObject metadata = null;

            storage.Batch(
                accessor =>
            {
                metadata = accessor.GetFile(fileName, 0, 0).Metadata;
                accessor.SetConfig(RavenFileNameHelper.ConflictConfigNameForFile(fileName), JsonExtensions.ToJObject(conflict));
                metadata[SynchronizationConstants.RavenSynchronizationConflict] = true;
                accessor.UpdateFileMetadata(fileName, metadata);
            });

            if (metadata != null)
            {
                index.Index(fileName, metadata);
            }
        }
 public override void FillConflicts(ConflictItem conflict, bool target)
 {
     if (conflict != null)
     {
         var source = Path.Combine(Directory, conflict.NameWithSubPath);
         var info   = new FileInfo(source);
         if (target)
         {
             conflict.TargetFileSize = info.Length;
             conflict.TargetVersion  = FileVersion.Get(source);
             conflict.TargetDateTime = info.LastWriteTime;
         }
         else
         {
             conflict.SourceVersion  = FileVersion.Get(source);
             conflict.SourceDateTime = info.LastWriteTime;
         }
     }
 }
예제 #13
0
 void TakeItems(Item[] items, CancellationToken cancellationToken)
 {
     operationItems.Clear();
     foreach (var item in items.Where(n => n.Kind == Kind.Directory))
     {
         if (cancellationToken.IsCancellationRequested)
         {
             throw new CancelledException();
         }
         operationItems.Add(ConflictItem.CreateConflictDirectoryItem(item.Name, null));
     }
     foreach (var item in items.Where(n => n.Kind == Kind.File))
     {
         if (cancellationToken.IsCancellationRequested)
         {
             throw new CancelledException();
         }
         operationItems.Add(ConflictItem.CreateConflictFileItem(item));
     }
 }
예제 #14
0
        public bool TryResolveConflict(string fileName, ConflictItem conflict, RavenJObject localMetadata, RavenJObject remoteMetadata, out ConflictResolutionStrategy strategy)
        {
            foreach (var resolver in Resolvers)
            {
                if (resolver.TryResolve(fileName, localMetadata, remoteMetadata, out strategy) == false)
                {
                    continue;
                }

                switch (strategy)
                {
                case ConflictResolutionStrategy.CurrentVersion:
                    ApplyCurrentStrategy(fileName, conflict, localMetadata);
                    return(true);

                case ConflictResolutionStrategy.RemoteVersion:
                    ApplyRemoteStrategy(fileName, conflict, localMetadata);
                    return(true);
                }
            }

            strategy = ConflictResolutionStrategy.NoResolution;
            return(false);
        }
예제 #15
0
        protected async Task <SynchronizationReport> HandleConflict(IAsyncFilesSynchronizationCommands destination, ConflictItem conflict, ILog log)
        {
            var conflictResolutionStrategy = await destination.Commands.Synchronization.GetResolutionStrategyFromDestinationResolvers(conflict, FileMetadata);

            switch (conflictResolutionStrategy)
            {
            case ConflictResolutionStrategy.NoResolution:
                return(await ApplyConflictOnDestinationAsync(conflict, FileMetadata, destination, ServerInfo.FileSystemUrl, log));

            case ConflictResolutionStrategy.CurrentVersion:
                await ApplyConflictOnDestinationAsync(conflict, FileMetadata, destination, ServerInfo.FileSystemUrl, log);

                await destination.Commands.Synchronization.ResolveConflictAsync(FileName, conflictResolutionStrategy);

                return(new SynchronizationReport(FileName, FileETag, SynchronizationType));

            case ConflictResolutionStrategy.RemoteVersion:
                // we can push the file even though it conflicted, the conflict will be automatically resolved on the destination side
                return(null);

            default:
                return(new SynchronizationReport(FileName, FileETag, SynchronizationType)
                {
                    Exception = new SynchronizationException(string.Format("Unknown resulution stragegy: {0}", conflictResolutionStrategy)),
                });
            }
        }
예제 #16
0
 public virtual void FillConflicts(ConflictItem oi, bool target)
 {
 }
예제 #17
0
 public virtual void ExtractSubItems(List <ConflictItem> operationItems, ConflictItem directoryItem, CancellationToken cancellationToken)
 {
 }
예제 #18
0
        public async Task <ConflictResolutionStrategy> GetResolutionStrategyFromDestinationResolvers(ConflictItem conflict, RavenJObject localMetadata)
        {
            var requestUriString = string.Format("{0}/synchronization/ResolutionStrategyFromServerResolvers", baseUrl);

            using (var request = RequestFactory.CreateHttpJsonRequest(new CreateHttpJsonRequestParams(this, requestUriString, HttpMethods.Post, Credentials, Conventions)).AddOperationHeaders(OperationsHeaders))
            {
                request.AddHeaders(localMetadata);

                try
                {
                    await request.WriteWithObjectAsync(conflict).ConfigureAwait(false);

                    var response = await request.ReadResponseJsonAsync().ConfigureAwait(false);

                    return(response.JsonDeserialization <ConflictResolutionStrategy>());
                }
                catch (Exception e)
                {
                    throw e.SimplifyException();
                }
            }
        }