Skip to content

Commit

Permalink
feat: update redb to v2 (#2120)
Browse files Browse the repository at this point in the history
## Description

`redb` 2.0.0 was released:
https://github.com/cberner/redb/releases/tag/v2.0.0

most relevant for us: 
> 2.0.0 uses a new file format that optimizes len() to be constant time.
This means that it is not backwards compatible with 1.x. To upgrade,
consider using a pattern like that shown in the
[upgrade_v1_to_v2](https://github.com/cberner/redb/blob/222a37f4600588261b0983eebcd074bb69d6e5a0/tests/backward_compatibility.rs#L282-L299)
test.

and some nice API changes that will simplify the iroh-sync codebase (no
more ouroboros for self-refential structs needed!)

> * Remove lifetimes from read-only tables
> * Remove lifetime from WriteTransaction and ReadTransaction

and some further API changes, see the notes.

---

* [x] Update iroh-bytes to redb v2
* Did some crude search&replaces to remove now unneeded lifetime bounds.
Compiles now, let's see what test says.
* [x] Migration for iroh-bytes db
* Code adapted from here
https://github.com/n0-computer/migrate-bao-store-redb/blob/main/src/main.rs
* [x] Update  iroh-sync to redb v2
* This will be a bit more involved as iroh-bytes because we hit more API
changes, but also great because we can remove `ouroborous` because
iterators can now own a range
* [x] Migration for iroh-sync db

The migrations likely need a dependency to redb v1 to read the old
database, so at least for one release cycle we'll have to depend on both
redb v2 and v1.

## Notes & open questions

This currently includes an extra-safeguard by preserving the old
databases for sync and blobs as `docs.redb.backup-redb-v1` and
`blobs.db-backup-redb-v1` - do we want this or delete the backups after
successfull migration?


## Change checklist

- [x] Self-review.
- [ ] Documentation updates if relevant.
- [ ] Tests if relevant.

---------

Co-authored-by: Friedel Ziegelmayer <me@dignifiedquire.com>
  • Loading branch information
Frando and dignifiedquire committed Apr 9, 2024
1 parent 314c883 commit ceaf168
Show file tree
Hide file tree
Showing 14 changed files with 692 additions and 383 deletions.
85 changes: 15 additions & 70 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion iroh-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data-encoding = { version = "2.3.3", optional = true }
hex = "0.4.3"
multibase = { version = "0.9.1", optional = true }
postcard = { version = "1", default-features = false, features = ["alloc", "use-std", "experimental-derive"], optional = true }
redb = { version = "1.5.1", optional = true }
redb = { version = "2.0.0", optional = true }
serde = { version = "1", features = ["derive"] }
serde-error = "0.1.2"
thiserror = "1"
Expand Down
6 changes: 3 additions & 3 deletions iroh-base/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ pub struct HashAndFormat {
mod redb_support {
use super::{Hash, HashAndFormat};
use postcard::experimental::max_size::MaxSize;
use redb::{RedbKey, RedbValue};
use redb::{Key as RedbKey, Value as RedbValue};

impl RedbValue for Hash {
type SelfType<'a> = Self;
Expand Down Expand Up @@ -421,7 +421,7 @@ mod tests {
#[cfg(feature = "redb")]
#[test]
fn hash_redb() {
use redb::RedbValue;
use redb::Value as RedbValue;
let bytes: [u8; 32] = (0..32).collect::<Vec<_>>().as_slice().try_into().unwrap();
let hash = Hash::from(bytes);
assert_eq!(<Hash as RedbValue>::fixed_width(), Some(32));
Expand All @@ -446,7 +446,7 @@ mod tests {
#[cfg(feature = "redb")]
#[test]
fn hash_and_format_redb() {
use redb::RedbValue;
use redb::Value as RedbValue;
let hash_bytes: [u8; 32] = (0..32).collect::<Vec<_>>().as_slice().try_into().unwrap();
let hash = Hash::from(hash_bytes);
let haf = HashAndFormat::raw(hash);
Expand Down
6 changes: 4 additions & 2 deletions iroh-bytes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ postcard = { version = "1", default-features = false, features = ["alloc", "use-
quinn = "0.10"
rand = "0.8"
range-collections = "0.4.0"
redb = { version = "1.5.1", optional = true }
redb = { version = "2.0.0", optional = true }
redb_v1 = { package = "redb", version = "1.5.1", optional = true }
reflink-copy = { version = "0.1.8", optional = true }
self_cell = "1.0.1"
serde = { version = "1", features = ["derive"] }
serde-error = "0.1.2"
smallvec = { version = "1.10.0", features = ["serde", "const_new"] }
tempfile = { version = "3.10.0", optional = true }
thiserror = "1"
tokio = { version = "1", features = ["fs"] }
tokio-util = { version = "0.7", features = ["io-util", "io", "rt"] }
Expand All @@ -64,7 +66,7 @@ tempfile = "3.10.0"

[features]
default = ["fs-store"]
fs-store = ["reflink-copy", "redb"]
fs-store = ["reflink-copy", "redb", "redb_v1", "tempfile"]
downloader = ["iroh-net", "parking_lot", "tokio-util/time"]
metrics = ["iroh-metrics"]

Expand Down
16 changes: 13 additions & 3 deletions iroh-bytes/src/store/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,14 @@ use futures::{channel::oneshot, Stream, StreamExt};

use iroh_base::hash::{BlobFormat, Hash, HashAndFormat};
use iroh_io::AsyncSliceReader;
use redb::{AccessGuard, ReadableTable, StorageError};
use redb::{AccessGuard, DatabaseError, ReadableTable, StorageError};
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use tokio::io::AsyncWriteExt;
use tracing::trace_span;

mod import_flat_store;
mod migrate_redb_v1_v2;
mod tables;
#[doc(hidden)]
pub mod test_support;
Expand Down Expand Up @@ -307,7 +308,7 @@ impl EntryState {
}
}

impl redb::RedbValue for EntryState {
impl redb::Value for EntryState {
type SelfType<'a> = EntryState;

type AsBytes<'a> = SmallVec<[u8; 128]>;
Expand Down Expand Up @@ -1218,6 +1219,8 @@ pub(crate) enum ActorError {
Io(#[from] io::Error),
#[error("inconsistent database state: {0}")]
Inconsistent(String),
#[error("error during database migration: {0}")]
Migration(#[source] anyhow::Error),
}

impl From<ActorError> for io::Error {
Expand Down Expand Up @@ -1435,7 +1438,14 @@ impl Actor {
temp: Arc<RwLock<TempCounterMap>>,
rt: tokio::runtime::Handle,
) -> ActorResult<(Self, flume::Sender<ActorMessage>)> {
let db = redb::Database::create(path)?;
let db = match redb::Database::create(path) {
Ok(db) => db,
Err(DatabaseError::UpgradeRequired(1)) => {
migrate_redb_v1_v2::run(path).map_err(ActorError::Migration)?
}
Err(err) => return Err(err.into()),
};

let txn = db.begin_write()?;
// create tables and drop them just to create them.
let mut t = Default::default();
Expand Down
Loading

0 comments on commit ceaf168

Please sign in to comment.