Exemple #1
0
        public Task <HttpResponseMessage> ExportFilesystem(StudioTasksController.ExportData smugglerOptionsJson)
        {
            var result = GetEmptyMessage();

            var taskId        = smugglerOptionsJson.ProgressTaskId;
            var requestString = smugglerOptionsJson.DownloadOptions;
            SmugglerFilesOptions smugglerOptions;

            using (var jsonReader = new RavenJsonTextReader(new StringReader(requestString)))
            {
                var serializer = JsonExtensions.CreateDefaultJsonSerializer();
                smugglerOptions = (SmugglerFilesOptions)serializer.Deserialize(jsonReader, typeof(SmugglerFilesOptions));
            }

            var fileName = string.IsNullOrEmpty(smugglerOptions.NoneDefualtFileName) || (smugglerOptions.NoneDefualtFileName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) ?
                           $"Dump of {FileSystemName}, {DateTime.Now.ToString("yyyy-MM-dd HH-mm", CultureInfo.InvariantCulture)}" :
                           smugglerOptions.NoneDefualtFileName;

            //create PushStreamContent object that will be called when the output stream will be ready.
            result.Content = new PushStreamContent(async(outputStream, content, arg3) =>
            {
                var status = new DataDumperOperationStatus();
                var tcs    = new TaskCompletionSource <object>();
                var sp     = Stopwatch.StartNew();

                try
                {
                    FileSystem.Tasks.AddTask(tcs.Task, status, new TaskActions.PendingTaskDescription
                    {
                        StartTime = SystemTime.UtcNow,
                        TaskType  = TaskActions.PendingTaskType.ExportFileSystem,
                        Payload   = "Exporting file system, file name: " + fileName
                    }, taskId, smugglerOptions.CancelToken, skipStatusCheck: true);

                    var dataDumper       = new FilesystemDataDumper(FileSystem, smugglerOptions);
                    dataDumper.Progress += s => status.MarkProgress(s);
                    await dataDumper.ExportData(
                        new SmugglerExportOptions <FilesConnectionStringOptions>
                    {
                        ToStream = outputStream
                    }).ConfigureAwait(false);

                    const string message = "Completed export";
                    status.MarkCompleted(message, sp.Elapsed);
                }
                catch (OperationCanceledException e)
                {
                    status.MarkCanceled(e.Message);
                }
                catch (Exception e)
                {
                    status.ExceptionDetails = e.ToString();
                    status.MarkFaulted(e.ToString());

                    throw;
                }
                finally
                {
                    tcs.SetResult("Completed");
                    outputStream.Close();
                }
            });

            result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = fileName + ".ravenfsdump"
            };

            return(new CompletedTask <HttpResponseMessage>(result));
        }
Exemple #2
0
        public async Task <HttpResponseMessage> ImportFilesystem(int batchSize, bool stripReplicationInformation, bool shouldDisableVersioningBundle)
        {
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }

            string tempPath     = FileSystem.Configuration.TempPath;
            var    fullTempPath = tempPath + Constants.TempUploadsDirectoryName;

            if (File.Exists(fullTempPath))
            {
                File.Delete(fullTempPath);
            }
            if (Directory.Exists(fullTempPath) == false)
            {
                Directory.CreateDirectory(fullTempPath);
            }

            var streamProvider = new MultipartFileStreamProvider(fullTempPath);
            await Request.Content.ReadAsMultipartAsync(streamProvider).ConfigureAwait(false);

            var uploadedFilePath = streamProvider.FileData[0].LocalFileName;

            string fileName    = null;
            var    fileContent = streamProvider.Contents.SingleOrDefault();

            if (fileContent != null)
            {
                fileName = fileContent.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
            }

            var status = new DataDumperOperationStatus();
            var cts    = new CancellationTokenSource();

            var task = Task.Run(async() =>
            {
                try
                {
                    var dataDumper            = new FilesystemDataDumper(FileSystem);
                    dataDumper.Progress      += s => status.MarkProgress(s);
                    var smugglerOptions       = dataDumper.Options;
                    smugglerOptions.BatchSize = batchSize;
                    smugglerOptions.ShouldDisableVersioningBundle = shouldDisableVersioningBundle;
                    smugglerOptions.StripReplicationInformation   = stripReplicationInformation;
                    smugglerOptions.CancelToken = cts;

                    await dataDumper.ImportData(new SmugglerImportOptions <FilesConnectionStringOptions> {
                        FromFile = uploadedFilePath
                    }).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    if (cts.Token.IsCancellationRequested)
                    {
                        status.MarkCanceled("Task was cancelled");
                        cts.Token.ThrowIfCancellationRequested(); //needed for displaying the task status as canceled and not faulted
                    }

                    if (e is InvalidDataException)
                    {
                        status.ExceptionDetails = e.Message;
                    }
                    else if (e is OperationVetoedException && e.Message.Contains(VersioningTriggerActions.CreationOfHistoricalRevisionIsNotAllowed))
                    {
                        status.ExceptionDetails = "You are trying to import historical documents while the versioning bundle is enabled. " +
                                                  "You should disable versioning during such import. Please mark the checkbox 'Disable versioning bundle during import' at Import File System";
                    }
                    else
                    {
                        status.ExceptionDetails = e.ToString();
                    }
                    status.MarkFaulted(status.ExceptionDetails);
                    throw;
                }
                finally
                {
                    status.MarkCompleted();
                    File.Delete(uploadedFilePath);
                }
            }, cts.Token);

            long id;

            FileSystem.Tasks.AddTask(task, status, new TaskActions.PendingTaskDescription
            {
                StartTime = SystemTime.UtcNow,
                TaskType  = TaskActions.PendingTaskType.ImportFileSystem,
                Payload   = fileName
            }, out id, cts);

            return(GetMessageWithObject(new
            {
                OperationId = id
            }, HttpStatusCode.Accepted));
        }
