예제 #1
0
        public async Task Should_resume_file_copying_from_client()
        {
            var client = NewAsyncClient();
            var rfs    = GetFileSystem();

            string fileName = FileHeader.Canonize("file.bin");
            string newName  = FileHeader.Canonize("file2.bin");

            await client.UploadAsync(fileName, new RandomStream(1));

            // create config to say to the server that rename operation performed last time were not finished
            var copyOpConfig  = RavenFileNameHelper.CopyOperationConfigNameForFile(fileName, newName);
            var copyOperation = new CopyFileOperation
            {
                SourceFilename         = fileName,
                TargetFilename         = newName,
                MetadataAfterOperation = new RavenJObject()
            };

            rfs.Storage.Batch(accessor => accessor.SetConfigurationValue(copyOpConfig, copyOperation));

            await client.Storage.RetryCopyingAsync();

            IEnumerable <string> configNames = await client.Configuration.GetKeyNamesAsync();

            Assert.DoesNotContain(copyOpConfig, configNames);

            var renamedMetadata = await client.GetMetadataForAsync(newName);

            Assert.NotNull(renamedMetadata);
        }
        /// <summary>
        /// Will deploy local file and its attributes to remote server.
        /// </summary>
        /// <param name="sourceFile"></param>
        /// <param name="destFile"></param>
        /// <returns></returns>
        public static IOfferRemoteDeployment File(this IOfferRemoteDeployment remote, string sourceFile, string destFile)
        {
            var copyFileOperation = new CopyFileOperation(sourceFile, destFile);

            OperationExecutor.Execute((RemoteBuilder)remote, copyFileOperation);
            return(remote);
        }
예제 #3
0
        public HttpResponseMessage Copy(string name, string targetFilename)
        {
            name           = FileHeader.Canonize(name);
            targetFilename = FileHeader.Canonize(targetFilename);
            var etag = GetEtag();

            Storage.Batch(accessor =>
            {
                FileSystem.Synchronizations.AssertFileIsNotBeingSynced(name);

                var existingFile = accessor.ReadFile(name);
                if (existingFile == null || existingFile.Metadata.Value <bool>(SynchronizationConstants.RavenDeleteMarker))
                {
                    throw new FileNotFoundException();
                }

                var renamingFile = accessor.ReadFile(targetFilename);
                if (renamingFile != null && renamingFile.Metadata.Value <bool>(SynchronizationConstants.RavenDeleteMarker) == false)
                {
                    throw new FileExistsException("Cannot copy because file " + targetFilename + " already exists");
                }

                var metadata = existingFile.Metadata;

                if (etag != null && existingFile.Etag != etag)
                {
                    throw new ConcurrencyException("Operation attempted on file '" + name + "' using a non current etag")
                    {
                        ActualETag   = existingFile.Etag,
                        ExpectedETag = etag
                    }
                }
                ;

                Historian.UpdateLastModified(metadata);

                var operation = new CopyFileOperation
                {
                    FileSystem             = FileSystem.Name,
                    SourceFilename         = name,
                    TargetFilename         = targetFilename,
                    MetadataAfterOperation = metadata
                };

                accessor.SetConfig(RavenFileNameHelper.CopyOperationConfigNameForFile(name), JsonExtensions.ToJObject(operation));
                accessor.PulseTransaction(); // commit rename operation config

                Files.ExecuteCopyOperation(operation);
            });

            if (Log.IsDebugEnabled)
            {
                Log.Debug("File '{0}' was copied to '{1}'", name, targetFilename);
            }

            FileSystem.Synchronizations.StartSynchronizeDestinationsInBackground();

            return(GetEmptyMessage(HttpStatusCode.NoContent));
        }
        /// <summary>
        /// Will deploy local file and its attributes to remote server.
        /// </summary>
        /// <param name="sourceFile"></param>
        /// <param name="destFile"></param>
        /// <returns></returns>
        public static IOfferRemoteDeployment File(this IOfferRemoteDeployment remote, string sourceFile, string destFile)
        {
            var copyFileOperation = new CopyFileOperation(sourceFile, destFile);

            Configure.Operation(remote, copyFileOperation);
            //Configure.DeploymentOperations.AddOperation(copyFileOperation);
            return(remote);
        }
