protected SynchronizationWorkItem(string fileName, string sourceServerUrl, TransactionalStorage storage) { Storage = storage; FileName = fileName; FileAndPages fileAndPages = null; Storage.Batch(accessor => fileAndPages = accessor.GetFile(fileName, 0, 0)); FileMetadata = fileAndPages.Metadata; ServerInfo = new ServerInfo { Id = Storage.Id, Url = sourceServerUrl }; conflictDetector = new ConflictDetector(); conflictResolver = new ConflictResolver(); }
private void SaveSynchronizationSourceInformation(ServerInfo sourceServer, Guid lastSourceEtag, StorageActionsAccessor 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.Url, DestinationServerId = Storage.Id }; var key = SynchronizationConstants.RavenSynchronizationSourcesBasePath + "/" + sourceServer.Id; accessor.SetConfig(key, synchronizationSourceInfo.AsConfig()); Log.Debug("Saved last synchronized file ETag {0} from {1} ({2})", lastSourceEtag, sourceServer.Url, sourceServer.Id); }
private void PublishSynchronizationNotification(string fileName, ServerInfo sourceServer, SynchronizationType type, SynchronizationAction action) { Publisher.Publish(new SynchronizationUpdate { FileName = fileName, SourceServerUrl = sourceServer.Url, SourceServerId = sourceServer.Id, Type = type, Action = action, SynchronizationDirection = SynchronizationDirection.Incoming }); }
private void AssertConflictDetection(string fileName, NameValueCollection localMetadata, NameValueCollection sourceMetadata, ServerInfo sourceServer, out bool isConflictResolved) { var conflict = ConflictDetector.Check(fileName, localMetadata, sourceMetadata, sourceServer.Url); isConflictResolved = ConflictResolver.IsResolved(localMetadata, conflict); if (conflict != null && !isConflictResolved) { ConflictArtifactManager.Create(fileName, conflict); Publisher.Publish(new ConflictDetected { FileName = fileName, SourceServerUrl = sourceServer.Url }); Log.Debug( "File '{0}' is in conflict with synchronized version from {1} ({2}). File marked as conflicted, conflict configuration item created", fileName, sourceServer.Url, 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(); 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(); } }