Exemple #3
0
        public async Task <HttpResponseMessage> ImportDatabase(int batchSize, bool includeExpiredDocuments, bool stripReplicationInformation, bool shouldDisableVersioningBundle, ItemType operateOnTypes, string filtersPipeDelimited, string transformScript)
        {
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }

            var tempPath     = Database.Configuration.TempPath;
            var fullTempPath = tempPath + Constants.TempUploadsDirectoryName;

            if (File.Exists(fullTempPath))
            {
                File.Delete(fullTempPath);
            }
            if (Directory.Exists(fullTempPath) == false)
            {
                Directory.CreateDirectory(fullTempPath);
            }

            var streamProvider = new MultipartFileStreamProvider(fullTempPath);
            await Request.Content.ReadAsMultipartAsync(streamProvider).ConfigureAwait(false);

            var uploadedFilePath = streamProvider.FileData[0].LocalFileName;

            string fileName    = null;
            var    fileContent = streamProvider.Contents.SingleOrDefault();

            if (fileContent != null)
            {
                fileName = fileContent.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
            }

            var status = new DataDumperOperationStatus();
            var cts    = new CancellationTokenSource();

            var user = CurrentOperationContext.User.Value;

            if (user == null)
            {
                user = RequestContext.Principal;
            }
            var requestDisposables = CurrentOperationContext.RequestDisposables.Value;
            var headers            = CurrentOperationContext.Headers.Value;

            var task = Task.Run(async() =>
            {
                try
                {
                    CurrentOperationContext.User.Value = user;
                    CurrentOperationContext.RequestDisposables.Value = requestDisposables;
                    CurrentOperationContext.Headers.Value            = headers;
                    using (var fileStream = File.Open(uploadedFilePath, FileMode.Open, FileAccess.Read))
                    {
                        var dataDumper                                = new DatabaseDataDumper(Database);
                        dataDumper.Progress                          += s => status.MarkProgress(s);
                        var smugglerOptions                           = dataDumper.Options;
                        smugglerOptions.BatchSize                     = batchSize;
                        smugglerOptions.ShouldExcludeExpired          = !includeExpiredDocuments;
                        smugglerOptions.StripReplicationInformation   = stripReplicationInformation;
                        smugglerOptions.ShouldDisableVersioningBundle = shouldDisableVersioningBundle;
                        smugglerOptions.OperateOnTypes                = operateOnTypes;
                        smugglerOptions.TransformScript               = transformScript;
                        smugglerOptions.CancelToken                   = cts;

                        // Filters are passed in without the aid of the model binder. Instead, we pass in a list of FilterSettings using a string like this: pathHere;;;valueHere;;;true|||againPathHere;;;anotherValue;;;false
                        // Why? Because I don't see a way to pass a list of a values to a WebAPI method that accepts a file upload, outside of passing in a simple string value and parsing it ourselves.
                        if (filtersPipeDelimited != null)
                        {
                            smugglerOptions.Filters.AddRange(filtersPipeDelimited
                                                             .Split(new[] { "|||" }, StringSplitOptions.RemoveEmptyEntries)
                                                             .Select(f => f.Split(new[] { ";;;" }, StringSplitOptions.RemoveEmptyEntries))
                                                             .Select(o => new FilterSetting {
                                Path = o[0], Values = new List <string> {
                                    o[1]
                                }, ShouldMatch = bool.Parse(o[2])
                            }));
                        }

                        await dataDumper.ImportData(new SmugglerImportOptions <RavenConnectionStringOptions> {
                            FromStream = fileStream
                        }).ConfigureAwait(false);
                    }
                    // use the last status which contains info about amount of doc/indexes imported
                    status.MarkCompleted(status.State.Value <string>("Progress"));
                }
                catch (Exception e)
                {
                    if (cts.Token.IsCancellationRequested)
                    {
                        status.MarkCanceled("Task was cancelled");
                        cts.Token.ThrowIfCancellationRequested(); //needed for displaying the task status as canceled and not faulted
                    }

                    if (e is InvalidDataException)
                    {
                        status.ExceptionDetails = e.Message;
                    }
                    else if (e is JsonReaderException)
                    {
                        status.ExceptionDetails = "Failed to load JSON Data. Please make sure you are importing .ravendbdump file, exported by smuggler (aka database export). If you are importing a .ravendbdump file then the file may be corrupted";
                    }
                    else if (e is OperationVetoedException && e.Message.Contains(VersioningPutTrigger.CreationOfHistoricalRevisionIsNotAllowed))
                    {
                        status.ExceptionDetails = "You are trying to import historical documents while the versioning bundle is enabled. " +
                                                  "The versioning bundle is enabled. You should disable versioning during import. " +
                                                  "Please mark the checkbox 'Disable versioning bundle during import' at Import Database: Advanced settings before importing";
                    }
                    else
                    {
                        status.ExceptionDetails = e.ToString();
                    }
                    status.MarkFaulted(e.ToString());
                    throw;
                }
                finally
                {
                    File.Delete(uploadedFilePath);
                }
            }, cts.Token);

            long id;

            Database.Tasks.AddTask(task, status, new TaskActions.PendingTaskDescription
            {
                StartTime   = SystemTime.UtcNow,
                TaskType    = TaskActions.PendingTaskType.ExportDatabase,
                Description = fileName
            }, out id, cts);

            return(GetMessageWithObject(new
            {
                OperationId = id
            }, HttpStatusCode.Accepted));
        }