public ConfigurationStorage(DocumentDatabase db) { var path = db.Configuration.Core.DataDirectory.Combine("Configuration"); var options = db.Configuration.Core.RunInMemory ? StorageEnvironmentOptions.CreateMemoryOnly(path.FullPath, db.Configuration.Storage.TempPath?.FullPath, db.IoChanges, db.CatastrophicFailureNotification) : StorageEnvironmentOptions.ForPath(path.FullPath, db.Configuration.Storage.TempPath?.FullPath, null, db.IoChanges, db.CatastrophicFailureNotification); options.OnNonDurableFileSystemError += db.HandleNonDurableFileSystemError; options.OnRecoveryError += db.HandleOnRecoveryError; options.CompressTxAboveSizeInBytes = db.Configuration.Storage.CompressTxAboveSize.GetValue(SizeUnit.Bytes); options.SchemaVersion = SchemaUpgrader.CurrentVersion.ConfigurationVersion; options.SchemaUpgrader = SchemaUpgrader.Upgrader(SchemaUpgrader.StorageType.Configuration, this, null); options.ForceUsing32BitsPager = db.Configuration.Storage.ForceUsing32BitsPager; options.TimeToSyncAfterFlashInSec = (int)db.Configuration.Storage.TimeToSyncAfterFlash.AsTimeSpan.TotalSeconds; options.NumOfConcurrentSyncsPerPhysDrive = db.Configuration.Storage.NumberOfConcurrentSyncsPerPhysicalDrive; Sodium.CloneKey(out options.MasterKey, db.MasterKey); Environment = new StorageEnvironment(options); NotificationsStorage = new NotificationsStorage(db.Name); OperationsStorage = new OperationsStorage(); ContextPool = new TransactionContextPool(Environment); }
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; var documentDatabase = await _serverStore.DatabasesLandlord.TryGetOrCreateResourceStore(_database); var configuration = _serverStore.DatabasesLandlord.CreateDatabaseConfiguration(_database); using (await _serverStore.DatabasesLandlord.UnloadAndLockDatabase(_database)) using (var src = DocumentsStorage.GetStorageEnvironmentOptionsFromConfiguration(configuration, new IoChangesNotifications(), new CatastrophicFailureNotification(exception => throw new InvalidOperationException($"Failed to compact database {_database}", exception)))) { src.ForceUsing32BitsPager = configuration.Storage.ForceUsing32BitsPager; src.OnNonDurableFileSystemError += documentDatabase.HandleNonDurableFileSystemError; src.OnRecoveryError += documentDatabase.HandleOnRecoveryError; src.CompressTxAboveSizeInBytes = configuration.Storage.CompressTxAboveSize.GetValue(SizeUnit.Bytes); src.TimeToSyncAfterFlashInSec = (int)configuration.Storage.TimeToSyncAfterFlash.AsTimeSpan.TotalSeconds; src.NumOfConcurrentSyncsPerPhysDrive = configuration.Storage.NumberOfConcurrentSyncsPerPhysicalDrive; Sodium.CloneKey(out src.MasterKey, documentDatabase.MasterKey); var basePath = configuration.Core.DataDirectory.FullPath; IOExtensions.DeleteDirectory(basePath + "-Compacting"); IOExtensions.DeleteDirectory(basePath + "-old"); try { configuration.Core.DataDirectory = new PathSetting(basePath + "-Compacting"); using (var dst = DocumentsStorage.GetStorageEnvironmentOptionsFromConfiguration(configuration, new IoChangesNotifications(), new CatastrophicFailureNotification(exception => throw new InvalidOperationException($"Failed to compact database {_database}", exception)))) { dst.OnNonDurableFileSystemError += documentDatabase.HandleNonDurableFileSystemError; dst.OnRecoveryError += documentDatabase.HandleOnRecoveryError; dst.CompressTxAboveSizeInBytes = configuration.Storage.CompressTxAboveSize.GetValue(SizeUnit.Bytes); dst.ForceUsing32BitsPager = configuration.Storage.ForceUsing32BitsPager; dst.TimeToSyncAfterFlashInSec = (int)configuration.Storage.TimeToSyncAfterFlash.AsTimeSpan.TotalSeconds; dst.NumOfConcurrentSyncsPerPhysDrive = configuration.Storage.NumberOfConcurrentSyncsPerPhysicalDrive; Sodium.CloneKey(out dst.MasterKey, documentDatabase.MasterKey); _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.AddMessage(progressReport.Message); onProgress?.Invoke(result); }, _token); } _token.ThrowIfCancellationRequested(); IOExtensions.MoveDirectory(basePath, basePath + "-old"); IOExtensions.MoveDirectory(basePath + "-Compacting", basePath); var oldIndexesPath = new PathSetting(basePath + "-old").Combine("Indexes"); var newIndexesPath = new PathSetting(basePath).Combine("Indexes"); IOExtensions.MoveDirectory(oldIndexesPath.FullPath, newIndexesPath.FullPath); var oldConfigPath = new PathSetting(basePath + "-old").Combine("Configuration"); var newConfigPath = new PathSetting(basePath).Combine("Configuration"); IOExtensions.MoveDirectory(oldConfigPath.FullPath, newConfigPath.FullPath); } catch (Exception e) { throw new InvalidOperationException($"Failed to execute compaction for {_database}", e); } finally { IOExtensions.DeleteDirectory(basePath + "-Compacting"); IOExtensions.DeleteDirectory(basePath + "-old"); _isCompactionInProgress = false; } } }