Open or create a table in the given target directory.
(dir: &Path)
| 437 | |
| 438 | /// Open or create a table in the given target directory. |
| 439 | pub fn open_or_create<T: Table>(dir: &Path) -> anyhow::Result<T> { |
| 440 | use rocksdb::{BlockBasedOptions, DBCompressionType, DataBlockIndexType, Options}; |
| 441 | |
| 442 | // `BlockBasedOptions` doesn't impl `Clone`. |
| 443 | macro_rules! common_block { |
| 444 | () => {{ |
| 445 | let mut opt = BlockBasedOptions::default(); |
| 446 | opt.set_bloom_filter(10.0, false); |
| 447 | opt.set_format_version(5); |
| 448 | opt.set_data_block_index_type(DataBlockIndexType::BinaryAndHash); |
| 449 | opt |
| 450 | }}; |
| 451 | } |
| 452 | |
| 453 | lazy_static::lazy_static! { |
| 454 | static ref COMMON_BLOCK: BlockBasedOptions = common_block!(); |
| 455 | |
| 456 | static ref COMMON: Options = { |
| 457 | let mut opt = Options::default(); |
| 458 | opt.create_if_missing(true); |
| 459 | opt.set_allow_mmap_reads(true); |
| 460 | opt.set_unordered_write(true); |
| 461 | opt.set_block_based_table_factory(&COMMON_BLOCK); |
| 462 | opt |
| 463 | }; |
| 464 | |
| 465 | static ref SEQ_READ_BLOCK: BlockBasedOptions = { |
| 466 | let mut opt = common_block!(); |
| 467 | opt.set_block_size(256 * 1024); // 256KiB |
| 468 | opt |
| 469 | }; |
| 470 | |
| 471 | static ref SEQ_READ: Options = { |
| 472 | let mut opt = COMMON.clone(); |
| 473 | opt.set_compression_type(DBCompressionType::Zstd); |
| 474 | opt.set_advise_random_on_open(false); |
| 475 | opt.set_block_based_table_factory(&SEQ_READ_BLOCK); |
| 476 | opt |
| 477 | }; |
| 478 | } |
| 479 | |
| 480 | let mut opt = match T::STORAGE_OPT { |
| 481 | StorageOpt::RandomAccess => COMMON.clone(), |
| 482 | StorageOpt::SeqRead => SEQ_READ.clone(), |
| 483 | }; |
| 484 | |
| 485 | if let MergeOperator::Associative(op) = T::MERGE_OP { |
| 486 | let name = std::ffi::CStr::from_bytes_with_nul(b"custom\0").unwrap(); |
| 487 | opt.set_merge_operator(name, wrap_merge::<T>(op), wrap_merge::<T>(op)); |
| 488 | } |
| 489 | |
| 490 | let path = dir.join(table_name::<T>()); |
| 491 | let raw = rocksdb::DB::open(&opt, path)?; |
| 492 | |
| 493 | Ok(T::from(raw)) |
| 494 | } |
| 495 | |
| 496 | fn wrap_merge<T: Table>(func: MergeFn<T>) -> Box<dyn rocksdb::merge_operator::MergeFn> { |