public async Task <HttpResponseMessage> MultipartProceed() { if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } var fileName = Request.Headers.GetValues(SyncingMultipartConstants.FileName).FirstOrDefault(); var tempFileName = RavenFileNameHelper.DownloadingFileName(fileName); var sourceServerInfo = InnerHeaders.Value <ServerInfo>(SyncingMultipartConstants.SourceServerInfo); var sourceFileETag = Guid.Parse(InnerHeaders.GetValues("ETag").First().Trim('\"')); var report = new SynchronizationReport(fileName, sourceFileETag, SynchronizationType.ContentUpdate); Log.Debug("Starting to process multipart synchronization request of a file '{0}' with ETag {1} from {2}", fileName, sourceFileETag, sourceServerInfo); StorageStream localFile = null; var isNewFile = false; var isConflictResolved = false; try { Storage.Batch(accessor => { AssertFileIsNotBeingSynced(fileName, accessor); FileLockManager.LockByCreatingSyncConfiguration(fileName, sourceServerInfo, accessor); }); PublishSynchronizationNotification(fileName, sourceServerInfo, report.Type, SynchronizationAction.Start); Storage.Batch(accessor => StartupProceed(fileName, accessor)); RavenJObject sourceMetadata = GetFilteredMetadataFromHeaders(InnerHeaders); // InnerHeaders.FilterHeadersToObject(); var localMetadata = GetLocalMetadata(fileName); if (localMetadata != null) { AssertConflictDetection(fileName, localMetadata, sourceMetadata, sourceServerInfo, out isConflictResolved); localFile = StorageStream.Reading(Storage, fileName); } else { isNewFile = true; } Historian.UpdateLastModified(sourceMetadata); var synchronizingFile = SynchronizingFileStream.CreatingOrOpeningAndWritting(Storage, Search, StorageOperationsTask, tempFileName, sourceMetadata); var provider = new MultipartSyncStreamProvider(synchronizingFile, localFile); Log.Debug("Starting to process multipart content of a file '{0}'", fileName); await Request.Content.ReadAsMultipartAsync(provider); Log.Debug("Multipart content of a file '{0}' was processed", fileName); report.BytesCopied = provider.BytesCopied; report.BytesTransfered = provider.BytesTransfered; report.NeedListLength = provider.NumberOfFileParts; synchronizingFile.PreventUploadComplete = false; synchronizingFile.Dispose(); sourceMetadata["Content-MD5"] = synchronizingFile.FileHash; Storage.Batch(accessor => accessor.UpdateFileMetadata(tempFileName, sourceMetadata)); Storage.Batch(accessor => { StorageOperationsTask.IndicateFileToDelete(fileName); accessor.RenameFile(tempFileName, fileName); Search.Delete(tempFileName); Search.Index(fileName, sourceMetadata); }); if (isNewFile) { Log.Debug("Temporary downloading file '{0}' was renamed to '{1}'. Indexes was updated.", tempFileName, fileName); } else { Log.Debug("Old file '{0}' was deleted. Indexes was updated.", fileName); } if (isConflictResolved) { ConflictArtifactManager.Delete(fileName); Publisher.Publish(new ConflictResolvedNotification { FileName = fileName }); } } catch (Exception ex) { report.Exception = ex; } finally { if (localFile != null) { localFile.Dispose(); } } if (report.Exception == null) { Log.Debug( "File '{0}' was synchronized successfully from {1}. {2} bytes were transfered and {3} bytes copied. Need list length was {4}", fileName, sourceServerInfo, report.BytesTransfered, report.BytesCopied, report.NeedListLength); } else { Log.WarnException( string.Format("Error has occurred during synchronization of a file '{0}' from {1}", fileName, sourceServerInfo), report.Exception); } FinishSynchronization(fileName, report, sourceServerInfo, sourceFileETag); PublishFileNotification(fileName, isNewFile ? FileChangeAction.Add : FileChangeAction.Update); PublishSynchronizationNotification(fileName, sourceServerInfo, report.Type, SynchronizationAction.Finish); return(this.GetMessageWithObject(report, HttpStatusCode.OK)); }
public HttpResponseMessage Delete(string fileName) { var sourceServerInfo = InnerHeaders.Value <ServerInfo>(SyncingMultipartConstants.SourceServerInfo); var sourceFileETag = Guid.Parse(InnerHeaders.GetValues("ETag").First().Trim('\"')); Log.Debug("Starting to delete a file '{0}' with ETag {1} from {2} because of synchronization", fileName, sourceFileETag, sourceServerInfo); var report = new SynchronizationReport(fileName, sourceFileETag, SynchronizationType.Delete); try { Storage.Batch(accessor => { AssertFileIsNotBeingSynced(fileName, accessor); FileLockManager.LockByCreatingSyncConfiguration(fileName, sourceServerInfo, accessor); }); PublishSynchronizationNotification(fileName, sourceServerInfo, report.Type, SynchronizationAction.Start); Storage.Batch(accessor => StartupProceed(fileName, accessor)); var localMetadata = GetLocalMetadata(fileName); if (localMetadata != null) { // REVIEW: Use InnerHeaders for consistency? var sourceMetadata = GetFilteredMetadataFromHeaders(Request.Headers); // Request.Headers.FilterHeadersToObject(); bool isConflictResolved; AssertConflictDetection(fileName, localMetadata, sourceMetadata, sourceServerInfo, out isConflictResolved); Storage.Batch(accessor => { StorageOperationsTask.IndicateFileToDelete(fileName); var tombstoneMetadata = new RavenJObject { { SynchronizationConstants.RavenSynchronizationHistory, localMetadata[SynchronizationConstants.RavenSynchronizationHistory] }, { SynchronizationConstants.RavenSynchronizationVersion, localMetadata[SynchronizationConstants.RavenSynchronizationVersion] }, { SynchronizationConstants.RavenSynchronizationSource, localMetadata[SynchronizationConstants.RavenSynchronizationSource] } }.WithDeleteMarker(); Historian.UpdateLastModified(tombstoneMetadata); accessor.PutFile(fileName, 0, tombstoneMetadata, true); }); PublishFileNotification(fileName, FileChangeAction.Delete); } } catch (Exception ex) { report.Exception = ex; Log.WarnException(string.Format("Error was occurred during deletion synchronization of file '{0}' from {1}", fileName, sourceServerInfo), ex); } finally { FinishSynchronization(fileName, report, sourceServerInfo, sourceFileETag); PublishSynchronizationNotification(fileName, sourceServerInfo, report.Type, SynchronizationAction.Finish); } if (report.Exception == null) { Log.Debug("File '{0}' was deleted during synchronization from {1}", fileName, sourceServerInfo); } return(this.GetMessageWithObject(report, HttpStatusCode.OK)); }
public HttpResponseMessage Rename(string fileName, string rename) { var sourceServerInfo = InnerHeaders.Value <ServerInfo>(SyncingMultipartConstants.SourceServerInfo); var sourceFileETag = Guid.Parse(InnerHeaders.GetValues("ETag").First().Trim('\"')); var sourceMetadata = GetFilteredMetadataFromHeaders(InnerHeaders); Log.Debug("Starting to rename a file '{0}' to '{1}' with ETag {2} from {3} because of synchronization", fileName, rename, sourceFileETag, sourceServerInfo); var report = new SynchronizationReport(fileName, sourceFileETag, SynchronizationType.Rename); try { Storage.Batch(accessor => { AssertFileIsNotBeingSynced(fileName, accessor); FileLockManager.LockByCreatingSyncConfiguration(fileName, sourceServerInfo, accessor); }); PublishSynchronizationNotification(fileName, sourceServerInfo, report.Type, SynchronizationAction.Start); Storage.Batch(accessor => StartupProceed(fileName, accessor)); var localMetadata = GetLocalMetadata(fileName); bool isConflictResolved; AssertConflictDetection(fileName, localMetadata, sourceMetadata, sourceServerInfo, out isConflictResolved); if (isConflictResolved) { ConflictArtifactManager.Delete(fileName); Publisher.Publish(new ConflictResolvedNotification { FileName = fileName }); } StorageOperationsTask.RenameFile(new RenameFileOperation { Name = fileName, Rename = rename, MetadataAfterOperation = sourceMetadata.WithETag(sourceFileETag).DropRenameMarkers() }); } catch (Exception ex) { report.Exception = ex; Log.WarnException(string.Format("Error was occurred during renaming synchronization of file '{0}' from {1}", fileName, sourceServerInfo), ex); } finally { FinishSynchronization(fileName, report, sourceServerInfo, sourceFileETag); PublishSynchronizationNotification(fileName, sourceServerInfo, report.Type, SynchronizationAction.Finish); } if (report.Exception == null) { Log.Debug("File '{0}' was renamed to '{1}' during synchronization from {2}", fileName, rename, sourceServerInfo); } return(this.GetMessageWithObject(report, HttpStatusCode.OK)); }
public HttpResponseMessage UpdateMetadata(string fileName) { var sourceServerInfo = InnerHeaders.Value <ServerInfo>(SyncingMultipartConstants.SourceServerInfo); // REVIEW: (Oren) It works, but it seems to me it is not an scalable solution. var sourceFileETag = Guid.Parse(InnerHeaders.GetValues("ETag").First().Trim('\"')); Log.Debug("Starting to update a metadata of file '{0}' with ETag {1} from {2} because of synchronization", fileName, sourceFileETag, sourceServerInfo); var report = new SynchronizationReport(fileName, sourceFileETag, SynchronizationType.MetadataUpdate); try { Storage.Batch(accessor => { AssertFileIsNotBeingSynced(fileName, accessor); FileLockManager.LockByCreatingSyncConfiguration(fileName, sourceServerInfo, accessor); }); PublishSynchronizationNotification(fileName, sourceServerInfo, report.Type, SynchronizationAction.Start); Storage.Batch(accessor => StartupProceed(fileName, accessor)); var localMetadata = GetLocalMetadata(fileName); var sourceMetadata = GetFilteredMetadataFromHeaders(InnerHeaders); bool isConflictResolved; AssertConflictDetection(fileName, localMetadata, sourceMetadata, sourceServerInfo, out isConflictResolved); Historian.UpdateLastModified(sourceMetadata); Storage.Batch(accessor => accessor.UpdateFileMetadata(fileName, sourceMetadata)); Search.Index(fileName, sourceMetadata); if (isConflictResolved) { ConflictArtifactManager.Delete(fileName); Publisher.Publish(new ConflictResolvedNotification { FileName = fileName }); } PublishFileNotification(fileName, FileChangeAction.Update); } catch (Exception ex) { report.Exception = ex; Log.WarnException( string.Format("Error was occured during metadata synchronization of file '{0}' from {1}", fileName, sourceServerInfo), ex); } finally { FinishSynchronization(fileName, report, sourceServerInfo, sourceFileETag); PublishSynchronizationNotification(fileName, sourceServerInfo, report.Type, SynchronizationAction.Finish); } if (report.Exception == null) { Log.Debug("Metadata of file '{0}' was synchronized successfully from {1}", fileName, sourceServerInfo); } return(this.GetMessageWithObject(report, HttpStatusCode.OK)); }