文件读写复制操作,对System.IO的一些封装
示例#1
0
 public void Dispose()
 {
     IOExtensions.DeleteDirectory("Data");
     IOExtensions.DeleteDirectory("NHibernate");
 }
 public override void Dispose()
 {
     IOExtensions.DeleteDirectory(path);
     base.Dispose();
 }
示例#3
0
 public void Dispose()
 {
     IOExtensions.DeleteDirectory(path);
 }
示例#4
0
        public async Task MetadataIsPreserved()
        {
            using (var store = NewStore())
            {
                var server          = GetServer();
                var outputDirectory = Path.Combine(server.Configuration.DataDirectory, "Export");
                try
                {
                    var dumper = new SmugglerFilesApi {
                        Options = { Incremental = true }
                    };

                    FileHeader originalFile;
                    using (var session = store.OpenAsyncSession())
                    {
                        session.RegisterUpload("test1.file", CreateRandomFileStream(12800));
                        await session.SaveChangesAsync();

                        // content update after a metadata change
                        originalFile = await session.LoadFileAsync("test1.file");

                        originalFile.Metadata["Test"] = new RavenJValue("Value");
                        await session.SaveChangesAsync();
                    }

                    using (new FilesStore {
                        Url = server.Url
                    }.Initialize())
                    {
                        // now perform full backup
                        await dumper.ExportData(new SmugglerExportOptions <FilesConnectionStringOptions>
                        {
                            ToFile = outputDirectory,
                            From   = new FilesConnectionStringOptions
                            {
                                Url = server.Url,
                                DefaultFileSystem = store.DefaultFileSystem,
                            }
                        });
                    }

                    await VerifyDump(store, outputDirectory, s =>
                    {
                        using (var session = s.OpenAsyncSession())
                        {
                            var file = session.LoadFileAsync("test1.file").Result;

                            Assert.Equal(originalFile.CreationDate, file.CreationDate);
                            Assert.Equal(originalFile.Directory, file.Directory);
                            Assert.Equal(originalFile.Extension, file.Extension);
                            Assert.Equal(originalFile.FullPath, file.FullPath);
                            Assert.Equal(originalFile.Name, file.Name);
                            Assert.Equal(originalFile.TotalSize, file.TotalSize);
                            Assert.Equal(originalFile.UploadedSize, file.UploadedSize);
                            Assert.Equal(originalFile.LastModified, file.LastModified);

                            Assert.True(file.Metadata.ContainsKey("Test"));
                        }
                    });
                }
                finally
                {
                    IOExtensions.DeleteDirectory(outputDirectory);
                }
            }
        }
示例#5
0
 public override void Dispose()
 {
     base.Dispose();
     IOExtensions.DeleteDirectory(BackupDir);
 }
示例#6
0
        private void DumpStacktrace(ZipArchive package)
        {
            var stacktraceRequsted = GetQueryStringValue("stacktrace");

            if (stacktraceRequsted != null)
            {
                var stacktrace = package.CreateEntry("stacktraces.txt", CompressionLevel.Optimal);

                var jsonSerializer = new JsonSerializer {
                    Formatting = Formatting.Indented
                };
                jsonSerializer.Converters.Add(new EtagJsonConverter());

                using (var stacktraceStream = stacktrace.Open())
                {
                    string ravenDebugDir = null;

                    try
                    {
                        if (Debugger.IsAttached)
                        {
                            throw new InvalidOperationException("Cannot get stacktraces when debugger is attached");
                        }

                        ravenDebugDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
                        var ravenDebugExe    = Path.Combine(ravenDebugDir, "Raven.Debug.exe");
                        var ravenDebugOutput = Path.Combine(ravenDebugDir, "stacktraces.txt");

                        Directory.CreateDirectory(ravenDebugDir);

                        if (Environment.Is64BitProcess)
                        {
                            ExtractResource("Raven.Database.Util.Raven.Debug.x64.Raven.Debug.exe", ravenDebugExe);
                        }
                        else
                        {
                            ExtractResource("Raven.Database.Util.Raven.Debug.x86.Raven.Debug.exe", ravenDebugExe);
                        }

                        var process = new Process {
                            StartInfo = new ProcessStartInfo {
                                Arguments = string.Format("-pid={0} /stacktrace -output={1}", Process.GetCurrentProcess().Id, ravenDebugOutput), FileName = ravenDebugExe, WindowStyle = ProcessWindowStyle.Hidden,
                            }
                        };

                        process.Start();

                        process.WaitForExit();

                        using (var stackDumpOutputStream = File.Open(ravenDebugOutput, FileMode.Open))
                        {
                            stackDumpOutputStream.CopyTo(stacktraceStream);
                        }
                    }
                    catch (Exception ex)
                    {
                        var streamWriter = new StreamWriter(stacktraceStream);
                        jsonSerializer.Serialize(streamWriter, new { Error = "Exception occurred during getting stacktraces of the RavenDB process. Exception: " + ex });
                        streamWriter.Flush();
                    }
                    finally
                    {
                        if (ravenDebugDir != null && Directory.Exists(ravenDebugDir))
                        {
                            IOExtensions.DeleteDirectory(ravenDebugDir);
                        }
                    }

                    stacktraceStream.Flush();
                }
            }
        }
示例#7
0
        public async Task CanHandleFilesExceptionsGracefully()
        {
            using (var store = NewStore())
            {
                var server          = GetServer();
                var outputDirectory = Path.Combine(server.Configuration.DataDirectory, "Export");

                var alreadyReset = false;
                var proxyPort    = 8070;
                var forwarder    = new ProxyServer(ref proxyPort, server.Configuration.Port)
                {
                    VetoTransfer = (totalRead, buffer) =>
                    {
                        if (alreadyReset == false && totalRead > 28000)
                        {
                            alreadyReset = true;
                            return(true);
                        }
                        return(false);
                    }
                };

                try
                {
                    ReseedRandom(100); // Force a random distribution.

                    await InitializeWithRandomFiles(store, 20, 30);

                    // now perform full backup
                    var dumper = new SmugglerFilesApi {
                        Options = { Incremental = true }
                    };

                    ExportFilesResult exportResult = null;
                    try
                    {
                        // We will ensure this one will fail somewhere along the line.
                        exportResult = await dumper.ExportData(
                            new SmugglerExportOptions <FilesConnectionStringOptions>
                        {
                            ToFile = outputDirectory,
                            From   = new FilesConnectionStringOptions
                            {
                                Url = "http://localhost:" + proxyPort,
                                DefaultFileSystem = store.DefaultFileSystem,
                            }
                        });
                    }
                    catch (SmugglerExportException inner)
                    {
                        exportResult = new ExportFilesResult
                        {
                            FilePath = inner.File
                        };
                    }

                    Assert.NotNull(exportResult);
                    Assert.True(!string.IsNullOrWhiteSpace(exportResult.FilePath));

                    // Continue with the incremental dump.
                    exportResult = await dumper.ExportData(
                        new SmugglerExportOptions <FilesConnectionStringOptions>
                    {
                        ToFile = outputDirectory,
                        From   = new FilesConnectionStringOptions
                        {
                            Url = server.Url,
                            DefaultFileSystem = store.DefaultFileSystem,
                        }
                    });

                    // Import everything and verify all files are there.
                    await VerifyDump(store, outputDirectory, s =>
                    {
                        using (var session = s.OpenAsyncSession())
                        {
                            var files = s.AsyncFilesCommands.BrowseAsync().Result;
                            Assert.Equal(20, files.Count());
                        }
                    });
                }
                finally
                {
                    forwarder.Dispose();
                    IOExtensions.DeleteDirectory(outputDirectory);
                }
            }
        }
示例#8
0
 public override void Dispose()
 {
     IOExtensions.DeleteDirectory("Data");
     IOExtensions.DeleteDirectory("Test");
     base.Dispose();
 }
