aboutsummaryrefslogtreecommitdiff
path: root/src/garage
diff options
context:
space:
mode:
authorAlex <alex@adnab.me>2020-11-21 16:01:26 +0100
committerAlex <alex@adnab.me>2020-11-21 16:01:26 +0100
commitb3814b15ccc233d7c4233b43816cce20db278f17 (patch)
treef37a1ce39bfae7c3f706162e186df4064635bd74 /src/garage
parent5dc304ac41c2ae0699fbdd56117b60c517a1ad39 (diff)
parenta8b3c8fd5898400d64310f61bb1a41dd5fefe5ea (diff)
downloadgarage-b3814b15ccc233d7c4233b43816cce20db278f17.tar.gz
garage-b3814b15ccc233d7c4233b43816cce20db278f17.zip
Merge pull request 'Use cleaner CRDT data types for objects to avoid accidents like #16' (#18) from feature/better-crdt into master
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/18
Diffstat (limited to 'src/garage')
-rw-r--r--src/garage/admin_rpc.rs128
1 files changed, 54 insertions, 74 deletions
diff --git a/src/garage/admin_rpc.rs b/src/garage/admin_rpc.rs
index 778e4a1d..a23d3e95 100644
--- a/src/garage/admin_rpc.rs
+++ b/src/garage/admin_rpc.rs
@@ -2,9 +2,9 @@ use std::sync::Arc;
use serde::{Deserialize, Serialize};
-use garage_util::data::*;
use garage_util::error::Error;
+use garage_table::crdt::CRDT;
use garage_table::*;
use garage_rpc::rpc_client::*;
@@ -79,25 +79,26 @@ impl AdminRpcHandler {
Ok(AdminRPC::BucketInfo(bucket))
}
BucketOperation::Create(query) => {
- let bucket = self.garage.bucket_table.get(&EmptyKey, &query.name).await?;
- if bucket.as_ref().filter(|b| !b.deleted).is_some() {
- return Err(Error::BadRPC(format!(
- "Bucket {} already exists",
- query.name
- )));
- }
- let new_time = match bucket {
- Some(b) => std::cmp::max(b.timestamp + 1, now_msec()),
- None => now_msec(),
+ let bucket = match self.garage.bucket_table.get(&EmptyKey, &query.name).await? {
+ Some(mut bucket) => {
+ if !bucket.is_deleted() {
+ return Err(Error::BadRPC(format!(
+ "Bucket {} already exists",
+ query.name
+ )));
+ }
+ bucket
+ .state
+ .update(BucketState::Present(crdt::LWWMap::new()));
+ bucket
+ }
+ None => Bucket::new(query.name.clone()),
};
- self.garage
- .bucket_table
- .insert(&Bucket::new(query.name.clone(), new_time, false, vec![]))
- .await?;
+ self.garage.bucket_table.insert(&bucket).await?;
Ok(AdminRPC::Ok(format!("Bucket {} was created.", query.name)))
}
BucketOperation::Delete(query) => {
- let bucket = self.get_existing_bucket(&query.name).await?;
+ let mut bucket = self.get_existing_bucket(&query.name).await?;
let objects = self
.garage
.object_table
@@ -112,25 +113,18 @@ impl AdminRpcHandler {
)));
}
// --- done checking, now commit ---
- for ak in bucket.authorized_keys() {
- if let Some(key) = self.garage.key_table.get(&EmptyKey, &ak.key_id).await? {
- if !key.deleted {
+ for (key_id, _, _) in bucket.authorized_keys() {
+ if let Some(key) = self.garage.key_table.get(&EmptyKey, key_id).await? {
+ if !key.deleted.get() {
self.update_key_bucket(key, &bucket.name, false, false)
.await?;
}
} else {
- return Err(Error::Message(format!("Key not found: {}", ak.key_id)));
+ return Err(Error::Message(format!("Key not found: {}", key_id)));
}
}
- self.garage
- .bucket_table
- .insert(&Bucket::new(
- query.name.clone(),
- std::cmp::max(bucket.timestamp + 1, now_msec()),
- true,
- vec![],
- ))
- .await?;
+ bucket.state.update(BucketState::Deleted);
+ self.garage.bucket_table.insert(&bucket).await?;
Ok(AdminRPC::Ok(format!("Bucket {} was deleted.", query.name)))
}
BucketOperation::Allow(query) => {
@@ -173,7 +167,7 @@ impl AdminRpcHandler {
.get_range(&EmptyKey, None, Some(DeletedFilter::NotDeleted), 10000)
.await?
.iter()
- .map(|k| (k.key_id.to_string(), k.name.to_string()))
+ .map(|k| (k.key_id.to_string(), k.name.get().clone()))
.collect::<Vec<_>>();
Ok(AdminRPC::KeyList(key_ids))
}
@@ -182,14 +176,13 @@ impl AdminRpcHandler {
Ok(AdminRPC::KeyInfo(key))
}
KeyOperation::New(query) => {
- let key = Key::new(query.name, vec![]);
+ let key = Key::new(query.name);
self.garage.key_table.insert(&key).await?;
Ok(AdminRPC::KeyInfo(key))
}
KeyOperation::Rename(query) => {
let mut key = self.get_existing_key(&query.key_id).await?;
- key.name_timestamp = std::cmp::max(key.name_timestamp + 1, now_msec());
- key.name = query.new_name;
+ key.name.update(query.new_name);
self.garage.key_table.insert(&key).await?;
Ok(AdminRPC::KeyInfo(key))
}
@@ -201,16 +194,14 @@ impl AdminRpcHandler {
)));
}
// --- done checking, now commit ---
- for ab in key.authorized_buckets().iter() {
- if let Some(bucket) =
- self.garage.bucket_table.get(&EmptyKey, &ab.bucket).await?
- {
- if !bucket.deleted {
+ for (ab_name, _, _) in key.authorized_buckets.items().iter() {
+ if let Some(bucket) = self.garage.bucket_table.get(&EmptyKey, ab_name).await? {
+ if !bucket.is_deleted() {
self.update_bucket_key(bucket, &key.key_id, false, false)
.await?;
}
} else {
- return Err(Error::Message(format!("Bucket not found: {}", ab.bucket)));
+ return Err(Error::Message(format!("Bucket not found: {}", ab_name)));
}
}
let del_key = Key::delete(key.key_id);
@@ -228,7 +219,7 @@ impl AdminRpcHandler {
.bucket_table
.get(&EmptyKey, bucket)
.await?
- .filter(|b| !b.deleted)
+ .filter(|b| !b.is_deleted())
.map(Ok)
.unwrap_or(Err(Error::BadRPC(format!(
"Bucket {} does not exist",
@@ -241,7 +232,7 @@ impl AdminRpcHandler {
.key_table
.get(&EmptyKey, id)
.await?
- .filter(|k| !k.deleted)
+ .filter(|k| !k.deleted.get())
.map(Ok)
.unwrap_or(Err(Error::BadRPC(format!("Key {} does not exist", id))))
}
@@ -253,23 +244,20 @@ impl AdminRpcHandler {
allow_read: bool,
allow_write: bool,
) -> Result<(), Error> {
- let timestamp = match bucket
- .authorized_keys()
- .iter()
- .find(|x| x.key_id == *key_id)
- {
- None => now_msec(),
- Some(ab) => std::cmp::max(ab.timestamp + 1, now_msec()),
- };
- bucket.clear_keys();
- bucket
- .add_key(AllowedKey {
- key_id: key_id.clone(),
- timestamp,
- allow_read,
- allow_write,
- })
- .unwrap();
+ if let BucketState::Present(ak) = bucket.state.get_mut() {
+ let old_ak = ak.take_and_clear();
+ ak.merge(&old_ak.update_mutator(
+ key_id.to_string(),
+ PermissionSet {
+ allow_read,
+ allow_write,
+ },
+ ));
+ } else {
+ return Err(Error::Message(format!(
+ "Bucket is deleted in update_bucket_key"
+ )));
+ }
self.garage.bucket_table.insert(&bucket).await?;
Ok(())
}
@@ -281,22 +269,14 @@ impl AdminRpcHandler {
allow_read: bool,
allow_write: bool,
) -> Result<(), Error> {
- let timestamp = match key
- .authorized_buckets()
- .iter()
- .find(|x| x.bucket == *bucket)
- {
- None => now_msec(),
- Some(ab) => std::cmp::max(ab.timestamp + 1, now_msec()),
- };
- key.clear_buckets();
- key.add_bucket(AllowedBucket {
- bucket: bucket.clone(),
- timestamp,
- allow_read,
- allow_write,
- })
- .unwrap();
+ let old_map = key.authorized_buckets.take_and_clear();
+ key.authorized_buckets.merge(&old_map.update_mutator(
+ bucket.clone(),
+ PermissionSet {
+ allow_read,
+ allow_write,
+ },
+ ));
self.garage.key_table.insert(&key).await?;
Ok(())
}