public SynchronizationMultipartRequest(IAsyncFilesSynchronizationCommands destination, ServerInfo serverInfo, string fileName, RavenJObject sourceMetadata, Stream sourceStream, IList<RdcNeed> needList) { this.destination = destination; this.serverInfo = serverInfo; this.fileName = fileName; this.sourceMetadata = sourceMetadata; this.sourceStream = sourceStream; this.needList = needList; syncingBoundary = "syncing"; }
public void LockByCreatingSyncConfiguration(string fileName, ServerInfo sourceServer, IStorageActionsAccessor accessor) { var syncLock = new SynchronizationLock { SourceServer = sourceServer, FileLockedAt = DateTime.UtcNow }; accessor.SetConfig(RavenFileNameHelper.SyncLockNameForFile(fileName), JsonExtensions.ToJObject(syncLock)); log.Debug("File '{0}' was locked", fileName); }
protected SynchronizationWorkItem(string fileName, string sourceServerUrl, ITransactionalStorage storage) { Storage = storage; FileName = fileName; FileAndPagesInformation fileAndPages = null; Storage.Batch(accessor => fileAndPages = accessor.GetFile(fileName, 0, 0)); FileMetadata = fileAndPages.Metadata; ServerInfo = new ServerInfo { Id = Storage.Id, FileSystemUrl = sourceServerUrl }; conflictDetector = new ConflictDetector(); conflictResolver = new ConflictResolver(null, null); }
public void IncomingSynchronizationStarted(string fileName, ServerInfo sourceServerInfo, Guid sourceFileETag, SynchronizationType type) { var activeForDestination = activeIncomingSynchronizations.GetOrAdd(sourceServerInfo.FileSystemUrl, new ConcurrentDictionary<string, SynchronizationDetails>()); var syncDetails = new SynchronizationDetails() { DestinationUrl = sourceServerInfo.FileSystemUrl, FileETag = sourceFileETag, FileName = fileName, Type = type }; if (activeForDestination.TryAdd(fileName, syncDetails)) { Log.Debug("File '{0}' with ETag {1} was added to an incoming active synchronization queue for a destination {2}", fileName, sourceFileETag, sourceServerInfo.FileSystemUrl); } }
public void IncomingSynchronizationFinished(string fileName, ServerInfo sourceServerInfo, Guid sourceFileETag) { ConcurrentDictionary<string, SynchronizationDetails> activeSourceTasks; if (activeIncomingSynchronizations.TryGetValue(sourceServerInfo.FileSystemUrl, out activeSourceTasks) == false) { Log.Warn("Could not get an active synchronization queue for {0}", sourceServerInfo.FileSystemUrl); return; } SynchronizationDetails removingItem; if (activeSourceTasks.TryRemove(fileName, out removingItem)) { Log.Debug("File '{0}' with ETag {1} was removed from an active synchronization queue for a destination {2}", fileName, sourceFileETag, sourceServerInfo); } }
private void SaveSynchronizationSourceInformation(ServerInfo sourceServer, Guid lastSourceEtag, IStorageActionsAccessor accessor) { var lastSynchronizationInformation = GetLastSynchronization(sourceServer.Id, accessor); if (Buffers.Compare(lastSynchronizationInformation.LastSourceFileEtag.ToByteArray(), lastSourceEtag.ToByteArray()) > 0) { return; } var synchronizationSourceInfo = new SourceSynchronizationInformation { LastSourceFileEtag = lastSourceEtag, SourceServerUrl = sourceServer.FileSystemUrl, DestinationServerId = Storage.Id }; var key = SynchronizationConstants.RavenSynchronizationSourcesBasePath + "/" + sourceServer.Id; accessor.SetConfig(key, JsonExtensions.ToJObject(synchronizationSourceInfo)); Log.Debug("Saved last synchronized file ETag {0} from {1} ({2})", lastSourceEtag, sourceServer.FileSystemUrl, sourceServer.Id); }
private void PublishSynchronizationNotification(string fileSystemName, string fileName, ServerInfo sourceServer, SynchronizationType type, SynchronizationAction action) { Publisher.Publish(new SynchronizationUpdateNotification { FileName = fileName, SourceFileSystemUrl = sourceServer.FileSystemUrl, SourceServerId = sourceServer.Id, Type = type, Action = action, Direction = SynchronizationDirection.Incoming }); }
private void AssertConflictDetection(string fileName, RavenJObject localMetadata, RavenJObject sourceMetadata, ServerInfo sourceServer, out bool isConflictResolved) { var conflict = ConflictDetector.Check(fileName, localMetadata, sourceMetadata, sourceServer.FileSystemUrl); if (conflict == null) { isConflictResolved = false; return; } isConflictResolved = ConflictResolver.CheckIfResolvedByRemoteStrategy(localMetadata, conflict); if(isConflictResolved) return; ConflictResolutionStrategy strategy; if (ConflictResolver.TryResolveConflict(fileName, conflict, localMetadata, sourceMetadata, out strategy)) { switch (strategy) { case ConflictResolutionStrategy.RemoteVersion: Log.Debug("Conflict automatically resolved by choosing remote version of the file {0}", fileName); return; case ConflictResolutionStrategy.CurrentVersion: Storage.Batch(accessor => { accessor.UpdateFileMetadata(fileName, localMetadata); ConflictArtifactManager.Delete(fileName, accessor); }); Log.Debug("Conflict automatically resolved by choosing current version of the file {0}", fileName); throw new ConflictResolvedInFavourOfCurrentVersion(); } } ConflictArtifactManager.Create(fileName, conflict); Publisher.Publish(new ConflictNotification { FileName = fileName, SourceServerUrl = sourceServer.FileSystemUrl, Status = ConflictStatus.Detected, RemoteFileHeader = new FileHeader(fileName, localMetadata) }); Log.Debug( "File '{0}' is in conflict with synchronized version from {1} ({2}). File marked as conflicted, conflict configuration item created", fileName, sourceServer.FileSystemUrl, sourceServer.Id); throw new SynchronizationException(string.Format("File {0} is conflicted", fileName)); }
private void FinishSynchronization(string fileName, SynchronizationReport report, ServerInfo sourceServer, Guid sourceFileETag) { try { // we want to execute those operation in a single batch but we also have to ensure that // Raven/Synchronization/Sources/sourceServerId config is modified only by one finishing synchronization at the same time SynchronizationFinishLocks.GetOrAdd(sourceServer.Id, new ReaderWriterLockSlim()).EnterWriteLock(); SynchronizationTask.IncomingSynchronizationFinished(fileName, sourceServer, sourceFileETag); Storage.Batch(accessor => { SaveSynchronizationReport(fileName, accessor, report); FileLockManager.UnlockByDeletingSyncConfiguration(fileName, accessor); if (report.Exception == null) { SaveSynchronizationSourceInformation(sourceServer, sourceFileETag, accessor); } }); } catch (Exception ex) { Log.ErrorException( string.Format("Failed to finish synchronization of a file '{0}' from {1}", fileName, sourceServer), ex); } finally { SynchronizationFinishLocks.GetOrAdd(sourceServer.Id, new ReaderWriterLockSlim()).ExitWriteLock(); } }