示例#9
0
        public async Task Execute(Action <IOperationProgress> onProgress, CompactionResult result)
        {
            if (_isCompactionInProgress)
            {
                throw new InvalidOperationException($"Database '{_database}' cannot be compacted because compaction is already in progress.");
            }

            result.AddMessage($"Started database compaction for {_database}");
            onProgress?.Invoke(result.Progress);

            _isCompactionInProgress = true;
            bool   done                 = false;
            string compactDirectory     = null;
            string tmpDirectory         = null;
            string compactTempDirectory = null;

            byte[] encryptionKey = null;
            try
            {
                var documentDatabase = await _serverStore.DatabasesLandlord.TryGetOrCreateResourceStore(_database);

                var configuration = _serverStore.DatabasesLandlord.CreateDatabaseConfiguration(_database);

                DatabaseRecord databaseRecord = documentDatabase.ReadDatabaseRecord();


                // save the key before unloading the database (it is zeroed when disposing DocumentDatabase).
                if (documentDatabase.MasterKey != null)
                {
                    encryptionKey = documentDatabase.MasterKey.ToArray();
                }

                using (await _serverStore.DatabasesLandlord.UnloadAndLockDatabase(_database, "it is being compacted"))
                    using (var src = DocumentsStorage.GetStorageEnvironmentOptionsFromConfiguration(configuration, new IoChangesNotifications
                    {
                        DisableIoMetrics = true
                    },
                                                                                                    new CatastrophicFailureNotification((endId, path, exception, stacktrace) => throw new InvalidOperationException($"Failed to compact database {_database} ({path}), StackTrace='{stacktrace}'", exception))))
                    {
                        InitializeOptions(src, configuration, documentDatabase, encryptionKey);
                        DirectoryExecUtils.SubscribeToOnDirectoryInitializeExec(src, configuration.Storage, documentDatabase.Name, DirectoryExecUtils.EnvironmentType.Compaction, Logger);

                        var basePath = configuration.Core.DataDirectory.FullPath;
                        compactDirectory = basePath + "-compacting";
                        tmpDirectory     = basePath + "-old";

                        EnsureDirectoriesPermission(basePath, compactDirectory, tmpDirectory);

                        IOExtensions.DeleteDirectory(compactDirectory);
                        IOExtensions.DeleteDirectory(tmpDirectory);

                        configuration.Core.DataDirectory = new PathSetting(compactDirectory);

                        if (configuration.Storage.TempPath != null)
                        {
                            compactTempDirectory = configuration.Storage.TempPath.FullPath + "-temp-compacting";

                            EnsureDirectoriesPermission(compactTempDirectory);
                            IOExtensions.DeleteDirectory(compactTempDirectory);

                            configuration.Storage.TempPath = new PathSetting(compactTempDirectory);
                        }

                        var revisionsPrefix   = CollectionName.GetTablePrefix(CollectionTableType.Revisions);
                        var collectionsPrefix = CollectionName.GetTablePrefix(CollectionTableType.Documents);

                        var compressedCollectionsTableNames = databaseRecord.DocumentsCompression?.Collections
                                                              .Select(name => new CollectionName(name).GetTableName(CollectionTableType.Documents))
                                                              .ToHashSet(StringComparer.OrdinalIgnoreCase);

                        using (var dst = DocumentsStorage.GetStorageEnvironmentOptionsFromConfiguration(configuration, new IoChangesNotifications
                        {
                            DisableIoMetrics = true
                        },
                                                                                                        new CatastrophicFailureNotification((envId, path, exception, stacktrace) => throw new InvalidOperationException($"Failed to compact database {_database} ({path}). StackTrace='{stacktrace}'", exception))))
                        {
                            InitializeOptions(dst, configuration, documentDatabase, encryptionKey);
                            DirectoryExecUtils.SubscribeToOnDirectoryInitializeExec(dst, configuration.Storage, documentDatabase.Name, DirectoryExecUtils.EnvironmentType.Compaction, Logger);

                            _token.ThrowIfCancellationRequested();
                            StorageCompaction.Execute(src, (StorageEnvironmentOptions.DirectoryStorageEnvironmentOptions)dst, progressReport =>
                            {
                                result.Progress.TreeProgress   = progressReport.TreeProgress;
                                result.Progress.TreeTotal      = progressReport.TreeTotal;
                                result.Progress.TreeName       = progressReport.TreeName;
                                result.Progress.GlobalProgress = progressReport.GlobalProgress;
                                result.Progress.GlobalTotal    = progressReport.GlobalTotal;
                                result.AddMessage(progressReport.Message);
                                onProgress?.Invoke(result.Progress);
                            }, (name, schema) =>
                            {
                                bool isRevision   = name.StartsWith(revisionsPrefix, StringComparison.OrdinalIgnoreCase);
                                bool isCollection = name.StartsWith(collectionsPrefix, StringComparison.OrdinalIgnoreCase);
                                schema.Compressed =
                                    (isRevision && databaseRecord.DocumentsCompression?.CompressRevisions == true) ||
                                    (isCollection && databaseRecord.DocumentsCompression?.CompressAllCollections == true) ||
                                    compressedCollectionsTableNames?.Contains(name) == true;
                            }, _token);
                        }

                        result.TreeName = null;

                        _token.ThrowIfCancellationRequested();

                        EnsureDirectoriesPermission(basePath, compactDirectory, tmpDirectory);
                        IOExtensions.DeleteDirectory(tmpDirectory);

                        SwitchDatabaseDirectories(basePath, tmpDirectory, compactDirectory);
                        done = true;
                    }
            }
            catch (Exception e)
            {
                throw new InvalidOperationException($"Failed to execute compaction for {_database}", e);
            }
            finally
            {
                IOExtensions.DeleteDirectory(compactDirectory);
                if (done)
                {
                    IOExtensions.DeleteDirectory(tmpDirectory);

                    if (compactTempDirectory != null)
                    {
                        IOExtensions.DeleteDirectory(compactTempDirectory);
                    }
                }
                _isCompactionInProgress = false;
                if (encryptionKey != null)
                {
                    Sodium.ZeroBuffer(encryptionKey);
                }
            }
        }
示例#10
0
        public void CheckDirectoryPermissions()
        {
            if (Core.RunInMemory)
            {
                return;
            }

            Dictionary <string, KeyValuePair <string, string> > results = null;

            foreach (var configurationProperty in typeof(RavenConfiguration).GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                if (configurationProperty.PropertyType.IsSubclassOf(typeof(ConfigurationCategory)) == false)
                {
                    continue;
                }

                var categoryValue = configurationProperty.GetValue(this);

                foreach (var categoryProperty in configurationProperty.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    if (categoryProperty.PropertyType != typeof(PathSetting))
                    {
                        continue;
                    }

                    var pathSettingValue = categoryProperty.GetValue(categoryValue) as PathSetting;
                    if (pathSettingValue == null)
                    {
                        continue;
                    }

                    var readOnly = categoryProperty.GetCustomAttribute <ReadOnlyPathAttribute>();
                    if (readOnly != null)
                    {
                        continue;
                    }

                    var fileName = Guid.NewGuid().ToString("N");

                    var path     = pathSettingValue.ToFullPath();
                    var fullPath = Path.Combine(path, fileName);

                    var configEntry = categoryProperty.GetCustomAttributes <ConfigurationEntryAttribute>()
                                      .OrderBy(x => x.Order)
                                      .First();

                    if (configEntry.Scope == ConfigurationEntryScope.ServerWideOnly &&
                        ResourceType == ResourceType.Database)
                    {
                        continue;
                    }

                    var configurationKey = configEntry.Key;

                    string createdDirectory = null;
                    try
                    {
                        // if there is no 'path' directory, we are going to create a directory with a similar name, in order to avoid deleting a directory in use afterwards,
                        // and write a sample file inside it, in order to check write permissions.
                        if (Directory.Exists(path) == false)
                        {
                            var curPathCounterVal = Interlocked.Increment(ref _pathCounter);
                            // test that we can create the directory, but
                            // not actually create it
                            createdDirectory = path + "$" + curPathCounterVal.ToString();
                            Directory.CreateDirectory(createdDirectory);
                            var createdFile = Path.Combine(createdDirectory, "test.file");
                            File.WriteAllText(createdFile, string.Empty);
                            File.Delete(createdFile);
                        }
                        // in case there is a 'path' directory, we are going to try and write to it some file, in order to check write permissions
                        else
                        {
                            File.WriteAllText(fullPath, string.Empty);
                            File.Delete(fullPath);
                        }
                    }
                    catch (Exception e)
                    {
                        if (results == null)
                        {
                            results = new Dictionary <string, KeyValuePair <string, string> >();
                        }

                        var errorousDirPath = createdDirectory ?? path;
                        results[configurationKey] = new KeyValuePair <string, string>(errorousDirPath, e.Message);
                    }
                    finally
                    {
                        if (createdDirectory != null)
                        {
                            Interlocked.Decrement(ref _pathCounter);
                            IOExtensions.DeleteDirectory(createdDirectory);
                        }
                    }
                }
            }

            if (results == null || results.Count == 0)
            {
                return;
            }

            var sb = new StringBuilder("Could not access some of the specified paths. Please check if you have sufficient privileges to access following paths:");

            sb.Append(Environment.NewLine);

            foreach (var result in results)
            {
                sb.AppendLine($"Key: '{result.Key}' Path: '{result.Value.Key}' Error: '{result.Value.Value}'");
            }

            throw new InvalidOperationException(sb.ToString());
        }
