Gatekeeper service etc. Still missing attenuations etc. But almost there!
This commit is contained in:
parent
e5acc6a7a6
commit
d968eb34f2
|
@ -1,3 +1,3 @@
|
|||
´³bundle·µ³tunnelRelay„´³schema·³version‘³definitions·³Input´³orµµ±eof´³lit³eof„„µ±packet´³rec´³lit³packet„´³tupleµ´³named³bs´³atom³
|
||||
ByteString„„„„„„µ±segment´³rec´³lit³segment„´³tupleµ´³named³bs´³atom³
|
||||
ByteString„„„„„„„„„³embeddedType´³refµ³ EntityRef„³Ref„„„„„
|
||||
ByteString„„„„„„„„³Output´³rec´³lit³event„´³tupleµ´³named³oid´³refµ³sturdy„³Oid„„´³named³event´³refµ³internalProtocol„³Event„„„„„³SyncGc´³rec´³lit³sync-gc„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³
RelayProtocol´³orµµ±Input´³refµ„³Input„„µ±Output´³refµ„³Output„„µ±SyncGc´³refµ„³SyncGc„„„„„³embeddedType´³refµ³ EntityRef„³Ref„„„„„
|
|
@ -1,4 +1,8 @@
|
|||
version 1 .
|
||||
embeddedType EntityRef.Ref .
|
||||
|
||||
RelayProtocol = Input / Output / SyncGc .
|
||||
|
||||
Input = =eof / <packet @bs bytes> / <segment @bs bytes>.
|
||||
Output = <event @oid sturdy.Oid @event internalProtocol.Event>.
|
||||
SyncGc = <sync-gc @peer #!#t>.
|
||||
|
|
194
src/actor.rs
194
src/actor.rs
|
@ -1,12 +1,12 @@
|
|||
use futures::Future;
|
||||
pub use futures::future::BoxFuture;
|
||||
|
||||
pub use std::future::ready;
|
||||
|
||||
use super::Assertion;
|
||||
use super::ActorId;
|
||||
use super::Handle;
|
||||
use super::schemas::internal_protocol::*;
|
||||
use super::error::Error;
|
||||
use super::error::error;
|
||||
|
||||
use preserves::value::Domain;
|
||||
use preserves::value::IOValue;
|
||||
|
@ -22,7 +22,12 @@ use tokio::select;
|
|||
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use tracing::{Instrument, trace, error};
|
||||
use tracing;
|
||||
use tracing::Instrument;
|
||||
|
||||
pub type Assertion = super::schemas::dataspace::_Any;
|
||||
pub use super::schemas::internal_protocol::Handle;
|
||||
pub use super::schemas::internal_protocol::Oid;
|
||||
|
||||
pub type ActorResult = Result<(), Error>;
|
||||
pub type ActorHandle = tokio::task::JoinHandle<ActorResult>;
|
||||
|
@ -38,7 +43,7 @@ pub trait Entity: Send {
|
|||
Ok(())
|
||||
}
|
||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref>) -> ActorResult {
|
||||
t.message(peer, Assertion::new(true));
|
||||
t.message(&peer, Assertion::new(true));
|
||||
Ok(())
|
||||
}
|
||||
fn turn_end(&mut self, _t: &mut Activation) -> ActorResult {
|
||||
|
@ -88,7 +93,7 @@ pub struct Actor {
|
|||
exit_hooks: Vec<Oid>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Ref {
|
||||
pub relay: Mailbox,
|
||||
pub target: Oid,
|
||||
|
@ -97,6 +102,18 @@ pub struct Ref {
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
preserves_schema::support::lazy_static! {
|
||||
pub static ref INERT_REF: Arc<Ref> = {
|
||||
struct InertEntity;
|
||||
impl crate::actor::Entity for InertEntity {}
|
||||
let mut ac = Actor::new();
|
||||
let e = ac.create(InertEntity);
|
||||
ac.boot(tracing::info_span!(parent: None, "INERT_REF"),
|
||||
|t| Box::pin(ready(Ok(t.actor.shutdown()))));
|
||||
e
|
||||
};
|
||||
}
|
||||
|
||||
impl<'activation> Activation<'activation> {
|
||||
pub fn for_actor(actor: &'activation mut Actor) -> Self {
|
||||
Activation {
|
||||
|
@ -106,11 +123,11 @@ impl<'activation> Activation<'activation> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn assert<M>(&mut self, r: Arc<Ref>, a: M) -> Handle where M: Into<Assertion> {
|
||||
pub fn assert<M>(&mut self, r: &Arc<Ref>, a: M) -> Handle where M: Into<Assertion> {
|
||||
let handle = crate::next_handle();
|
||||
self.queue_for(&r).push((Arc::clone(&r), Event::Assert(Box::new(
|
||||
self.queue_for(r).push((Arc::clone(r), Event::Assert(Box::new(
|
||||
Assert { assertion: Assertion(a.into()), handle: handle.clone() }))));
|
||||
self.actor.outbound_assertions.insert(handle.clone(), r);
|
||||
self.actor.outbound_assertions.insert(handle.clone(), Arc::clone(r));
|
||||
handle
|
||||
}
|
||||
|
||||
|
@ -124,11 +141,15 @@ impl<'activation> Activation<'activation> {
|
|||
self.queue_for(&r).push((r, Event::Retract(Box::new(Retract { handle }))));
|
||||
}
|
||||
|
||||
pub fn message<M>(&mut self, r: Arc<Ref>, m: M) where M: Into<Assertion> {
|
||||
self.queue_for(&r).push((r, Event::Message(Box::new(
|
||||
pub fn message<M>(&mut self, r: &Arc<Ref>, m: M) where M: Into<Assertion> {
|
||||
self.queue_for(r).push((Arc::clone(r), Event::Message(Box::new(
|
||||
Message { body: Assertion(m.into()) }))))
|
||||
}
|
||||
|
||||
pub fn sync(&mut self, r: &Arc<Ref>, peer: Arc<Ref>) {
|
||||
self.queue_for(r).push((Arc::clone(r), Event::Sync(Box::new(Sync { peer }))));
|
||||
}
|
||||
|
||||
pub fn set_turn_end_flag(&mut self) {
|
||||
self.turn_end_revisit_flag = true;
|
||||
}
|
||||
|
@ -168,6 +189,9 @@ impl<'activation> Activation<'activation> {
|
|||
|
||||
impl<'activation> Drop for Activation<'activation> {
|
||||
fn drop(&mut self) {
|
||||
if self.turn_end_revisit_flag {
|
||||
panic!("turn_end_revisit_flag is set");
|
||||
}
|
||||
self.deliver()
|
||||
}
|
||||
}
|
||||
|
@ -221,9 +245,9 @@ impl Clone for Mailbox {
|
|||
queue_depth: Arc::clone(queue_depth),
|
||||
mailbox_count: Arc::clone(mailbox_count),
|
||||
};
|
||||
trace!(old_mailbox = debug(&self),
|
||||
new_mailbox = debug(&new_mailbox),
|
||||
new_mailbox_refcount = debug(_old_refcount + 1));
|
||||
// tracing::trace!(old_mailbox = debug(&self),
|
||||
// new_mailbox = debug(&new_mailbox),
|
||||
// new_mailbox_refcount = debug(_old_refcount + 1));
|
||||
new_mailbox
|
||||
}
|
||||
}
|
||||
|
@ -232,8 +256,8 @@ impl Drop for Mailbox {
|
|||
fn drop(&mut self) {
|
||||
let old_mailbox_refcount = self.mailbox_count.fetch_sub(1, Ordering::SeqCst);
|
||||
let new_mailbox_refcount = old_mailbox_refcount - 1;
|
||||
trace!(mailbox = debug(&self),
|
||||
new_mailbox_refcount);
|
||||
// tracing::trace!(mailbox = debug(&self),
|
||||
// new_mailbox_refcount);
|
||||
if new_mailbox_refcount == 0 {
|
||||
let _ = self.tx.send(SystemMessage::Release);
|
||||
()
|
||||
|
@ -245,7 +269,7 @@ impl Actor {
|
|||
pub fn new() -> Self {
|
||||
let (tx, rx) = unbounded_channel();
|
||||
let actor_id = crate::next_actor_id();
|
||||
trace!(id = actor_id, "Actor::new");
|
||||
// tracing::trace!(id = actor_id, "Actor::new");
|
||||
Actor {
|
||||
actor_id,
|
||||
tx,
|
||||
|
@ -260,6 +284,22 @@ impl Actor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_and_start<E: Entity + Send + 'static>(name: tracing::Span, e: E) -> Arc<Ref> {
|
||||
Self::create_and_start_rec(name, e, |_, _, _| ())
|
||||
}
|
||||
|
||||
pub fn create_and_start_rec<E: Entity + Send + 'static,
|
||||
F: FnOnce(&mut Self, &mut E, &Arc<Ref>) -> ()>(
|
||||
name: tracing::Span,
|
||||
e: E,
|
||||
f: F,
|
||||
) -> Arc<Ref> {
|
||||
let mut ac = Self::new();
|
||||
let r = ac.create_rec(e, f);
|
||||
ac.start(name);
|
||||
r
|
||||
}
|
||||
|
||||
pub fn id(&self) -> ActorId {
|
||||
self.actor_id
|
||||
}
|
||||
|
@ -273,8 +313,8 @@ impl Actor {
|
|||
queue_depth: Arc::clone(&self.queue_depth),
|
||||
mailbox_count: Arc::clone(&self.mailbox_count),
|
||||
};
|
||||
trace!(new_mailbox = debug(&new_mailbox),
|
||||
new_mailbox_refcount = debug(_old_refcount + 1));
|
||||
// tracing::trace!(new_mailbox = debug(&new_mailbox),
|
||||
// new_mailbox_refcount = debug(_old_refcount + 1));
|
||||
new_mailbox
|
||||
}
|
||||
|
||||
|
@ -284,22 +324,30 @@ impl Actor {
|
|||
}
|
||||
|
||||
pub fn create<E: Entity + Send + 'static>(&mut self, e: E) -> Arc<Ref> {
|
||||
let r = Ref {
|
||||
relay: self.mailbox(),
|
||||
target: crate::next_oid(),
|
||||
};
|
||||
self.oid_map.insert(r.target.clone(), Box::new(e));
|
||||
Arc::new(r)
|
||||
self.create_rec(e, |_, _, _| ())
|
||||
}
|
||||
|
||||
pub fn boot<F: 'static + Send + FnOnce(&mut Self) -> BoxFuture<ActorResult>>(
|
||||
pub fn create_rec<E: Entity + Send + 'static,
|
||||
F: FnOnce(&mut Self, &mut E, &Arc<Ref>) -> ()>(
|
||||
&mut self,
|
||||
mut e: E,
|
||||
f: F,
|
||||
) -> Arc<Ref> {
|
||||
let oid = crate::next_oid();
|
||||
let r = Arc::new(Ref { relay: self.mailbox(), target: oid.clone() });
|
||||
f(self, &mut e, &r);
|
||||
self.oid_map.insert(oid, Box::new(e));
|
||||
r
|
||||
}
|
||||
|
||||
pub fn boot<F: 'static + Send + for<'a> FnOnce(&'a mut Activation) -> BoxFuture<'a, ActorResult>>(
|
||||
mut self,
|
||||
name: tracing::Span,
|
||||
boot: F,
|
||||
) -> ActorHandle {
|
||||
let id = self.id();
|
||||
name.record("actor_id", &self.id());
|
||||
tokio::spawn(async move {
|
||||
trace!(id, "start");
|
||||
tracing::trace!("start");
|
||||
let result = self.run(boot).await;
|
||||
{
|
||||
let mut t = Activation::for_actor(&mut self);
|
||||
|
@ -308,9 +356,9 @@ impl Actor {
|
|||
None => (),
|
||||
Some((k, mut e)) => {
|
||||
if let Err(err) = e.exit_hook(&mut t, &result).await {
|
||||
tracing::warn!(err = debug(err),
|
||||
oid = debug(oid),
|
||||
"error in exit hook");
|
||||
tracing::error!(err = debug(err),
|
||||
oid = debug(oid),
|
||||
"error in exit hook");
|
||||
}
|
||||
t.actor.oid_map.insert(k, e);
|
||||
}
|
||||
|
@ -318,8 +366,11 @@ impl Actor {
|
|||
}
|
||||
}
|
||||
match &result {
|
||||
Ok(()) => trace!(id, "normal stop"),
|
||||
Err(e) => error!(id, "error stop: {}", e),
|
||||
Ok(()) => {
|
||||
tracing::trace!("normal stop");
|
||||
()
|
||||
}
|
||||
Err(e) => tracing::error!("error stop: {}", e),
|
||||
}
|
||||
result
|
||||
}.instrument(name))
|
||||
|
@ -329,32 +380,28 @@ impl Actor {
|
|||
self.boot(name, |_ac| Box::pin(ready(Ok(()))))
|
||||
}
|
||||
|
||||
async fn run<F: 'static + Send + FnOnce(&mut Self) -> BoxFuture<ActorResult>>(
|
||||
async fn run<F: 'static + Send + for<'a> FnOnce(&'a mut Activation) -> BoxFuture<'a, ActorResult>>(
|
||||
&mut self,
|
||||
boot: F,
|
||||
) -> ActorResult {
|
||||
let id = self.id();
|
||||
trace!(id, "boot");
|
||||
boot(self).await?;
|
||||
trace!(id, "run");
|
||||
let _id = self.id();
|
||||
// tracing::trace!(_id, "boot");
|
||||
boot(&mut Activation::for_actor(self)).await?;
|
||||
// tracing::trace!(_id, "run");
|
||||
loop {
|
||||
match self.rx.recv().await {
|
||||
None =>
|
||||
Err(Error {
|
||||
message: "Unexpected channel close".to_owned(),
|
||||
detail: _Any::new(false),
|
||||
})?,
|
||||
Err(error("Unexpected channel close", _Any::new(false)))?,
|
||||
Some(m) => {
|
||||
trace!(id, m = debug(&m), "system message");
|
||||
if self.handle(m)? {
|
||||
let should_stop = self.handle(m).await?;
|
||||
if should_stop {
|
||||
return Ok(());
|
||||
}
|
||||
// We would have a loop calling try_recv until it answers "no more at
|
||||
// present" here, to avoid decrementing queue_depth for every message
|
||||
// (instead zeroing it on queue empty - it only needs to be approximate),
|
||||
// but try_recv has been removed from mpsc at the time of writing. See
|
||||
// https://github.com/tokio-rs/tokio/issues/3350 .
|
||||
self.queue_depth.fetch_sub(1, Ordering::Relaxed);
|
||||
// https://github.com/tokio-rs/tokio/issues/3350 . (***)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -364,11 +411,14 @@ impl Actor {
|
|||
self.exit_hooks.push(oid.clone())
|
||||
}
|
||||
|
||||
fn handle(&mut self, m: SystemMessage) -> Result<bool, Error> {
|
||||
async fn handle(&mut self, m: SystemMessage) -> Result<bool, Error> {
|
||||
match m {
|
||||
SystemMessage::Release =>
|
||||
Ok(true),
|
||||
SystemMessage::Release => {
|
||||
tracing::trace!("SystemMessage::Release");
|
||||
Ok(true)
|
||||
}
|
||||
SystemMessage::ReleaseOid(oid) => {
|
||||
tracing::trace!("SystemMessage::ReleaseOid({:?})", &oid);
|
||||
self.oid_map.remove(&oid);
|
||||
Ok(false)
|
||||
}
|
||||
|
@ -399,13 +449,16 @@ impl Actor {
|
|||
revisit_oids.push(oid);
|
||||
}
|
||||
}
|
||||
for oid in revisit_oids {
|
||||
for oid in revisit_oids.into_iter() {
|
||||
t.with_oid(&oid, |_| Ok(()), |t, e| e.turn_end(t))?;
|
||||
}
|
||||
t.actor.queue_depth.fetch_sub(1, Ordering::Relaxed); // see (***) in this file
|
||||
Ok(false)
|
||||
}
|
||||
SystemMessage::Crash(e) =>
|
||||
SystemMessage::Crash(e) => {
|
||||
tracing::trace!("SystemMessage::Crash({:?})", &e);
|
||||
Err(e)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,26 +466,29 @@ impl Actor {
|
|||
&mut self,
|
||||
name: tracing::Span,
|
||||
boot: F,
|
||||
) -> ActorHandle {
|
||||
let id = self.id();
|
||||
) {
|
||||
let mailbox = self.mailbox();
|
||||
let token = CancellationToken::new();
|
||||
let task_id = self.next_task_id;
|
||||
self.next_task_id += 1;
|
||||
let handle = {
|
||||
name.record("task_id", &task_id);
|
||||
{
|
||||
let token = token.clone();
|
||||
tokio::spawn(async move {
|
||||
trace!(id, task_id, "linked task start");
|
||||
tracing::trace!(task_id, "linked task start");
|
||||
select! {
|
||||
_ = token.cancelled() => {
|
||||
trace!(id, task_id, "linked task cancelled");
|
||||
tracing::trace!(task_id, "linked task cancelled");
|
||||
Ok(())
|
||||
}
|
||||
result = boot => {
|
||||
match &result {
|
||||
Ok(()) => trace!(id, task_id, "linked task normal stop"),
|
||||
Ok(()) => {
|
||||
tracing::trace!(task_id, "linked task normal stop");
|
||||
()
|
||||
}
|
||||
Err(e) => {
|
||||
error!(id, task_id, "linked task error: {}", e);
|
||||
tracing::error!(task_id, "linked task error: {}", e);
|
||||
let _ = mailbox.tx.send(SystemMessage::Crash(e.clone()));
|
||||
()
|
||||
}
|
||||
|
@ -440,10 +496,9 @@ impl Actor {
|
|||
result
|
||||
}
|
||||
}
|
||||
}.instrument(name))
|
||||
};
|
||||
}.instrument(name));
|
||||
}
|
||||
self.linked_tasks.insert(task_id, token);
|
||||
handle
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,8 +511,10 @@ impl Drop for Actor {
|
|||
let to_clear = std::mem::take(&mut self.outbound_assertions);
|
||||
let mut t = Activation::for_actor(self);
|
||||
for (handle, r) in to_clear.into_iter() {
|
||||
tracing::trace!(h = debug(&handle), "retract on termination");
|
||||
t.retract_known_ref(r, handle);
|
||||
}
|
||||
tracing::trace!("Actor::drop");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,6 +524,12 @@ impl Ref {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Ref {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
write!(f, "⌜{}:{}⌝", self.relay.actor_id, self.target.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Ref {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.relay.tx.send(SystemMessage::ReleaseOid(self.target.clone()));
|
||||
|
@ -488,3 +551,14 @@ impl std::convert::From<&Ref> for IOValue {
|
|||
panic!("Attempted to deserialize Ref via IOValue");
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! name {
|
||||
() => {tracing::info_span!(actor_id = tracing::field::Empty,
|
||||
task_id = tracing::field::Empty,
|
||||
oid = tracing::field::Empty)};
|
||||
($($item:tt)*) => {tracing::info_span!($($item)*,
|
||||
actor_id = tracing::field::Empty,
|
||||
task_id = tracing::field::Empty,
|
||||
oid = tracing::field::Empty)}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
use futures::SinkExt;
|
||||
use futures::StreamExt;
|
||||
|
||||
use preserves::value::Map;
|
||||
use preserves::value::NestedValue;
|
||||
use preserves::value::Value;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::future::ready;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
||||
use structopt::StructOpt; // for from_args in main
|
||||
|
||||
use syndicate::actor::*;
|
||||
use syndicate::dataspace::*;
|
||||
use syndicate::during::DuringEntity;
|
||||
use syndicate::during::DuringResult;
|
||||
use syndicate::error::Error;
|
||||
use syndicate::error::error;
|
||||
use syndicate::config;
|
||||
use syndicate::relay;
|
||||
use syndicate::schemas::internal_protocol::_Any;
|
||||
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::net::TcpStream;
|
||||
|
@ -71,19 +80,29 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
trace!("startup");
|
||||
|
||||
let ds = {
|
||||
let mut ac = Actor::new();
|
||||
let ds = ac.create(Dataspace::new());
|
||||
daemons.push(ac.start(tracing::info_span!("dataspace")));
|
||||
ds
|
||||
};
|
||||
let ds = Actor::create_and_start(syndicate::name!("dataspace"), Dataspace::new());
|
||||
let gateway = Actor::create_and_start(syndicate::name!("gateway"),
|
||||
DuringEntity::new(Arc::clone(&ds), handle_resolve));
|
||||
{
|
||||
let ds = Arc::clone(&ds);
|
||||
Actor::new().boot(syndicate::name!("rootcap"), |t| Box::pin(async move {
|
||||
use syndicate::schemas::gatekeeper;
|
||||
t.assert(&ds, &gatekeeper::Bind {
|
||||
oid: _Any::new("syndicate"),
|
||||
key: vec![0; 16],
|
||||
target: ds.clone(),
|
||||
});
|
||||
Ok(())
|
||||
}));
|
||||
}
|
||||
|
||||
for port in config.ports.clone() {
|
||||
let ds = Arc::clone(&ds);
|
||||
let gateway = Arc::clone(&gateway);
|
||||
let config = Arc::clone(&config);
|
||||
let mut ac = Actor::new();
|
||||
ac.linked_task(tracing::info_span!("tcp", port), run_listener(ds, port, config));
|
||||
daemons.push(ac.start(tracing::info_span!("tcp", port)));
|
||||
daemons.push(Actor::new().boot(
|
||||
syndicate::name!("tcp", port),
|
||||
move |t| Box::pin(ready(Ok(t.actor.linked_task(syndicate::name!("listener"),
|
||||
run_listener(gateway, port, config)))))));
|
||||
}
|
||||
|
||||
futures::future::join_all(daemons).await;
|
||||
|
@ -93,7 +112,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
fn message_error<E: std::fmt::Display>(e: E) -> Error {
|
||||
error(&e.to_string(), false)
|
||||
error(&e.to_string(), _Any::new(false))
|
||||
}
|
||||
|
||||
fn extract_binary_packets(
|
||||
|
@ -117,9 +136,9 @@ fn extract_binary_packets(
|
|||
}
|
||||
|
||||
async fn run_connection(
|
||||
ac: &mut Actor,
|
||||
t: &mut Activation<'_>,
|
||||
stream: TcpStream,
|
||||
ds: Arc<Ref>,
|
||||
gateway: Arc<Ref>,
|
||||
addr: std::net::SocketAddr,
|
||||
config: Arc<config::ServerConfig>,
|
||||
) -> ActorResult {
|
||||
|
@ -141,21 +160,69 @@ async fn run_connection(
|
|||
(relay::Input::Bytes(Box::pin(i)), relay::Output::Bytes(Box::pin(o)))
|
||||
}
|
||||
}
|
||||
0 => Err(error("closed before starting", false))?,
|
||||
0 => Err(error("closed before starting", _Any::new(false)))?,
|
||||
_ => unreachable!()
|
||||
};
|
||||
Ok(relay::TunnelRelay::run(ac, i, o)?)
|
||||
relay::TunnelRelay::run(t, i, o, Some(gateway), None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn run_listener(ds: Arc<Ref>, port: u16, config: Arc<config::ServerConfig>) -> ActorResult {
|
||||
async fn run_listener(
|
||||
gateway: Arc<Ref>,
|
||||
port: u16,
|
||||
config: Arc<config::ServerConfig>,
|
||||
) -> ActorResult {
|
||||
let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await?;
|
||||
loop {
|
||||
let (stream, addr) = listener.accept().await?;
|
||||
let ds = Arc::clone(&ds);
|
||||
let gateway = Arc::clone(&gateway);
|
||||
let config = Arc::clone(&config);
|
||||
let ac = Actor::new();
|
||||
let id = ac.id();
|
||||
ac.boot(tracing::info_span!(parent: None, "connection", id),
|
||||
move |ac| Box::pin(run_connection(ac, stream, ds, addr, config)));
|
||||
ac.boot(syndicate::name!(parent: None, "connection"),
|
||||
move |t| Box::pin(run_connection(t, stream, gateway, addr, config)));
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
fn handle_resolve(ds: &mut Arc<Ref>, t: &mut Activation, a: Assertion) -> DuringResult<Arc<Ref>> {
|
||||
use syndicate::schemas::dataspace;
|
||||
use syndicate::schemas::dataspace_patterns as p;
|
||||
use syndicate::schemas::gatekeeper;
|
||||
match gatekeeper::Resolve::try_from(&a) {
|
||||
Err(_) => Ok(None),
|
||||
Ok(gatekeeper::Resolve { sturdyref, observer }) => {
|
||||
// TODO: codegen plugin to generate pattern constructors
|
||||
let handler = t.actor.create(DuringEntity::new(observer, |observer, t, a| {
|
||||
let bindings = a.value().to_sequence()?;
|
||||
let key = bindings[0].value().to_bytestring()?;
|
||||
let target = bindings[1].value().to_embedded()?;
|
||||
tracing::trace!(key = debug(&key), target = debug(&target), "resolved!");
|
||||
// TODO attenuation and validity checks
|
||||
let h = t.assert(observer, _Any::domain(Arc::clone(target)));
|
||||
Ok(Some(Box::new(|_observer, t| Ok(t.retract(h)))))
|
||||
}));
|
||||
let oh = t.assert(ds, &dataspace::Observe {
|
||||
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
|
||||
ctor: Box::new(p::CRec {
|
||||
label: Value::symbol("bind").wrap(),
|
||||
arity: 3.into(),
|
||||
}),
|
||||
members: Map::from_iter(vec![
|
||||
(0.into(), p::Pattern::DLit(Box::new(p::DLit { value: sturdyref.oid }))),
|
||||
(1.into(), p::Pattern::DBind(Box::new(p::DBind {
|
||||
name: "key".to_owned(),
|
||||
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)),
|
||||
}))),
|
||||
(2.into(), p::Pattern::DBind(Box::new(p::DBind {
|
||||
name: "target".to_owned(),
|
||||
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)),
|
||||
}))),
|
||||
].into_iter())
|
||||
})),
|
||||
observer: handler,
|
||||
});
|
||||
Ok(Some(Box::new(|_ds, t| Ok(t.retract(oh)))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use super::Assertion;
|
||||
use super::Handle;
|
||||
use super::skeleton;
|
||||
use super::actor::*;
|
||||
use super::schemas::dataspace::*;
|
||||
|
@ -70,7 +68,7 @@ impl Dataspace {
|
|||
|
||||
impl Entity for Dataspace {
|
||||
fn assert(&mut self, t: &mut Activation, a: Assertion, h: Handle) -> ActorResult {
|
||||
tracing::trace!(action = debug(&a), "assert");
|
||||
tracing::trace!(assertion = debug(&a), handle = debug(&h), "assert");
|
||||
|
||||
let old_assertions = self.index.assertion_count();
|
||||
self.index.insert(t, &a);
|
||||
|
@ -88,9 +86,11 @@ impl Entity for Dataspace {
|
|||
}
|
||||
|
||||
fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult {
|
||||
tracing::trace!(handle = debug(&h), "retract");
|
||||
|
||||
if let Some((a, maybe_o)) = self.handle_map.remove(&h) {
|
||||
if let Some(o) = maybe_o {
|
||||
self.index.remove_observer(o.pattern, &o.observer);
|
||||
self.index.remove_observer(t, o.pattern, &o.observer);
|
||||
self.churn.observers_removed += 1;
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,8 @@ impl Entity for Dataspace {
|
|||
}
|
||||
|
||||
fn message(&mut self, t: &mut Activation, m: Assertion) -> ActorResult {
|
||||
tracing::trace!(body = debug(&m), "message");
|
||||
|
||||
self.index.send(t, &m, &mut self.churn.messages_delivered);
|
||||
self.churn.messages_injected += 1;
|
||||
Ok(())
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
use crate::actor::*;
|
||||
use crate::error::Error;
|
||||
|
||||
use preserves::value::Map;
|
||||
|
||||
pub type DuringRetractionHandler<T> = Box<dyn Send + FnOnce(&mut T, &mut Activation) -> ActorResult>;
|
||||
pub struct During<T>(Map<Handle, DuringRetractionHandler<T>>);
|
||||
|
||||
pub type DuringResult<E> =
|
||||
Result<Option<Box<dyn 'static + Send + FnOnce(&mut E, &mut Activation) -> ActorResult>>,
|
||||
Error>;
|
||||
|
||||
pub struct DuringEntity<E, Fa>
|
||||
where
|
||||
E: 'static + Send,
|
||||
Fa: Send + FnMut(&mut E, &mut Activation, Assertion) -> DuringResult<E>,
|
||||
{
|
||||
state: E,
|
||||
handler: Fa,
|
||||
during: During<E>,
|
||||
}
|
||||
|
||||
impl<T> During<T> {
|
||||
pub fn new() -> Self {
|
||||
During(Map::new())
|
||||
}
|
||||
|
||||
pub fn await_retraction<F: 'static + Send + FnOnce(&mut T, &mut Activation) -> ActorResult>(
|
||||
&mut self,
|
||||
h: Handle,
|
||||
f: F,
|
||||
) -> ActorResult {
|
||||
self.0.insert(h, Box::new(f));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn retract(&mut self, h: Handle) -> DuringRetractionHandler<T> {
|
||||
self.0.remove(&h).unwrap_or_else(|| Box::new(|_, _| Ok(())))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, Fa> DuringEntity<E, Fa>
|
||||
where
|
||||
E: 'static + Send,
|
||||
Fa: Send + FnMut(&mut E, &mut Activation, Assertion) -> DuringResult<E>,
|
||||
{
|
||||
pub fn new(state: E, handler: Fa) -> Self {
|
||||
DuringEntity {
|
||||
state,
|
||||
handler,
|
||||
during: During::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, Fa> Entity for DuringEntity<E, Fa>
|
||||
where
|
||||
E: 'static + Send,
|
||||
Fa: Send + FnMut(&mut E, &mut Activation, Assertion) -> DuringResult<E>,
|
||||
{
|
||||
fn assert(&mut self, t: &mut Activation, a: Assertion, h: Handle) -> ActorResult {
|
||||
match (self.handler)(&mut self.state, t, a)? {
|
||||
Some(f) => self.during.await_retraction(h, f),
|
||||
None => Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult {
|
||||
self.during.retract(h)(&mut self.state, t)
|
||||
}
|
||||
}
|
16
src/error.rs
16
src/error.rs
|
@ -3,7 +3,6 @@ pub use super::schemas::internal_protocol::_Ptr;
|
|||
pub use super::schemas::internal_protocol::Error;
|
||||
|
||||
use preserves::value::NestedValue;
|
||||
use preserves::value::Value;
|
||||
use preserves_schema::support::ParseError;
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
@ -14,28 +13,33 @@ impl std::fmt::Display for Error {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn error<Detail>(message: &str, detail: Detail) -> Error where Value<_Any, _Ptr>: From<Detail> {
|
||||
pub fn error<Detail>(message: &str, detail: Detail) -> Error where _Any: From<Detail> {
|
||||
Error {
|
||||
message: message.to_owned(),
|
||||
detail: _Any::new(detail),
|
||||
detail: detail.into(),
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Error {
|
||||
fn from(v: &str) -> Self {
|
||||
error(v, false)
|
||||
error(v, _Any::new(false))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(v: std::io::Error) -> Self {
|
||||
error(&format!("{}", v), false)
|
||||
error(&format!("{}", v), _Any::new(false))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseError> for Error {
|
||||
fn from(v: ParseError) -> Self {
|
||||
error(&format!("{}", v), false)
|
||||
error(&format!("{}", v), _Any::new(false))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<preserves::error::Error> for Error {
|
||||
fn from(v: preserves::error::Error) -> Self {
|
||||
error(&format!("{}", v), _Any::new(false))
|
||||
}
|
||||
}
|
||||
|
|
29
src/lib.rs
29
src/lib.rs
|
@ -1,42 +1,47 @@
|
|||
pub use preserves::value;
|
||||
|
||||
pub use schemas::internal_protocol::Handle;
|
||||
pub use schemas::internal_protocol::Oid;
|
||||
|
||||
use std::sync::atomic::AtomicU64;
|
||||
use std::sync::atomic::Ordering;
|
||||
use actor::Handle;
|
||||
use actor::Oid;
|
||||
|
||||
pub mod actor;
|
||||
pub mod bag;
|
||||
pub mod config;
|
||||
pub mod dataspace;
|
||||
pub mod during;
|
||||
pub mod error;
|
||||
pub mod pattern;
|
||||
pub mod relay;
|
||||
pub mod schemas;
|
||||
pub mod skeleton;
|
||||
pub mod tracer;
|
||||
|
||||
pub type Assertion = schemas::dataspace::_Any;
|
||||
pub use tracer::tracer;
|
||||
pub use tracer::tracer_top;
|
||||
|
||||
pub type ActorId = u64;
|
||||
static NEXT_ACTOR_ID: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
const BUMP_AMOUNT: u8 = 10;
|
||||
|
||||
static NEXT_ACTOR_ID: AtomicU64 = AtomicU64::new(1);
|
||||
pub fn next_actor_id() -> ActorId {
|
||||
NEXT_ACTOR_ID.fetch_add(1, Ordering::Relaxed)
|
||||
NEXT_ACTOR_ID.fetch_add(BUMP_AMOUNT.into(), Ordering::Relaxed)
|
||||
}
|
||||
|
||||
static NEXT_OID: AtomicU64 = AtomicU64::new(0);
|
||||
static NEXT_OID: AtomicU64 = AtomicU64::new(2);
|
||||
pub fn next_oid() -> Oid {
|
||||
Oid(value::signed_integer::SignedInteger::from(
|
||||
NEXT_OID.fetch_add(1, Ordering::Relaxed) as u128))
|
||||
NEXT_OID.fetch_add(BUMP_AMOUNT.into(), Ordering::Relaxed) as u128))
|
||||
}
|
||||
|
||||
static NEXT_HANDLE: AtomicU64 = AtomicU64::new(0);
|
||||
static NEXT_HANDLE: AtomicU64 = AtomicU64::new(3);
|
||||
pub fn next_handle() -> Handle {
|
||||
Handle(value::signed_integer::SignedInteger::from(
|
||||
NEXT_HANDLE.fetch_add(1, Ordering::Relaxed) as u128))
|
||||
NEXT_HANDLE.fetch_add(BUMP_AMOUNT.into(), Ordering::Relaxed) as u128))
|
||||
}
|
||||
|
||||
static NEXT_MAILBOX_ID: AtomicU64 = AtomicU64::new(0);
|
||||
static NEXT_MAILBOX_ID: AtomicU64 = AtomicU64::new(4);
|
||||
pub fn next_mailbox_id() -> u64 {
|
||||
NEXT_MAILBOX_ID.fetch_add(1, Ordering::Relaxed)
|
||||
NEXT_MAILBOX_ID.fetch_add(BUMP_AMOUNT.into(), Ordering::Relaxed)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::Assertion;
|
||||
use crate::actor::Assertion;
|
||||
use crate::schemas::dataspace_patterns::*;
|
||||
|
||||
use preserves::value::NestedValue;
|
||||
|
|
398
src/relay.rs
398
src/relay.rs
|
@ -3,7 +3,9 @@ use bytes::BytesMut;
|
|||
|
||||
use crate::actor::*;
|
||||
use crate::error::Error;
|
||||
use crate::error::error;
|
||||
use crate::schemas::internal_protocol::*;
|
||||
use crate::schemas::sturdy;
|
||||
use crate::schemas::tunnel_relay;
|
||||
|
||||
use futures::Sink;
|
||||
|
@ -17,40 +19,45 @@ use preserves::value::DomainDecode;
|
|||
use preserves::value::DomainEncode;
|
||||
use preserves::value::IOValue;
|
||||
use preserves::value::Map;
|
||||
use preserves::value::NestedValue;
|
||||
use preserves::value::NoEmbeddedDomainCodec;
|
||||
use preserves::value::PackedReader;
|
||||
use preserves::value::PackedWriter;
|
||||
use preserves::value::Reader;
|
||||
use preserves::value::Writer;
|
||||
use preserves_schema::support::lazy_static;
|
||||
use preserves::value::signed_integer::SignedInteger;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use tokio::io::AsyncRead;
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::io::AsyncWrite;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver};
|
||||
|
||||
use tracing;
|
||||
|
||||
struct WireSymbol {
|
||||
oid: Oid,
|
||||
oid: sturdy::Oid,
|
||||
obj: Arc<Ref>,
|
||||
ref_count: atomic::AtomicUsize,
|
||||
ref_count: AtomicUsize,
|
||||
}
|
||||
|
||||
struct Membrane {
|
||||
oid_map: Map<Oid, Arc<WireSymbol>>,
|
||||
oid_map: Map<sturdy::Oid, Arc<WireSymbol>>,
|
||||
ref_map: Map<Arc<Ref>, Arc<WireSymbol>>,
|
||||
}
|
||||
|
||||
struct Membranes {
|
||||
exported: Membrane,
|
||||
imported: Membrane,
|
||||
next_export_oid: usize,
|
||||
}
|
||||
|
||||
pub enum Input {
|
||||
|
@ -66,32 +73,29 @@ pub enum Output {
|
|||
// There are other kinds of relay. This one has exactly two participants connected to each other.
|
||||
pub struct TunnelRelay
|
||||
{
|
||||
self_ref: Arc<Ref>,
|
||||
input_buffer: BytesMut,
|
||||
o: Output,
|
||||
inbound_assertions: Map</* remote */ Handle, (/* local */ Handle, Vec<Arc<WireSymbol>>)>,
|
||||
outbound_assertions: Map<Handle, Vec<Arc<WireSymbol>>>,
|
||||
membranes: Membranes,
|
||||
pending_outbound: Vec<TurnEvent>,
|
||||
output: UnboundedSender<Vec<u8>>,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref INERT_REF: Arc<Ref> = {
|
||||
struct InertEntity;
|
||||
impl crate::actor::Entity for InertEntity {}
|
||||
let mut ac = crate::actor::Actor::new();
|
||||
ac.create(InertEntity)
|
||||
};
|
||||
struct RelayEntity {
|
||||
relay_ref: Arc<Ref>,
|
||||
oid: sturdy::Oid,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
impl WireSymbol {
|
||||
fn acquire(&self) {
|
||||
self.ref_count.fetch_add(1, atomic::Ordering::Relaxed);
|
||||
self.ref_count.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn release(&self) -> bool {
|
||||
self.ref_count.fetch_sub(1, atomic::Ordering::Relaxed) == 1
|
||||
self.ref_count.fetch_sub(1, Ordering::SeqCst) == 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,17 +107,23 @@ impl Membrane {
|
|||
}
|
||||
}
|
||||
|
||||
fn insert(&mut self, oid: Oid, obj: Arc<Ref>) -> Arc<WireSymbol> {
|
||||
fn insert(&mut self, oid: sturdy::Oid, obj: Arc<Ref>) -> Arc<WireSymbol> {
|
||||
let ws = Arc::new(WireSymbol {
|
||||
oid: oid.clone(),
|
||||
obj: Arc::clone(&obj),
|
||||
ref_count: atomic::AtomicUsize::new(0),
|
||||
ref_count: AtomicUsize::new(0),
|
||||
});
|
||||
self.oid_map.insert(oid, Arc::clone(&ws));
|
||||
self.ref_map.insert(obj, Arc::clone(&ws));
|
||||
ws
|
||||
}
|
||||
|
||||
fn acquire(&mut self, r: &Arc<Ref>) -> Arc<WireSymbol> {
|
||||
let ws = self.ref_map.get(r).expect("WireSymbol must be present at acquire() time");
|
||||
ws.acquire();
|
||||
Arc::clone(ws)
|
||||
}
|
||||
|
||||
fn release(&mut self, ws: &Arc<WireSymbol>) {
|
||||
if ws.release() {
|
||||
self.oid_map.remove(&ws.oid);
|
||||
|
@ -123,24 +133,44 @@ impl Membrane {
|
|||
}
|
||||
|
||||
impl TunnelRelay {
|
||||
pub fn run(ac: &mut Actor, i: Input, o: Output) -> ActorResult {
|
||||
let tr = ac.create(TunnelRelay {
|
||||
pub fn run(
|
||||
t: &mut Activation,
|
||||
i: Input,
|
||||
o: Output,
|
||||
initial_ref: Option<Arc<Ref>>,
|
||||
initial_oid: Option<sturdy::Oid>,
|
||||
) -> Option<Arc<Ref>> {
|
||||
let (output_tx, output_rx) = unbounded_channel();
|
||||
let mut tr = TunnelRelay {
|
||||
self_ref: Arc::clone(&*INERT_REF), /* placeholder */
|
||||
input_buffer: BytesMut::with_capacity(1024),
|
||||
o,
|
||||
output: output_tx,
|
||||
inbound_assertions: Map::new(),
|
||||
outbound_assertions: Map::new(),
|
||||
membranes: Membranes {
|
||||
exported: Membrane::new(),
|
||||
imported: Membrane::new(),
|
||||
next_export_oid: 0,
|
||||
},
|
||||
pending_outbound: Vec::new(),
|
||||
};
|
||||
if let Some(ir) = initial_ref {
|
||||
tr.membranes.export_ref(ir, true);
|
||||
}
|
||||
let mut result = None;
|
||||
let tr_ref = t.actor.create_rec(tr, |ac, tr, tr_ref| {
|
||||
tr.self_ref = Arc::clone(tr_ref);
|
||||
if let Some(io) = initial_oid {
|
||||
result = Some(Arc::clone(&tr.membranes.import_oid(ac, tr_ref, io).obj));
|
||||
}
|
||||
});
|
||||
ac.add_exit_hook(&tr.target);
|
||||
ac.linked_task(tracing::info_span!("reader"), input_loop(i, tr));
|
||||
Ok(())
|
||||
t.actor.add_exit_hook(&tr_ref.target);
|
||||
t.actor.linked_task(crate::name!("writer"), output_loop(o, output_rx));
|
||||
t.actor.linked_task(crate::name!("reader"), input_loop(i, tr_ref));
|
||||
result
|
||||
}
|
||||
|
||||
fn handle_packet(&mut self, p: Packet) -> ActorResult {
|
||||
fn handle_inbound_packet(&mut self, t: &mut Activation, p: Packet) -> ActorResult {
|
||||
match p {
|
||||
Packet::Error(b) => {
|
||||
tracing::info!(message = debug(b.message.clone()),
|
||||
|
@ -151,45 +181,194 @@ impl TunnelRelay {
|
|||
Packet::Turn(b) => {
|
||||
let Turn(events) = *b;
|
||||
for TurnEvent { oid, event } in events {
|
||||
tracing::info!(oid = debug(oid), event = debug(event))
|
||||
let target = match self.membranes.exported.oid_map.get(&sturdy::Oid(oid.0.clone())) {
|
||||
Some(ws) => &ws.obj,
|
||||
None => return Err(error("Cannot deliver event: nonexistent oid",
|
||||
_Any::from(&TurnEvent { oid, event }))),
|
||||
};
|
||||
match event {
|
||||
Event::Assert(b) => {
|
||||
let Assert { assertion: Assertion(a), handle: remote_handle } = *b;
|
||||
let mut imported = vec![];
|
||||
let imported_membrane = &mut self.membranes.imported;
|
||||
a.foreach_embedded::<_, Error>(&mut |r| {
|
||||
Ok(imported.push(imported_membrane.acquire(r)))
|
||||
})?;
|
||||
let local_handle = t.assert(target, a);
|
||||
if let Some(_) = self.inbound_assertions.insert(remote_handle, (local_handle, imported)) {
|
||||
return Err(error("Assertion with duplicate handle", _Any::new(false)));
|
||||
}
|
||||
}
|
||||
Event::Retract(b) => {
|
||||
let Retract { handle: remote_handle } = *b;
|
||||
let (local_handle, imported) = match self.inbound_assertions.remove(&remote_handle) {
|
||||
None => return Err(error("Retraction of nonexistent handle", _Any::from(&remote_handle))),
|
||||
Some(wss) => wss,
|
||||
};
|
||||
for ws in imported.into_iter() {
|
||||
self.membranes.imported.release(&ws);
|
||||
}
|
||||
t.retract(local_handle);
|
||||
}
|
||||
Event::Message(b) => {
|
||||
let Message { body: Assertion(a) } = *b;
|
||||
let imported_membrane = &mut self.membranes.imported;
|
||||
a.foreach_embedded(&mut |r| {
|
||||
let ws = imported_membrane.acquire(r);
|
||||
match ws.ref_count.load(Ordering::SeqCst) {
|
||||
1 => Err(error("Cannot receive transient reference", _Any::new(false))),
|
||||
_ => Ok(())
|
||||
}
|
||||
})?;
|
||||
t.message(target, a);
|
||||
}
|
||||
Event::Sync(b) => {
|
||||
let Sync { peer } = *b;
|
||||
self.membranes.imported.acquire(&peer);
|
||||
struct SyncPeer {
|
||||
tr: Arc<Ref>,
|
||||
peer: Arc<Ref>,
|
||||
}
|
||||
impl Entity for SyncPeer {
|
||||
fn message(&mut self, t: &mut Activation, a: _Any) -> ActorResult {
|
||||
if let Some(true) = a.value().as_boolean() {
|
||||
t.message(&self.peer, _Any::new(true));
|
||||
t.message(&self.tr, &tunnel_relay::SyncGc {
|
||||
peer: Arc::clone(&self.peer)
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
let k = t.actor.create(SyncPeer {
|
||||
tr: Arc::clone(&self.self_ref),
|
||||
peer: Arc::clone(&peer),
|
||||
});
|
||||
t.sync(&peer, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_event(&mut self, oid: Oid, event: Event) -> bool {
|
||||
let need_flush = self.pending_outbound.is_empty();
|
||||
self.pending_outbound.push(TurnEvent { oid, event });
|
||||
need_flush
|
||||
}
|
||||
|
||||
pub fn decode_packet(&mut self, bs: &[u8]) -> Result<Packet, Error> {
|
||||
let mut src = BytesBinarySource::new(bs);
|
||||
Ok(Packet::try_from(&src.packed::<_, _Any, _>(&mut self.membranes).demand_next(false)?)?)
|
||||
fn handle_outbound_event(&mut self, t: &mut Activation, mut event: Event) -> Result<Event, Error> {
|
||||
match &mut event {
|
||||
Event::Assert(b) => {
|
||||
let Assert { assertion: Assertion(a), handle } = &**b;
|
||||
let mut outbound = Vec::new();
|
||||
a.foreach_embedded::<_, Error>(
|
||||
&mut |r| Ok(outbound.push(self.membranes.export_ref(Arc::clone(r), true))))?;
|
||||
self.outbound_assertions.insert(handle.clone(), outbound);
|
||||
}
|
||||
Event::Retract(b) => {
|
||||
let Retract { handle } = &**b;
|
||||
if let Some(outbound) = self.outbound_assertions.remove(handle) {
|
||||
for ws in outbound.into_iter() {
|
||||
self.membranes.exported.release(&ws);
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::Message(b) => {
|
||||
let Message { body: Assertion(a) } = &**b;
|
||||
a.foreach_embedded(&mut |r| {
|
||||
let ws = self.membranes.export_ref(Arc::clone(r), false);
|
||||
match ws.ref_count.load(Ordering::SeqCst) {
|
||||
0 => Err(error("Cannot send transient reference", _Any::new(false))),
|
||||
_ => Ok(())
|
||||
}
|
||||
})?;
|
||||
},
|
||||
Event::Sync(_b) => panic!("TODO not yet implemented"),
|
||||
}
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
fn encode_packet(&mut self, p: Packet) -> Result<Vec<u8>, Error> {
|
||||
Ok(PackedWriter::encode::<_, _Any, _>(&mut self.membranes, &_Any::from(&p))?)
|
||||
let item = _Any::from(&p);
|
||||
tracing::trace!(packet = debug(&item), "<--");
|
||||
Ok(PackedWriter::encode::<_, _Any, _>(&mut self.membranes, &item)?)
|
||||
}
|
||||
|
||||
pub async fn send_packet(&mut self, p: Packet) -> ActorResult {
|
||||
pub fn send_packet(&mut self, p: Packet) -> ActorResult {
|
||||
let bs = self.encode_packet(p)?;
|
||||
match &mut self.o {
|
||||
Output::Packets(sink) => Ok(sink.send(bs).await?),
|
||||
Output::Bytes(w) => Ok(w.write_all(&bs).await?),
|
||||
}
|
||||
let _ = self.output.send(bs);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl DomainDecode<_Ptr> for Membranes {
|
||||
impl Membranes {
|
||||
fn export_ref(&mut self, obj: Arc<Ref>, and_acquire: bool) -> Arc<WireSymbol> {
|
||||
let ws = match self.exported.ref_map.get(&obj) {
|
||||
None => {
|
||||
let oid = sturdy::Oid(SignedInteger::from(self.next_export_oid as u128));
|
||||
self.next_export_oid += 1;
|
||||
self.exported.insert(oid, obj)
|
||||
}
|
||||
Some(ws) => Arc::clone(ws)
|
||||
};
|
||||
if and_acquire {
|
||||
ws.acquire();
|
||||
}
|
||||
ws
|
||||
}
|
||||
|
||||
fn import_oid(
|
||||
&mut self,
|
||||
ac: &mut Actor,
|
||||
relay_ref: &Arc<Ref>,
|
||||
oid: sturdy::Oid,
|
||||
) -> Arc<WireSymbol> {
|
||||
let obj = ac.create(RelayEntity { relay_ref: Arc::clone(relay_ref), oid: oid.clone() });
|
||||
self.imported.insert(oid, obj)
|
||||
}
|
||||
|
||||
fn decode_embedded<'de, 'src, S: BinarySource<'de>>(
|
||||
&mut self,
|
||||
t: &mut Activation,
|
||||
relay_ref: &Arc<Ref>,
|
||||
src: &'src mut S,
|
||||
_read_annotations: bool,
|
||||
) -> io::Result<_Ptr> {
|
||||
let v: IOValue = PackedReader::new(src, NoEmbeddedDomainCodec).demand_next(false)?;
|
||||
Ok(Arc::new(_Dom::try_from(&v)?))
|
||||
match sturdy::WireRef::try_from(&v)? {
|
||||
sturdy::WireRef::Mine{ oid: b } => {
|
||||
let oid = *b;
|
||||
match self.imported.oid_map.get(&oid) {
|
||||
Some(ws) => Ok(Arc::clone(&ws.obj)),
|
||||
None => Ok(Arc::clone(&self.import_oid(t.actor, relay_ref, oid).obj)),
|
||||
}
|
||||
}
|
||||
sturdy::WireRef::Yours { oid: b, attenuation } => {
|
||||
let oid = *b;
|
||||
match self.exported.oid_map.get(&oid) {
|
||||
Some(ws) => {
|
||||
if attenuation.is_empty() {
|
||||
Ok(Arc::clone(&ws.obj))
|
||||
} else {
|
||||
// TODO
|
||||
panic!("Non-empty attenuation not yet implemented")
|
||||
}
|
||||
}
|
||||
None => Ok(Arc::clone(&*INERT_REF)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ActivatedMembranes<'a, 'activation, 'm>(&'a mut Activation<'activation>,
|
||||
&'m Arc<Ref>,
|
||||
&'m mut Membranes);
|
||||
|
||||
impl<'a, 'activation, 'm> DomainDecode<_Ptr> for ActivatedMembranes<'a, 'activation, 'm> {
|
||||
fn decode_embedded<'de, 'src, S: BinarySource<'de>>(
|
||||
&mut self,
|
||||
src: &'src mut S,
|
||||
read_annotations: bool,
|
||||
) -> io::Result<_Ptr> {
|
||||
self.2.decode_embedded(self.0, self.1, src, read_annotations)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +378,17 @@ impl DomainEncode<_Ptr> for Membranes {
|
|||
w: &mut W,
|
||||
d: &_Ptr,
|
||||
) -> io::Result<()> {
|
||||
w.write(&mut NoEmbeddedDomainCodec, &IOValue::from(d.as_ref()))
|
||||
w.write(&mut NoEmbeddedDomainCodec, &_Any::from(&match self.exported.ref_map.get(d) {
|
||||
Some(ws) => sturdy::WireRef::Mine { oid: Box::new(ws.oid.clone()) },
|
||||
None => match self.imported.ref_map.get(d) {
|
||||
Some(ws) => {
|
||||
// TODO: attenuation check
|
||||
sturdy::WireRef::Yours { oid: Box::new(ws.oid.clone()), attenuation: vec![] }
|
||||
}
|
||||
None =>
|
||||
sturdy::WireRef::Mine { oid: Box::new(self.export_ref(Arc::clone(d), false).oid.clone()) },
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,47 +436,122 @@ pub async fn input_loop(
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn output_loop(
|
||||
mut o: Output,
|
||||
mut output_rx: UnboundedReceiver<Vec<u8>>,
|
||||
) -> ActorResult {
|
||||
loop {
|
||||
match output_rx.recv().await {
|
||||
None =>
|
||||
return Ok(()),
|
||||
Some(bs) => match &mut o {
|
||||
Output::Packets(sink) => sink.send(bs).await?,
|
||||
Output::Bytes(w) => w.write_all(&bs).await?,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for TunnelRelay {
|
||||
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
|
||||
if let Ok(m) = tunnel_relay::Input::try_from(&m) {
|
||||
if let Ok(m) = tunnel_relay::RelayProtocol::try_from(&m) {
|
||||
match m {
|
||||
tunnel_relay::Input::Eof => {
|
||||
tracing::info!("eof");
|
||||
t.actor.shutdown();
|
||||
}
|
||||
tunnel_relay::Input::Packet { bs } => {
|
||||
let p = self.decode_packet(&bs)?;
|
||||
self.handle_packet(p)?
|
||||
}
|
||||
tunnel_relay::Input::Segment { bs } => {
|
||||
self.input_buffer.extend_from_slice(&bs);
|
||||
loop {
|
||||
let (e, count) = {
|
||||
let mut src = BytesBinarySource::new(&self.input_buffer);
|
||||
let mut r = src.packed::<_, _Any, _>(&mut self.membranes);
|
||||
let e = r.next(false)?;
|
||||
(e, r.source.index)
|
||||
};
|
||||
match e {
|
||||
None => break,
|
||||
Some(item) => {
|
||||
self.input_buffer.advance(count);
|
||||
self.handle_packet(Packet::try_from(&item)?)?;
|
||||
tunnel_relay::RelayProtocol::Input(b) => match *b {
|
||||
tunnel_relay::Input::Eof => {
|
||||
t.actor.shutdown();
|
||||
}
|
||||
tunnel_relay::Input::Packet { bs } => {
|
||||
let mut src = BytesBinarySource::new(&bs);
|
||||
let item = src.packed::<_, _Any, _>(
|
||||
&mut ActivatedMembranes(t, &self.self_ref, &mut self.membranes))
|
||||
.demand_next(false)?;
|
||||
tracing::trace!(packet = debug(&item), "-->");
|
||||
self.handle_inbound_packet(t, Packet::try_from(&item)?)?
|
||||
}
|
||||
tunnel_relay::Input::Segment { bs } => {
|
||||
self.input_buffer.extend_from_slice(&bs);
|
||||
loop {
|
||||
let (e, count) = {
|
||||
let mut src = BytesBinarySource::new(&self.input_buffer);
|
||||
let mut dec = ActivatedMembranes(t, &self.self_ref, &mut self.membranes);
|
||||
let mut r = src.packed::<_, _Any, _>(&mut dec);
|
||||
let e = r.next(false)?;
|
||||
(e, r.source.index)
|
||||
};
|
||||
match e {
|
||||
None => break,
|
||||
Some(item) => {
|
||||
self.input_buffer.advance(count);
|
||||
tracing::trace!(packet = debug(&item), "-->");
|
||||
self.handle_inbound_packet(t, Packet::try_from(&item)?)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tunnel_relay::RelayProtocol::Output(b) => match *b {
|
||||
tunnel_relay::Output { oid, event } => {
|
||||
if self.pending_outbound.is_empty() {
|
||||
t.set_turn_end_flag();
|
||||
}
|
||||
let turn_event = TurnEvent {
|
||||
oid: Oid(oid.0),
|
||||
event: self.handle_outbound_event(t, event)?,
|
||||
};
|
||||
self.pending_outbound.push(turn_event);
|
||||
}
|
||||
}
|
||||
tunnel_relay::RelayProtocol::SyncGc(b) => match *b {
|
||||
tunnel_relay::SyncGc { peer } => {
|
||||
if let Some(ws) = self.membranes.imported.ref_map.get(&peer) {
|
||||
let ws = Arc::clone(ws); // cloned to release the borrow to permit the release
|
||||
self.membranes.imported.release(&ws);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn turn_end(&mut self, _t: &mut Activation) -> ActorResult {
|
||||
let events = std::mem::take(&mut self.pending_outbound);
|
||||
self.send_packet(Packet::Turn(Box::new(Turn(events))))
|
||||
}
|
||||
|
||||
fn exit_hook(&mut self, _t: &mut Activation, exit_status: &ActorResult) -> BoxFuture<ActorResult> {
|
||||
if let Err(e) = exit_status {
|
||||
let e = e.clone();
|
||||
Box::pin(self.send_packet(Packet::Error(Box::new(e))))
|
||||
Box::pin(ready(self.send_packet(Packet::Error(Box::new(e)))))
|
||||
} else {
|
||||
Box::pin(ready(Ok(())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for RelayEntity {
|
||||
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, &tunnel_relay::Output {
|
||||
oid: self.oid.clone(),
|
||||
event: Event::Assert(Box::new(Assert { assertion: Assertion(a), handle: h })),
|
||||
}))
|
||||
}
|
||||
fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, &tunnel_relay::Output {
|
||||
oid: self.oid.clone(),
|
||||
event: Event::Retract(Box::new(Retract { handle: h })),
|
||||
}))
|
||||
}
|
||||
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, &tunnel_relay::Output {
|
||||
oid: self.oid.clone(),
|
||||
event: Event::Message(Box::new(Message { body: Assertion(m) })),
|
||||
}))
|
||||
}
|
||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref>) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, &tunnel_relay::Output {
|
||||
oid: self.oid.clone(),
|
||||
event: Event::Sync(Box::new(Sync { peer })),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use super::Assertion;
|
||||
use super::bag;
|
||||
|
||||
use preserves::value::{Map, Set, Value, NestedValue};
|
||||
|
@ -7,6 +6,7 @@ use std::convert::TryFrom;
|
|||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::actor::Assertion;
|
||||
use crate::actor::Activation;
|
||||
use crate::actor::Ref;
|
||||
use crate::schemas::internal_protocol::Handle;
|
||||
|
@ -85,11 +85,12 @@ impl Index {
|
|||
|
||||
pub fn remove_observer(
|
||||
&mut self,
|
||||
t: &mut Activation,
|
||||
pat: ds::Pattern,
|
||||
observer: &Arc<Ref>,
|
||||
) {
|
||||
let analysis = pattern::PatternAnalysis::new(&pat);
|
||||
self.root.extend(&pat).remove_observer(analysis, observer);
|
||||
self.root.extend(&pat).remove_observer(t, analysis, observer);
|
||||
self.observer_count -= 1;
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ impl Index {
|
|||
|es, cs| {
|
||||
if es.cached_captures.change(cs.clone(), 1) == bag::Net::AbsentToPresent {
|
||||
for (observer, capture_map) in &mut es.endpoints {
|
||||
capture_map.insert(cs.clone(), t.assert(observer.clone(), cs.clone()));
|
||||
capture_map.insert(cs.clone(), t.assert(observer, cs.clone()));
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -150,7 +151,7 @@ impl Index {
|
|||
|es, cs| {
|
||||
*delivery_count += es.endpoints.len();
|
||||
for observer in es.endpoints.keys() {
|
||||
t.message(observer.clone(), cs.clone());
|
||||
t.message(observer, cs.clone());
|
||||
}
|
||||
}).perform(&mut self.root);
|
||||
}
|
||||
|
@ -417,13 +418,14 @@ impl Continuation {
|
|||
});
|
||||
let mut capture_map = Map::new();
|
||||
for cs in endpoints.cached_captures.keys() {
|
||||
capture_map.insert(cs.clone(), t.assert(observer.clone(), cs.clone()));
|
||||
capture_map.insert(cs.clone(), t.assert(observer, cs.clone()));
|
||||
}
|
||||
endpoints.endpoints.insert(observer.clone(), capture_map);
|
||||
}
|
||||
|
||||
pub fn remove_observer(
|
||||
&mut self,
|
||||
t: &mut Activation,
|
||||
analysis: pattern::PatternAnalysis,
|
||||
observer: &Arc<Ref>,
|
||||
) {
|
||||
|
@ -439,7 +441,11 @@ impl Continuation {
|
|||
= leaf.endpoints_map.entry(analysis.capture_paths)
|
||||
{
|
||||
let endpoints = endpoints_entry.get_mut();
|
||||
endpoints.endpoints.remove(observer);
|
||||
if let Some(capture_map) = endpoints.endpoints.remove(observer) {
|
||||
for handle in capture_map.into_values() {
|
||||
t.retract(handle)
|
||||
}
|
||||
}
|
||||
if endpoints.endpoints.is_empty() {
|
||||
endpoints_entry.remove_entry();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
use crate::actor::*;
|
||||
|
||||
use preserves::value::NestedValue;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Tracer(tracing::Span);
|
||||
|
||||
fn set_name_oid(_ac: &mut Actor, t: &mut Tracer, r: &Arc<Ref>) {
|
||||
t.0.record("oid", &tracing::field::display(&r.target.0));
|
||||
}
|
||||
|
||||
pub fn tracer(ac: &mut Actor, name: tracing::Span) -> Arc<Ref> {
|
||||
ac.create_rec(Tracer(name), set_name_oid)
|
||||
}
|
||||
|
||||
pub fn tracer_top(name: tracing::Span) -> Arc<Ref> {
|
||||
Actor::create_and_start_rec(crate::name!(parent: None, "tracer"), Tracer(name), set_name_oid)
|
||||
}
|
||||
|
||||
impl Entity for Tracer {
|
||||
fn assert(&mut self, _t: &mut Activation, a: Assertion, h: Handle) -> ActorResult {
|
||||
let _guard = self.0.enter();
|
||||
tracing::trace!(a = debug(&a), h = debug(&h), "assert");
|
||||
Ok(())
|
||||
}
|
||||
fn retract(&mut self, _t: &mut Activation, h: Handle) -> ActorResult {
|
||||
let _guard = self.0.enter();
|
||||
tracing::trace!(h = debug(&h), "retract");
|
||||
Ok(())
|
||||
}
|
||||
fn message(&mut self, _t: &mut Activation, m: Assertion) -> ActorResult {
|
||||
let _guard = self.0.enter();
|
||||
tracing::trace!(m = debug(&m), "message");
|
||||
Ok(())
|
||||
}
|
||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref>) -> ActorResult {
|
||||
let _guard = self.0.enter();
|
||||
tracing::trace!(peer = debug(&peer), "sync");
|
||||
t.message(&peer, Assertion::new(true));
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue