fixes
This commit is contained in:
@@ -160,6 +160,25 @@ impl veilid_server::Server for VeilidServerImpl {
|
||||
|
||||
Promise::ok(())
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&mut self,
|
||||
params: veilid_server::DebugParams,
|
||||
mut results: veilid_server::DebugResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
trace!("VeilidServerImpl::attach");
|
||||
let veilid_api = self.veilid_api.clone();
|
||||
let what = pry!(pry!(params.get()).get_what()).to_owned();
|
||||
|
||||
Promise::from_future(async move {
|
||||
let output = veilid_api
|
||||
.debug(what)
|
||||
.await
|
||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?;
|
||||
results.get().set_output(output.as_str());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// --- Client API Server-Side ---------------------------------
|
||||
@@ -268,9 +287,11 @@ impl ClientApi {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_state_change(self: Rc<Self>, changed: veilid_core::VeilidStateChange) {
|
||||
trace!("state changed: {:?}", changed);
|
||||
|
||||
fn send_request_to_all_clients<F, T>(self: Rc<Self>, request: F)
|
||||
where
|
||||
F: Fn(u64, &mut RegistrationHandle) -> ::capnp::capability::RemotePromise<T>,
|
||||
T: capnp::traits::Pipelined + for<'a> capnp::traits::Owned<'a> + 'static + Unpin,
|
||||
{
|
||||
// Send status update to each registered client
|
||||
let registration_map = self.inner.borrow().registration_map.clone();
|
||||
let registration_map1 = registration_map.clone();
|
||||
@@ -278,17 +299,16 @@ impl ClientApi {
|
||||
for (&id, mut registration) in regs.iter_mut() {
|
||||
if registration.requests_in_flight > 5 {
|
||||
debug!(
|
||||
"too many requests in flight for status updates: {}",
|
||||
"too many requests in flight: {}",
|
||||
registration.requests_in_flight
|
||||
);
|
||||
}
|
||||
registration.requests_in_flight += 1;
|
||||
// Make a state changed request
|
||||
let mut request = registration.client.state_changed_request();
|
||||
let rpc_changed = request.get().init_changed();
|
||||
ClientApi::convert_state_changed(&changed, rpc_changed);
|
||||
|
||||
let request_promise = request(id, registration);
|
||||
|
||||
let registration_map2 = registration_map1.clone();
|
||||
async_std::task::spawn_local(request.send().promise.map(move |r| match r {
|
||||
async_std::task::spawn_local(request_promise.promise.map(move |r| match r {
|
||||
Ok(_) => {
|
||||
if let Some(ref mut s) =
|
||||
registration_map2.borrow_mut().registrations.get_mut(&id)
|
||||
@@ -304,6 +324,23 @@ impl ClientApi {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_state_change(self: Rc<Self>, changed: veilid_core::VeilidStateChange) {
|
||||
self.send_request_to_all_clients(|_id, registration| {
|
||||
let mut request = registration.client.state_changed_request();
|
||||
let rpc_changed = request.get().init_changed();
|
||||
ClientApi::convert_state_changed(&changed, rpc_changed);
|
||||
request.send()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn handle_client_log(self: Rc<Self>, message: String) {
|
||||
self.send_request_to_all_clients(|_id, registration| {
|
||||
let mut request = registration.client.log_message_request();
|
||||
request.get().set_message(&message);
|
||||
request.send()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn run(self: Rc<Self>, bind_addrs: Vec<SocketAddr>) {
|
||||
// Create client api VeilidServer
|
||||
let veilid_server_impl = VeilidServerImpl::new(self.inner.borrow().veilid_api.clone());
|
||||
|
48
veilid-server/src/client_log_channel.rs
Normal file
48
veilid-server/src/client_log_channel.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
use async_std::channel::{bounded, Receiver, RecvError, Sender, TrySendError};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ClientLogChannelInner {
|
||||
sender: Sender<String>,
|
||||
receiver: Receiver<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClientLogChannel {
|
||||
inner: Arc<ClientLogChannelInner>,
|
||||
}
|
||||
|
||||
impl ClientLogChannel {
|
||||
pub fn new() -> Self {
|
||||
let (sender, receiver) = bounded(1);
|
||||
Self {
|
||||
inner: Arc::new(ClientLogChannelInner { sender, receiver }),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn recv(&self) -> Result<String, RecvError> {
|
||||
self.inner.receiver.recv().await
|
||||
}
|
||||
}
|
||||
|
||||
impl std::io::Write for ClientLogChannel {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
if let Err(e) = self
|
||||
.inner
|
||||
.sender
|
||||
.try_send(String::from_utf8_lossy(buf).to_string())
|
||||
{
|
||||
match e {
|
||||
TrySendError::Full(_) => Err(std::io::Error::from(std::io::ErrorKind::WouldBlock)),
|
||||
TrySendError::Closed(_) => {
|
||||
Err(std::io::Error::from(std::io::ErrorKind::BrokenPipe))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(buf.len())
|
||||
}
|
||||
}
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
#![deny(unused_must_use)]
|
||||
|
||||
mod client_api;
|
||||
mod client_log_channel;
|
||||
mod settings;
|
||||
|
||||
#[allow(clippy::all)]
|
||||
|
@@ -29,6 +29,9 @@ logging:
|
||||
path: ""
|
||||
append: true
|
||||
level: "info"
|
||||
client:
|
||||
enable: false
|
||||
level: "info"
|
||||
testing:
|
||||
subnode_index: 0
|
||||
core:
|
||||
@@ -283,6 +286,12 @@ pub struct File {
|
||||
pub level: LogLevel,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Client {
|
||||
pub enabled: bool,
|
||||
pub level: LogLevel,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ClientApi {
|
||||
pub enabled: bool,
|
||||
@@ -293,6 +302,7 @@ pub struct ClientApi {
|
||||
pub struct Logging {
|
||||
pub terminal: Terminal,
|
||||
pub file: File,
|
||||
pub client: Client,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -928,6 +938,8 @@ mod tests {
|
||||
assert_eq!(s.logging.file.path, "");
|
||||
assert_eq!(s.logging.file.append, true);
|
||||
assert_eq!(s.logging.file.level, LogLevel::Info);
|
||||
assert_eq!(s.logging.client.enabled, true);
|
||||
assert_eq!(s.logging.client.level, LogLevel::Info);
|
||||
assert_eq!(s.testing.subnode_index, 0);
|
||||
assert_eq!(
|
||||
s.core.tablestore.directory,
|
||||
|
@@ -1,8 +1,10 @@
|
||||
#[cfg(unix)]
|
||||
use crate::client_api;
|
||||
use crate::client_log_channel::*;
|
||||
use crate::settings;
|
||||
use async_std::channel::{bounded, Receiver, Sender};
|
||||
use clap::{App, Arg};
|
||||
use futures::*;
|
||||
use lazy_static::*;
|
||||
use log::*;
|
||||
use parking_lot::Mutex;
|
||||
@@ -187,7 +189,7 @@ pub async fn main() -> Result<(), String> {
|
||||
|
||||
// Set up loggers
|
||||
let mut logs: Vec<Box<dyn SharedLogger>> = Vec::new();
|
||||
|
||||
let mut client_log_channel: Option<ClientLogChannel> = None;
|
||||
let mut cb = ConfigBuilder::new();
|
||||
cb.add_filter_ignore_str("async_std");
|
||||
cb.add_filter_ignore_str("async_io");
|
||||
@@ -228,6 +230,15 @@ pub async fn main() -> Result<(), String> {
|
||||
logfile,
|
||||
))
|
||||
}
|
||||
if settingsr.logging.client.enabled {
|
||||
let clog = ClientLogChannel::new();
|
||||
client_log_channel = Some(clog.clone());
|
||||
logs.push(WriteLogger::new(
|
||||
settings::convert_loglevel(settingsr.logging.file.level),
|
||||
cb.build(),
|
||||
clog,
|
||||
))
|
||||
}
|
||||
CombinedLogger::init(logs).map_err(|e| format!("failed to init logs: {}", e))?;
|
||||
|
||||
// Create Veilid Core
|
||||
@@ -280,12 +291,27 @@ pub async fn main() -> Result<(), String> {
|
||||
let capi_jh = async_std::task::spawn_local(async move {
|
||||
trace!("state change processing started");
|
||||
while let Ok(change) = receiver.recv().await {
|
||||
if let Some(c) = capi2.borrow_mut().as_mut().cloned() {
|
||||
if let Some(c) = capi2.borrow().as_ref().cloned() {
|
||||
c.handle_state_change(change);
|
||||
}
|
||||
}
|
||||
trace!("state change processing stopped");
|
||||
});
|
||||
// Handle log messages on main thread for capnproto rpc
|
||||
let capi2 = capi.clone();
|
||||
let capi_jh2 = if let Some(client_log_channel) = client_log_channel {
|
||||
Some(async_std::task::spawn_local(async move {
|
||||
trace!("client logging started");
|
||||
while let Ok(message) = client_log_channel.recv().await {
|
||||
if let Some(c) = capi2.borrow().as_ref().cloned() {
|
||||
c.handle_client_log(message);
|
||||
}
|
||||
}
|
||||
trace!("client logging stopped")
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Auto-attach if desired
|
||||
if auto_attach {
|
||||
@@ -313,8 +339,11 @@ pub async fn main() -> Result<(), String> {
|
||||
// Shut down Veilid API
|
||||
veilid_api.shutdown().await;
|
||||
|
||||
// Wait for statechanged handler to exit
|
||||
// Wait for client api handlers to exit
|
||||
capi_jh.await;
|
||||
if let Some(capi_jh2) = capi_jh2 {
|
||||
capi_jh2.await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Reference in New Issue
Block a user