using nanomsg polling
This commit is contained in:
parent
47cfab2bbf
commit
aea185471a
@ -23,11 +23,15 @@ extern crate nanomsg;
|
|||||||
pub use ipc::*;
|
pub use ipc::*;
|
||||||
|
|
||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
use nanomsg::{Socket, Protocol, Error, Endpoint};
|
use nanomsg::{Socket, Protocol, Error, Endpoint, PollRequest, PollFd, PollInOut};
|
||||||
|
|
||||||
|
const POLL_TIMEOUT: isize = 100;
|
||||||
|
|
||||||
pub struct Worker<S> where S: IpcInterface<S> {
|
pub struct Worker<S> where S: IpcInterface<S> {
|
||||||
service: Arc<S>,
|
service: Arc<S>,
|
||||||
sockets: Vec<(Socket, Endpoint)>,
|
sockets: Vec<(Socket, Endpoint)>,
|
||||||
|
polls: Vec<PollFd>,
|
||||||
|
buf: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -40,43 +44,55 @@ impl<S> Worker<S> where S: IpcInterface<S> {
|
|||||||
Worker::<S> {
|
Worker::<S> {
|
||||||
service: service.clone(),
|
service: service.clone(),
|
||||||
sockets: Vec::new(),
|
sockets: Vec::new(),
|
||||||
|
polls: Vec::new(),
|
||||||
|
buf: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll(&mut self) {
|
pub fn poll(&mut self) {
|
||||||
for item in self.sockets.iter_mut() {
|
let mut request = PollRequest::new(&mut self.polls[..]);
|
||||||
let socket = &mut item.0;
|
let _result_guard = Socket::poll(&mut request, POLL_TIMEOUT);
|
||||||
let mut buf = Vec::new();
|
|
||||||
// non-blocking read only ok if there is something to read from socket
|
|
||||||
match socket.nb_read_to_end(&mut buf) {
|
|
||||||
Ok(method_sign_len) => {
|
|
||||||
if method_sign_len >= 2 {
|
|
||||||
// method_num
|
|
||||||
let method_num = buf[1] as u16 * 256 + buf[0] as u16;
|
|
||||||
// payload
|
|
||||||
let payload = &buf[2..];
|
|
||||||
|
|
||||||
// dispatching for ipc interface
|
for (fd_index, fd) in request.get_fds().iter().enumerate() {
|
||||||
let result = self.service.dispatch_buf(method_num, payload);
|
if fd.can_read() {
|
||||||
|
let (ref mut socket, _) = self.sockets[fd_index];
|
||||||
|
unsafe { self.buf.set_len(0); }
|
||||||
|
match socket.nb_read_to_end(&mut self.buf) {
|
||||||
|
Ok(method_sign_len) => {
|
||||||
|
if method_sign_len >= 2 {
|
||||||
|
// method_num
|
||||||
|
let method_num = self.buf[1] as u16 * 256 + self.buf[0] as u16;
|
||||||
|
// payload
|
||||||
|
let payload = &self.buf[2..];
|
||||||
|
|
||||||
if let Err(e) = socket.nb_write(&result) {
|
// dispatching for ipc interface
|
||||||
warn!(target: "ipc", "Failed to write response: {:?}", e);
|
let result = self.service.dispatch_buf(method_num, payload);
|
||||||
|
|
||||||
|
if let Err(e) = socket.nb_write(&result) {
|
||||||
|
warn!(target: "ipc", "Failed to write response: {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
warn!(target: "ipc", "Failed to read method signature from socket: unexpected message length({})", method_sign_len);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(Error::TryAgain) => {
|
||||||
|
},
|
||||||
|
Err(x) => {
|
||||||
|
warn!(target: "ipc", "Error polling connections {:?}", x);
|
||||||
|
panic!();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
warn!(target: "ipc", "Failed to read method signature from socket: unexpected message length({})", method_sign_len);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(Error::TryAgain) => {
|
|
||||||
},
|
|
||||||
Err(x) => {
|
|
||||||
warn!(target: "ipc", "Error polling connections {:?}", x);
|
|
||||||
panic!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rebuild_poll_request(&mut self) {
|
||||||
|
self.polls = self.sockets.iter()
|
||||||
|
.map(|&(ref socket, _)| socket.new_pollfd(PollInOut::In))
|
||||||
|
.collect::<Vec<PollFd>>();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_duplex(&mut self, addr: &str) -> Result<(), SocketError> {
|
pub fn add_duplex(&mut self, addr: &str) -> Result<(), SocketError> {
|
||||||
let mut socket = try!(Socket::new(Protocol::Pair).map_err(|e| {
|
let mut socket = try!(Socket::new(Protocol::Pair).map_err(|e| {
|
||||||
warn!(target: "ipc", "Failed to create ipc socket: {:?}", e);
|
warn!(target: "ipc", "Failed to create ipc socket: {:?}", e);
|
||||||
@ -89,6 +105,9 @@ impl<S> Worker<S> where S: IpcInterface<S> {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
self.sockets.push((socket, endpoint));
|
self.sockets.push((socket, endpoint));
|
||||||
|
|
||||||
|
self.rebuild_poll_request();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,7 +188,7 @@ mod tests {
|
|||||||
worker.add_duplex(url).unwrap();
|
worker.add_duplex(url).unwrap();
|
||||||
|
|
||||||
let (_socket, _endpoint) = dummy_write(url, &vec![0, 0, 7, 7, 6, 6]);
|
let (_socket, _endpoint) = dummy_write(url, &vec![0, 0, 7, 7, 6, 6]);
|
||||||
for _ in 0..100 { worker.poll(); }
|
worker.poll();
|
||||||
|
|
||||||
assert_eq!(1, worker.service.methods_stack.read().unwrap().len());
|
assert_eq!(1, worker.service.methods_stack.read().unwrap().len());
|
||||||
assert_eq!(0, worker.service.methods_stack.read().unwrap()[0].method_num);
|
assert_eq!(0, worker.service.methods_stack.read().unwrap()[0].method_num);
|
||||||
@ -186,7 +205,7 @@ mod tests {
|
|||||||
let message = [0u8; 1024*1024];
|
let message = [0u8; 1024*1024];
|
||||||
|
|
||||||
let (_socket, _endpoint) = dummy_write(url, &message);
|
let (_socket, _endpoint) = dummy_write(url, &message);
|
||||||
for _ in 0..1000 { worker.poll(); }
|
worker.poll();
|
||||||
|
|
||||||
assert_eq!(1, worker.service.methods_stack.read().unwrap().len());
|
assert_eq!(1, worker.service.methods_stack.read().unwrap().len());
|
||||||
assert_eq!(0, worker.service.methods_stack.read().unwrap()[0].method_num);
|
assert_eq!(0, worker.service.methods_stack.read().unwrap()[0].method_num);
|
||||||
|
Loading…
Reference in New Issue
Block a user