예제 #5
0
        public void ExecuteCopyOperation(CopyFileOperation operation)
        {
            var configName = RavenFileNameHelper.CopyOperationConfigNameForFile(operation.SourceFilename, operation.TargetFilename);

            Storage.Batch(accessor =>
            {
                AssertPutOperationNotVetoed(operation.TargetFilename, operation.MetadataAfterOperation);

                var targetTombstrone = accessor.ReadFile(operation.TargetFilename);

                if (targetTombstrone != null &&
                    targetTombstrone.Metadata[SynchronizationConstants.RavenDeleteMarker] != null)
                {
                    // if there is a tombstone delete it
                    accessor.Delete(targetTombstrone.FullPath);
                }

                FileSystem.PutTriggers.Apply(trigger => trigger.OnPut(operation.TargetFilename, operation.MetadataAfterOperation));

                accessor.CopyFile(operation.SourceFilename, operation.TargetFilename, true);
                var putResult = accessor.UpdateFileMetadata(operation.TargetFilename, operation.MetadataAfterOperation, null);

                FileSystem.PutTriggers.Apply(trigger => trigger.AfterPut(operation.TargetFilename, null, operation.MetadataAfterOperation));

                accessor.DeleteConfig(configName);

                Search.Index(operation.TargetFilename, operation.MetadataAfterOperation, putResult.Etag);
            });

            Publisher.Publish(new ConfigurationChangeNotification {
                Name = configName, Action = ConfigurationChangeAction.Set
            });
            Publisher.Publish(new FileChangeNotification {
                File = operation.TargetFilename, Action = FileChangeAction.Add
            });
        }
예제 #6
0
        public void Run()
        {
            var operations = new List <IFileSystemCloningOperation>();

            var sourceDirectoryFileSystemSite      = this.DeploymentSource_SecretsDirectory_FileSystemSiteProvider.GetDeploymentSourceSecretsDirectoryFileSystemSite();
            var destinationDirectoryFileSystemSite = this.DeploymentDestination_SecretsDirectory_FileSystemSiteProvider.GetDeploymentDestinationSecretsDirectoryFileSystemSite();

            var secretsFileNames = this.SecretsFileNamesProvider.GetSecretsFileNames();

            foreach (var secretsFileName in secretsFileNames)
            {
                var sourceFilePath      = this.StringlyTypedPathOperator.Combine(sourceDirectoryFileSystemSite.DirectoryPath, secretsFileName);
                var destinationFilePath = this.StringlyTypedPathOperator.Combine(destinationDirectoryFileSystemSite.DirectoryPath, secretsFileName);

                var copyFileOperation = new CopyFileOperation(sourceFilePath, destinationFilePath);

                operations.Add(copyFileOperation);
            }

            foreach (var operation in operations)
            {
                operation.Execute(sourceDirectoryFileSystemSite.FileSystemOperator, destinationDirectoryFileSystemSite.FileSystemOperator);
            }
        }
