diff --git a/slasher/src/database/interface.rs b/slasher/src/database/interface.rs index dcbb82fe93e..81d32f2b133 100644 --- a/slasher/src/database/interface.rs +++ b/slasher/src/database/interface.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "redb")] +use crate::database::CURRENT_SCHEMA_VERSION; use crate::{Config, DatabaseBackend, Error}; use std::borrow::Cow; use std::marker::PhantomData; @@ -119,6 +121,35 @@ impl Environment { _ => vec![], } } + + /// Upgrade the database if necessary (only meaningful for Redb). + pub fn upgrade(&self) -> Result<(), Error> { + match self { + #[cfg(feature = "redb")] + Self::Redb(env) => { + tracing::info!( + "Starting SlasherDB Redb schema to version {}", + CURRENT_SCHEMA_VERSION + ); + env.upgrade()?; + tracing::info!( + "Finished SlasherDB Redb schema upgrade to version {}", + CURRENT_SCHEMA_VERSION + ); + Ok(()) + } + _ => Ok(()), + } + } + + /// Returns true if this database is using Redb as the backend + pub fn is_redb(&self) -> bool { + #[cfg(feature = "redb")] + { + matches!(self, Self::Redb(_)) + } + false + } } impl<'env> RwTransaction<'env> { diff --git a/slasher/src/database/redb_impl.rs b/slasher/src/database/redb_impl.rs index 4198e826455..348934e83ff 100644 --- a/slasher/src/database/redb_impl.rs +++ b/slasher/src/database/redb_impl.rs @@ -102,6 +102,12 @@ impl Environment { _phantom: PhantomData, }) } + + /// Upgrade the underlying Redb environment if necessary + /// Currently a no-op because schema versioning is handled in `SlasherDB::migrate` + pub fn upgrade(&self) -> Result<(), Error> { + Ok(()) + } } impl<'env> RwTransaction<'env> { diff --git a/slasher/src/migrate.rs b/slasher/src/migrate.rs index ec552a19d0d..cab73045bb9 100644 --- a/slasher/src/migrate.rs +++ b/slasher/src/migrate.rs @@ -9,7 +9,12 @@ impl SlasherDB { drop(txn); if let Some(schema_version) = schema_version { - match (schema_version, CURRENT_SCHEMA_VERSION) { + tracing::info!( + "Found SlasherDB on-disk schema version v{} (software target v{})", + schema_version, + CURRENT_SCHEMA_VERSION + ); + return match (schema_version, CURRENT_SCHEMA_VERSION) { // Schema v3 changed the underlying database from LMDB to MDBX. Unless the user did // some manual hacking it should be impossible to read an MDBX schema version < 3. (from, _) if from < 3 => Err(Error::IncompatibleSchemaVersion { @@ -17,13 +22,27 @@ impl SlasherDB { software_schema_version: CURRENT_SCHEMA_VERSION, }), (x, y) if x == y => Ok(self), - (_, _) => Err(Error::IncompatibleSchemaVersion { - database_schema_version: schema_version, - software_schema_version: CURRENT_SCHEMA_VERSION, + + (from, to) if from + 1 == to && self.env.is_redb() => { + self.env.upgrade()?; + let mut txn = self.begin_rw_txn()?; + self.store_schema_version(&mut txn)?; + txn.commit()?; + Ok(self) + } + + (from, to) => Err(Error::IncompatibleSchemaVersion { + database_schema_version: from, + software_schema_version: to, }), - } - } else { - Ok(self) + }; } + + // Store the schema version for future runs + let mut txn = self.begin_rw_txn()?; + self.store_schema_version(&mut txn)?; + txn.commit()?; + + Ok(self) } }