mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-11 14:56:53 +00:00
Refactor how things are migrated
This commit is contained in:
+16
-14
@@ -10,6 +10,7 @@ use garage_db::counted_tree_hack::CountedTree;
|
||||
|
||||
use garage_util::data::*;
|
||||
use garage_util::error::*;
|
||||
use garage_util::migrate::Migrate;
|
||||
|
||||
use garage_rpc::system::System;
|
||||
|
||||
@@ -219,7 +220,8 @@ where
|
||||
// data format, the messagepack encoding changed. In this case,
|
||||
// we also have to write the migrated value in the table and update
|
||||
// the associated Merkle tree entry.
|
||||
let new_bytes = rmp_to_vec_all_named(&new_entry)
|
||||
let new_bytes = new_entry
|
||||
.encode()
|
||||
.map_err(Error::RmpEncode)
|
||||
.map_err(db::TxError::Abort)?;
|
||||
let changed = Some(&new_bytes[..]) != old_bytes.as_deref();
|
||||
@@ -329,9 +331,9 @@ where
|
||||
Some(old_v) => {
|
||||
let mut entry = self.decode_entry(&old_v).map_err(db::TxError::Abort)?;
|
||||
entry.merge(ins);
|
||||
rmp_to_vec_all_named(&entry)
|
||||
entry.encode()
|
||||
}
|
||||
None => rmp_to_vec_all_named(ins),
|
||||
None => ins.encode(),
|
||||
};
|
||||
let new_entry = new_entry
|
||||
.map_err(Error::RmpEncode)
|
||||
@@ -351,18 +353,18 @@ where
|
||||
}
|
||||
|
||||
pub fn decode_entry(&self, bytes: &[u8]) -> Result<F::E, Error> {
|
||||
match rmp_serde::decode::from_read_ref::<_, F::E>(bytes) {
|
||||
Ok(x) => Ok(x),
|
||||
Err(e) => match F::try_migrate(bytes) {
|
||||
Some(x) => Ok(x),
|
||||
None => {
|
||||
warn!("Unable to decode entry of {}: {}", F::TABLE_NAME, e);
|
||||
for line in hexdump::hexdump_iter(bytes) {
|
||||
debug!("{}", line);
|
||||
}
|
||||
Err(e.into())
|
||||
match F::E::decode(bytes) {
|
||||
Some(x) => Ok(x),
|
||||
None => {
|
||||
error!("Unable to decode entry of {}", F::TABLE_NAME);
|
||||
for line in hexdump::hexdump_iter(bytes) {
|
||||
debug!("{}", line);
|
||||
}
|
||||
},
|
||||
Err(Error::Message(format!(
|
||||
"Unable to decode entry of {}",
|
||||
F::TABLE_NAME
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-11
@@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use garage_db as db;
|
||||
use garage_util::data::*;
|
||||
use garage_util::migrate::Migrate;
|
||||
|
||||
use crate::crdt::Crdt;
|
||||
|
||||
@@ -46,7 +47,7 @@ impl SortKey for FixedBytes32 {
|
||||
|
||||
/// Trait for an entry in a table. It must be sortable and partitionnable.
|
||||
pub trait Entry<P: PartitionKey, S: SortKey>:
|
||||
Crdt + PartialEq + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync
|
||||
Crdt + PartialEq + Clone + Migrate + Send + Sync + 'static
|
||||
{
|
||||
/// Get the key used to partition
|
||||
fn partition_key(&self) -> &P;
|
||||
@@ -65,23 +66,23 @@ pub trait TableSchema: Send + Sync + 'static {
|
||||
const TABLE_NAME: &'static str;
|
||||
|
||||
/// The partition key used in that table
|
||||
type P: PartitionKey + Clone + PartialEq + Serialize + for<'de> Deserialize<'de> + Send + Sync;
|
||||
type P: PartitionKey
|
||||
+ Clone
|
||||
+ PartialEq
|
||||
+ Serialize
|
||||
+ for<'de> Deserialize<'de>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static;
|
||||
/// The sort key used int that table
|
||||
type S: SortKey + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync;
|
||||
type S: SortKey + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static;
|
||||
|
||||
/// They type for an entry in that table
|
||||
type E: Entry<Self::P, Self::S>;
|
||||
|
||||
/// The type for a filter that can be applied to select entries
|
||||
/// (e.g. filter out deleted entries)
|
||||
type Filter: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync;
|
||||
|
||||
// Action to take if not able to decode current version:
|
||||
// try loading from an older version
|
||||
/// Try migrating an entry from an older version
|
||||
fn try_migrate(_bytes: &[u8]) -> Option<Self::E> {
|
||||
None
|
||||
}
|
||||
type Filter: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static;
|
||||
|
||||
/// Actions triggered by data changing in a table. If such actions
|
||||
/// include updates to the local database that should be applied
|
||||
|
||||
+3
-3
@@ -302,7 +302,7 @@ where
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
let root_ck_hash = hash_of::<MerkleNode>(&root_ck)?;
|
||||
let root_ck_hash = hash_of_merkle_node(&root_ck)?;
|
||||
|
||||
// Check if they have the same root checksum
|
||||
// If so, do nothing.
|
||||
@@ -468,7 +468,7 @@ where
|
||||
match message {
|
||||
SyncRpc::RootCkHash(range, h) => {
|
||||
let (_root_ck_key, root_ck) = self.get_root_ck(*range)?;
|
||||
let hash = hash_of::<MerkleNode>(&root_ck)?;
|
||||
let hash = hash_of_merkle_node(&root_ck)?;
|
||||
Ok(SyncRpc::RootCkDifferent(hash != *h))
|
||||
}
|
||||
SyncRpc::GetNode(k) => {
|
||||
@@ -622,7 +622,7 @@ impl<F: TableSchema + 'static, R: TableReplication + 'static> Worker for SyncWor
|
||||
|
||||
// ---- UTIL ----
|
||||
|
||||
fn hash_of<T: Serialize>(x: &T) -> Result<Hash, Error> {
|
||||
fn hash_of_merkle_node(x: &MerkleNode) -> Result<Hash, Error> {
|
||||
Ok(blake2sum(&rmp_to_vec_all_named(x)?[..]))
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -18,6 +18,7 @@ use garage_util::background::BackgroundRunner;
|
||||
use garage_util::data::*;
|
||||
use garage_util::error::Error;
|
||||
use garage_util::metrics::RecordDuration;
|
||||
use garage_util::migrate::Migrate;
|
||||
|
||||
use garage_rpc::system::System;
|
||||
use garage_rpc::*;
|
||||
@@ -122,7 +123,7 @@ where
|
||||
let hash = e.partition_key().hash();
|
||||
let who = self.data.replication.write_nodes(&hash);
|
||||
|
||||
let e_enc = Arc::new(ByteBuf::from(rmp_to_vec_all_named(e)?));
|
||||
let e_enc = Arc::new(ByteBuf::from(e.encode()?));
|
||||
let rpc = TableRpc::<F>::Update(vec![e_enc]);
|
||||
|
||||
self.system
|
||||
@@ -173,7 +174,7 @@ where
|
||||
let entry = entry.borrow();
|
||||
let hash = entry.partition_key().hash();
|
||||
let who = self.data.replication.write_nodes(&hash);
|
||||
let e_enc = Arc::new(ByteBuf::from(rmp_to_vec_all_named(entry)?));
|
||||
let e_enc = Arc::new(ByteBuf::from(entry.encode()?));
|
||||
for node in who {
|
||||
call_list.entry(node).or_default().push(e_enc.clone());
|
||||
}
|
||||
@@ -412,7 +413,7 @@ where
|
||||
// =============== UTILITY FUNCTION FOR CLIENT OPERATIONS ===============
|
||||
|
||||
async fn repair_on_read(&self, who: &[Uuid], what: F::E) -> Result<(), Error> {
|
||||
let what_enc = Arc::new(ByteBuf::from(rmp_to_vec_all_named(&what)?));
|
||||
let what_enc = Arc::new(ByteBuf::from(what.encode()?));
|
||||
self.system
|
||||
.rpc
|
||||
.try_call_many(
|
||||
|
||||
Reference in New Issue
Block a user