public HttpResponseMessage Post(string name) { if (name.StartsWith(CopyPrefix)) { var targetFileName = GetQueryStringValue("targetFilename"); return(Copy(name.Substring(CopyPrefix.Length), targetFileName)); } name = FileHeader.Canonize(name); var metadata = GetFilteredMetadataFromHeaders(ReadInnerHeaders); var etag = GetEtag(); Storage.Batch(accessor => { Synchronizations.AssertFileIsNotBeingSynced(name); Historian.Update(name, metadata); Files.UpdateMetadata(name, metadata, etag); SynchronizationTask.Context.NotifyAboutWork(); }); return(GetEmptyMessage(HttpStatusCode.NoContent)); }
public HttpResponseMessage Delete(string name) { name = FileHeader.Canonize(name); Storage.Batch(accessor => { Synchronizations.AssertFileIsNotBeingSynced(name); var fileAndPages = accessor.GetFile(name, 0, 0); var metadata = fileAndPages.Metadata; if (metadata == null) { throw new FileNotFoundException(); } if (metadata.Keys.Contains(SynchronizationConstants.RavenDeleteMarker)) { throw new FileNotFoundException(); } Files.IndicateFileToDelete(name, GetEtag()); if (!name.EndsWith(RavenFileNameHelper.DownloadingFileSuffix)) // don't create a tombstone for .downloading file { Files.PutTombstone(name, metadata); accessor.DeleteConfig(RavenFileNameHelper.ConflictConfigNameForFile(name)); // delete conflict item too } }); SynchronizationTask.Context.NotifyAboutWork(); return(GetEmptyMessage(HttpStatusCode.NoContent)); }
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)); }
public async Task <HttpResponseMessage> Put(string name, bool preserveTimestamps = false) { var metadata = GetFilteredMetadataFromHeaders(ReadInnerHeaders); var etag = GetEtag(); var options = new FileActions.PutOperationOptions(); long contentSize; if (long.TryParse(GetHeader(Constants.FileSystem.RavenFsSize), out contentSize)) { options.ContentSize = contentSize; } DateTimeOffset lastModified; if (DateTimeOffset.TryParse(GetHeader(Constants.RavenLastModified), out lastModified)) { options.LastModified = lastModified; } options.PreserveTimestamps = preserveTimestamps; options.ContentLength = Request.Content.Headers.ContentLength; options.TransferEncodingChunked = Request.Headers.TransferEncodingChunked ?? false; await FileSystem.Files.PutAsync(name, etag, metadata, () => Request.Content.ReadAsStreamAsync(), options); Synchronizations.StartSynchronizeDestinationsInBackground(); return(GetEmptyMessage(HttpStatusCode.Created)); }
public HttpResponseMessage LastSynchronization(Guid from) { SourceSynchronizationInformation lastEtag = Synchronizations.GetLastSynchronization(from); Log.Debug("Got synchronization last ETag request from {0}: [{1}]", from, lastEtag); return(GetMessageWithObject(lastEtag) .WithNoCache()); }
public HttpResponseMessage Status(string fileName) { fileName = FileHeader.Canonize(fileName); var report = Synchronizations.GetSynchronizationReport(fileName); return(GetMessageWithObject(report) .WithNoCache()); }
private FileStatus CheckSynchronizedFileStatus(string filename, Etag etag) { var report = Synchronizations.GetSynchronizationReport(filename); if (report == null || report.FileETag != etag) { return(FileStatus.Unknown); } return(report.Exception == null ? FileStatus.Safe : FileStatus.Broken); }
public HttpResponseMessage Post(string name) { name = FileHeader.Canonize(name); var metadata = GetFilteredMetadataFromHeaders(ReadInnerHeaders); var etag = GetEtag(); Storage.Batch(accessor => { Synchronizations.AssertFileIsNotBeingSynced(name); Historian.Update(name, metadata); Files.UpdateMetadata(name, metadata, etag); SynchronizationTask.Context.NotifyAboutWork(); }); return(GetEmptyMessage(HttpStatusCode.NoContent)); }
public HttpResponseMessage Post(string name) { name = FileHeader.Canonize(name); var metadata = GetFilteredMetadataFromHeaders(ReadInnerHeaders); var etag = GetEtag(); Storage.Batch(accessor => { Synchronizations.AssertFileIsNotBeingSynced(name); Historian.Update(name, metadata); Files.UpdateMetadata(name, metadata, etag); Synchronizations.StartSynchronizeDestinationsInBackground(); }); //Hack needed by jquery on the client side. We need to find a better solution for this return(GetEmptyMessage(HttpStatusCode.NoContent)); }
public async Task <HttpResponseMessage> ResolutionStrategyFromServerResolvers() { var conflict = await ReadJsonObjectAsync <ConflictItem>(); var localMetadata = Synchronizations.GetLocalMetadata(conflict.FileName); if (localMetadata == null) { throw new InvalidOperationException(string.Format("Could not find the medatada of the file: {0}", conflict.FileName)); } var sourceMetadata = GetFilteredMetadataFromHeaders(ReadInnerHeaders); ConflictResolutionStrategy strategy; if (ConflictResolver.TryResolveConflict(conflict.FileName, conflict, localMetadata, sourceMetadata, out strategy)) { return(GetMessageWithObject(strategy)); } return(GetMessageWithObject(ConflictResolutionStrategy.NoResolution)); }
private void DeleteFiles(IEnumerable <string> keys, int totalResults, Action <string> progress) { Storage.Batch(accessor => { var files = keys.Select(accessor.ReadFile); foreach (var fileWithIndex in files.Select((value, i) => new { i, value })) { var file = fileWithIndex.value; var fileName = file.FullPath; try { Synchronizations.AssertFileIsNotBeingSynced(fileName); } catch (Exception) { //ignore files that are being synced continue; } var metadata = file.Metadata; if (metadata == null || metadata.Keys.Contains(SynchronizationConstants.RavenDeleteMarker)) { continue; } Historian.Update(fileName, metadata); Files.IndicateFileToDelete(fileName, null); // don't create a tombstone for .downloading file if (!fileName.EndsWith(RavenFileNameHelper.DownloadingFileSuffix)) { Files.PutTombstone(fileName, metadata); accessor.DeleteConfig(RavenFileNameHelper.ConflictConfigNameForFile(fileName)); // delete conflict item too } progress(string.Format("File {0}/{1} was deleted, name: '{2}'.", fileWithIndex.i, totalResults, fileName)); } }); }
public HttpResponseMessage IncrementLastETag(Guid sourceServerId, string sourceFileSystemUrl, string sourceFileETag) { Synchronizations.IncrementLastEtag(sourceServerId, sourceFileSystemUrl, sourceFileETag); return(GetEmptyMessage()); }