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)), }); }
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()); }
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)); }
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)), }); }
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); }
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); } }
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); } }
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; } } }
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)); } }
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); }
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)), }); } }
public virtual void FillConflicts(ConflictItem oi, bool target) { }
public virtual void ExtractSubItems(List <ConflictItem> operationItems, ConflictItem directoryItem, CancellationToken cancellationToken) { }
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(); } } }