diff --git a/CHANGELOG.md b/CHANGELOG.md index 7237bb715c8..0f3b70be51d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [#1924](https://github.com/FuelLabs/fuel-core/pull/1924): `dry_run_opt` has new `gas_price: Option` argument ### Added +- [#1939](https://github.com/FuelLabs/fuel-core/pull/1939): Added API functions to open a RocksDB in different modes. - [#1929](https://github.com/FuelLabs/fuel-core/pull/1929): Added support of customization of the state transition version in the `ChainConfig`. ### Removed diff --git a/crates/fuel-core/src/state/rocks_db.rs b/crates/fuel-core/src/state/rocks_db.rs index 23264fff198..564f89aa962 100644 --- a/crates/fuel-core/src/state/rocks_db.rs +++ b/crates/fuel-core/src/state/rocks_db.rs @@ -181,6 +181,69 @@ where columns: Vec, capacity: Option, ) -> DatabaseResult { + Self::open_with(DB::open_cf_descriptors, path, columns, capacity) + } + + pub fn open_read_only>( + path: P, + columns: Vec, + capacity: Option, + error_if_log_file_exist: bool, + ) -> DatabaseResult { + Self::open_with( + |options, primary_path, cfs| { + DB::open_cf_descriptors_read_only( + options, + primary_path, + cfs, + error_if_log_file_exist, + ) + }, + path, + columns, + capacity, + ) + } + + pub fn open_secondary( + path: PrimaryPath, + secondary_path: SecondaryPath, + columns: Vec, + capacity: Option, + ) -> DatabaseResult + where + PrimaryPath: AsRef, + SecondaryPath: AsRef, + { + Self::open_with( + |options, primary_path, cfs| { + DB::open_cf_descriptors_as_secondary( + options, + primary_path, + secondary_path.as_ref().to_path_buf(), + cfs, + ) + }, + path, + columns, + capacity, + ) + } + + pub fn open_with( + opener: F, + path: P, + columns: Vec, + capacity: Option, + ) -> DatabaseResult + where + F: Fn( + &Options, + PathBuf, + Vec, + ) -> Result, + P: AsRef, + { let path = path.as_ref().join(Description::name()); let mut block_opts = BlockBasedOptions::default(); // See https://github.com/facebook/rocksdb/blob/a1523efcdf2f0e8133b9a9f6e170a0dad49f928f/include/rocksdb/table.h#L246-L271 for details on what the format versions are/do. @@ -237,9 +300,10 @@ where let iterator = cf_descriptors_to_open .clone() .into_iter() - .map(|(name, opts)| ColumnFamilyDescriptor::new(name, opts)); + .map(|(name, opts)| ColumnFamilyDescriptor::new(name, opts)) + .collect::>(); - let db = match DB::open_cf_descriptors(&opts, &path, iterator) { + let db = match opener(&opts, path.clone(), iterator) { Ok(db) => { Ok(db) }, @@ -251,9 +315,10 @@ where let iterator = cf_descriptors_to_open .clone() .into_iter() - .map(|(name, opts)| ColumnFamilyDescriptor::new(name, opts)); + .map(|(name, opts)| ColumnFamilyDescriptor::new(name, opts)) + .collect::>(); - DB::open_cf_descriptors(&opts, &path, iterator) + opener(&opts, path, iterator) }, } .map_err(|e| DatabaseError::Other(e.into()))?; @@ -802,4 +867,59 @@ mod tests { assert!(!db.exists(&key, Column::Metadata).unwrap()); } + + #[test] + fn open_primary_db_second_time_fails() { + // Given + let (_primary_db, tmp_dir) = create_db(); + + // When + let old_columns = + vec![Column::Coins, Column::Messages, Column::UploadedBytecodes]; + let result = RocksDb::::open(tmp_dir.path(), old_columns.clone(), None); + + // Then + assert!(result.is_err()); + } + + #[test] + fn open_second_read_only_db() { + // Given + let (_primary_db, tmp_dir) = create_db(); + + // When + let old_columns = + vec![Column::Coins, Column::Messages, Column::UploadedBytecodes]; + let result = RocksDb::::open_read_only( + tmp_dir.path(), + old_columns.clone(), + None, + false, + ) + .map(|_| ()); + + // Then + assert_eq!(Ok(()), result); + } + + #[test] + fn open_secondary_db() { + // Given + let (_primary_db, tmp_dir) = create_db(); + let secondary_temp = TempDir::new().unwrap(); + + // When + let old_columns = + vec![Column::Coins, Column::Messages, Column::UploadedBytecodes]; + let result = RocksDb::::open_secondary( + tmp_dir.path(), + secondary_temp.path(), + old_columns.clone(), + None, + ) + .map(|_| ()); + + // Then + assert_eq!(Ok(()), result); + } }