Skip to content

Commit

Permalink
runtime/rust: allow creation of external nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddrysdale committed Apr 7, 2020
1 parent c160b48 commit 10d346d
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions oak/server/rust/oak_runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ default = []
# - `cd cargo && cargo raze` needs re-running, and the results checked in
byteorder = { version = "*", default-features = false }
itertools = "*"
lazy_static = "*"
log = { version = "*" }
oak_abi = "=0.1.0"
prost = "*"
Expand Down
11 changes: 7 additions & 4 deletions oak/server/rust/oak_runtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use itertools::Itertools;
use std::collections::HashMap;
use std::sync::Arc;

use log::error;
use log::{error, warn};

use oak_abi::OakStatus;

Expand Down Expand Up @@ -96,9 +96,12 @@ pub fn from_protobuf(
OakStatus::ErrInvalidArgs
})?
}
Some(_) => {
error!("Pseudo-node not implemented!");
return Err(OakStatus::ErrInvalidArgs);
Some(node_config) => {
warn!(
"Assuming pseudo-Node of type {:?} implemented externally!",
node_config
);
node::Configuration::External
}
},
);
Expand Down
97 changes: 97 additions & 0 deletions oak/server/rust/oak_runtime/src/node/external.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// Copyright 2020 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use crate::runtime::{Handle, RuntimeProxy};
use crate::NodeId;
use lazy_static::lazy_static;
use log::{error, info};
use oak_abi::OakStatus;
use std::sync::RwLock;
use std::thread;
use std::thread::JoinHandle;

pub type NodeFactory = fn(config_name: &str, node_id: NodeId, handle: Handle);

lazy_static! {
static ref FACTORY: RwLock<Option<NodeFactory>> = RwLock::new(None);
}

pub fn register_factory(factory: NodeFactory) {
info!("register external node factory");
*FACTORY.write().unwrap() = Some(factory);
}

pub struct PseudoNode {
config_name: String,
runtime: RuntimeProxy,
reader: Handle,
thread_handle: Option<JoinHandle<()>>,
}

impl PseudoNode {
pub fn new(config_name: &str, runtime: RuntimeProxy, reader: Handle) -> Self {
Self {
config_name: config_name.to_string(),
runtime,
reader,
thread_handle: None,
}
}
}

impl super::Node for PseudoNode {
fn start(&mut self) -> Result<(), OakStatus> {
// Clone or copy all the captured values and move them into the closure, for simplicity.
let config_name = self.config_name.clone();
let runtime = self.runtime.clone();
let reader = self.reader;
let thread_handle = thread::Builder::new()
.name(format!("external={}", config_name))
.spawn(move || {
let pretty_name = format!("{}-{:?}:", config_name, thread::current());
let factory_fn: NodeFactory = FACTORY
.read()
.expect("unlock failed")
.expect("no registered factory");
info!(
"invoke external node factory with '{}', reader={:?} on thread {:?}",
config_name,
reader,
thread::current(),
);
factory_fn(&config_name, runtime.node_id, reader);

info!(
"{} LOG: exiting pseudo-Node thread {:?}",
pretty_name,
thread::current()
);
runtime.exit_node();
})
.expect("failed to spawn thread");
info!("external node started on thread {:?}", thread_handle);
self.thread_handle = Some(thread_handle);
Ok(())
}

fn stop(&mut self) {
if let Some(join_handle) = self.thread_handle.take() {
if let Err(err) = join_handle.join() {
error!("error while stopping external node: {:?}", err);
}
}
}
}
12 changes: 11 additions & 1 deletion oak/server/rust/oak_runtime/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use oak_abi::OakStatus;
use crate::runtime::RuntimeProxy;
use crate::Handle;

pub mod external;
mod logger;
mod wasm;

Expand Down Expand Up @@ -57,7 +58,11 @@ pub enum Configuration {
// instance, but wasmi doesn't allow this. We make do with having a copyable
// `Arc<wasmi::Module>` that we pass to new nodes, and clone to to spawn new
// `wasmi::ModuleInstances`.
WasmNode { module: Arc<wasmi::Module> },
WasmNode {
module: Arc<wasmi::Module>,
},

External,
}

/// A enumeration for errors occuring when building `Configuration` from protobuf types.
Expand Down Expand Up @@ -108,6 +113,11 @@ impl Configuration {
entrypoint,
initial_reader,
)),
Configuration::External => Box::new(external::PseudoNode::new(
config_name,
runtime,
initial_reader,
)),
}
}
}

0 comments on commit 10d346d

Please sign in to comment.