public void IndicateFileToDelete(string fileName, Etag etag) { var deletingFileName = RavenFileNameHelper.DeletingFileName(fileName); var fileExists = true; Storage.Batch(accessor => { AssertDeleteOperationNotVetoed(fileName); var existingFile = accessor.ReadFile(fileName); if (existingFile == null) { // do nothing if file does not exist fileExists = false; return; } if (existingFile.Metadata[SynchronizationConstants.RavenDeleteMarker] != null) { // if it is a tombstone drop it accessor.Delete(fileName); fileExists = false; return; } if (etag != null && existingFile.Etag != etag) throw new ConcurrencyException("Operation attempted on file '" + fileName + "' using a non current etag") { ActualETag = existingFile.Etag, ExpectedETag = etag }; var metadata = new RavenJObject(existingFile.Metadata).WithDeleteMarker(); var renameSucceeded = false; int deleteAttempts = 0; do { try { accessor.RenameFile(fileName, deletingFileName); renameSucceeded = true; } catch (FileExistsException) // it means that .deleting file was already existed { var deletingFileHeader = accessor.ReadFile(deletingFileName); if (deletingFileHeader != null && deletingFileHeader.Equals(existingFile)) { fileExists = false; // the same file already marked as deleted no need to do it again return; } if (deleteAttempts++ > 128) { Log.Warn("Could not rename a file '{0}' when a delete operation was performed", fileName); throw; } // we need to use different name to do a file rename deletingFileName = RavenFileNameHelper.DeletingFileName(fileName, RandomProvider.GetThreadRandom().Next()); } } while (renameSucceeded == false); accessor.UpdateFileMetadata(deletingFileName, metadata, null); accessor.DecrementFileCount(deletingFileName); Log.Debug("File '{0}' was renamed to '{1}' and marked as deleted", fileName, deletingFileName); var configName = RavenFileNameHelper.DeleteOperationConfigNameForFile(deletingFileName); var operation = new DeleteFileOperation { OriginalFileName = fileName, CurrentFileName = deletingFileName }; accessor.SetConfig(configName, JsonExtensions.ToJObject(operation)); FileSystem.DeleteTriggers.Apply(trigger => trigger.AfterDelete(fileName)); Publisher.Publish(new ConfigurationChangeNotification { Name = configName, Action = ConfigurationChangeAction.Set }); Publisher.Publish(new FileChangeNotification { File = fileName, Action = FileChangeAction.Delete }); Log.Debug("File '{0}' was deleted", fileName); }); if (fileExists) { Search.Delete(fileName); Search.Delete(deletingFileName); } }
public void IndicateFileToDelete(string fileName) { var deletingFileName = RavenFileNameHelper.DeletingFileName(fileName); var fileExists = true; storage.Batch(accessor => { var existingFileHeader = accessor.ReadFile(fileName); if (existingFileHeader == null) { // do nothing if file does not exist fileExists = false; return; } if (existingFileHeader.Metadata[SynchronizationConstants.RavenDeleteMarker] != null) { // if it is a tombstone drop it accessor.Delete(fileName); fileExists = false; return; } var metadata = new RavenJObject(existingFileHeader.Metadata).WithDeleteMarker(); var renameSucceeded = false; int deleteVersion = 0; do { try { accessor.RenameFile(fileName, deletingFileName); renameSucceeded = true; } catch (FileExistsException) // it means that .deleting file was already existed { var deletingFileHeader = accessor.ReadFile(deletingFileName); if (deletingFileHeader != null && deletingFileHeader.Equals(existingFileHeader)) { fileExists = false; // the same file already marked as deleted no need to do it again return; } // we need to use different name to do a file rename deleteVersion++; deletingFileName = RavenFileNameHelper.DeletingFileName(fileName, deleteVersion); } } while (!renameSucceeded && deleteVersion < 128); if (renameSucceeded) { accessor.UpdateFileMetadata(deletingFileName, metadata); accessor.DecrementFileCount(deletingFileName); Log.Debug(string.Format("File '{0}' was renamed to '{1}' and marked as deleted", fileName, deletingFileName)); var configName = RavenFileNameHelper.DeleteOperationConfigNameForFile(deletingFileName); var operation = new DeleteFileOperation { OriginalFileName = fileName, CurrentFileName = deletingFileName }; accessor.SetConfig(configName, JsonExtensions.ToJObject(operation)); notificationPublisher.Publish(new ConfigurationChangeNotification { Name = configName, Action = ConfigurationChangeAction.Set }); } else { Log.Warn("Could not rename a file '{0}' when a delete operation was performed", fileName); } }); if (fileExists) { search.Delete(fileName); search.Delete(deletingFileName); } }