Пример #1
0
        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);
        }
Пример #2
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;

            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;
                    }
                }
        }