예제 #7
0
        public HttpResponseMessage Copy(string name, string targetFilename)
        {
            name           = FileHeader.Canonize(name);
            targetFilename = FileHeader.Canonize(targetFilename);
            var etag = GetEtag();

            var retriesCount = 0;

            while (true)
            {
                try
                {
                    Storage.Batch(accessor =>
                    {
                        FileSystem.Synchronizations.AssertFileIsNotBeingSynced(name);

                        var existingFile = accessor.ReadFile(name);
                        if (existingFile == null || existingFile.Metadata.Value <bool>(SynchronizationConstants.RavenDeleteMarker))
                        {
                            throw new FileNotFoundException();
                        }

                        var renamingFile = accessor.ReadFile(targetFilename);
                        if (renamingFile != null && renamingFile.Metadata.Value <bool>(SynchronizationConstants.RavenDeleteMarker) == false)
                        {
                            throw new FileExistsException("Cannot copy because file " + targetFilename + " already exists");
                        }

                        var metadata = existingFile.Metadata;

                        if (etag != null && existingFile.Etag != etag)
                        {
                            throw new ConcurrencyException("Operation attempted on file '" + name + "' using a non current etag")
                            {
                                ActualETag   = existingFile.Etag,
                                ExpectedETag = etag
                            }
                        }
                        ;

                        Historian.UpdateLastModified(metadata);

                        var operation = new CopyFileOperation
                        {
                            FileSystem             = FileSystem.Name,
                            SourceFilename         = name,
                            TargetFilename         = targetFilename,
                            MetadataAfterOperation = metadata
                        };

                        accessor.SetConfig(RavenFileNameHelper.CopyOperationConfigNameForFile(name, targetFilename), JsonExtensions.ToJObject(operation));
                        var configName = RavenFileNameHelper.CopyOperationConfigNameForFile(operation.SourceFilename, operation.TargetFilename);
                        Files.AssertPutOperationNotVetoed(operation.TargetFilename, operation.MetadataAfterOperation);

                        var targetTombstrone = accessor.ReadFile(operation.TargetFilename);

                        if (targetTombstrone != null &&
                            targetTombstrone.Metadata[SynchronizationConstants.RavenDeleteMarker] != null)
                        {
                            // if there is a tombstone delete it
                            accessor.Delete(targetTombstrone.FullPath);
                        }

                        FileSystem.PutTriggers.Apply(trigger => trigger.OnPut(operation.TargetFilename, operation.MetadataAfterOperation));

                        accessor.CopyFile(operation.SourceFilename, operation.TargetFilename, true);
                        var putResult = accessor.UpdateFileMetadata(operation.TargetFilename, operation.MetadataAfterOperation, null);

                        FileSystem.PutTriggers.Apply(trigger => trigger.AfterPut(operation.TargetFilename, null, operation.MetadataAfterOperation));

                        accessor.DeleteConfig(configName);

                        Search.Index(operation.TargetFilename, operation.MetadataAfterOperation, putResult.Etag);


                        Publisher.Publish(new ConfigurationChangeNotification {
                            Name = configName, Action = ConfigurationChangeAction.Set
                        });
                        Publisher.Publish(new FileChangeNotification {
                            File = operation.TargetFilename, Action = FileChangeAction.Add
                        });
                    });

                    break;
                }
                catch (ConcurrencyException)
                {
                    // due to IncrementUsageCount performed concurrently on Voron storage
                    // Esent deals with that much better using Api.EscrowUpdate

                    if (retriesCount++ > 100)
                    {
                        throw;
                    }

                    Thread.Sleep(new Random().Next(1, 13));
                }
            }

            if (Log.IsDebugEnabled)
            {
                Log.Debug("File '{0}' was copied to '{1}'", name, targetFilename);
            }

            SynchronizationTask.Context.NotifyAboutWork();

            return(GetEmptyMessage(HttpStatusCode.NoContent));
        }
        public void Clone(FileSystemSite source, FileSystemSite destination, FileSystemCloningOptions options)
        {
            // Ensure the source and destination directories are directory indicated.
            var ensuredSource      = source.EnsureSiteDirectoryPathIsDirectoryIndicated(this.StringlyTypedPathOperator);
            var ensuredDestination = destination.EnsureSiteDirectoryPathIsDirectoryIndicated(this.StringlyTypedPathOperator);

            // Get all source file-system entries.
            var sourceFileSystemEntries = ensuredSource.FileSystemOperator.EnumerateFileSystemEntries(ensuredSource.DirectoryPath, true)
                                          .ToList();

            // Get all destination file-system entries.
            var destinationFileSystemEntries = ensuredDestination.FileSystemOperator.EnumerateFileSystemEntries(ensuredDestination.DirectoryPath, true)
                                               .ToList();

            // Create relative-path source and destination file-system entries.
            FileSystemEntry MakeRelativeEntry(string baseDirectoryPath, FileSystemEntry entry)
            {
                var sourceBaseDirectoryRelativeEntryPath = this.StringlyTypedPathOperator.GetRelativePath(baseDirectoryPath, entry.Path);

                var relativeEntry = FileSystemEntry.New(sourceBaseDirectoryRelativeEntryPath, entry.Type, entry.LastModifiedUTC);

                return(relativeEntry);
            }

            var sourceBaseDirectoryRelativePathEntries = sourceFileSystemEntries.Select(entry => MakeRelativeEntry(ensuredSource.DirectoryPath, entry))
                                                         .Select(fileSystemEntry =>
            {
                // Make sure we are using a common path format.
                var standardPathFileSystemEntry = fileSystemEntry.GetStandardPathFormatEntry(this.StringlyTypedPathOperator);
                return(standardPathFileSystemEntry);
            })
                                                         .ToList();

            var destinationBaseDirectoryRelativePathEntries = destinationFileSystemEntries.Select(entry => MakeRelativeEntry(ensuredDestination.DirectoryPath, entry))
                                                              .Select(fileSystemEntry =>
            {
                // Make sure we are using a common path format.
                var standardPathFileSystemEntry = fileSystemEntry.GetStandardPathFormatEntry(this.StringlyTypedPathOperator);
                return(standardPathFileSystemEntry);
            })
                                                              .ToList();

            // Write out source and destination data.

            // Get the file-system cloning difference.
            var difference = this.FileSystemCloningDifferencer.PerformDifference(sourceBaseDirectoryRelativePathEntries, destinationBaseDirectoryRelativePathEntries, options);

            // Create a list of operations, using absolute paths.
            var operations = new List <IFileSystemCloningOperation>();

            // Special case: the destination directory does not exist. If so, make sure it is created first to allow files to be copied into it!
            var destinationDirectoryExists = ensuredDestination.FileSystemOperator.ExistsDirectory(ensuredDestination.DirectoryPath);

            if (!destinationDirectoryExists)
            {
                var createDestinationDirectoryOperation = new CreateDirectoryOperation(ensuredDestination.DirectoryPath);

                operations.Add(createDestinationDirectoryOperation);
            }

            foreach (var directoryToCreate in difference.RelativeDirectoryPathsToCreate)
            {
                string destinationDirectoryToCreate = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, directoryToCreate);

                var createDirectoryOperation = new CreateDirectoryOperation(destinationDirectoryToCreate);

                operations.Add(createDirectoryOperation);
            }

            foreach (var directoryToDelete in difference.RelativeDirectoryPathsToDelete)
            {
                string destinationDirectoryToDelete = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, directoryToDelete);

                var deleteDirectoryOperation = new DeleteDirectoryOperation(destinationDirectoryToDelete);

                operations.Add(deleteDirectoryOperation);
            }

            foreach (var fileToCopy in difference.RelativeFilePathsToCopy)
            {
                string sourceFilePath      = this.StringlyTypedPathOperator.Combine(ensuredSource.DirectoryPath, fileToCopy);
                string destinationFilePath = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, fileToCopy);

                var copyFileOperation = new CopyFileOperation(sourceFilePath, destinationFilePath);

                operations.Add(copyFileOperation);
            }

            foreach (var fileToUpdate in difference.RelativeFilePathsToUpdate)
            {
                string sourceFilePath      = this.StringlyTypedPathOperator.Combine(ensuredSource.DirectoryPath, fileToUpdate);
                string destinationFilePath = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, fileToUpdate);

                var copyFileOperation = new CopyFileOperation(sourceFilePath, destinationFilePath);

                operations.Add(copyFileOperation);
            }

            foreach (var fileToDelete in difference.RelativeFilePathsToDelete)
            {
                string destinationFilePath = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, fileToDelete);

                var deleteFileOperation = new DeleteFileOperation(destinationFilePath);

                operations.Add(deleteFileOperation);
            }

            // Write out and allow approval of the list of operations?

            // Execute the list of operations.
            foreach (var operation in operations)
            {
                operation.Execute(ensuredSource.FileSystemOperator, ensuredDestination.FileSystemOperator);
            }
        }