public async Task PutAsync(string name, Etag etag, RavenJObject metadata, Func<Task<Stream>> streamAsync, PutOperationOptions options) { FileUpdateResult putResult = null; try { FileSystem.MetricsCounters.FilesPerSecond.Mark(); name = FileHeader.Canonize(name); if (options.PreserveTimestamps) { if (!metadata.ContainsKey(Constants.RavenCreationDate)) { if (metadata.ContainsKey(Constants.CreationDate)) metadata[Constants.RavenCreationDate] = metadata[Constants.CreationDate]; else throw new InvalidOperationException("Preserve Timestamps requires that the client includes the Raven-Creation-Date header."); } Historian.UpdateLastModified(metadata, options.LastModified.HasValue ? options.LastModified.Value : DateTimeOffset.UtcNow); } else { metadata[Constants.RavenCreationDate] = DateTimeOffset.UtcNow; Historian.UpdateLastModified(metadata); } // TODO: To keep current filesystems working. We should remove when adding a new migration. metadata[Constants.CreationDate] = metadata[Constants.RavenCreationDate].Value<DateTimeOffset>().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ", CultureInfo.InvariantCulture); Historian.Update(name, metadata); long? size = -1; Storage.Batch(accessor => { FileSystem.Synchronizations.AssertFileIsNotBeingSynced(name); AssertPutOperationNotVetoed(name, metadata); SynchronizationTask.Cancel(name); var contentLength = options.ContentLength; var contentSize = options.ContentSize; if (contentLength == 0 || contentSize.HasValue == false) { size = contentLength; if (options.TransferEncodingChunked) size = null; } else { size = contentSize; } FileSystem.PutTriggers.Apply(trigger => trigger.OnPut(name, metadata)); using (FileSystem.DisableAllTriggersForCurrentThread()) { IndicateFileToDelete(name, etag); } putResult = accessor.PutFile(name, size, metadata); FileSystem.PutTriggers.Apply(trigger => trigger.AfterPut(name, size, metadata)); Search.Index(name, metadata, putResult.Etag); }); Log.Debug("Inserted a new file '{0}' with ETag {1}", name, putResult.Etag); using (var contentStream = await streamAsync().ConfigureAwait(false)) using (var readFileToDatabase = new ReadFileToDatabase(BufferPool, Storage, FileSystem.PutTriggers, contentStream, name, metadata)) { await readFileToDatabase.Execute().ConfigureAwait(false); if (size != null && readFileToDatabase.TotalSizeRead != size) { throw new HttpResponseException(HttpStatusCode.BadRequest); } if (options.PreserveTimestamps == false) Historian.UpdateLastModified(metadata); // update with the final file size. Log.Debug("File '{0}' was uploaded. Starting to update file metadata and indexes", name); metadata["Content-MD5"] = readFileToDatabase.FileHash; FileUpdateResult updateMetadata = null; Storage.Batch(accessor => updateMetadata = accessor.UpdateFileMetadata(name, metadata, null)); long totalSizeRead = readFileToDatabase.TotalSizeRead; metadata["Content-Length"] = totalSizeRead.ToString(CultureInfo.InvariantCulture); Search.Index(name, metadata, updateMetadata.Etag); Publisher.Publish(new FileChangeNotification { Action = FileChangeAction.Add, File = name }); Log.Debug("Updates of '{0}' metadata and indexes were finished. New file ETag is {1}", name, updateMetadata.Etag); } } catch (Exception ex) { if (putResult != null) { using (FileSystem.DisableAllTriggersForCurrentThread()) { IndicateFileToDelete(name, null); } } Log.WarnException(string.Format("Failed to upload a file '{0}'", name), ex); throw; } }
public async Task PutAsync(string name, Etag etag, RavenJObject metadata, Func <Task <Stream> > streamAsync, PutOperationOptions options) { try { FileSystem.MetricsCounters.FilesPerSecond.Mark(); name = FileHeader.Canonize(name); if (options.PreserveTimestamps) { if (!metadata.ContainsKey(Constants.RavenCreationDate)) { if (metadata.ContainsKey(Constants.CreationDate)) { metadata[Constants.RavenCreationDate] = metadata[Constants.CreationDate]; } else { throw new InvalidOperationException("Preserve Timestamps requires that the client includes the Raven-Creation-Date header."); } } Historian.UpdateLastModified(metadata, options.LastModified.HasValue ? options.LastModified.Value : DateTimeOffset.UtcNow); } else { metadata[Constants.RavenCreationDate] = DateTimeOffset.UtcNow; Historian.UpdateLastModified(metadata); } // TODO: To keep current filesystems working. We should remove when adding a new migration. metadata[Constants.CreationDate] = metadata[Constants.RavenCreationDate].Value <DateTimeOffset>().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ", CultureInfo.InvariantCulture); Historian.Update(name, metadata); long?size = -1; Storage.Batch(accessor => { FileSystem.Synchronizations.AssertFileIsNotBeingSynced(name); AssertPutOperationNotVetoed(name, metadata); SynchronizationTask.Cancel(name); var contentLength = options.ContentLength; var contentSize = options.ContentSize; if (contentLength == 0 || contentSize.HasValue == false) { size = contentLength; if (options.TransferEncodingChunked) { size = null; } } else { size = contentSize; } FileSystem.PutTriggers.Apply(trigger => trigger.OnPut(name, metadata)); using (FileSystem.DisableAllTriggersForCurrentThread()) { IndicateFileToDelete(name, etag); } var putResult = accessor.PutFile(name, size, metadata); FileSystem.PutTriggers.Apply(trigger => trigger.AfterPut(name, size, metadata)); Search.Index(name, metadata, putResult.Etag); }); Log.Debug("Inserted a new file '{0}' with ETag {1}", name, metadata.Value <string>(Constants.MetadataEtagField)); using (var contentStream = await streamAsync()) using (var readFileToDatabase = new ReadFileToDatabase(BufferPool, Storage, FileSystem.PutTriggers, contentStream, name, metadata)) { await readFileToDatabase.Execute(); if (readFileToDatabase.TotalSizeRead != size) { using (FileSystem.DisableAllTriggersForCurrentThread()) { IndicateFileToDelete(name, null); } throw new HttpResponseException(HttpStatusCode.BadRequest); } if (options.PreserveTimestamps == false) { Historian.UpdateLastModified(metadata); // update with the final file size. } Log.Debug("File '{0}' was uploaded. Starting to update file metadata and indexes", name); metadata["Content-MD5"] = readFileToDatabase.FileHash; MetadataUpdateResult updateMetadata = null; Storage.Batch(accessor => updateMetadata = accessor.UpdateFileMetadata(name, metadata, null)); int totalSizeRead = readFileToDatabase.TotalSizeRead; metadata["Content-Length"] = totalSizeRead.ToString(CultureInfo.InvariantCulture); Search.Index(name, metadata, updateMetadata.Etag); Publisher.Publish(new FileChangeNotification { Action = FileChangeAction.Add, File = name }); Log.Debug("Updates of '{0}' metadata and indexes were finished. New file ETag is {1}", name, metadata.Value <string>(Constants.MetadataEtagField)); } } catch (Exception ex) { Log.WarnException(string.Format("Failed to upload a file '{0}'", name), ex); throw; } }