This repository has been archived by the owner on Nov 6, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Fast in-place migration for adding and removing column families #4687
Merged
Merged
Changes from 5 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
3cc007b
add and remove column families dynamically
rphmeier c2c699a
change migration to v11 to be faster
rphmeier ed0a256
docs
rphmeier ac82a83
test case and handle in-place migration correctly
rphmeier 868624c
return correct path for in-place migration
rphmeier da3c13f
split adding and dropping columns tests
rphmeier b487f00
address rightward drift
rphmeier File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,4 +28,4 @@ mod v10; | |
pub use self::v10::ToV10; | ||
|
||
mod v11; | ||
pub use self::v11::ToV11; | ||
pub use self::v11::TO_V11; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -410,6 +410,29 @@ struct DBAndColumns { | |
cfs: Vec<Column>, | ||
} | ||
|
||
// get column family configuration from database config. | ||
fn col_config(col: u32, config: &DatabaseConfig) -> Options { | ||
// default cache size for columns not specified. | ||
const DEFAULT_CACHE: usize = 2; | ||
|
||
let mut opts = Options::new(); | ||
opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction); | ||
opts.set_target_file_size_base(config.compaction.initial_file_size); | ||
opts.set_target_file_size_multiplier(config.compaction.file_size_multiplier); | ||
|
||
let col_opt = config.columns.map(|_| col); | ||
|
||
{ | ||
let cache_size = config.cache_sizes.get(&col_opt).cloned().unwrap_or(DEFAULT_CACHE); | ||
let mut block_opts = BlockBasedOptions::new(); | ||
// all goes to read cache. | ||
block_opts.set_cache(Cache::new(cache_size * 1024 * 1024)); | ||
opts.set_block_based_table_factory(&block_opts); | ||
} | ||
|
||
opts | ||
} | ||
|
||
/// Key-Value database. | ||
pub struct Database { | ||
db: RwLock<Option<DBAndColumns>>, | ||
|
@@ -434,9 +457,6 @@ impl Database { | |
|
||
/// Open database file. Creates if it does not exist. | ||
pub fn open(config: &DatabaseConfig, path: &str) -> Result<Database, String> { | ||
// default cache size for columns not specified. | ||
const DEFAULT_CACHE: usize = 2; | ||
|
||
let mut opts = Options::new(); | ||
if let Some(rate_limit) = config.compaction.write_rate_limit { | ||
opts.set_parsed_options(&format!("rate_limiter_bytes_per_sec={}", rate_limit))?; | ||
|
@@ -460,22 +480,7 @@ impl Database { | |
let cfnames: Vec<&str> = cfnames.iter().map(|n| n as &str).collect(); | ||
|
||
for col in 0 .. config.columns.unwrap_or(0) { | ||
let mut opts = Options::new(); | ||
opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction); | ||
opts.set_target_file_size_base(config.compaction.initial_file_size); | ||
opts.set_target_file_size_multiplier(config.compaction.file_size_multiplier); | ||
|
||
let col_opt = config.columns.map(|_| col); | ||
|
||
{ | ||
let cache_size = config.cache_sizes.get(&col_opt).cloned().unwrap_or(DEFAULT_CACHE); | ||
let mut block_opts = BlockBasedOptions::new(); | ||
// all goes to read cache. | ||
block_opts.set_cache(Cache::new(cache_size * 1024 * 1024)); | ||
opts.set_block_based_table_factory(&block_opts); | ||
} | ||
|
||
cf_options.push(opts); | ||
cf_options.push(col_config(col, &config)); | ||
} | ||
|
||
let mut write_opts = WriteOptions::new(); | ||
|
@@ -768,6 +773,42 @@ impl Database { | |
*self.flushing.write() = mem::replace(&mut *db.flushing.write(), Vec::new()); | ||
Ok(()) | ||
} | ||
|
||
/// The number of non-default column families. | ||
pub fn num_columns(&self) -> u32 { | ||
self.db.read().as_ref() | ||
.and_then(|db| if db.cfs.is_empty() { None } else { Some(db.cfs.len()) } ) | ||
.map(|n| n as u32) | ||
.unwrap_or(0) | ||
} | ||
|
||
/// Drop a column family. | ||
pub fn drop_column(&self) -> Result<(), String> { | ||
match *self.db.write() { | ||
Some(DBAndColumns { ref mut db, ref mut cfs }) => { | ||
if let Some(col) = cfs.pop() { | ||
let name = format!("col{}", cfs.len()); | ||
drop(col); | ||
db.drop_cf(&name)?; | ||
} | ||
Ok(()) | ||
}, | ||
None => Ok(()), | ||
} | ||
} | ||
|
||
/// Add a column family. | ||
pub fn add_column(&self) -> Result<(), String> { | ||
match *self.db.write() { | ||
Some(DBAndColumns { ref mut db, ref mut cfs }) => { | ||
let col = cfs.len() as u32; | ||
let name = format!("col{}", col); | ||
cfs.push(db.create_cf(&name, &col_config(col, &self.config))?); | ||
Ok(()) | ||
}, | ||
None => Ok(()), | ||
} | ||
} | ||
} | ||
|
||
// duplicate declaration of methods here to avoid trait import in certain existing cases | ||
|
@@ -886,4 +927,40 @@ mod tests { | |
let expected_output = Some(PathBuf::from("/sys/block/sda/queue/rotational")); | ||
assert_eq!(rotational_from_df_output(example_df), expected_output); | ||
} | ||
|
||
#[test] | ||
fn dynamic_add_drop_columns() { | ||
let config = DatabaseConfig::default(); | ||
let config_5 = DatabaseConfig::with_columns(Some(5)); | ||
|
||
let path = RandomTempPath::create_dir(); | ||
|
||
// open empty, add 5. | ||
{ | ||
let db = Database::open(&config, path.as_path().to_str().unwrap()).unwrap(); | ||
assert_eq!(db.num_columns(), 0); | ||
|
||
for i in 0..5 { | ||
db.add_column().unwrap(); | ||
assert_eq!(db.num_columns(), i + 1); | ||
} | ||
} | ||
|
||
// open 5, remove all. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. split to separate tests according to F.I.R.S.T ? |
||
{ | ||
let db = Database::open(&config_5, path.as_path().to_str().unwrap()).unwrap(); | ||
assert_eq!(db.num_columns(), 5); | ||
|
||
for i in (0..5).rev() { | ||
db.drop_column().unwrap(); | ||
assert_eq!(db.num_columns(), i); | ||
} | ||
} | ||
|
||
// reopen as 0. | ||
{ | ||
let db = Database::open(&config, path.as_path().to_str().unwrap()).unwrap(); | ||
assert_eq!(db.num_columns(), 0); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to avoid nesting?