2024-02-21 17:54:46 +00:00
|
|
|
//! Cuprate directories and filenames.
|
|
|
|
//!
|
2024-05-05 14:21:28 +00:00
|
|
|
//! # Environment variables on Linux
|
|
|
|
//! Note that this module's functions uses [`dirs`],
|
|
|
|
//! which adheres to the XDG standard on Linux.
|
2024-02-21 17:54:46 +00:00
|
|
|
//!
|
2024-08-20 21:53:32 +00:00
|
|
|
//! This means that the values returned by these statics
|
2024-05-05 14:21:28 +00:00
|
|
|
//! may change at runtime depending on environment variables,
|
|
|
|
//! for example:
|
|
|
|
//!
|
|
|
|
//! By default the config directory is `~/.config`, however
|
|
|
|
//! if `$XDG_CONFIG_HOME` is set to something, that will be
|
|
|
|
//! used instead.
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! # use cuprate_helper::fs::*;
|
|
|
|
//! # if cfg!(target_os = "linux") {
|
|
|
|
//! std::env::set_var("XDG_CONFIG_HOME", "/custom/path");
|
|
|
|
//! assert_eq!(
|
2024-08-20 21:53:32 +00:00
|
|
|
//! CUPRATE_CONFIG_DIR.to_string_lossy(),
|
2024-05-05 14:21:28 +00:00
|
|
|
//! "/custom/path/cuprate"
|
|
|
|
//! );
|
|
|
|
//! # }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! Reference:
|
|
|
|
//! - <https://github.com/Cuprate/cuprate/issues/46>
|
|
|
|
//! - <https://docs.rs/dirs>
|
2024-02-21 17:54:46 +00:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------- Use
|
2024-08-20 21:53:32 +00:00
|
|
|
use std::{path::PathBuf, sync::LazyLock};
|
2024-02-21 17:54:46 +00:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------- Const
|
|
|
|
/// Cuprate's main directory.
|
|
|
|
///
|
|
|
|
/// This is the head PATH node used for any top-level Cuprate directories.
|
|
|
|
///
|
|
|
|
/// | OS | PATH |
|
|
|
|
/// |---------|-----------------------------------------------------|
|
|
|
|
/// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\` |
|
|
|
|
/// | macOS | `/Users/Alice/Library/Application Support/Cuprate/` |
|
|
|
|
/// | Linux | `/home/alice/.config/cuprate/` |
|
|
|
|
///
|
|
|
|
/// This is shared between all Cuprate programs.
|
|
|
|
///
|
|
|
|
/// # Value
|
|
|
|
/// This is `Cuprate` on `Windows|macOS` and `cuprate` on everything else.
|
|
|
|
///
|
|
|
|
/// # Monero Equivalent
|
|
|
|
/// `.bitmonero`
|
|
|
|
pub const CUPRATE_DIR: &str = {
|
|
|
|
if cfg!(target_os = "windows") || cfg!(target_os = "macos") {
|
|
|
|
// The standard for main directories is capitalized.
|
|
|
|
"Cuprate"
|
|
|
|
} else {
|
|
|
|
// Standard on Linux + BSDs is lowercase.
|
|
|
|
"cuprate"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------- Directories
|
2024-08-20 21:53:32 +00:00
|
|
|
/// Create a `LazyLock` for common PATHs used by Cuprate.
|
2024-02-21 17:54:46 +00:00
|
|
|
///
|
|
|
|
/// This currently creates these directories:
|
2024-08-20 21:53:32 +00:00
|
|
|
/// - [`CUPRATE_CACHE_DIR`]
|
|
|
|
/// - [`CUPRATE_CONFIG_DIR`]
|
|
|
|
/// - [`CUPRATE_DATA_DIR`]
|
|
|
|
/// - [`CUPRATE_BLOCKCHAIN_DIR`]
|
|
|
|
macro_rules! impl_path_lazylock {
|
2024-02-21 17:54:46 +00:00
|
|
|
($(
|
|
|
|
$(#[$attr:meta])* // Documentation and any `derive`'s.
|
2024-08-20 21:53:32 +00:00
|
|
|
$name:ident, // Name of the corresponding `LazyLock`.
|
2024-02-21 17:54:46 +00:00
|
|
|
$dirs_fn:ident, // Name of the `dirs` function to use, the PATH prefix.
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
$sub_dirs:literal // Any sub-directories to add onto the PATH.
|
2024-02-21 17:54:46 +00:00
|
|
|
),* $(,)?) => {$(
|
2024-08-20 21:53:32 +00:00
|
|
|
// Create the `LazyLock` if needed, append
|
2024-02-21 17:54:46 +00:00
|
|
|
// the Cuprate directory string and return.
|
|
|
|
$(#[$attr])*
|
2024-08-20 21:53:32 +00:00
|
|
|
pub static $name: LazyLock<PathBuf> = LazyLock::new(|| {
|
|
|
|
// There's nothing we can do but panic if
|
|
|
|
// we cannot acquire critical system directories.
|
|
|
|
//
|
|
|
|
// Although, this realistically won't panic on
|
|
|
|
// normal systems for all OS's supported by `dirs`.
|
|
|
|
let mut path = dirs::$dirs_fn().unwrap();
|
|
|
|
|
|
|
|
// FIXME:
|
|
|
|
// Consider a user who does `HOME=/ ./cuprated`
|
|
|
|
//
|
|
|
|
// Should we say "that's stupid" and panic here?
|
|
|
|
// Or should it be respected?
|
|
|
|
// We really don't want a `rm -rf /` type of situation...
|
|
|
|
assert!(
|
|
|
|
path.parent().is_some(),
|
|
|
|
"SAFETY: returned OS PATH was either root or empty, aborting"
|
|
|
|
);
|
|
|
|
|
|
|
|
// Returned OS PATH should be absolute, not relative.
|
|
|
|
assert!(path.is_absolute(), "SAFETY: returned OS PATH was not absolute");
|
|
|
|
|
|
|
|
// Unconditionally prefix with the top-level Cuprate directory.
|
|
|
|
path.push(CUPRATE_DIR);
|
|
|
|
|
|
|
|
// Add any sub directories if specified in the macro.
|
|
|
|
if !$sub_dirs.is_empty() {
|
|
|
|
path.push($sub_dirs);
|
|
|
|
}
|
|
|
|
|
|
|
|
path
|
|
|
|
});
|
2024-02-21 17:54:46 +00:00
|
|
|
)*};
|
|
|
|
}
|
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
impl_path_lazylock! {
|
2024-02-21 17:54:46 +00:00
|
|
|
/// Cuprate's cache directory.
|
|
|
|
///
|
|
|
|
/// This is the PATH used for any Cuprate cache files.
|
|
|
|
///
|
|
|
|
/// | OS | PATH |
|
|
|
|
/// |---------|-----------------------------------------|
|
|
|
|
/// | Windows | `C:\Users\Alice\AppData\Local\Cuprate\` |
|
|
|
|
/// | macOS | `/Users/Alice/Library/Caches/Cuprate/` |
|
|
|
|
/// | Linux | `/home/alice/.cache/cuprate/` |
|
2024-08-20 21:53:32 +00:00
|
|
|
CUPRATE_CACHE_DIR,
|
2024-02-21 17:54:46 +00:00
|
|
|
cache_dir,
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
"",
|
2024-02-21 17:54:46 +00:00
|
|
|
|
|
|
|
/// Cuprate's config directory.
|
|
|
|
///
|
|
|
|
/// This is the PATH used for any Cuprate configuration files.
|
|
|
|
///
|
|
|
|
/// | OS | PATH |
|
|
|
|
/// |---------|-----------------------------------------------------|
|
|
|
|
/// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\` |
|
|
|
|
/// | macOS | `/Users/Alice/Library/Application Support/Cuprate/` |
|
|
|
|
/// | Linux | `/home/alice/.config/cuprate/` |
|
2024-08-20 21:53:32 +00:00
|
|
|
CUPRATE_CONFIG_DIR,
|
2024-02-21 17:54:46 +00:00
|
|
|
config_dir,
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
"",
|
2024-02-21 17:54:46 +00:00
|
|
|
|
|
|
|
/// Cuprate's data directory.
|
|
|
|
///
|
|
|
|
/// This is the PATH used for any Cuprate data files.
|
|
|
|
///
|
|
|
|
/// | OS | PATH |
|
|
|
|
/// |---------|-----------------------------------------------------|
|
|
|
|
/// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\` |
|
|
|
|
/// | macOS | `/Users/Alice/Library/Application Support/Cuprate/` |
|
|
|
|
/// | Linux | `/home/alice/.local/share/cuprate/` |
|
2024-08-20 21:53:32 +00:00
|
|
|
CUPRATE_DATA_DIR,
|
2024-02-21 17:54:46 +00:00
|
|
|
data_dir,
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
"",
|
|
|
|
|
2024-05-29 01:18:30 +00:00
|
|
|
/// Cuprate's blockchain directory.
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
///
|
2024-05-29 01:18:30 +00:00
|
|
|
/// This is the PATH used for any Cuprate blockchain files.
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
///
|
2024-05-29 01:18:30 +00:00
|
|
|
/// | OS | PATH |
|
|
|
|
/// |---------|----------------------------------------------------------------|
|
|
|
|
/// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\blockchain\` |
|
|
|
|
/// | macOS | `/Users/Alice/Library/Application Support/Cuprate/blockchain/` |
|
|
|
|
/// | Linux | `/home/alice/.local/share/cuprate/blockchain/` |
|
2024-08-20 21:53:32 +00:00
|
|
|
CUPRATE_BLOCKCHAIN_DIR,
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
data_dir,
|
2024-05-29 01:18:30 +00:00
|
|
|
"blockchain",
|
2024-08-22 01:09:07 +00:00
|
|
|
|
|
|
|
/// Cuprate's transaction pool directory.
|
|
|
|
///
|
|
|
|
/// This is the PATH used for any Cuprate txpool files.
|
|
|
|
///
|
|
|
|
/// | OS | PATH |
|
|
|
|
/// |---------|------------------------------------------------------------|
|
|
|
|
/// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\txpool\` |
|
|
|
|
/// | macOS | `/Users/Alice/Library/Application Support/Cuprate/txpool/` |
|
|
|
|
/// | Linux | `/home/alice/.local/share/cuprate/txpool/` |
|
|
|
|
CUPRATE_TXPOOL_DIR,
|
|
|
|
data_dir,
|
|
|
|
"txpool",
|
2024-02-21 17:54:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------- Tests
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
// Sanity check every PATH defined in this file.
|
|
|
|
//
|
|
|
|
// Each new PATH should be added to this test:
|
|
|
|
// - It must be `is_absolute()`
|
|
|
|
// - It must `ends_with()` the expected end PATH for the OS
|
2024-02-21 17:54:46 +00:00
|
|
|
#[test]
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
fn path_sanity_check() {
|
2024-08-20 21:53:32 +00:00
|
|
|
assert!(CUPRATE_CACHE_DIR.is_absolute());
|
|
|
|
assert!(CUPRATE_CONFIG_DIR.is_absolute());
|
|
|
|
assert!(CUPRATE_DATA_DIR.is_absolute());
|
|
|
|
assert!(CUPRATE_BLOCKCHAIN_DIR.is_absolute());
|
2024-02-21 17:54:46 +00:00
|
|
|
|
|
|
|
if cfg!(target_os = "windows") {
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_CACHE_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_cache_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(r"AppData\Local\Cuprate"));
|
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_CONFIG_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_config_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(r"AppData\Roaming\Cuprate"));
|
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_DATA_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_data_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(r"AppData\Roaming\Cuprate"));
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_BLOCKCHAIN_DIR;
|
2024-05-29 01:18:30 +00:00
|
|
|
println!("cuprate_blockchain_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(r"AppData\Roaming\Cuprate\blockchain"));
|
2024-08-22 01:09:07 +00:00
|
|
|
|
|
|
|
let dir = &*CUPRATE_TXPOOL_DIR;
|
|
|
|
println!("cuprate_txpool_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(r"AppData\Roaming\Cuprate\txpool"));
|
2024-02-21 17:54:46 +00:00
|
|
|
} else if cfg!(target_os = "macos") {
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_CACHE_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_cache_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with("Library/Caches/Cuprate"));
|
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_CONFIG_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_config_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with("Library/Application Support/Cuprate"));
|
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_DATA_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_data_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with("Library/Application Support/Cuprate"));
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_BLOCKCHAIN_DIR;
|
2024-05-29 01:18:30 +00:00
|
|
|
println!("cuprate_blockchain_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with("Library/Application Support/Cuprate/blockchain"));
|
2024-08-22 01:09:07 +00:00
|
|
|
|
|
|
|
let dir = &*CUPRATE_TXPOOL_DIR;
|
|
|
|
println!("cuprate_txpool_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with("Library/Application Support/Cuprate/txpool"));
|
2024-02-21 17:54:46 +00:00
|
|
|
} else {
|
|
|
|
// Assumes Linux.
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_CACHE_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_cache_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(".cache/cuprate"));
|
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_CONFIG_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_config_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(".config/cuprate"));
|
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_DATA_DIR;
|
2024-02-21 17:54:46 +00:00
|
|
|
println!("cuprate_data_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(".local/share/cuprate"));
|
database: Resizes, Shutdown, Flushing (#68)
* error: add `NeedsResize`
accidently removed, was `MapFull` before.
We need this because we as the writer thread must
react to this error in order to resize.
The writer thread doesn't have access to `heed::Error`, but
`Runtime::Error`, so this variant must exist
* env/backend: add `MANUAL_RESIZE` and `resize()`
* heed: respect `ReadersFull`, comment errors
* free: add `resize_memory_map()`
* env: add `Env::current_map_size`
* service: add `resize_map()`
* database: make `Env` itself cheaply clonable + threadsafe
`heed::Env` already uses `Arc` internally, but `sanakirja` does
not, so abstract this at the `Env` level instead of wrapping
`ConcreteEnv` in `Arc` ourselves.
* service: `Arc<ConcreteEnv>` -> `ConcreteEnv: Clone`
* env: add `SYNCS_PER_TX`, `path()`, `shutdown()`
* database: add `src/service/state.rs`
* service: add to `state.rs`, add `DatabaseState` to readers/writer
* add `parking_lot`
Okay, turns out we need to take locks in
`database/src/service/state.rs`...
`std`'s lock fairness policies are not well defined and
depend on the OS implementation, `parking_lot` on the other hand
has a fairness policy which is important when the writer needs
the lock but readers keep pouring in, essentially never letting
the writer do stuff.
* state: use `crossbeam::atomic::AtomicCell`
We have crossbeam as a dep anyway.
* heed: `heed::Env` -> `Arc<RwLock<heed::Env>>`
* service: add reader shutdown handle, use `Select` for msgs
* service: remove `state.rs`
We don't need this, we will represent shutdowns with channel
messages and `Select`, and mutual exclusion with a `RwLock`.
* service: fix misc reader/writer stuff
* database: add `config.rs`
* service: use `ReaderThreads` when spawning readers
* service: impl `shutdown()` for readers/writer
* service: return `DatabaseReaderReceivers` on shutdown via `JoinHandle`
Solves the issue of unfortunately timed `Request`s
that come in _right_ as we are shutting down.
If we (Cuprate) drop the database channels too early the requesting
thread will probably panic as they probably use `.unwrap()`,
never expecting a channel failure.
Returning this structure containing all the channels allows the
final shutdown code to carry these channels until the very end
of the program, at which point, all threads exit - no panics.
* remove `parking_lot`
Could be used as the database mutual exclusion lock.
Needs to be tested against `std`.
* config: add `path`
* env: `path()` -> `config()`, backend: impl `Drop`
* `Arc<ConcreteEnv>`, shutdown `service` on channel disconnect
* backend: add `Config` to `ConcreteEnv`
* service: use `std::thread::Builder` for readers/writer
* config: `PathBuf` -> `Cow<'static, Path>`
* misc docs, remove `RuntimeError::ShuttingDown`
* service: init & shutdown docs
* heed: impl `Env::resize_map()`
* heed: impl `Env::current_map_size()`
* lib.rs: add example crate usage test
* heed: `RwLock` comment
* helper: add `cuprate_database_dir()`
* config: use `cuprate_database_dir()`
* lib.rs: TODO example test
* database: add `page_size`
The database memory map size must be a multiple of
the OS page size. Why doesn't `heed` re-expose this?
It calls it when checking anyway...
https://docs.rs/heed/0.20.0-alpha.9/src/heed/env.rs.html#772
* free: impl `resize_memory_map()`
* free: docs
* env: add `disk_size_bytes()`
* config: impl `From<$num>` for `ReaderThreads`
* move `fs`-related constants to `cuprate_helper::fs`
* docs
* add `resize.rs`, `ResizeAlgorithm`
* env: use `ResizeAlgorithm` in `resize_map()`
* TODO: account for LMDB reader limit
* resize: docs, add `page_size()`, impl `fixed_bytes()`
* resize: impl `percent()`
* resize: docs
* env: take `ResizeAlgorithm` by value (it impls `Copy`)
* heed: TODO for `MDB_MAP_FULL` & `MDB_MAP_RESIZED`
* config: `From<Into<usize>>` for `ReaderThreads`
Co-authored-by: Boog900 <boog900@tutanota.com>
* env: move mutual exclusion doc to backend
* free: update invariant doc
Co-authored-by: Boog900 <boog900@tutanota.com>
* Update database/src/service/mod.rs
Co-authored-by: Boog900 <boog900@tutanota.com>
* fix `[allow(unused_imports)] // docs`
* move DB filename from `helper/` -> `database/`
* config: use `DATABASE_FILENAME`
* config: add `db_file_path()`
* lib: add non-`service` usage invariant docs
* table: seal `Table` trait, impl for all `crate::tables`
* fix docs
* fix docs pt.2
---------
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-02-25 19:46:36 +00:00
|
|
|
|
2024-08-20 21:53:32 +00:00
|
|
|
let dir = &*CUPRATE_BLOCKCHAIN_DIR;
|
2024-05-29 01:18:30 +00:00
|
|
|
println!("cuprate_blockchain_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(".local/share/cuprate/blockchain"));
|
2024-08-22 01:09:07 +00:00
|
|
|
|
|
|
|
let dir = &*CUPRATE_TXPOOL_DIR;
|
|
|
|
println!("cuprate_txpool_dir: {dir:?}");
|
|
|
|
assert!(dir.ends_with(".local/share/cuprate/txpool"));
|
2024-02-21 17:54:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|