Skip to content

Commit 6ec4e6e

Browse files
committed
template: split into main.rs and lib.rs
Split functionality between library crate and an executable crate that consumes the library. Signed-off-by: Manos Pitsidianakis <[email protected]>
1 parent 37e5270 commit 6ec4e6e

File tree

3 files changed

+116
-99
lines changed

3 files changed

+116
-99
lines changed

vhost-device-template/src/vhu_foo.rs renamed to vhost-device-template/src/backend.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
//
66
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
77

8-
use std::{
9-
convert,
10-
io::{self, Result as IoResult},
11-
};
8+
use std::io::Result as IoResult;
129

1310
use log::{info, warn};
1411
use thiserror::Error as ThisError;
@@ -34,7 +31,7 @@ type Result<T> = std::result::Result<T, Error>;
3431

3532
#[derive(Copy, Clone, Debug, Eq, PartialEq, ThisError)]
3633
/// Errors related to vhost-device-foo daemon.
37-
pub(crate) enum Error {
34+
pub enum Error {
3835
#[error("Failed to handle event, didn't match EPOLLIN")]
3936
HandleEventNotEpollIn,
4037
#[error("Failed to handle unknown event")]
@@ -47,13 +44,13 @@ pub(crate) enum Error {
4744
EventFdFailed,
4845
}
4946

50-
impl convert::From<Error> for io::Error {
47+
impl From<Error> for std::io::Error {
5148
fn from(e: Error) -> Self {
52-
io::Error::other(e)
49+
std::io::Error::other(e)
5350
}
5451
}
5552

56-
pub(crate) struct VhostUserFooBackend {
53+
pub struct VhostUserFooBackend {
5754
info: FooInfo,
5855
event_idx: bool,
5956
pub exit_event: EventFd,
@@ -469,15 +466,15 @@ mod tests {
469466
.handle_event(0, EventSet::OUT, &[vring.clone()], 0)
470467
.unwrap_err()
471468
.kind(),
472-
io::ErrorKind::Other
469+
std::io::ErrorKind::Other
473470
);
474471

475472
assert_eq!(
476473
backend
477474
.handle_event(1, EventSet::IN, &[vring.clone()], 0)
478475
.unwrap_err()
479476
.kind(),
480-
io::ErrorKind::Other
477+
std::io::ErrorKind::Other
481478
);
482479

483480
// Hit the loop part

vhost-device-template/src/lib.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// VIRTIO FOO Emulation via vhost-user
2+
//
3+
// Copyright 2023 Linaro Ltd. All Rights Reserved.
4+
// Viresh Kumar <[email protected]>
5+
//
6+
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
7+
8+
pub mod backend;
9+
10+
use std::{
11+
path::PathBuf,
12+
sync::{Arc, RwLock},
13+
thread::{spawn, JoinHandle},
14+
};
15+
16+
use backend::VhostUserFooBackend;
17+
use log::error;
18+
use thiserror::Error as ThisError;
19+
use vhost_user_backend::VhostUserDaemon;
20+
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
21+
22+
pub type Result<T> = std::result::Result<T, Error>;
23+
24+
#[derive(Debug, ThisError)]
25+
/// Errors related to low level foo helpers
26+
pub enum Error {
27+
#[error("Could not create backend: {0}")]
28+
CouldNotCreateBackend(backend::Error),
29+
#[error("Could not create daemon: {0}")]
30+
CouldNotCreateDaemon(vhost_user_backend::Error),
31+
#[error("Fatal error: {0}")]
32+
ServeFailed(vhost_user_backend::Error),
33+
}
34+
35+
#[derive(PartialEq, Debug)]
36+
pub struct FooConfiguration {
37+
pub socket_path: PathBuf,
38+
}
39+
40+
#[derive(Copy, Clone)]
41+
pub struct FooInfo {
42+
counter: u32,
43+
}
44+
45+
impl FooInfo {
46+
pub fn new() -> Self {
47+
Self { counter: 0 }
48+
}
49+
50+
pub fn counter(&mut self) -> u32 {
51+
self.counter += 1;
52+
self.counter
53+
}
54+
}
55+
56+
impl Default for FooInfo {
57+
fn default() -> Self {
58+
Self::new()
59+
}
60+
}
61+
62+
pub fn start_backend(config: FooConfiguration) -> Result<()> {
63+
let socket_path = config.socket_path.clone();
64+
let info = FooInfo::new();
65+
66+
let handle: JoinHandle<Result<()>> = spawn(move || loop {
67+
// There isn't much value in complicating code here to return an error from the
68+
// threads, and so the code uses unwrap() instead. The panic on a thread
69+
// won't cause trouble to the main() function and should be safe for the
70+
// daemon.
71+
let backend = Arc::new(RwLock::new(
72+
VhostUserFooBackend::new(info).map_err(Error::CouldNotCreateBackend)?,
73+
));
74+
75+
let mut daemon = VhostUserDaemon::new(
76+
String::from("vhost-device-template-backend"),
77+
backend,
78+
GuestMemoryAtomic::new(GuestMemoryMmap::new()),
79+
)
80+
.map_err(Error::CouldNotCreateDaemon)?;
81+
82+
daemon.serve(&socket_path).map_err(Error::ServeFailed)?;
83+
});
84+
85+
handle.join().map_err(std::panic::resume_unwind).unwrap()
86+
}
87+
88+
#[cfg(test)]
89+
mod tests {
90+
use std::path::Path;
91+
92+
use assert_matches::assert_matches;
93+
94+
use super::*;
95+
96+
#[test]
97+
fn test_fail_listener() {
98+
// This will fail the listeners and thread will panic.
99+
let socket_path = Path::new("/proc/foo/path/not/present").to_path_buf();
100+
let cmd_args = FooConfiguration { socket_path };
101+
102+
assert_matches!(start_backend(cmd_args).unwrap_err(), Error::ServeFailed(_));
103+
}
104+
}

vhost-device-template/src/main.rs

Lines changed: 5 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,10 @@
55
//
66
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
77

8-
mod vhu_foo;
9-
10-
use std::{
11-
path::PathBuf,
12-
process::exit,
13-
sync::{Arc, RwLock},
14-
thread::{spawn, JoinHandle},
15-
};
8+
use std::{path::PathBuf, process::exit};
169

1710
use clap::Parser;
18-
use log::error;
19-
use thiserror::Error as ThisError;
20-
use vhost_user_backend::VhostUserDaemon;
21-
use vhu_foo::VhostUserFooBackend;
22-
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
23-
24-
type Result<T> = std::result::Result<T, Error>;
25-
26-
#[derive(Debug, ThisError)]
27-
/// Errors related to low level foo helpers
28-
pub(crate) enum Error {
29-
#[error("Could not create backend: {0}")]
30-
CouldNotCreateBackend(vhu_foo::Error),
31-
#[error("Could not create daemon: {0}")]
32-
CouldNotCreateDaemon(vhost_user_backend::Error),
33-
#[error("Fatal error: {0}")]
34-
ServeFailed(vhost_user_backend::Error),
35-
}
36-
11+
use vhost_device_template::{start_backend, Error, FooConfiguration, Result};
3712
#[derive(Parser, Debug)]
3813
#[clap(author, version, about, long_about = None)]
3914
struct FooArgs {
@@ -42,11 +17,6 @@ struct FooArgs {
4217
socket_path: PathBuf,
4318
}
4419

45-
#[derive(PartialEq, Debug)]
46-
struct FooConfiguration {
47-
socket_path: PathBuf,
48-
}
49-
5020
impl TryFrom<FooArgs> for FooConfiguration {
5121
type Error = Error;
5222

@@ -61,55 +31,12 @@ impl TryFrom<FooArgs> for FooConfiguration {
6131
}
6232
}
6333

64-
#[derive(Copy, Clone)]
65-
pub(crate) struct FooInfo {
66-
counter: u32,
67-
}
68-
69-
impl FooInfo {
70-
pub fn new() -> Self {
71-
Self { counter: 0 }
72-
}
73-
74-
pub fn counter(&mut self) -> u32 {
75-
self.counter += 1;
76-
self.counter
77-
}
78-
}
79-
80-
fn start_backend(args: FooArgs) -> Result<()> {
81-
let config = FooConfiguration::try_from(args).unwrap();
82-
83-
let socket_path = config.socket_path.clone();
84-
let info = FooInfo::new();
85-
86-
let handle: JoinHandle<Result<()>> = spawn(move || loop {
87-
// There isn't much value in complicating code here to return an error from the
88-
// threads, and so the code uses unwrap() instead. The panic on a thread
89-
// won't cause trouble to the main() function and should be safe for the
90-
// daemon.
91-
let backend = Arc::new(RwLock::new(
92-
VhostUserFooBackend::new(info).map_err(Error::CouldNotCreateBackend)?,
93-
));
94-
95-
let mut daemon = VhostUserDaemon::new(
96-
String::from("vhost-device-template-backend"),
97-
backend,
98-
GuestMemoryAtomic::new(GuestMemoryMmap::new()),
99-
)
100-
.map_err(Error::CouldNotCreateDaemon)?;
101-
102-
daemon.serve(&socket_path).map_err(Error::ServeFailed)?;
103-
});
104-
105-
handle.join().map_err(std::panic::resume_unwind).unwrap()
106-
}
107-
10834
fn main() {
10935
env_logger::init();
11036

111-
if let Err(e) = start_backend(FooArgs::parse()) {
112-
error!("{e}");
37+
let config = FooConfiguration::try_from(FooArgs::parse()).unwrap();
38+
if let Err(e) = start_backend(config) {
39+
log::error!("{e}");
11340
exit(1);
11441
}
11542
}
@@ -118,8 +45,6 @@ fn main() {
11845
mod tests {
11946
use std::path::Path;
12047

121-
use assert_matches::assert_matches;
122-
12348
use super::*;
12449

12550
impl FooArgs {
@@ -143,13 +68,4 @@ mod tests {
14368

14469
assert_eq!(config, expected_config);
14570
}
146-
147-
#[test]
148-
fn test_fail_listener() {
149-
// This will fail the listeners and thread will panic.
150-
let socket_name = Path::new("~/path/not/present/foo");
151-
let cmd_args = FooArgs::from_args(socket_name);
152-
153-
assert_matches!(start_backend(cmd_args).unwrap_err(), Error::ServeFailed(_));
154-
}
15571
}

0 commit comments

Comments
 (0)