Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use mmap on MARF connections #2900

Merged
merged 25 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2a1b5bf
feat: vendor ctrlc package and add support for SIGBUS. Also, have the…
jcnelson Oct 26, 2021
d202d26
feat: add nix crate (to support vendored ctrlc package) and add the c…
jcnelson Oct 26, 2021
c55a6e4
refactor: db_mkdirs() now only returns one argument
jcnelson Oct 26, 2021
fd962c3
chore: give credit where credit is due for ctrlc
jcnelson Oct 26, 2021
c76a7f5
chore: expose ctrlc vendored package
jcnelson Oct 26, 2021
4cef87b
feat: expose ctrlc crate, with OS-specific packages
jcnelson Oct 26, 2021
36b2743
feat: use mmap by default in sqlite connections (256MB)
jcnelson Oct 26, 2021
0511532
chore: no longer need ctrlc
jcnelson Oct 26, 2021
4ef95f9
refactor: use deps/ctrlc now
jcnelson Oct 26, 2021
ede6334
fix: update docstrings to use deps::ctrlc
jcnelson Oct 26, 2021
0cde87c
fix: use move in docstring and use new arg
jcnelson Oct 26, 2021
cef19e6
fix: add unix and windows deps for vendored ctrlc package to libclarity
jcnelson Oct 26, 2021
9943a4b
fix: don't panic if we set a signal handler multiple times when testi…
jcnelson Oct 26, 2021
88185e0
refactor: only MARF databases will use mmap
jcnelson Oct 26, 2021
c5a276f
refactor: expose test module
jcnelson Oct 26, 2021
1e1d7c9
refactor: run original ctrlc tests as a unit test
jcnelson Oct 26, 2021
13eb05e
fix: don't mmap on sqlite_open()
jcnelson Oct 26, 2021
0a46823
fix: crash and burn on SIGBUS, and use async-safe (but rust unsafe) l…
jcnelson Oct 26, 2021
34f2cbf
fix: use proper libc types
jcnelson Oct 26, 2021
7062a02
chore: new Cargo lockfile
jcnelson Oct 26, 2021
684e8c9
chore: remove needless docstring example
jcnelson Oct 26, 2021
1ff6075
fix: have clarity target use nix and winapi for platform-specific nee…
jcnelson Oct 26, 2021
7403620
chore: updated cargo.lock
jcnelson Oct 27, 2021
0ae09f8
fix: windows-specific call to libc::write, because windows inexplicab…
jcnelson Oct 27, 2021
8303d22
chore: add CHANGELOG entry about mmap'ed connections
jcnelson Oct 27, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
## Changed

- Prioritize transaction inclusion in blocks by estimated fee rates (#2859).
- MARF sqlite connections will now use `mmap`'ed connections with up to 256MB
space (#2869).

## [2.0.11.3.0]

Expand Down
41 changes: 22 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ slog-json = { version = "2.3.0", optional = true }
chrono = "0.4.19"
libc = "0.2.82"

[target.'cfg(unix)'.dependencies]
nix = "0.23"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["consoleapi", "handleapi", "synchapi", "winbase"] }

[target.'cfg(windows)'.dev-dependencies]
winapi = { version = "0.3", features = ["fileapi", "processenv", "winnt"] }

[dependencies.serde_json]
version = "1.0"
features = ["arbitrary_precision", "unbounded_depth"]
Expand Down
9 changes: 9 additions & 0 deletions clarity/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ slog-json = { version = "2.3.0", optional = true }
chrono = "0.4.19"
libc = "0.2.82"

[target.'cfg(unix)'.dependencies]
nix = "0.23"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["consoleapi", "handleapi", "synchapi", "winbase"] }

[target.'cfg(windows)'.dev-dependencies]
winapi = { version = "0.3", features = ["fileapi", "processenv", "winnt"] }