示例#11
0
 protected void ClearDatabaseDirectory()
 {
     IOExtensions.DeleteDirectory(DbName);
     IOExtensions.DeleteDirectory(DbDirectory);
 }
        private async Task RunPeriodicExport(bool fullExport)
        {
            if (_cancellationToken.IsCancellationRequested)
            {
                return;
            }

            try
            {
                DocumentsOperationContext context;
                using (_database.DocumentsStorage.ContextPool.AllocateOperationContext(out context))
                {
                    var sp = Stopwatch.StartNew();
                    using (var tx = context.OpenReadTransaction())
                    {
                        var exportDirectory = _configuration.LocalFolderName ?? Path.Combine(_database.Configuration.Core.DataDirectory, "PeriodicExport-Temp");
                        if (Directory.Exists(exportDirectory) == false)
                        {
                            Directory.CreateDirectory(exportDirectory);
                        }

                        var now = SystemTime.UtcNow.ToString("yyyy-MM-dd-HH-mm", CultureInfo.InvariantCulture);

                        if (_status.LastFullExportDirectory == null ||
                            IsDirectoryExistsOrContainsFiles() == false ||
                            fullExport)
                        {
                            fullExport = true;
                            _status.LastFullExportDirectory = Path.Combine(exportDirectory, $"{now}.ravendb-{_database.Name}-backup");
                            Directory.CreateDirectory(_status.LastFullExportDirectory);
                        }

                        if (_logger.IsInfoEnabled)
                        {
                            _logger.Info($"Exporting a {(fullExport ? "full" : "incremental")} export");
                        }

                        if (fullExport == false)
                        {
                            var currentLastEtag = DocumentsStorage.ReadLastEtag(tx.InnerTransaction);
                            // No-op if nothing has changed
                            if (currentLastEtag == _status.LastDocsEtag)
                            {
                                return;
                            }
                        }

                        var dataExporter = new SmugglerExporter(_database)
                        {
                            Options = new DatabaseSmugglerOptions
                            {
                                RevisionDocumentsLimit = _exportLimit
                            }
                        };

                        string exportFilePath;

                        string fileName;
                        if (fullExport)
                        {
                            // create filename for full export
                            fileName       = $"{now}.ravendb-full-export";
                            exportFilePath = Path.Combine(_status.LastFullExportDirectory, fileName);
                            if (File.Exists(exportFilePath))
                            {
                                var counter = 1;
                                while (true)
                                {
                                    fileName       = $"{now} - {counter}.${Constants.PeriodicExport.FullExportExtension}";
                                    exportFilePath = Path.Combine(_status.LastFullExportDirectory, fileName);

                                    if (File.Exists(exportFilePath) == false)
                                    {
                                        break;
                                    }
                                    counter++;
                                }
                            }
                        }
                        else
                        {
                            // create filename for incremental export
                            fileName       = $"{now}-0.${Constants.PeriodicExport.IncrementalExportExtension}";
                            exportFilePath = Path.Combine(_status.LastFullExportDirectory, fileName);
                            if (File.Exists(exportFilePath))
                            {
                                var counter = 1;
                                while (true)
                                {
                                    fileName       = $"{now}-{counter}.${Constants.PeriodicExport.IncrementalExportExtension}";
                                    exportFilePath = Path.Combine(_status.LastFullExportDirectory, fileName);

                                    if (File.Exists(exportFilePath) == false)
                                    {
                                        break;
                                    }
                                    counter++;
                                }
                            }

                            dataExporter.StartDocsEtag = _status.LastDocsEtag;
                            if (dataExporter.StartDocsEtag == null)
                            {
                                IncrementalExport.ReadLastEtagsFromFile(_status.LastFullExportDirectory, context, dataExporter);
                            }
                        }

                        var exportResult = dataExporter.Export(context, exportFilePath);

                        if (fullExport == false)
                        {
                            // No-op if nothing has changed
                            if (exportResult.LastDocsEtag == _status.LastDocsEtag)
                            {
                                if (_logger.IsInfoEnabled)
                                {
                                    _logger.Info("Periodic export returned prematurely, nothing has changed since last export");
                                }
                                return;
                            }
                        }

                        try
                        {
                            await UploadToServer(exportFilePath, fileName, fullExport);
                        }
                        finally
                        {
                            // if user did not specify local folder we delete temporary file.
                            if (string.IsNullOrEmpty(_configuration.LocalFolderName))
                            {
                                IOExtensions.DeleteFile(exportFilePath);
                            }
                        }

                        _status.LastDocsEtag = exportResult.LastDocsEtag;
                        if (fullExport)
                        {
                            _status.LastFullExportAt = SystemTime.UtcNow;
                        }
                        else
                        {
                            _status.LastExportAt = SystemTime.UtcNow;
                        }

                        WriteStatus();
                    }
                    if (_logger.IsInfoEnabled)
                    {
                        _logger.Info($"Successfully exported {(fullExport ? "full" : "incremental")} export in {sp.ElapsedMilliseconds:#,#;;0} ms.");
                    }

                    _exportLimit = null;
                }
            }
            catch (OperationCanceledException)
            {
                // shutting down, probably
            }
            catch (ObjectDisposedException)
            {
                // shutting down, probably
            }
            catch (Exception e)
            {
                _exportLimit = 100;
                if (_logger.IsOperationsEnabled)
                {
                    _logger.Operations("Error when performing periodic export", e);
                }
                _database.Alerts.AddAlert(new Alert
                {
                    Type      = AlertType.PeriodicExport,
                    Message   = "Error in Periodic Export",
                    CreatedAt = SystemTime.UtcNow,
                    Severity  = AlertSeverity.Error,
                    Content   = new ExceptionAlertContent
                    {
                        Message   = e.Message,
                        Exception = e.ToString()
                    }
                });
            }
        }
示例#13
0
        public async Task CanHandleAttachmentExceptionsGracefully_Smuggler()
        {
            var backupPath = NewDataPath("BackupFolder");
            var server     = GetNewServer();

            int allowDownload = 0;

            var port      = 8070;
            var forwarder = new ProxyServer(ref port, 8079)
            {
                VetoTransfer = (totalRead, buffer) =>
                {
                    var payload = System.Text.Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
                    return(payload.Contains("GET /static/users/678 ") && Thread.VolatileRead(ref allowDownload) == 0);
                }
            };

            try
            {
                string databaseName;
                using (var store = new DocumentStore
                {
                    Url = "http://localhost:8079"
                })
                {
                    databaseName = store.DefaultDatabase;
                    store.Initialize();
                    InsertAttachments(store, 2000);
                }

                var dumper = new SmugglerDatabaseApi {
                    Options = { Limit = 1500, Incremental = true }
                };

                var allAttachments = new List <RavenJObject>();

                OperationState exportResult = null;
                try
                {
                    exportResult = dumper.ExportData(new SmugglerExportOptions <RavenConnectionStringOptions>
                    {
                        ToFile = backupPath,
                        From   = new RavenConnectionStringOptions
                        {
                            Url             = "http://localhost:" + port,
                            DefaultDatabase = databaseName,
                        }
                    }).Result;
                    Assert.False(true, "Previous op should throw.");
                }
                catch (AggregateException e)
                {
                    var extractSingleInnerException = e.ExtractSingleInnerException() as SmugglerExportException;
                    if (extractSingleInnerException == null)
                    {
                        throw;
                    }
                    var inner = extractSingleInnerException;
                    exportResult = new OperationState
                    {
                        FilePath = inner.File
                    };
                }
                Interlocked.Increment(ref allowDownload);

                using (var fileStream = new FileStream(exportResult.FilePath, FileMode.Open))
                    using (var stream = new GZipStream(fileStream, CompressionMode.Decompress))
                    {
                        var chunk1 = RavenJToken.TryLoad(stream) as RavenJObject;
                        var att1   = chunk1["Attachments"] as RavenJArray;
                        allAttachments.AddRange(att1.Values <RavenJObject>());
                    }

                exportResult = await dumper.ExportData(new SmugglerExportOptions <RavenConnectionStringOptions>
                {
                    ToFile = backupPath,
                    From   = new RavenConnectionStringOptions
                    {
                        Url             = "http://localhost:8070",
                        DefaultDatabase = databaseName,
                    }
                });

                using (var fileStream = new FileStream(exportResult.FilePath, FileMode.Open))
                    using (var stream = new GZipStream(fileStream, CompressionMode.Decompress))
                    {
                        var chunk2 = RavenJToken.TryLoad(stream) as RavenJObject;
                        var attr2  = chunk2["Attachments"] as RavenJArray;
                        allAttachments.AddRange(attr2.Values <RavenJObject>());
                    }

                Assert.Equal(2000, allAttachments.Count());
            }
            finally
            {
                IOExtensions.DeleteDirectory(backupPath);
                forwarder.Dispose();
                server.Dispose();
            }
        }
示例#14
0
        public async Task CanHandleDocumentExceptionsGracefully_Smuggler()
        {
            var backupPath = NewDataPath("BackupFolder");
            var server     = GetNewServer(databaseName: Constants.SystemDatabase);

            var alreadyReset = false;

            var port      = 8070;
            var forwarder = new ProxyServer(ref port, 8079)
            {
                VetoTransfer = (totalRead, buffer) =>
                {
                    if (alreadyReset == false && totalRead > 25000)
                    {
                        alreadyReset = true;
                        return(true);
                    }
                    return(false);
                }
            };

            try
            {
                string databaseName;
                using (var store = new DocumentStore
                {
                    Url = "http://localhost:8079"
                })
                {
                    databaseName = store.DefaultDatabase;
                    store.Initialize();
                    InsertUsers(store, 0, 2000);
                }

                var dumper = new SmugglerDatabaseApi {
                    Options = { Limit = 1900, Incremental = true }
                };

                var allDocs = new List <RavenJObject>();

                OperationState exportResult = null;

                try
                {
                    exportResult = await dumper.ExportData(new SmugglerExportOptions <RavenConnectionStringOptions>
                    {
                        ToFile = backupPath,
                        From   = new RavenConnectionStringOptions
                        {
                            Url             = "http://localhost:" + port,
                            DefaultDatabase = databaseName,
                        }
                    });

                    Assert.False(true, "Previous op should throw.");
                }
                catch (SmugglerExportException e)
                {
                    exportResult = new OperationState
                    {
                        FilePath = e.File
                    };
                }

                using (var fileSteam = new FileStream(exportResult.FilePath, FileMode.Open))
                    using (var stream = new GZipStream(fileSteam, CompressionMode.Decompress))
                    {
                        var chunk1 = RavenJToken.TryLoad(stream) as RavenJObject;
                        var doc1   = chunk1["Docs"] as RavenJArray;
                        allDocs.AddRange(doc1.Values <RavenJObject>());
                    }

                exportResult = await dumper.ExportData(new SmugglerExportOptions <RavenConnectionStringOptions>
                {
                    ToFile = backupPath,
                    From   = new RavenConnectionStringOptions
                    {
                        Url             = "http://localhost:8070",
                        DefaultDatabase = databaseName,
                    }
                });

                using (var fileStream = new FileStream(exportResult.FilePath, FileMode.Open))
                    using (var stream = new GZipStream(fileStream, CompressionMode.Decompress))
                    {
                        var chunk2 = RavenJToken.TryLoad(stream) as RavenJObject;
                        var doc2   = chunk2["Docs"] as RavenJArray;
                        allDocs.AddRange(doc2.Values <RavenJObject>());
                    }

                Assert.Equal(2000, allDocs.Count(d => (d.Value <string>("Name") ?? String.Empty).StartsWith("User")));
            }
            finally
            {
                forwarder.Dispose();
                server.Dispose();
                IOExtensions.DeleteDirectory(backupPath);
            }
        }
