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 13 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
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
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
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,
}
}
}
134 changes: 134 additions & 0 deletions src/deps/ctrlc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright (c) 2017 CtrlC developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Cross platform handling of Ctrl-C signals.
//!
//! [HandlerRoutine]:https://msdn.microsoft.com/en-us/library/windows/desktop/ms683242.aspx
//!
//! [set_handler()](fn.set_handler.html) allows setting a handler closure which is executed on
//! `Ctrl+C`. On Unix, this corresponds to a `SIGINT` signal. On windows, `Ctrl+C` corresponds to
//! [`CTRL_C_EVENT`][HandlerRoutine] or [`CTRL_BREAK_EVENT`][HandlerRoutine].
//!
//! Setting a handler will start a new dedicated signal handling thread where we
//! execute the handler each time we receive a `Ctrl+C` signal. There can only be
//! one handler, you would typically set one at the start of your program.
//!
//! This package was further modified for stacks-blockchain to handle SIGBUS in order to gracefully
//! shut down the node in the event of a sqlite memory error.
//!
//! # Example
//! ```no_run
//! use std::sync::atomic::{AtomicBool, Ordering};
//! use std::sync::Arc;
//!
//! fn main() {
//! let running = Arc::new(AtomicBool::new(true));
//! let r = running.clone();
//!
//! ctrlc::set_handler(move || {
//! r.store(false, Ordering::SeqCst);
//! }).expect("Error setting Ctrl-C handler");
//!
//! println!("Waiting for Ctrl-C...");
//! while running.load(Ordering::SeqCst) {}
//! println!("Got it! Exiting...");
//! }
//! ```
//!

#[macro_use]

mod error;
mod platform;
pub use self::error::Error;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;

#[derive(PartialEq, Clone)]
#[repr(u8)]
pub enum SignalId {
CtrlC = 0x00,
Termination = 0x01,
Bus = 0x02,
Other = 0xff,
}

impl std::fmt::Display for SignalId {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
match *self {
SignalId::CtrlC => write!(f, "CtrlC"),
SignalId::Termination => write!(f, "Termination"),
SignalId::Bus => write!(f, "Bus"),
SignalId::Other => write!(f, "Other"),
}
}
}

static INIT: AtomicBool = AtomicBool::new(false);

/// Register signal handler for Ctrl-C.
///
/// Starts a new dedicated signal handling thread. Should only be called once,
/// typically at the start of your program.
///
/// # Example
/// ```no_run
/// deps::ctrlc::set_handler(move |sig_id| println!("Hello world!")).expect("Error setting Ctrl-C handler");
/// ```
///
/// # Warning
/// On Unix, any existing `SIGINT`, `SIGTERM`, `SIGHUP`, `SIGBUS`, or `SA_SIGINFO`
/// posix signal handlers will be overwritten. On Windows, multiple handler routines are allowed,
/// but they are called on a last-registered, first-called basis until the signal is handled.
///
/// On Unix, signal dispositions and signal handlers are inherited by child processes created via
/// `fork(2)` on, but not by child processes created via `execve(2)`.
/// Signal handlers are not inherited on Windows.
///
/// # Errors
/// Will return an error if another `ctrlc::set_handler()` handler exists or if a
/// system error occurred while setting the handler.
///
/// # Panics
/// Any panic in the handler will not be caught and will cause the signal handler thread to stop.
///
pub fn set_handler<F>(mut user_handler: F) -> Result<(), Error>
where
F: FnMut(SignalId) -> () + 'static + Send,
{
if INIT
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_err()
{
return Err(Error::MultipleHandlers);
}

unsafe {
match platform::init_os_handler() {
Ok(_) => {}
Err(err) => {
INIT.store(false, Ordering::SeqCst);
return Err(err.into());
}
}
}

thread::Builder::new()
.name("signal-handler".into())
.spawn(move || loop {
let received_signal = unsafe {
platform::block_ctrl_c()
.expect("Critical system error while waiting for terminating signal")
};
user_handler(received_signal);
})
.expect("failed to spawn thread");

Ok(())
}
20 changes: 20 additions & 0 deletions src/deps/ctrlc/platform/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) 2017 CtrlC developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

#[cfg(unix)]
mod unix;

#[cfg(windows)]
mod windows;

#[cfg(unix)]
pub use self::unix::*;

#[cfg(windows)]
pub use self::windows::*;
Loading