[dependencies.serde_json]
version = "1.0"
features = ["arbitrary_precision", "unbounded_depth"]
Expand Down
10 changes: 4 additions & 6 deletions src/chainstate/burn/db/sortdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1989,10 +1989,9 @@ impl SortitionDB {
/// It's best not to call this if you are able to call connect(). If you must call this, do so
/// after you call connect() somewhere else, since connect() performs additional validations.
pub fn open(path: &str, readwrite: bool) -> Result<SortitionDB, db_error> {
let (db_path, index_path) = db_mkdirs(path)?;
let index_path = db_mkdirs(path)?;
debug!(
"Open sortdb '{}' as '{}', with index as '{}'",
db_path,
"Open sortdb as '{}', with index as '{}'",
if readwrite { "readwrite" } else { "readonly" },
index_path
);
Expand Down Expand Up @@ -2035,11 +2034,10 @@ impl SortitionDB {
Ok(_md) => false,
};

let (db_path, index_path) = db_mkdirs(path)?;
let index_path = db_mkdirs(path)?;
debug!(
"Connect/Open {} sortdb '{}' as '{}', with index as '{}'",
"Connect/Open {} sortdb as '{}', with index as '{}'",
if create_flag { "(create)" } else { "" },
db_path,
if readwrite { "readwrite" } else { "readonly" },
index_path
);
Expand Down
20 changes: 16 additions & 4 deletions src/chainstate/stacks/index/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ use chainstate::stacks::index::node::{
};
use chainstate::stacks::index::Error;
use chainstate::stacks::index::{trie_sql, BlockMap, MarfTrieId};
use util::db::sql_pragma;
use util::db::sqlite_open;
use util::db::tx_begin_immediate;
use util::db::tx_busy_handler;
use util::db::Error as db_error;
use util::db::SQLITE_MMAP_SIZE;
use util::log;

use crate::types::chainstate::BlockHeaderHash;
Expand Down Expand Up @@ -721,6 +723,16 @@ pub struct TrieFileStorage<T: MarfTrieId> {
pub test_genesis_block: Option<T>,
}

fn marf_sqlite_open<P: AsRef<Path>>(
db_path: P,
open_flags: OpenFlags,
foreign_keys: bool,
) -> Result<Connection, db_error> {
let db = sqlite_open(db_path, open_flags, foreign_keys)?;
sql_pragma(&db, "mmap_size", &SQLITE_MMAP_SIZE)?;
Ok(db)
}

impl<T: MarfTrieId> TrieFileStorage<T> {
pub fn connection<'a>(&'a mut self) -> TrieStorageConnection<'a, T> {
TrieStorageConnection {
Expand Down Expand Up @@ -796,7 +808,7 @@ impl<T: MarfTrieId> TrieFileStorage<T> {
}
};

let mut db = sqlite_open(db_path, open_flags, false)?;
let mut db = marf_sqlite_open(db_path, open_flags, false)?;
let db_path = db_path.to_string();

if create_flag {
Expand Down Expand Up @@ -865,7 +877,7 @@ impl<T: MarfTrieId> TrieFileStorage<T> {
}

pub fn reopen_readonly(&self) -> Result<TrieFileStorage<T>, Error> {
let db = sqlite_open(&self.db_path, OpenFlags::SQLITE_OPEN_READ_ONLY, false)?;
let db = marf_sqlite_open(&self.db_path, OpenFlags::SQLITE_OPEN_READ_ONLY, false)?;

trace!("Make read-only view of TrieFileStorage: {}", &self.db_path);

Expand Down Expand Up @@ -909,7 +921,7 @@ impl<'a, T: MarfTrieId> TrieStorageTransaction<'a, T> {
/// reopen this transaction as a read-only marf.
/// _does not_ preserve the cur_block/open tip
pub fn reopen_readonly(&self) -> Result<TrieFileStorage<T>, Error> {
let db = sqlite_open(&self.db_path, OpenFlags::SQLITE_OPEN_READ_ONLY, false)?;
let db = marf_sqlite_open(&self.db_path, OpenFlags::SQLITE_OPEN_READ_ONLY, false)?;

trace!(
"Make read-only view of TrieStorageTransaction: {}",
Expand Down Expand Up @@ -1283,7 +1295,7 @@ impl<'a, T: MarfTrieId> TrieStorageConnection<'a, T> {
/// Recover from partially-written state -- i.e. blow it away.
/// Doesn't get called automatically.
pub fn recover(db_path: &String) -> Result<(), Error> {
let conn = sqlite_open(db_path, OpenFlags::SQLITE_OPEN_READ_WRITE, false)?;
let conn = marf_sqlite_open(db_path, OpenFlags::SQLITE_OPEN_READ_WRITE, false)?;
trie_sql::clear_lock_data(&conn)
}

Expand Down
2 changes: 2 additions & 0 deletions src/deps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ snapshots of important libraries this codebase depends on.
* The `bitcoin` package was produced by Andrew Poelstra (https://github.com/rust-bitcoin/rust-bitcoin). License is CC0.
* The `httparse` package was produced by Sean McArthur
(https://github.com/seanmonstar/httparse). License is MIT.
* The `ctrlc` package was produced by Antti Keräne
(https://github.com/Detegr/rust-ctrlc). License is MIT.
46 changes: 46 additions & 0 deletions src/deps/ctrlc/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use deps::ctrlc::platform;
use std::fmt;

/// Ctrl-C error.
#[derive(Debug)]
pub enum Error {
/// Ctrl-C signal handler already registered.
MultipleHandlers,
/// Unexpected system error.
System(std::io::Error),
}

impl Error {
fn describe(&self) -> &str {
match *self {
Error::MultipleHandlers => "Ctrl-C signal handler already registered",
Error::System(_) => "Unexpected system error",
}
}
}

impl From<platform::Error> for Error {
fn from(e: platform::Error) -> Error {
let system_error = std::io::Error::new(std::io::ErrorKind::Other, e);
Error::System(system_error)
}
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Ctrl-C error: {}", self.describe())
}
}

impl std::error::Error for Error {
fn description(&self) -> &str {
self.describe()
}

fn cause(&self) -> Option<&dyn std::error::Error> {
match *self {
Error::System(ref e) => Some(e),
_ => None,
}
}
}
Loading