示例#15
0
        public async Task <IOperationResult> Execute(Action <IOperationProgress> onProgress)
        {
            var databaseName = _restoreConfiguration.DatabaseName;
            var result       = new RestoreResult
            {
                DataDirectory = _restoreConfiguration.DataDirectory
            };

            try
            {
                if (onProgress == null)
                {
                    onProgress = _ => { }
                }
                ;

                Stopwatch       sw = null;
                RestoreSettings restoreSettings = null;
                var             firstFile       = _filesToRestore[0];
                var             lastFile        = _filesToRestore.Last();

                var extension       = Path.GetExtension(firstFile);
                var snapshotRestore = false;
                if (extension == Constants.Documents.PeriodicBackup.SnapshotExtension)
                {
                    onProgress.Invoke(result.Progress);

                    snapshotRestore = true;
                    sw = Stopwatch.StartNew();
                    // restore the snapshot
                    restoreSettings = SnapshotRestore(firstFile,
                                                      _restoreConfiguration.DataDirectory,
                                                      onProgress,
                                                      result);

                    if (restoreSettings != null && _restoreConfiguration.SkipIndexes)
                    {
                        // remove all indexes from the database record
                        restoreSettings.DatabaseRecord.AutoIndexes = null;
                        restoreSettings.DatabaseRecord.Indexes     = null;
                    }

                    // removing the snapshot from the list of files
                    _filesToRestore.RemoveAt(0);
                }
                else
                {
                    result.SnapshotRestore.Skipped   = true;
                    result.SnapshotRestore.Processed = true;

                    onProgress.Invoke(result.Progress);
                }

                if (restoreSettings == null)
                {
                    restoreSettings = new RestoreSettings
                    {
                        DatabaseRecord = new DatabaseRecord(databaseName)
                        {
                            // we only have a smuggler restore
                            // use the encryption key to encrypt the database
                            Encrypted = _hasEncryptionKey
                        }
                    };

                    DatabaseHelper.Validate(databaseName, restoreSettings.DatabaseRecord, _serverStore.Configuration);
                }

                var databaseRecord = restoreSettings.DatabaseRecord;
                if (databaseRecord.Settings == null)
                {
                    databaseRecord.Settings = new Dictionary <string, string>();
                }

                var runInMemoryConfigurationKey = RavenConfiguration.GetKey(x => x.Core.RunInMemory);
                databaseRecord.Settings.Remove(runInMemoryConfigurationKey);
                if (_serverStore.Configuration.Core.RunInMemory)
                {
                    databaseRecord.Settings[runInMemoryConfigurationKey] = "false";
                }

                var dataDirectoryConfigurationKey = RavenConfiguration.GetKey(x => x.Core.DataDirectory);
                databaseRecord.Settings.Remove(dataDirectoryConfigurationKey); // removing because we want to restore to given location, not to serialized in backup one
                if (_restoringToDefaultDataDirectory == false)
                {
                    databaseRecord.Settings[dataDirectoryConfigurationKey] = _restoreConfiguration.DataDirectory;
                }

                if (_hasEncryptionKey)
                {
                    // save the encryption key so we'll be able to access the database
                    _serverStore.PutSecretKey(_restoreConfiguration.EncryptionKey,
                                              databaseName, overwrite: false);
                }

                var addToInitLog = new Action <string>(txt => // init log is not save in mem during RestoreBackup
                {
                    var msg = $"[RestoreBackup] {DateTime.UtcNow} :: Database '{databaseName}' : {txt}";
                    if (Logger.IsInfoEnabled)
                    {
                        Logger.Info(msg);
                    }
                });

                var configuration = _serverStore
                                    .DatabasesLandlord
                                    .CreateDatabaseConfiguration(databaseName, ignoreDisabledDatabase: true, ignoreBeenDeleted: true, ignoreNotRelevant: true, databaseRecord);

                using (var database = new DocumentDatabase(databaseName, configuration, _serverStore, addToInitLog))
                {
                    // smuggler needs an existing document database to operate
                    var options = InitializeOptions.SkipLoadingDatabaseRecord;
                    if (snapshotRestore)
                    {
                        options |= InitializeOptions.GenerateNewDatabaseId;
                    }

                    database.Initialize(options);

                    if (snapshotRestore)
                    {
                        result.SnapshotRestore.Processed = true;

                        var summary = database.GetDatabaseSummary();
                        result.Documents.ReadCount             += summary.DocumentsCount;
                        result.Documents.Attachments.ReadCount += summary.AttachmentsCount;
                        result.Counters.ReadCount          += summary.CountersCount;
                        result.RevisionDocuments.ReadCount += summary.RevisionsCount;
                        result.Conflicts.ReadCount         += summary.ConflictsCount;
                        result.Indexes.ReadCount           += databaseRecord.GetIndexesCount();
                        result.AddInfo($"Successfully restored {result.SnapshotRestore.ReadCount} " +
                                       $"files during snapshot restore, took: {sw.ElapsedMilliseconds:#,#;;0}ms");
                        onProgress.Invoke(result.Progress);
                    }

                    using (database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                    {
                        SmugglerRestore(_restoreConfiguration.BackupLocation, database, context, databaseRecord, onProgress, result);

                        result.DatabaseRecord.Processed    = true;
                        result.Documents.Processed         = true;
                        result.RevisionDocuments.Processed = true;
                        result.Conflicts.Processed         = true;
                        result.Indexes.Processed           = true;
                        result.Counters.Processed          = true;
                        onProgress.Invoke(result.Progress);

                        databaseRecord.Topology = new DatabaseTopology();
                        // restoring to the current node only
                        databaseRecord.Topology.Members.Add(_nodeTag);
                        databaseRecord.Disabled = true; // we are currently restoring, shouldn't try to access it
                        _serverStore.EnsureNotPassive();

                        DisableOngoingTasksIfNeeded(databaseRecord);

                        var(index, _) = await _serverStore.WriteDatabaseRecordAsync(databaseName, databaseRecord, null, restoreSettings.DatabaseValues, isRestore : true);

                        await _serverStore.Cluster.WaitForIndexNotification(index);

                        // restore identities & cmpXchg values
                        RestoreFromLastFile(onProgress, database, lastFile, context, result);
                    }
                }

                // after the db for restore is done, we can safely set the db status to active
                databaseRecord          = _serverStore.LoadDatabaseRecord(databaseName, out _);
                databaseRecord.Disabled = false;

                var(updateIndex, _) = await _serverStore.WriteDatabaseRecordAsync(databaseName, databaseRecord, null);

                await _serverStore.Cluster.WaitForIndexNotification(updateIndex);

                if (databaseRecord.Topology.RelevantFor(_serverStore.NodeTag))
                {
                    // we need to wait for the database record change to be propagated properly
                    var db = await _serverStore.DatabasesLandlord.TryGetOrCreateResourceStore(databaseName);

                    await db.RachisLogIndexNotifications.WaitForIndexNotification(updateIndex, _operationCancelToken.Token);
                }

                return(result);
            }
            catch (Exception e)
            {
                if (Logger.IsOperationsEnabled)
                {
                    Logger.Operations("Failed to restore database", e);
                }

                var alert = AlertRaised.Create(
                    _restoreConfiguration.DatabaseName,
                    "Failed to restore database",
                    $"Could not restore database named {_restoreConfiguration.DatabaseName}",
                    AlertType.RestoreError,
                    NotificationSeverity.Error,
                    details: new ExceptionDetails(e));
                _serverStore.NotificationCenter.Add(alert);

                if (_serverStore.LoadDatabaseRecord(_restoreConfiguration.DatabaseName, out var _) == null)
                {
                    // delete any files that we already created during the restore
                    IOExtensions.DeleteDirectory(_restoreConfiguration.DataDirectory);
                }
                else
                {
                    var deleteResult = await _serverStore.DeleteDatabaseAsync(_restoreConfiguration.DatabaseName, true, new[] { _serverStore.NodeTag });

                    await _serverStore.Cluster.WaitForIndexNotification(deleteResult.Index);
                }

                result.AddError($"Error occurred during restore of database {databaseName}. Exception: {e.Message}");
                onProgress.Invoke(result.Progress);
                throw;
            }
            finally
            {
                _operationCancelToken.Dispose();
            }
        }
示例#16
0
        public void AfterFailedRestoreOfIndex_ShouldGenerateWarningAndResetIt()
        {
            using (var db = new DocumentDatabase(new RavenConfiguration
            {
                DataDirectory = DataDir,
                RunInUnreliableYetFastModeThatIsNotSuitableForProduction = false,
                Settings =
                {
                    { "Raven/Esent/CircularLog", "false" }
                }
            }))
            {
                db.SpinBackgroundWorkers();
                db.PutIndex(new RavenDocumentsByEntityName().IndexName, new RavenDocumentsByEntityName().CreateIndexDefinition());

                db.Put("users/1", null, RavenJObject.Parse("{'Name':'Arek'}"), RavenJObject.Parse("{'Raven-Entity-Name':'Users'}"), null);
                db.Put("users/2", null, RavenJObject.Parse("{'Name':'David'}"), RavenJObject.Parse("{'Raven-Entity-Name':'Users'}"), null);

                WaitForIndexing(db);

                db.StartBackup(BackupDir, false, new DatabaseDocument());
                WaitForBackup(db, true);

                db.Put("users/3", null, RavenJObject.Parse("{'Name':'Daniel'}"), RavenJObject.Parse("{'Raven-Entity-Name':'Users'}"), null);

                WaitForIndexing(db);

                db.StartBackup(BackupDir, true, new DatabaseDocument());
                WaitForBackup(db, true);
            }
            IOExtensions.DeleteDirectory(DataDir);

            var incrementalDirectories = Directory.GetDirectories(BackupDir, "Inc*");

            // delete 'index-files.required-for-index-restore' to make backup corrupted according to the reported error
            File.Delete(Path.Combine(incrementalDirectories.First(),
                                     "Indexes\\Raven%2fDocumentsByEntityName\\index-files.required-for-index-restore"));

            var sb = new StringBuilder();

            DocumentDatabase.Restore(new RavenConfiguration(), BackupDir, DataDir, s => sb.Append(s), defrag: true);

            Assert.Contains(
                "Error: Index Raven%2fDocumentsByEntityName could not be restored. All already copied index files was deleted." +
                " Index will be recreated after launching Raven instance",
                sb.ToString());

            using (var db = new DocumentDatabase(new RavenConfiguration {
                DataDirectory = DataDir
            }))
            {
                db.SpinBackgroundWorkers();
                QueryResult queryResult;
                do
                {
                    queryResult = db.Query("Raven/DocumentsByEntityName", new IndexQuery
                    {
                        Query    = "Tag:[[Users]]",
                        PageSize = 10
                    }, CancellationToken.None);
                } while (queryResult.IsStale);
                Assert.Equal(3, queryResult.Results.Count);
            }
        }
示例#17
0
        public void Dispose()
        {
            transactionalStorage.Dispose();

            IOExtensions.DeleteDirectory("test");
        }
示例#18
0
        public async Task can_export_all_documents()
        {
            var backupPath = Path.Combine(NewDataPath(forceCreateDir: true), "export.dump");

            try
            {
                using (var store = GetDocumentStore())
                {
                    using (var commands = store.Commands())
                    {
                        for (var i = 0; i < 1000; i++)
                        {
                            commands.Put("users/" + (i + 1), null, new { Name = "test #" + i }, new Dictionary <string, object>
                            {
                                { Constants.Documents.Metadata.Collection, "Users" }
                            });
                        }
                    }

                    var task1 = Task.Run(async() =>
                    {
                        // now perform full backup
                        await store.Smuggler.ExportAsync(new DatabaseSmugglerExportOptions(), backupPath);
                    });
                    var task2 = Task.Run(() =>
                    {
                        // change the one document, this document should be exported (any version of it)
                        for (var i = 0; i < 100; i++)
                        {
                            using (var session = store.OpenSession())
                            {
                                var user  = session.Load <User>("users/1000");
                                user.Name = "test" + i;
                                session.SaveChanges();
                            }
                        }
                    });

                    await Task.WhenAll(task1, task2);
                }

                using (var store = GetDocumentStore())
                {
                    // import all the data
                    await store.Smuggler.ImportAsync(new DatabaseSmugglerImportOptions(), backupPath);

                    using (var session = store.OpenSession())
                    {
                        var user = session.Load <User>("users/1000");
                        //the document should exist in the export (any version of it)
                        Assert.NotNull(user);

                        var list = session.Query <User>()
                                   .Customize(x => x.WaitForNonStaleResults())
                                   .Take(1024)
                                   .ToList();
                        Assert.Equal(1000, list.Count);
                    }

                    var stats = store.Maintenance.Send(new GetStatisticsOperation());
                    Assert.Equal(1000, stats.CountOfDocuments);
                }
            }
            finally
            {
                IOExtensions.DeleteDirectory(backupPath);
            }
        }
示例#19
0
        public async Task Execute(Action <IOperationProgress> onProgress, CompactionResult result)
        {
            if (_isCompactionInProgress)
            {
                throw new InvalidOperationException($"Database '{_database}' cannot be compacted because compaction is already in progress.");
            }

            result.AddMessage($"Started database compaction for {_database}");
            onProgress?.Invoke(result);

            _isCompactionInProgress = true;
            bool   done             = false;
            string compactDirectory = null;
            string tmpDirectory     = null;

            try
            {
                var documentDatabase = await _serverStore.DatabasesLandlord.TryGetOrCreateResourceStore(_database);

                var configuration = _serverStore.DatabasesLandlord.CreateDatabaseConfiguration(_database);

                using (await _serverStore.DatabasesLandlord.UnloadAndLockDatabase(_database, "it is being compacted"))
                    using (var src = DocumentsStorage.GetStorageEnvironmentOptionsFromConfiguration(configuration, new IoChangesNotifications(),
                                                                                                    new CatastrophicFailureNotification((endId, path, exception) => throw new InvalidOperationException($"Failed to compact database {_database} ({path})", exception))))
                    {
                        InitializeOptions(src, configuration, documentDatabase);
                        DirectoryExecUtils.SubscribeToOnDirectoryExec(src, configuration.Storage, documentDatabase.Name, DirectoryExecUtils.EnvironmentType.Compaction, Logger);

                        var basePath = configuration.Core.DataDirectory.FullPath;
                        compactDirectory = basePath + "-compacting";
                        tmpDirectory     = basePath + "-old";

                        EnsureDirectoriesPermission(basePath, compactDirectory, tmpDirectory);

                        IOExtensions.DeleteDirectory(compactDirectory);
                        IOExtensions.DeleteDirectory(tmpDirectory);
                        configuration.Core.DataDirectory = new PathSetting(compactDirectory);
                        using (var dst = DocumentsStorage.GetStorageEnvironmentOptionsFromConfiguration(configuration, new IoChangesNotifications(),
                                                                                                        new CatastrophicFailureNotification((envId, path, exception) => throw new InvalidOperationException($"Failed to compact database {_database} ({path})", exception))))
                        {
                            InitializeOptions(dst, configuration, documentDatabase);
                            DirectoryExecUtils.SubscribeToOnDirectoryExec(dst, configuration.Storage, documentDatabase.Name, DirectoryExecUtils.EnvironmentType.Compaction, Logger);

                            _token.ThrowIfCancellationRequested();
                            StorageCompaction.Execute(src, (StorageEnvironmentOptions.DirectoryStorageEnvironmentOptions)dst, progressReport =>
                            {
                                result.Progress.TreeProgress   = progressReport.TreeProgress;
                                result.Progress.TreeTotal      = progressReport.TreeTotal;
                                result.Progress.TreeName       = progressReport.TreeName;
                                result.Progress.GlobalProgress = progressReport.GlobalProgress;
                                result.Progress.GlobalTotal    = progressReport.GlobalTotal;
                                result.AddMessage(progressReport.Message);
                                onProgress?.Invoke(result);
                            }, _token);
                        }

                        result.TreeName = null;

                        _token.ThrowIfCancellationRequested();

                        EnsureDirectoriesPermission(basePath, compactDirectory, tmpDirectory);
                        IOExtensions.DeleteDirectory(tmpDirectory);

                        SwitchDatabaseDirectories(basePath, tmpDirectory, compactDirectory);
                        done = true;
                    }
            }
            catch (Exception e)
            {
                throw new InvalidOperationException($"Failed to execute compaction for {_database}", e);
            }
            finally
            {
                IOExtensions.DeleteDirectory(compactDirectory);
                if (done)
                {
                    IOExtensions.DeleteDirectory(tmpDirectory);
                }
                _isCompactionInProgress = false;
            }
        }
示例#20
0
 public RavenDB_1041()
 {
     IOExtensions.DeleteDirectory("Database #0");
     IOExtensions.DeleteDirectory("Database #1");
     IOExtensions.DeleteDirectory("Database #2");
 }
示例#21
0
        public async Task ContentIsPreserved_MultipleDirectories()
        {
            using (var store = NewStore())
            {
                ReseedRandom(100); // Force a random distribution.

                var server          = GetServer();
                var outputDirectory = Path.Combine(server.Configuration.DataDirectory, "Export");
                try
                {
                    var dumper = new SmugglerFilesApi {
                        Options = { Incremental = false }
                    };

                    var files = new Stream[10];
                    using (var session = store.OpenAsyncSession())
                    {
                        for (int i = 0; i < files.Length; i++)
                        {
                            files[i] = CreateRandomFileStream(100 * i + 12);
                            session.RegisterUpload(i + "/test.file", files[i]);
                        }

                        await session.SaveChangesAsync();
                    }

                    ExportFilesResult result;
                    using (new FilesStore {
                        Url = server.Url
                    }.Initialize())
                    {
                        // now perform full backup
                        result = await dumper.ExportData(new SmugglerExportOptions <FilesConnectionStringOptions>
                        {
                            ToFile = outputDirectory,
                            From   = new FilesConnectionStringOptions
                            {
                                Url = server.Url,
                                DefaultFileSystem = store.DefaultFileSystem,
                            }
                        });
                    }

                    await VerifyDump(store, result.FilePath, s =>
                    {
                        for (int i = 0; i < files.Length; i++)
                        {
                            using (var session = s.OpenAsyncSession())
                            {
                                var file   = session.LoadFileAsync(i + "/test.file").Result;
                                var stream = session.DownloadAsync(file).Result;

                                files[i].Position = 0;
                                Assert.Equal(files[i].GetMD5Hash(), stream.GetMD5Hash());
                            }
                        }
                    });
                }
                finally
                {
                    IOExtensions.DeleteDirectory(outputDirectory);
                }
            }
        }
示例#22
0
        private static void AddTwitterFilesToProject()
        {
            string _twitterNativeFolder = AssetsUtility.AssetPathToAbsolutePath(kRelativePathToTwitterNativeFiles);
            string _twitterConfileFile  = Path.Combine(_twitterNativeFolder, "Config.txt");

            // Re move the files if version has changed
            if (File.Exists(_twitterConfileFile))
            {
                string _fileVersion = File.ReadAllText(_twitterConfileFile);

                if (string.Compare(_fileVersion, EditorPrefs.GetString(kTwitterConfigKey, "0")) == 0)
                {
                    return;
                }

                EditorPrefs.SetString(kTwitterConfigKey, _fileVersion);
            }

            // Start moving files and framework
            string _projectPath           = AssetsUtility.GetProjectPath();
            string _twitterExternalFolder = Path.Combine(_projectPath, kExtenalFolderRelativePath + "/Twitter");

            if (Directory.Exists(_twitterExternalFolder))
            {
                Directory.Delete(_twitterExternalFolder, true);
            }

            Directory.CreateDirectory(_twitterExternalFolder);

            List <string> _twitterFilesList  = new List <string>();
            List <string> _twitterFolderList = new List <string>();

            // ***********************
            // Source code section
            // ***********************
            string _nativeCodeSourceFolder = Path.Combine(_twitterNativeFolder, "Source");
            string _nativeCodeDestFolder   = Path.Combine(_twitterExternalFolder, "Source");

            // Copying folder
            IOExtensions.CopyFilesRecursively(_nativeCodeSourceFolder, _nativeCodeDestFolder);

            // Adding source folder to modifier
            _twitterFolderList.Add("Twitter/Source:-fno-objc-arc");

            // ***********************
            // Framework Section
            // ***********************
            string[] _zippedFrameworkFiles = Directory.GetFiles(_twitterNativeFolder, "*.gz", SearchOption.AllDirectories);
            string   _destFrameworkFolder  = Path.Combine(_twitterExternalFolder, "Framework");

            if (!Directory.Exists(_destFrameworkFolder))
            {
                Directory.CreateDirectory(_destFrameworkFolder);
            }

            // Iterate through each zip files
            foreach (string _curZippedFile in _zippedFrameworkFiles)
            {
                Zip.DecompressToDirectory(_curZippedFile, _destFrameworkFolder);

                // Adding file to modifier
                _twitterFilesList.Add("Twitter/Framework/" + Path.GetFileNameWithoutExtension(_curZippedFile));
            }

            // ***********************
            // Xcode modifier Section
            // ***********************
            Dictionary <string, object> _xcodeModDict = new Dictionary <string, object>();

            _xcodeModDict["group"]      = "NativePlugins-Twitter";
            _xcodeModDict["libs"]       = new string[0];
            _xcodeModDict["frameworks"] = new string[] {
                "Accounts.framework:weak",
                "Social.framework:weak"
            };
            _xcodeModDict["headerpaths"] = new string[0];
            _xcodeModDict["files"]       = _twitterFilesList;
            _xcodeModDict["folders"]     = _twitterFolderList;
            _xcodeModDict["excludes"]    = new string[] {
                "^.*.meta$",
                "^.*.mdown$",
                "^.*.pdf$",
                "^.*.DS_Store"
            };
            _xcodeModDict["compiler_flags"] = new string[0];
            _xcodeModDict["linker_flags"]   = new string[0];

            File.WriteAllText(GetTwitterXcodeModFilePath(), _xcodeModDict.ToJSON());
        }
示例#23
0
 public SmugglerApiTests()
 {
     NonAdminHttp.EnsureCanListenToWhenInNonAdminContext(Port1);
     NonAdminHttp.EnsureCanListenToWhenInNonAdminContext(Port2);
     IOExtensions.DeleteDirectory(BackupDir);
 }
示例#24
0
 public IncrementalBackupTest()
 {
     IOExtensions.DeleteDirectory(BackupDir);
 }
示例#25
0
        public async Task Smuggler_filtering_next_etag_incremental_export_to_file()
        {
            using (var server = GetNewServer())
            {
                var file = Path.Combine(NewDataPath(), "Incremental");
                IOExtensions.DeleteDirectory(file);
                using (var store = new DocumentStore {
                    Url = server.SystemDatabase.Configuration.ServerUrl
                }.Initialize())
                {
                    store
                    .DatabaseCommands
                    .GlobalAdmin
                    .CreateDatabase(new DatabaseDocument
                    {
                        Id       = "Dba1",
                        Settings =
                        {
                            { "Raven/DataDir", "Dba1" }
                        }
                    });
                    store.DatabaseCommands.EnsureDatabaseExists("Dba1");
                }
                using (var store1 = new DocumentStore
                {
                    Url = server.SystemDatabase.Configuration.ServerUrl,
                    DefaultDatabase = "Dba1"
                }.Initialize())
                {
                    StoreWorkerseDba1(store1);
                    using (var session = store1.OpenSession())
                    {
                        var workers = session.Query <Worker>().ToList();
                        Assert.Equal(3, workers.Count);

                        var index1 = store1.DatabaseCommands.GetIndex("WorkerByName");
                        var index2 = store1.DatabaseCommands.GetIndex("WorkerByAge");
                        var index3 = store1.DatabaseCommands.GetIndex("WorkerAccountNumber");
                        Assert.Equal("WorkerByName", index1.Name);
                        Assert.Equal("WorkerByAge", index2.Name);
                        Assert.Equal("WorkerAccountNumber", index3.Name);
                    }
                }

                SmugglerDatabaseApi smugglerApi = new SmugglerDatabaseApi(new SmugglerDatabaseOptions
                {
                    OperateOnTypes = ItemType.Documents | ItemType.Indexes,
                    Incremental    = true
                });
                smugglerApi.Options.Filters.Add(new FilterSetting
                {
                    Path        = "Name",
                    ShouldMatch = true,
                    Values      = { "worker/21", "worker/33" }
                });

                await smugglerApi.ExportData(
                    new SmugglerExportOptions <RavenConnectionStringOptions>
                {
                    ToFile = file,
                    From   = new RavenConnectionStringOptions
                    {
                        Url             = server.SystemDatabase.Configuration.ServerUrl,
                        DefaultDatabase = "Dba1"
                    }
                });


                //check file after first export



                using (var store1 = new DocumentStore
                {
                    Url = server.SystemDatabase.Configuration.ServerUrl,
                    DefaultDatabase = "Dba1"
                }.Initialize())
                {
                    StoreWorkerseDba1(store1);
                }


                //Second time Export

                smugglerApi = new SmugglerDatabaseApi(new SmugglerDatabaseOptions
                {
                    OperateOnTypes = ItemType.Documents | ItemType.Indexes,
                    Incremental    = true
                });
                smugglerApi.Options.Filters.Add(new FilterSetting
                {
                    Path        = "Name",
                    ShouldMatch = true,
                    Values      = { "worker/21", "worker/33" }
                });
                await smugglerApi.ExportData(
                    new SmugglerExportOptions <RavenConnectionStringOptions>
                {
                    ToFile = file,
                    From   = new RavenConnectionStringOptions
                    {
                        Url             = server.SystemDatabase.Configuration.ServerUrl,
                        DefaultDatabase = "Dba1"
                    }
                });

                using (var store2 = new DocumentStore
                {
                    Url = server.SystemDatabase.Configuration.ServerUrl,
                    DefaultDatabase = "Dba2"
                }.Initialize())
                {
                    smugglerApi = new SmugglerDatabaseApi(new SmugglerDatabaseOptions
                    {
                        OperateOnTypes = ItemType.Documents | ItemType.Indexes,
                        Incremental    = true
                    });

                    await smugglerApi.ImportData(new SmugglerImportOptions <RavenConnectionStringOptions>
                    {
                        FromFile = file,
                        To       = new RavenConnectionStringOptions
                        {
                            Url             = server.SystemDatabase.Configuration.ServerUrl,
                            DefaultDatabase = "Dba2"
                        }
                    });

                    using (var session = store2.OpenSession())
                    {
                        var workers = session.Query <Worker>().ToList();
                        Assert.Equal(0, workers.Count);
                    }
                }
            }
        }
示例#26
0
        private InternalBackupResult CreateLocalBackupOrSnapshot(PeriodicBackupStatus status, string backupFilePath, long?startDocumentEtag, long?startRaftIndex)
        {
            var internalBackupResult = new InternalBackupResult();

            using (status.LocalBackup.UpdateStats(_isFullBackup))
            {
                // will rename the file after the backup is finished
                var tempBackupFilePath = backupFilePath + InProgressExtension;

                try
                {
                    BackupTypeValidation();

                    AddInfo($"Started {GetBackupDescription(_configuration.BackupType, _isFullBackup)}");
                    if (_configuration.BackupType == BackupType.Backup ||
                        _configuration.BackupType == BackupType.Snapshot && _isFullBackup == false)
                    {
                        // smuggler backup
                        var options = new DatabaseSmugglerOptionsServerSide
                        {
                            AuthorizationStatus = AuthorizationStatus.DatabaseAdmin,
                            IncludeArtificial   = true // we want to include artificial in backup
                        };

                        options.OperateOnTypes |= DatabaseItemType.Tombstones;
                        options.OperateOnTypes |= DatabaseItemType.CompareExchangeTombstones;

                        var currentBackupResult = CreateBackup(options, tempBackupFilePath, startDocumentEtag, startRaftIndex);

                        if (_isFullBackup)
                        {
                            internalBackupResult = currentBackupResult;
                        }
                        else
                        {
                            if (_backupResult.GetLastEtag() == _previousBackupStatus.LastEtag &&
                                _backupResult.GetLastRaftIndex() == _previousBackupStatus.LastRaftIndex.LastEtag)
                            {
                                internalBackupResult.LastDocumentEtag         = startDocumentEtag ?? 0;
                                internalBackupResult.LastDatabaseChangeVector = _previousBackupStatus.LastDatabaseChangeVector;
                                internalBackupResult.LastRaftIndex            = startRaftIndex ?? 0;
                            }
                            else
                            {
                                internalBackupResult = currentBackupResult;
                            }
                        }
                    }
                    else
                    {
                        // snapshot backup
                        ValidateFreeSpaceForSnapshot(tempBackupFilePath);

                        (internalBackupResult.LastDocumentEtag, internalBackupResult.LastDatabaseChangeVector) = _database.ReadLastEtagAndChangeVector();
                        internalBackupResult.LastRaftIndex = GetDatabaseEtagForBackup();
                        var databaseSummary = _database.GetDatabaseSummary();
                        var indexesCount    = _database.IndexStore.Count;

                        var totalSw          = Stopwatch.StartNew();
                        var sw               = Stopwatch.StartNew();
                        var compressionLevel = _configuration.SnapshotSettings?.CompressionLevel ?? CompressionLevel.Optimal;
                        var smugglerResult   = _database.FullBackupTo(tempBackupFilePath, compressionLevel,
                                                                      info =>
                        {
                            AddInfo(info.Message);

                            _backupResult.SnapshotBackup.ReadCount += info.FilesCount;
                            if (sw.ElapsedMilliseconds > 0 && info.FilesCount > 0)
                            {
                                AddInfo($"Backed up {_backupResult.SnapshotBackup.ReadCount} " +
                                        $"file{(_backupResult.SnapshotBackup.ReadCount > 1 ? "s" : string.Empty)}");
                                sw.Restart();
                            }
                        }, TaskCancelToken.Token);

                        EnsureSnapshotProcessed(databaseSummary, smugglerResult, indexesCount);

                        AddInfo($"Backed up {_backupResult.SnapshotBackup.ReadCount} files, " +
                                $"took: {totalSw.ElapsedMilliseconds:#,#;;0}ms");
                    }

                    IOExtensions.RenameFile(tempBackupFilePath, backupFilePath);

                    status.LocalBackup.Exception = null;
                }
                catch (Exception e)
                {
                    status.LocalBackup.Exception = e.ToString();

                    // deleting the temp backup file if the backup failed
                    DeleteFile(tempBackupFilePath);
                    throw;
                }
            }

            if (_backupToLocalFolder)
            {
                var localRetentionPolicy = new LocalRetentionPolicyRunner(_retentionPolicyParameters, _configuration.LocalSettings.FolderPath);
                localRetentionPolicy.Execute();
            }

            return(internalBackupResult);
        }
示例#27
0
 public void Dispose()
 {
     documentStore.Dispose();
     server.Dispose();
     IOExtensions.DeleteDirectory("HiLoData");
 }
示例#28
0
        private void TimerCallback(bool fullBackup)
        {
            if (currentTask != null)
            {
                return;
            }

            if (Database.Disposed)
            {
                Dispose();
                return;
            }

            // we have shared lock for both incremental and full backup.
            lock (this)
            {
                if (currentTask != null)
                {
                    return;
                }
                currentTask = Task.Factory.StartNew(async() =>
                {
                    var documentDatabase = Database;
                    if (documentDatabase == null)
                    {
                        return;
                    }
                    using (LogContext.WithResource(documentDatabase.Name))
                    {
                        try
                        {
                            OperationState exportResult;
                            bool performAnotherRun = false;
                            do
                            {
                                var dataDumper = new DatabaseDataDumper(documentDatabase, new SmugglerDatabaseOptions()
                                {
                                    Limit = backupLimit
                                });
                                var localBackupConfigs = exportConfigs;
                                var localBackupStatus  = exportStatus;
                                if (localBackupConfigs == null)
                                {
                                    return;
                                }

                                if (localBackupConfigs.Disabled)
                                {
                                    return;
                                }

                                if (fullBackup == false)
                                {
                                    var currentEtags = dataDumper.Operations.FetchCurrentMaxEtags();
                                    // No-op if nothing has changed
                                    if (currentEtags.LastDocsEtag == localBackupStatus.LastDocsEtag &&
                                        currentEtags.LastAttachmentsEtag == localBackupStatus.LastAttachmentsEtag &&
                                        currentEtags.LastDocDeleteEtag == localBackupStatus.LastDocsDeletionEtag &&
                                        currentEtags.LastAttachmentsDeleteEtag == localBackupStatus.LastAttachmentDeletionEtag)
                                    {
                                        return;
                                    }
                                }

                                var backupPath = localBackupConfigs.LocalFolderName ?? Path.Combine(documentDatabase.Configuration.DataDirectory, "PeriodicExport-Temp");
                                if (Directory.Exists(backupPath) == false)
                                {
                                    Directory.CreateDirectory(backupPath);
                                }

                                if (fullBackup)
                                {
                                    // create filename for full dump
                                    backupPath = Path.Combine(backupPath, SystemTime.UtcNow.ToString("yyyy-MM-dd-HH-mm", CultureInfo.InvariantCulture) + ".ravendb-full-dump");
                                    if (File.Exists(backupPath))
                                    {
                                        var counter = 1;
                                        while (true)
                                        {
                                            backupPath = Path.Combine(Path.GetDirectoryName(backupPath), SystemTime.UtcNow.ToString("yyyy-MM-dd-HH-mm", CultureInfo.InvariantCulture) + " - " + counter + ".ravendb-full-dump");

                                            if (File.Exists(backupPath) == false)
                                            {
                                                break;
                                            }
                                            counter++;
                                        }
                                    }
                                }

                                var smugglerOptions = dataDumper.Options;
                                if (fullBackup == false)
                                {
                                    smugglerOptions.StartDocsEtag                = localBackupStatus.LastDocsEtag;
                                    smugglerOptions.StartAttachmentsEtag         = localBackupStatus.LastAttachmentsEtag;
                                    smugglerOptions.StartDocsDeletionEtag        = localBackupStatus.LastDocsDeletionEtag;
                                    smugglerOptions.StartAttachmentsDeletionEtag = localBackupStatus.LastAttachmentDeletionEtag;
                                    smugglerOptions.Incremental     = true;
                                    smugglerOptions.ExportDeletions = true;
                                }
                                exportResult = await dataDumper.ExportData(new SmugglerExportOptions <RavenConnectionStringOptions> {
                                    ToFile = backupPath
                                }).ConfigureAwait(false);

                                if (fullBackup == false)
                                {
                                    // No-op if nothing has changed
                                    if (exportResult.LastDocsEtag == localBackupStatus.LastDocsEtag &&
                                        exportResult.LastAttachmentsEtag == localBackupStatus.LastAttachmentsEtag &&
                                        exportResult.LastDocDeleteEtag == localBackupStatus.LastDocsDeletionEtag &&
                                        exportResult.LastAttachmentsDeleteEtag == localBackupStatus.LastAttachmentDeletionEtag)
                                    {
                                        logger.Info("Periodic export returned prematurely, nothing has changed since last export");
                                        return;
                                    }
                                }

                                try
                                {
                                    await UploadToServer(exportResult.FilePath, localBackupConfigs, fullBackup).ConfigureAwait(false);
                                }
                                finally
                                {
                                    // if user did not specify local folder we delete temporary file.
                                    if (String.IsNullOrEmpty(localBackupConfigs.LocalFolderName))
                                    {
                                        IOExtensions.DeleteFile(exportResult.FilePath);
                                    }
                                }

                                localBackupStatus.LastAttachmentsEtag        = exportResult.LastAttachmentsEtag;
                                localBackupStatus.LastDocsEtag               = exportResult.LastDocsEtag;
                                localBackupStatus.LastDocsDeletionEtag       = exportResult.LastDocDeleteEtag;
                                localBackupStatus.LastAttachmentDeletionEtag = exportResult.LastAttachmentsDeleteEtag;

                                if (fullBackup)
                                {
                                    localBackupStatus.LastFullBackup = SystemTime.UtcNow;
                                }
                                else
                                {
                                    localBackupStatus.LastBackup = SystemTime.UtcNow;
                                }

                                var ravenJObject = JsonExtensions.ToJObject(localBackupStatus);
                                ravenJObject.Remove("Id");
                                var putResult = documentDatabase.Documents.Put(PeriodicExportStatus.RavenDocumentKey, null, ravenJObject,
                                                                               new RavenJObject(), null);

                                // this result in exportStatus being refreshed
                                localBackupStatus = exportStatus;
                                if (localBackupStatus != null)
                                {
                                    if (localBackupStatus.LastDocsEtag.IncrementBy(1) == putResult.ETag) // the last etag is with just us
                                    {
                                        localBackupStatus.LastDocsEtag = putResult.ETag;                 // so we can skip it for the next time
                                    }
                                }

                                if (backupLimit != int.MaxValue)
                                {
                                    backupLimit       = int.MaxValue;
                                    performAnotherRun = true;
                                }
                                else
                                {
                                    performAnotherRun = false;
                                }
                            } while (performAnotherRun);
                        }
                        catch (ObjectDisposedException)
                        {
                            // shutting down, probably
                        }
                        catch (OperationCanceledException)
                        {
                            // shutting down, probably
                        }
                        catch (Exception e)
                        {
                            backupLimit = 100;
                            logger.ErrorException("Error when performing periodic export", e);
                            Database.AddAlert(new Alert
                            {
                                AlertLevel = AlertLevel.Error,
                                CreatedAt  = SystemTime.UtcNow,
                                Message    = e.Message,
                                Title      = "Error in Periodic Export",
                                Exception  = e.ToString(),
                                UniqueKey  = "Periodic Export Error",
                            });
                        }
                    }
                })
                              .Unwrap();

                currentTask.ContinueWith(_ =>
                {
                    currentTask = null;
                });
            }
        }
示例#29
0
 public void Dispose()
 {
     server.Dispose();
     store.Dispose();
     IOExtensions.DeleteDirectory(path);
 }
示例#30
0
        public async Task <IOperationResult> RunPeriodicBackup(Action <IOperationProgress> onProgress)
        {
            AddInfo($"Started task: '{_configuration.Name}'", onProgress);

            var totalSw           = Stopwatch.StartNew();
            var operationCanceled = false;

            var runningBackupStatus = _periodicBackup.RunningBackupStatus = new PeriodicBackupStatus
            {
                TaskId                        = _configuration.TaskId,
                BackupType                    = _configuration.BackupType,
                LastEtag                      = _previousBackupStatus.LastEtag,
                LastRaftIndex                 = _previousBackupStatus.LastRaftIndex,
                LastFullBackup                = _previousBackupStatus.LastFullBackup,
                LastIncrementalBackup         = _previousBackupStatus.LastIncrementalBackup,
                LastFullBackupInternal        = _previousBackupStatus.LastFullBackupInternal,
                LastIncrementalBackupInternal = _previousBackupStatus.LastIncrementalBackupInternal,
                IsFull                        = _isFullBackup,
                LocalBackup                   = _previousBackupStatus.LocalBackup,
                LastOperationId               = _previousBackupStatus.LastOperationId,
                FolderName                    = _previousBackupStatus.FolderName
            };

            try
            {
                var now = DateTime.Now.ToString(DateTimeFormat, CultureInfo.InvariantCulture);

                if (runningBackupStatus.LocalBackup == null)
                {
                    runningBackupStatus.LocalBackup = new LocalBackup();
                }

                if (runningBackupStatus.LastRaftIndex == null)
                {
                    runningBackupStatus.LastRaftIndex = new LastRaftIndex();
                }

                if (_logger.IsInfoEnabled)
                {
                    var fullBackupText = "a " + (_configuration.BackupType == BackupType.Backup ? "full backup" : "snapshot");
                    _logger.Info($"Creating {(_isFullBackup ? fullBackupText : "an incremental backup")}");
                }
                var currentLastRaftIndex = GetDatabaseEtagForBackup();

                if (_isFullBackup == false)
                {
                    // if we come from old version the _previousBackupStatus won't have LastRaftIndex
                    if (_previousBackupStatus.LastRaftIndex == null)
                    {
                        _previousBackupStatus.LastRaftIndex = new LastRaftIndex();
                    }

                    // no-op if nothing has changed
                    var currentLastEtag = _database.ReadLastEtag();
                    if ((currentLastEtag == _previousBackupStatus.LastEtag) && (currentLastRaftIndex == _previousBackupStatus.LastRaftIndex.LastEtag))
                    {
                        var message = "Skipping incremental backup because " +
                                      $"last etag ({currentLastEtag:#,#;;0}) hasn't changed since last backup";

                        if (_logger.IsInfoEnabled)
                        {
                            _logger.Info(message);
                        }

                        UpdateOperationId(runningBackupStatus);
                        runningBackupStatus.LastIncrementalBackup = _startTime;
                        DatabaseSmuggler.EnsureProcessed(_backupResult);
                        AddInfo(message, onProgress);

                        return(_backupResult);
                    }
                }

                GenerateFolderNameAndBackupDirectory(now, out var folderName, out var backupDirectory);
                var startDocumentEtag = _isFullBackup == false ? _previousBackupStatus.LastEtag : null;
                var fileName          = GetFileName(_isFullBackup, backupDirectory.FullPath, now, _configuration.BackupType, out string backupFilePath);
                var lastEtag          = CreateLocalBackupOrSnapshot(runningBackupStatus, backupFilePath, startDocumentEtag, onProgress);

                runningBackupStatus.LocalBackup.BackupDirectory = _backupToLocalFolder ? backupDirectory.FullPath : null;
                runningBackupStatus.LocalBackup.TempFolderUsed  = _backupToLocalFolder == false;
                runningBackupStatus.IsFull = _isFullBackup;

                try
                {
                    await UploadToServer(backupFilePath, folderName, fileName, onProgress);
                }
                finally
                {
                    runningBackupStatus.UploadToS3      = _backupResult.S3Backup;
                    runningBackupStatus.UploadToAzure   = _backupResult.AzureBackup;
                    runningBackupStatus.UploadToGlacier = _backupResult.GlacierBackup;
                    runningBackupStatus.UploadToFtp     = _backupResult.FtpBackup;

                    // if user did not specify local folder we delete the temporary file
                    if (_backupToLocalFolder == false)
                    {
                        IOExtensions.DeleteFile(backupFilePath);
                    }
                }

                UpdateOperationId(runningBackupStatus);
                runningBackupStatus.LastEtag = lastEtag;
                runningBackupStatus.LastRaftIndex.LastEtag = currentLastRaftIndex;
                runningBackupStatus.FolderName             = folderName;
                if (_isFullBackup)
                {
                    runningBackupStatus.LastFullBackup = _periodicBackup.StartTime;
                }
                else
                {
                    runningBackupStatus.LastIncrementalBackup = _periodicBackup.StartTime;
                }

                totalSw.Stop();

                if (_logger.IsInfoEnabled)
                {
                    var fullBackupText = "a " + (_configuration.BackupType == BackupType.Backup ? " full backup" : " snapshot");
                    _logger.Info($"Successfully created {(_isFullBackup ? fullBackupText : "an incremental backup")} " +
                                 $"in {totalSw.ElapsedMilliseconds:#,#;;0} ms");
                }

                return(_backupResult);
            }
            catch (OperationCanceledException)
            {
                operationCanceled = TaskCancelToken.Token.IsCancellationRequested &&
                                    _databaseShutdownCancellationToken.IsCancellationRequested;
                throw;
            }
            catch (ObjectDisposedException)
            {
                // shutting down, probably
                operationCanceled = true;
                throw;
            }
            catch (Exception e)
            {
                const string message = "Error when performing periodic backup";

                runningBackupStatus.Error = new Error
                {
                    Exception = e.ToString(),
                    At        = DateTime.UtcNow
                };

                if (_logger.IsOperationsEnabled)
                {
                    _logger.Operations(message, e);
                }

                _database.NotificationCenter.Add(AlertRaised.Create(
                                                     _database.Name,
                                                     $"Periodic Backup task: '{_periodicBackup.Configuration.Name}'",
                                                     message,
                                                     AlertType.PeriodicBackup,
                                                     NotificationSeverity.Error,
                                                     details: new ExceptionDetails(e)));

                throw;
            }
            finally
            {
                if (operationCanceled == false)
                {
                    // whether we succeeded or not,
                    // we need to update the last backup time to avoid
                    // starting a new backup right after this one
                    if (_isFullBackup)
                    {
                        runningBackupStatus.LastFullBackupInternal = _startTime;
                    }
                    else
                    {
                        runningBackupStatus.LastIncrementalBackupInternal = _startTime;
                    }

                    runningBackupStatus.NodeTag      = _serverStore.NodeTag;
                    runningBackupStatus.DurationInMs = totalSw.ElapsedMilliseconds;
                    runningBackupStatus.Version      = ++_previousBackupStatus.Version;

                    _periodicBackup.BackupStatus = runningBackupStatus;

                    // save the backup status
                    await WriteStatus(runningBackupStatus, onProgress);
                }
            }
        }