diff --git a/src/storage.rs b/src/storage.rs index 6799fb4..3875ae0 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -43,10 +43,61 @@ const RRDP_SOURCE_KEY_PREFIX: &str = "rrdp_source:"; const RRDP_SOURCE_MEMBER_KEY_PREFIX: &str = "rrdp_source_member:"; const RRDP_URI_OWNER_KEY_PREFIX: &str = "rrdp_uri_owner:"; -fn cf_opts() -> Options { - let mut opts = Options::default(); +const WORK_DB_BLOB_MODE_ENV: &str = "RPKI_WORK_DB_BLOB_MODE"; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum WorkDbBlobMode { + Current, + Disabled, + Lz4, +} + +fn parse_work_db_blob_mode(raw: &str) -> Option { + match raw.trim().to_ascii_lowercase().as_str() { + "" | "default" => Some(default_work_db_blob_mode()), + "current" | "legacy" => Some(WorkDbBlobMode::Current), + "disabled" | "disable" | "off" | "none" | "no_blob" | "no-blob" => { + Some(WorkDbBlobMode::Disabled) + } + "lz4" | "blob_lz4" | "blob-lz4" => Some(WorkDbBlobMode::Lz4), + _ => None, + } +} + +fn default_work_db_blob_mode() -> WorkDbBlobMode { + WorkDbBlobMode::Disabled +} + +fn work_db_blob_mode_from_env() -> WorkDbBlobMode { + let Ok(raw) = std::env::var(WORK_DB_BLOB_MODE_ENV) else { + return default_work_db_blob_mode(); + }; + match parse_work_db_blob_mode(&raw) { + Some(mode) => mode, + None => { + eprintln!( + "warning: unsupported {WORK_DB_BLOB_MODE_ENV}={raw:?}; using default work-db blobdb mode" + ); + default_work_db_blob_mode() + } + } +} + +fn configure_work_db_options(opts: &mut Options, blob_mode: WorkDbBlobMode) { opts.set_compression_type(DBCompressionType::Lz4); - enable_blobdb_if_supported(&mut opts); + match blob_mode { + WorkDbBlobMode::Current => enable_blobdb_current(opts), + WorkDbBlobMode::Disabled => {} + WorkDbBlobMode::Lz4 => { + enable_blobdb_current(opts); + opts.set_blob_compression_type(DBCompressionType::Lz4); + } + } +} + +fn cf_opts(blob_mode: WorkDbBlobMode) -> Options { + let mut opts = Options::default(); + configure_work_db_options(&mut opts, blob_mode); opts } @@ -55,9 +106,15 @@ fn raw_blob_key(sha256_hex: &str) -> String { } pub fn column_family_descriptors() -> Vec { + column_family_descriptors_for_blob_mode(work_db_blob_mode_from_env()) +} + +fn column_family_descriptors_for_blob_mode( + blob_mode: WorkDbBlobMode, +) -> Vec { ALL_COLUMN_FAMILY_NAMES .iter() - .map(|name| ColumnFamilyDescriptor::new(*name, cf_opts())) + .map(|name| ColumnFamilyDescriptor::new(*name, cf_opts(blob_mode))) .collect() } @@ -846,11 +903,15 @@ impl RocksStore { let mut base_opts = Options::default(); base_opts.create_if_missing(true); base_opts.create_missing_column_families(true); - base_opts.set_compression_type(DBCompressionType::Lz4); - enable_blobdb_if_supported(&mut base_opts); + let blob_mode = work_db_blob_mode_from_env(); + configure_work_db_options(&mut base_opts, blob_mode); - let db = DB::open_cf_descriptors(&base_opts, path, column_family_descriptors()) - .map_err(|e| StorageError::RocksDb(e.to_string()))?; + let db = DB::open_cf_descriptors( + &base_opts, + path, + column_family_descriptors_for_blob_mode(blob_mode), + ) + .map_err(|e| StorageError::RocksDb(e.to_string()))?; Ok(Self { db, @@ -1731,7 +1792,7 @@ fn parse_time(field: &'static str, value: &PackTime) -> StorageResult RepositoryViewEntry { RepositoryViewEntry { rsync_uri: rsync_uri.to_string(),