Skip to content

Commit

Permalink
Jscatena/vector clock types (#42)
Browse files Browse the repository at this point in the history
* skeleton of type state pattern in place

* Revert "skeleton of type state pattern in place"

This reverts commit 7d9c63f.

* Changes in place, accidentally set rustfmt too aggressive...

* getting there with chasing types through

* more chasing

* Hopefully done chasing changes through the system

* cargo fmt pass

* wasm addition

* JournalCheckpoint only holds Filesystem clock

* remove actor clock from drive initialization
  • Loading branch information
jscatena88 authored Jul 8, 2024
1 parent 416dc96 commit 5bcc637
Show file tree
Hide file tree
Showing 18 changed files with 751 additions and 295 deletions.
32 changes: 17 additions & 15 deletions src/codec/meta/actor_settings.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
use ecdsa::signature::rand_core::CryptoRngCore;
use futures::{AsyncWrite, AsyncWriteExt};
use winnow::binary::le_u8;
use winnow::token::take;
use winnow::Parser;
use winnow::{binary::le_u8, token::take, Parser};

use crate::codec::crypto::{
AccessKey, AsymLockedAccessKey, AsymLockedAccessKeyError, SigningKey, VerifyingKey,
use crate::codec::{
crypto::{AccessKey, AsymLockedAccessKey, AsymLockedAccessKeyError, SigningKey, VerifyingKey},
header::AccessMask,
meta::{UserAgent, VectorClockActorSnapshot},
ParserResult, Stream,
};
use crate::codec::header::AccessMask;
use crate::codec::meta::{UserAgent, VectorClock, VectorClockSnapshot};
use crate::codec::{ParserResult, Stream};

const KEY_PRESENT_BIT: u8 = 0b0000_0001;

#[derive(Clone, Debug)]
pub struct ActorSettings {
verifying_key: VerifyingKey,
vector_clock: VectorClock,
vector_clock: VectorClockActorSnapshot,

access_mask: AccessMask,
filesystem_key: Option<AsymLockedAccessKey>,
Expand Down Expand Up @@ -176,8 +174,12 @@ impl ActorSettings {
Ok(Some(open_key))
}

pub fn new(verifying_key: VerifyingKey, access_mask: AccessMask) -> Self {
let vector_clock = VectorClock::initialize();
pub fn new(
verifying_key: VerifyingKey,
access_mask: AccessMask,
vector_clock: VectorClockActorSnapshot,
) -> Self {
// Should we test that the actor id associated with the verifying key matches the actor id of the vector clock?
let user_agent = UserAgent::current();

Self {
Expand All @@ -195,7 +197,7 @@ impl ActorSettings {

pub fn parse(input: Stream) -> ParserResult<Self> {
let (input, verifying_key) = VerifyingKey::parse(input)?;
let (input, vector_clock) = VectorClock::parse(input)?;
let (input, vector_clock) = VectorClockActorSnapshot::parse(input)?;
let (input, access_mask) = AccessMask::parse(input)?;
let (input, user_agent) = UserAgent::parse(input)?;

Expand All @@ -220,7 +222,7 @@ impl ActorSettings {

pub const fn size() -> usize {
VerifyingKey::size()
+ VectorClock::size()
+ VectorClockActorSnapshot::size()
+ AccessMask::size()
+ UserAgent::size()
+ 3 * (1 + AsymLockedAccessKey::size())
Expand All @@ -234,8 +236,8 @@ impl ActorSettings {
self.user_agent.clone()
}

pub fn vector_clock(&self) -> VectorClockSnapshot {
VectorClockSnapshot::from(&self.vector_clock)
pub fn vector_clock(&self) -> VectorClockActorSnapshot {
self.vector_clock
}

pub fn verifying_key(&self) -> VerifyingKey {
Expand Down
12 changes: 7 additions & 5 deletions src/codec/meta/journal_checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

use futures::io::AsyncWrite;

use crate::codec::meta::{Cid, VectorClockSnapshot};
use crate::codec::meta::{Cid, VectorClockFilesystemSnapshot};
use crate::codec::{ParserResult, Stream};

#[derive(Clone, Debug, PartialEq)]
pub struct JournalCheckpoint {
merkle_root_cid: Cid,
vector: VectorClockSnapshot,
vector: VectorClockFilesystemSnapshot,
}

impl JournalCheckpoint {
Expand All @@ -27,7 +27,7 @@ impl JournalCheckpoint {

pub fn parse(input: Stream) -> ParserResult<Self> {
let (input, merkle_root_cid) = Cid::parse(input)?;
let (input, vector) = VectorClockSnapshot::parse(input)?;
let (input, vector) = VectorClockFilesystemSnapshot::parse(input)?;

let journal_checkpoint = JournalCheckpoint {
merkle_root_cid,
Expand All @@ -38,14 +38,16 @@ impl JournalCheckpoint {
}

pub const fn size() -> usize {
Cid::size() + VectorClockSnapshot::size()
Cid::size() + VectorClockFilesystemSnapshot::size()
}
}

#[cfg(test)]
mod tests {
use winnow::Partial;

use crate::codec::VectorClockFilesystem;

use super::*;

#[cfg(target_arch = "wasm32")]
Expand All @@ -56,7 +58,7 @@ mod tests {
async fn test_user_agent_roundtrip() {
let checkpoint = JournalCheckpoint {
merkle_root_cid: Cid::from([0; 32]),
vector: VectorClockSnapshot::from(0),
vector: (&VectorClockFilesystem::initialize()).as_snapshot(),
};

let mut buffer = Vec::with_capacity(JournalCheckpoint::size());
Expand Down
8 changes: 7 additions & 1 deletion src/codec/meta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ pub use journal_checkpoint::JournalCheckpoint;
pub use meta_key::MetaKey;
pub use permanent_id::PermanentId;
pub use user_agent::UserAgent;
pub use vector_clock::{VectorClock, VectorClockSnapshot};
pub use vector_clock::{
Actor as VectorClockActor, ActorSnapshot as VectorClockActorSnapshot,
Filesystem as VectorClockFilesystem,
FilesystemActorSnapshot as VectorClockFilesystemActorSnapshot,
FilesystemSnapshot as VectorClockFilesystemSnapshot, Node as VectorClockNode,
NodeActorSnapshot as VectorClockNodeActorSnapshot, NodeSnapshot as VectorClockNodeSnapshot,
};
93 changes: 93 additions & 0 deletions src/codec/meta/vector_clock/actor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use super::clock_inner::{ClockInner, ClockInnerSnapshot};
use crate::codec::{ActorId, ParserResult, Stream};

use futures::AsyncWrite;

#[derive(Debug, PartialEq, Clone)]
pub struct Actor {
id: ActorId,
clock: ClockInner,
}

impl Actor {
fn new(id: ActorId, clock: ClockInner) -> Self {
Self { id, clock }
}

pub fn initialize(actor_id: ActorId) -> Self {
Self::new(actor_id, ClockInner::initialize())
}

pub fn as_snapshot(&self) -> ActorSnapshot {
self.into()
}

pub async fn encode<W: AsyncWrite + Unpin + Send>(
&self,
writer: &mut W,
) -> std::io::Result<usize> {
ActorSnapshot::from(self).encode(writer).await
}

pub fn parse(input: Stream) -> ParserResult<Self> {
let (input, snapshot) = ActorSnapshot::parse(input)?;
Ok((input, Self::new(snapshot.id, snapshot.clock.into())))
}
}

impl From<ActorSnapshot> for Actor {
fn from(value: ActorSnapshot) -> Self {
Self::new(value.id, value.clock.into())
}
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct ActorSnapshot {
id: ActorId,
clock: ClockInnerSnapshot,
}

impl ActorSnapshot {
fn new(id: ActorId, clock: ClockInnerSnapshot) -> Self {
Self { id, clock }
}

pub const fn size() -> usize {
ActorId::size() + ClockInnerSnapshot::size()
}

pub async fn encode<W: AsyncWrite + Unpin + Send>(
&self,
writer: &mut W,
) -> std::io::Result<usize> {
self.id.encode(writer).await?;
self.clock.encode(writer).await
}

pub fn parse(input: Stream) -> ParserResult<Self> {
let (input, id) = ActorId::parse(input)?;
let (input, clock) = ClockInnerSnapshot::parse(input)?;
Ok((input, Self::new(id, clock)))
}
}

impl PartialOrd for ActorSnapshot {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for ActorSnapshot {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id).then(self.clock.cmp(&other.clock))
}
}

impl From<&Actor> for ActorSnapshot {
fn from(value: &Actor) -> Self {
Self {
id: value.id,
clock: (&value.clock).into(),
}
}
}
Loading

0 comments on commit 5bcc637

Please sign in to comment.