private void HandleOnRecoveryError(StorageEnvironmentWithType.StorageEnvironmentType type, string resourceName, object environment, RecoveryErrorEventArgs e) { NotificationCenter.NotificationCenter nc; string title; switch (type) { case StorageEnvironmentWithType.StorageEnvironmentType.Configuration: case StorageEnvironmentWithType.StorageEnvironmentType.Documents: nc = _serverStore?.NotificationCenter; title = $"Database Recovery Error - {resourceName ?? "Unknown Database"}"; if (type == StorageEnvironmentWithType.StorageEnvironmentType.Configuration) { title += " (configuration storage)"; } break; case StorageEnvironmentWithType.StorageEnvironmentType.Index: nc = NotificationCenter; title = $"Index Recovery Error - {resourceName ?? "Unknown Index"}"; break; default: throw new ArgumentOutOfRangeException(nameof(type), type.ToString()); } nc?.Add(AlertRaised.Create(Name, title, $"{e.Message}{Environment.NewLine}{Environment.NewLine}Environment: {environment}", AlertType.RecoveryError, NotificationSeverity.Error, key: resourceName)); }
private static StorageEnvironment OpenEnvironmentWithPossibleLayoutUpdate(StorageEnvironmentOptions.DirectoryStorageEnvironmentOptions options, StorageEnvironmentWithType.StorageEnvironmentType type) { try { var oldOwnsPager = options.OwnsPagers; options.OwnsPagers = false; try { return(new StorageEnvironment(options)); } finally { options.OwnsPagers = oldOwnsPager; } } catch (InvalidJournalException e) { var basePath = options.BasePath; var preRtmJournalPath = basePath.Combine("Journal"); var journalsPath = options.JournalPath; if (Directory.Exists(preRtmJournalPath.FullPath)) { TryMoveJournals(preRtmJournalPath, journalsPath); Directory.Delete(preRtmJournalPath.FullPath); } else { if (TryMoveJournals(basePath, journalsPath) == false) { var message = $"Failed to open a storage at {options} due to invalid or missing journal files. In order to load the storage successfully we need all journals to be not corrupted. "; string ravenServer = Assembly.GetAssembly(typeof(StorageLoader)).GetName().Name + (PlatformDetails.RunningOnPosix ? string.Empty : ".exe"); switch (type) { case StorageEnvironmentWithType.StorageEnvironmentType.Index: message += "The recommended approach is to reset the index in order to recover from this error. Alternatively you can temporarily start the server in " + $"dangerous mode so it will ignore invalid journals on startup: {Environment.NewLine}" + $"{ravenServer} --{RavenConfiguration.GetKey(x => x.Storage.IgnoreInvalidJournalErrors)}=true{Environment.NewLine}" + "This switch is meant to be use only for recovery purposes. Please make sure that you won't use it after you manage to recover your data. " + "Eventually you should reset the index anyway to be sure you won't experience any invalid data errors in the future."; break; case StorageEnvironmentWithType.StorageEnvironmentType.Documents: message += "You can load a database by starting the server in dangerous mode temporarily so it will ignore invalid journals on startup but you need to " + $"export and import database immediately afterwards: {Environment.NewLine}" + $"{ravenServer} --{RavenConfiguration.GetKey(x => x.Storage.IgnoreInvalidJournalErrors)}=true{Environment.NewLine}" + "This switch is meant to be use only for recovery purposes. Please make sure that you won't use it after you manage to recover your data. " + "If you won't be able to export the database successfully you need restore the database from the backup or use Voron.Recovery tool. "; break; case StorageEnvironmentWithType.StorageEnvironmentType.Configuration: message += $"You can delete the configuration storage folder at '{basePath.FullPath}' and restart the server. It will be recreated on database startup." + "This storage contains only notifications and alerts that you see in RavenDB studio"; break; case StorageEnvironmentWithType.StorageEnvironmentType.System: message += "You can start the server in dangerous mode temporarily so it will ignore invalid journals on startup:" + $"{ravenServer} --{RavenConfiguration.GetKey(x => x.Storage.IgnoreInvalidJournalErrors)}=true{Environment.NewLine}" + "This switch is meant to be use only for recovery purposes. Please make sure that you won't use it after you manage to recover your data. " + $"Eventually you should delete the system storage at '{basePath.FullPath}', start the server and create your databases again with the usage of existing data."; break; default: throw new ArgumentException($"Unknown storage type: {type}", nameof(type)); } throw new InvalidJournalException($"{message}{Environment.NewLine}Error details: {e.Message}"); } } return(new StorageEnvironment(options)); } }
public static StorageEnvironment OpenEnvironment(StorageEnvironmentOptions options, StorageEnvironmentWithType.StorageEnvironmentType type) { try { if (options is StorageEnvironmentOptions.DirectoryStorageEnvironmentOptions directoryOptions) { return(OpenEnvironmentWithPossibleLayoutUpdate(directoryOptions, type)); } return(new StorageEnvironment(options)); } catch (Exception) { options.Dispose(); throw; } }