misuse-resistant bindings for io_uring, focusing on users who want to do high-performance storage.
This is a very early-stage project, but it will be the core of sled's IO stack over time. It is built with a specific high-level application in mind: a high performance storage engine and replication system.
sled expects to use the following features:
tcp echo server: ```rust use std::{ io::{self, prelude::*}, net::{TcpListener, TcpStream}, };
fn proxy(a: &TcpStream, b: &TcpStream) -> io::Result<()> { let ring = rio::new()?; let mut buf = vec![0u8; 1]; loop { let read = ring.readatordered( a, &mut buf, 0, rio::Ordering::Link, )?; let write = ring.writeat(b, &buf, 0)?; ring.submit_all()?; read.wait()?; write.wait()?; } }
fn main() -> io::Result<()> { let acceptor = TcpListener::bind("127.0.0.1:6666")?;
for stream_res in acceptor.incoming() {
let stream = stream_res?;
proxy(&stream, &stream);
}
Ok(())
} ```
file reading:
```rust let mut ring = rio::new().expect("create uring"); let file = std::fs::open("file").expect("openat"); let dater: &mut [u8] = &[0; 66]; let completion = ring.read(&file, &mut dater, at)?;
// if using threads completion.wait()?;
// if using async completion.await? ```
file writing:
```rust let mut ring = rio::new().expect("create uring"); let file = std::fs::create("file").expect("openat"); let dater: &[u8] = &[6; 66]; let completion = ring.read_at(&file, &dater, at)?;
// if using threads completion.wait()?;
// if using async completion.await? ```
speedy ODIRECT shi0t (try this at home / run the odirect example)
```rust use std::{ fs::OpenOptions, io::Result, os::unix::fs::OpenOptionsExt, };
const CHUNK_SIZE: u64 = 4096 * 256;
// O_DIRECT
requires all reads and writes
// to be aligned to the block device's block
// size. 4096 might not be the best, or even
// a valid one, for yours!
struct Aligned([u8; CHUNK_SIZE as usize]);
fn main() -> Result<()> { // start the ring let ring = rio::new()?;
// open output file, with `O_DIRECT` set
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.custom_flags(libc::O_DIRECT)
.open("file")?;
let out_buf = Aligned([42; CHUNK_SIZE as usize]);
let out_slice: &[u8] = &out_buf.0;
let in_buf = Aligned([42; CHUNK_SIZE as usize]);
let in_slice: &[u8] = &in_buf.0;
let mut completions = vec![];
for i in 0..(10 * 1024) {
let at = i * CHUNK_SIZE;
// By setting the `Link` order,
// we specify that the following
// read should happen after this
// write.
let write = ring.write_at_ordered(
&file,
&out_slice,
at,
rio::Ordering::Link,
)?;
completions.push(write);
let read = ring.read_at(&file, &in_slice, at)?;
completions.push(read);
}
// Submissions will happen lazily when we fill up
// the submission queue, but we should hit this
// ourselves for now. In the future there might
// be a thread that does this automatically
// at some interval if there's work to submit.
ring.submit_all()?;
for completion in completions.into_iter() {
completion.wait()?;
}
Ok(())
} ```