private void BackupLogs(OperationContext context, string instancePath, string name) { if (_logManager != null) { _logManager.BackupAsync(context, new AbsolutePath(instancePath), name).Result.IgnoreFailure(); Task.Run(() => _logManager.GarbageCollect(context)).FireAndForget(context, severityOnException: Severity.Error); } }
private BoolResult Load(OperationContext context, StoreSlot activeSlot, bool clean) { try { var storeLocation = GetStoreLocation(activeSlot); if (Directory.Exists(storeLocation)) { // We backup right before loading. This means we should never loose any logs, but it also means // the backup directory will only hold logs for DBs that have already been overwritten. if (_logManager != null) { _logManager.BackupAsync(context, new AbsolutePath(storeLocation), activeSlot.ToString()).Result.IgnoreFailure(); Task.Run(() => _logManager.GarbageCollect(context)).FireAndForget(context, severityOnException: Severity.Error); } if (clean) { FileUtilities.DeleteDirectoryContents(storeLocation, deleteRootDirectory: true); } } Directory.CreateDirectory(storeLocation); Tracer.Info(context, $"Creating RocksDb store at '{storeLocation}'."); var possibleStore = KeyValueStoreAccessor.Open( new KeyValueStoreAccessor.RocksDbStoreArguments() { StoreDirectory = storeLocation, AdditionalColumns = new[] { nameof(Columns.ClusterState), nameof(Columns.Metadata) }, RotateLogs = true, EnableStatistics = true, FastOpen = true, }, // When an exception is caught from within methods using the database, this handler is called to // decide whether the exception should be rethrown in user code, and the database invalidated. Our // policy is to only invalidate if it is an exception coming from RocksDb, but not from our code. failureHandler: failureEvent => { // By default, rethrow is true iff it is a user error. We invalidate only if it isn't failureEvent.Invalidate = !failureEvent.Rethrow; }, // The database may be invalidated for a number of reasons, all related to latent bugs in our code. // For example, exceptions thrown from methods that are operating on the DB. If that happens, we // call a user-defined handler. This is because the instance is invalid after this happens. invalidationHandler: failure => OnDatabaseInvalidated(context, failure), // It is possible we may fail to open an already existing database. This can happen (most commonly) // due to corruption, among others. If this happens, then we want to recreate it from empty. This // only helps for the memoization store. onFailureDeleteExistingStoreAndRetry: _configuration.OnFailureDeleteExistingStoreAndRetry, // If the previous flag is true, and it does happen that we invalidate the database, we want to log // it explicitly. onStoreReset: failure => { Tracer.Error(context, $"RocksDb critical error caused store to reset: {failure.DescribeIncludingInnerFailures()}"); }); if (possibleStore.Succeeded) { var oldKeyValueStore = _keyValueStore; var store = possibleStore.Result; if (oldKeyValueStore == null) { _keyValueStore = new KeyValueStoreGuard(store); } else { // Just replace the inner accessor oldKeyValueStore.Replace(store); } _activeSlot = activeSlot; _storeLocation = storeLocation; } return(possibleStore.Succeeded ? BoolResult.Success : new BoolResult($"Failed to initialize a RocksDb store at {_storeLocation}:", possibleStore.Failure.DescribeIncludingInnerFailures())); } catch (Exception ex) when(ex.IsRecoverableIoException()) { return(new BoolResult(ex)); } }