Dataspace links into skeleton; seems to be working
This commit is contained in:
parent
6098c62604
commit
482f903149
126
src/dataspace.rs
126
src/dataspace.rs
|
@ -1,27 +1,31 @@
|
||||||
use super::V;
|
use super::V;
|
||||||
use super::ConnId;
|
use super::ConnId;
|
||||||
use super::packets;
|
use super::packets::{self, Assertion, EndpointName, Captures};
|
||||||
use super::skeleton;
|
use super::skeleton;
|
||||||
|
|
||||||
use preserves::value::Map;
|
use preserves::value::{self, Map, NestedValue};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
pub type DataspaceRef = Arc<RwLock<Dataspace>>;
|
pub type DataspaceRef = Arc<RwLock<Dataspace>>;
|
||||||
|
pub type DataspaceError = (String, V);
|
||||||
|
|
||||||
pub enum DataspaceError {
|
#[derive(Debug)]
|
||||||
|
struct Actor {
|
||||||
|
tx: UnboundedSender<packets::Out>,
|
||||||
|
endpoints: Map<EndpointName, ActorEndpoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DataspaceError> for std::io::Error {
|
#[derive(Debug)]
|
||||||
fn from(v: DataspaceError) -> Self {
|
struct ActorEndpoint {
|
||||||
panic!("No DataspaceErrors to convert!")
|
analysis_results: Option<skeleton::AnalysisResults>,
|
||||||
}
|
assertion: Assertion,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Dataspace {
|
pub struct Dataspace {
|
||||||
name: V,
|
name: V,
|
||||||
peers: Map<ConnId, UnboundedSender<packets::Out>>,
|
peers: Map<ConnId, Actor>,
|
||||||
index: skeleton::Index,
|
index: skeleton::Index,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,17 +40,117 @@ impl Dataspace {
|
||||||
|
|
||||||
pub fn register(&mut self, id: ConnId, tx: UnboundedSender<packets::Out>) {
|
pub fn register(&mut self, id: ConnId, tx: UnboundedSender<packets::Out>) {
|
||||||
assert!(!self.peers.contains_key(&id));
|
assert!(!self.peers.contains_key(&id));
|
||||||
self.peers.insert(id, tx);
|
self.peers.insert(id, Actor {
|
||||||
|
tx,
|
||||||
|
endpoints: Map::new(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deregister(&mut self, id: ConnId) {
|
pub fn deregister(&mut self, id: ConnId) {
|
||||||
self.peers.remove(&id);
|
let ac = self.peers.remove(&id).unwrap();
|
||||||
|
let mut outbound_turns: Map<ConnId, Vec<packets::Event>> = Map::new();
|
||||||
|
for (epname, ep) in ac.endpoints {
|
||||||
|
self.remove_endpoint(&mut outbound_turns, id, &epname, ep);
|
||||||
|
}
|
||||||
|
outbound_turns.remove(&id);
|
||||||
|
self.deliver_outbound_turns(outbound_turns);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn turn(&mut self, actions: Vec<packets::Action>) -> Result<(), DataspaceError> {
|
fn remove_endpoint(&mut self,
|
||||||
|
mut outbound_turns: &mut Map<ConnId, Vec<packets::Event>>,
|
||||||
|
id: ConnId,
|
||||||
|
epname: &EndpointName,
|
||||||
|
ep: ActorEndpoint)
|
||||||
|
{
|
||||||
|
let ActorEndpoint{ analysis_results, assertion } = ep;
|
||||||
|
if let Some(ar) = analysis_results {
|
||||||
|
self.index.remove_endpoint(&ar, skeleton::Endpoint {
|
||||||
|
connection: id,
|
||||||
|
name: epname.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
schedule_events(&mut outbound_turns,
|
||||||
|
self.index.remove((&assertion).into()),
|
||||||
|
|epname, cs| packets::Event::Del(epname, cs));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn turn(&mut self, id: ConnId, actions: Vec<packets::Action>) ->
|
||||||
|
Result<(), DataspaceError>
|
||||||
|
{
|
||||||
|
let mut outbound_turns: Map<ConnId, Vec<packets::Event>> = Map::new();
|
||||||
for a in actions {
|
for a in actions {
|
||||||
println!("Turn action: {:?}", &a);
|
println!("Turn action: {:?}", &a);
|
||||||
|
match a {
|
||||||
|
packets::Action::Assert(ref epname, ref assertion) => {
|
||||||
|
let ac = self.peers.get_mut(&id).unwrap();
|
||||||
|
if ac.endpoints.contains_key(&epname) {
|
||||||
|
return Err(("Duplicate endpoint name".to_string(),
|
||||||
|
value::to_value(a).unwrap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ar =
|
||||||
|
if let Some(fs) = assertion.value().as_simple_record("Observe", Some(1)) {
|
||||||
|
let ar = skeleton::analyze(&fs[0]);
|
||||||
|
let events = self.index.add_endpoint(&ar, skeleton::Endpoint {
|
||||||
|
connection: id,
|
||||||
|
name: epname.clone(),
|
||||||
|
});
|
||||||
|
outbound_turns.entry(id).or_insert_with(Vec::new).extend(events);
|
||||||
|
Some(ar)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
schedule_events(&mut outbound_turns,
|
||||||
|
self.index.insert(assertion.into()),
|
||||||
|
|epname, cs| packets::Event::Add(epname, cs));
|
||||||
|
|
||||||
|
ac.endpoints.insert(epname.clone(), ActorEndpoint {
|
||||||
|
analysis_results: ar,
|
||||||
|
assertion: assertion.clone()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
packets::Action::Clear(ref epname) => {
|
||||||
|
let ac = self.peers.get_mut(&id).unwrap();
|
||||||
|
match ac.endpoints.remove(epname) {
|
||||||
|
None => {
|
||||||
|
return Err(("Nonexistent endpoint name".to_string(),
|
||||||
|
value::to_value(a).unwrap()));
|
||||||
|
}
|
||||||
|
Some(ep) => {
|
||||||
|
self.remove_endpoint(&mut outbound_turns, id, epname, ep);
|
||||||
|
outbound_turns.entry(id).or_insert_with(Vec::new)
|
||||||
|
.push(packets::Event::End(epname.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packets::Action::Message(ref assertion) => {
|
||||||
|
schedule_events(&mut outbound_turns,
|
||||||
|
self.index.send(assertion.into()),
|
||||||
|
|epname, cs| packets::Event::Msg(epname, cs));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
self.deliver_outbound_turns(outbound_turns);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deliver_outbound_turns(&mut self, outbound_turns: Map<ConnId, Vec<packets::Event>>) {
|
||||||
|
for (target, events) in outbound_turns {
|
||||||
|
let _ = self.peers.get_mut(&target).unwrap().tx.try_send(packets::Out::Turn(events));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schedule_events<C>(outbound_turns: &mut Map<ConnId, Vec<packets::Event>>,
|
||||||
|
events: skeleton::Events,
|
||||||
|
ctor: C)
|
||||||
|
where C: Fn(EndpointName, Captures) -> packets::Event
|
||||||
|
{
|
||||||
|
for (eps, cs) in events {
|
||||||
|
for ep in eps {
|
||||||
|
outbound_turns.entry(ep.connection).or_insert_with(Vec::new)
|
||||||
|
.push(ctor(ep.name, cs.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
id += 1;
|
id += 1;
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
match peer::Peer::new(connid, stream).await.run(spaces).await {
|
match peer::Peer::new(connid, stream).await.run(spaces).await {
|
||||||
Ok(_) => (),
|
Ok(_) => println!("Connection {} ({:?}) terminated", connid, addr),
|
||||||
Err(e) => println!("Connection {:?} died with {:?}", addr, e),
|
Err(e) => println!("Connection {} ({:?}) died with {:?}", connid, addr, e),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub enum In {
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum Out {
|
pub enum Out {
|
||||||
Err(String),
|
Err(String, V),
|
||||||
Turn(Vec<Event>),
|
Turn(Vec<Event>),
|
||||||
Ping(),
|
Ping(),
|
||||||
Pong(),
|
Pong(),
|
||||||
|
|
36
src/peer.rs
36
src/peer.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use super::V;
|
||||||
use super::ConnId;
|
use super::ConnId;
|
||||||
use super::dataspace;
|
use super::dataspace;
|
||||||
use super::packets;
|
use super::packets;
|
||||||
|
@ -21,8 +22,8 @@ pub struct Peer {
|
||||||
space: Option<dataspace::DataspaceRef>,
|
space: Option<dataspace::DataspaceRef>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn err(s: &str) -> packets::Out {
|
fn err(s: &str, ctx: V) -> packets::Out {
|
||||||
packets::Out::Err(s.into())
|
packets::Out::Err(s.into(), ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Peer {
|
impl Peer {
|
||||||
|
@ -47,7 +48,7 @@ impl Peer {
|
||||||
} else {
|
} else {
|
||||||
let e: String = format!("Expected initial Connect, got {:?}", firstpacket);
|
let e: String = format!("Expected initial Connect, got {:?}", firstpacket);
|
||||||
println!("{:?}: {}", self.id, e);
|
println!("{:?}: {}", self.id, e);
|
||||||
self.frames.send(err(&e)).await?;
|
self.frames.send(err(&e, value::Value::from(false).wrap())).await?;
|
||||||
return Ok(())
|
return Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,14 +67,23 @@ impl Peer {
|
||||||
Ok(p) => {
|
Ok(p) => {
|
||||||
println!("{:?}: input {:?}", self.id, &p);
|
println!("{:?}: input {:?}", self.id, &p);
|
||||||
match p {
|
match p {
|
||||||
packets::In::Turn(actions) =>
|
packets::In::Turn(actions) => {
|
||||||
self.space.as_ref().unwrap().write().unwrap().turn(actions)?,
|
match self.space.as_ref().unwrap().write().unwrap()
|
||||||
|
.turn(self.id, actions)
|
||||||
|
{
|
||||||
|
Ok(()) => (),
|
||||||
|
Err((msg, ctx)) => {
|
||||||
|
to_send.push(err(&msg, ctx));
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
packets::In::Ping() =>
|
packets::In::Ping() =>
|
||||||
to_send.push(packets::Out::Pong()),
|
to_send.push(packets::Out::Pong()),
|
||||||
packets::In::Pong() =>
|
packets::In::Pong() =>
|
||||||
(),
|
(),
|
||||||
packets::In::Connect(dsname) => {
|
packets::In::Connect(_) => {
|
||||||
to_send.push(err("Unexpected Connect"));
|
to_send.push(err("Unexpected Connect", value::to_value(p).unwrap()));
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,12 +91,11 @@ impl Peer {
|
||||||
Err(packets::DecodeError::Read(value::decoder::Error::Eof)) => running = false,
|
Err(packets::DecodeError::Read(value::decoder::Error::Eof)) => running = false,
|
||||||
Err(packets::DecodeError::Read(value::decoder::Error::Io(e))) => return Err(e),
|
Err(packets::DecodeError::Read(value::decoder::Error::Io(e))) => return Err(e),
|
||||||
Err(packets::DecodeError::Read(value::decoder::Error::Syntax(s))) => {
|
Err(packets::DecodeError::Read(value::decoder::Error::Syntax(s))) => {
|
||||||
to_send.push(err(s));
|
to_send.push(err(s, value::Value::from(false).wrap()));
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
Err(packets::DecodeError::Parse(e, v)) => {
|
Err(packets::DecodeError::Parse(e, v)) => {
|
||||||
to_send.push(err(&format!(
|
to_send.push(err(&format!("Packet deserialization error: {}", e), v));
|
||||||
"Packet deserialization error ({}) decoding {:?}", e, v)));
|
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,15 +106,16 @@ impl Peer {
|
||||||
Some(msg) => to_send.push(msg),
|
Some(msg) => to_send.push(msg),
|
||||||
None => {
|
None => {
|
||||||
/* weird. */
|
/* weird. */
|
||||||
to_send.push(err("Outbound channel closed unexpectedly"));
|
to_send.push(err("Outbound channel closed unexpectedly",
|
||||||
|
value::Value::from(false).wrap()));
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for v in to_send {
|
for v in to_send {
|
||||||
if let packets::Out::Err(ref msg) = v {
|
if let packets::Out::Err(ref msg, ref ctx) = v {
|
||||||
println!("{:?}: connection crashed: {}", self.id, msg);
|
println!("{:?}: connection crashed: {}; context {:?}", self.id, msg, ctx);
|
||||||
} else {
|
} else {
|
||||||
println!("{:?}: output {:?}", self.id, &v);
|
println!("{:?}: output {:?}", self.id, &v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,21 +14,23 @@ use std::sync::Arc;
|
||||||
|
|
||||||
type Bag<A> = bag::BTreeBag<A>;
|
type Bag<A> = bag::BTreeBag<A>;
|
||||||
|
|
||||||
type Path = Vec<usize>;
|
pub type Path = Vec<usize>;
|
||||||
type Paths = Vec<Path>;
|
pub type Paths = Vec<Path>;
|
||||||
type Events = Vec<(Vec<Endpoint>, Captures)>;
|
pub type Events = Vec<(Vec<Endpoint>, Captures)>;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub struct Endpoint {
|
pub struct Endpoint {
|
||||||
connection: ConnId,
|
pub connection: ConnId,
|
||||||
name: EndpointName,
|
pub name: EndpointName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Skeleton {
|
pub enum Skeleton {
|
||||||
Blank,
|
Blank,
|
||||||
Guarded(Guard, Vec<Skeleton>)
|
Guarded(Guard, Vec<Skeleton>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct AnalysisResults {
|
pub struct AnalysisResults {
|
||||||
pub skeleton: Skeleton,
|
pub skeleton: Skeleton,
|
||||||
pub const_paths: Paths,
|
pub const_paths: Paths,
|
||||||
|
@ -48,7 +50,7 @@ impl Index {
|
||||||
Index{ all_assertions: Bag::new(), root: Node::new(Continuation::new(Set::new())) }
|
Index{ all_assertions: Bag::new(), root: Node::new(Continuation::new(Set::new())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_endpoint(&mut self, analysis_results: AnalysisResults, endpoint: Endpoint)
|
pub fn add_endpoint(&mut self, analysis_results: &AnalysisResults, endpoint: Endpoint)
|
||||||
-> Vec<Event>
|
-> Vec<Event>
|
||||||
{
|
{
|
||||||
let continuation = self.root.extend(&analysis_results.skeleton);
|
let continuation = self.root.extend(&analysis_results.skeleton);
|
||||||
|
@ -62,8 +64,8 @@ impl Index {
|
||||||
}
|
}
|
||||||
cvm
|
cvm
|
||||||
});
|
});
|
||||||
let capture_paths = analysis_results.capture_paths;
|
let capture_paths = &analysis_results.capture_paths;
|
||||||
let leaf = const_val_map.entry(analysis_results.const_vals).or_insert_with(Leaf::new);
|
let leaf = const_val_map.entry(analysis_results.const_vals.clone()).or_insert_with(Leaf::new);
|
||||||
let leaf_cached_assertions = &leaf.cached_assertions;
|
let leaf_cached_assertions = &leaf.cached_assertions;
|
||||||
let endpoints = leaf.endpoints_map.entry(capture_paths.clone()).or_insert_with(|| {
|
let endpoints = leaf.endpoints_map.entry(capture_paths.clone()).or_insert_with(|| {
|
||||||
let mut b = Bag::new();
|
let mut b = Bag::new();
|
||||||
|
@ -83,18 +85,18 @@ impl Index {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_endpoint(&mut self, analysis_results: AnalysisResults, endpoint: Endpoint) {
|
pub fn remove_endpoint(&mut self, analysis_results: &AnalysisResults, endpoint: Endpoint) {
|
||||||
let continuation = self.root.extend(&analysis_results.skeleton);
|
let continuation = self.root.extend(&analysis_results.skeleton);
|
||||||
if let Entry::Occupied(mut const_val_map_entry)
|
if let Entry::Occupied(mut const_val_map_entry)
|
||||||
= continuation.leaf_map.entry(analysis_results.const_paths)
|
= continuation.leaf_map.entry(analysis_results.const_paths.clone())
|
||||||
{
|
{
|
||||||
let const_val_map = const_val_map_entry.get_mut();
|
let const_val_map = const_val_map_entry.get_mut();
|
||||||
if let Entry::Occupied(mut leaf_entry)
|
if let Entry::Occupied(mut leaf_entry)
|
||||||
= const_val_map.entry(analysis_results.const_vals)
|
= const_val_map.entry(analysis_results.const_vals.clone())
|
||||||
{
|
{
|
||||||
let leaf = leaf_entry.get_mut();
|
let leaf = leaf_entry.get_mut();
|
||||||
if let Entry::Occupied(mut endpoints_entry)
|
if let Entry::Occupied(mut endpoints_entry)
|
||||||
= leaf.endpoints_map.entry(analysis_results.capture_paths)
|
= leaf.endpoints_map.entry(analysis_results.capture_paths.clone())
|
||||||
{
|
{
|
||||||
let endpoints = endpoints_entry.get_mut();
|
let endpoints = endpoints_entry.get_mut();
|
||||||
endpoints.endpoints.remove(&endpoint);
|
endpoints.endpoints.remove(&endpoint);
|
||||||
|
@ -112,15 +114,15 @@ impl Index {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(&mut self, v: CachedAssertion) -> Events {
|
pub fn insert(&mut self, v: CachedAssertion) -> Events {
|
||||||
self.adjust(v, 1)
|
self.adjust(v, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove(&mut self, v: CachedAssertion) -> Events {
|
pub fn remove(&mut self, v: CachedAssertion) -> Events {
|
||||||
self.adjust(v, -1)
|
self.adjust(v, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adjust(&mut self, outer_value: CachedAssertion, delta: bag::Count) -> Events {
|
pub fn adjust(&mut self, outer_value: CachedAssertion, delta: bag::Count) -> Events {
|
||||||
let mut outputs = Vec::new();
|
let mut outputs = Vec::new();
|
||||||
let net = self.all_assertions.change(outer_value.clone(), delta);
|
let net = self.all_assertions.change(outer_value.clone(), delta);
|
||||||
match net {
|
match net {
|
||||||
|
@ -155,7 +157,7 @@ impl Index {
|
||||||
outputs
|
outputs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&mut self, outer_value: CachedAssertion) -> Events {
|
pub fn send(&mut self, outer_value: CachedAssertion) -> Events {
|
||||||
let mut outputs = Vec::new();
|
let mut outputs = Vec::new();
|
||||||
Modification::new(
|
Modification::new(
|
||||||
false,
|
false,
|
||||||
|
@ -273,7 +275,7 @@ where FCont: FnMut(&mut Continuation, &CachedAssertion) -> (),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform(&mut self, n: &mut Node) {
|
fn perform(&mut self, n: &mut Node) {
|
||||||
self.node(n, &Stack::Item(self.outer_value_term, &Stack::Empty))
|
self.node(n, &Stack::Item(&Value::from(vec![self.outer_value_term.clone()]).wrap(), &Stack::Empty))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node(&mut self, n: &mut Node, term_stack: &Stack<&Assertion>) {
|
fn node(&mut self, n: &mut Node, term_stack: &Stack<&Assertion>) {
|
||||||
|
@ -417,6 +419,12 @@ pub enum CachedAssertion {
|
||||||
Unrestricted(Assertion),
|
Unrestricted(Assertion),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&Assertion> for CachedAssertion {
|
||||||
|
fn from(a: &Assertion) -> Self {
|
||||||
|
CachedAssertion::Unrestricted(a.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CachedAssertion {
|
impl CachedAssertion {
|
||||||
fn unscope(&self) -> &Assertion {
|
fn unscope(&self) -> &Assertion {
|
||||||
match self {
|
match self {
|
||||||
|
|
Loading…
Reference in New Issue