Skip to content

Commit

Permalink
Add an example
Browse files Browse the repository at this point in the history
  • Loading branch information
al8n committed Sep 14, 2024
1 parent 811832a commit 381c9e5
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 1 deletion.
1 change: 0 additions & 1 deletion examples/foo.rs

This file was deleted.

174 changes: 174 additions & 0 deletions examples/zero_cost.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
use std::{cmp, sync::Arc, thread::spawn};

use orderwal::{swmr::generic::*, utils::*, OpenOptions, Options};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct Person {
id: u64,
name: String,
}

impl Person {
fn random() -> Self {
Self {
id: rand::random(),
name: names::Generator::default().next().unwrap(),
}
}
}

#[derive(Debug)]
struct PersonRef<'a> {
id: u64,
name: &'a str,
}

impl<'a> PartialEq for PersonRef<'a> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id && self.name == other.name
}
}

impl<'a> Eq for PersonRef<'a> {}

impl<'a> PartialOrd for PersonRef<'a> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl<'a> Ord for PersonRef<'a> {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self
.id
.cmp(&other.id)
.then_with(|| self.name.cmp(other.name))
}
}

impl Equivalent<Person> for PersonRef<'_> {
fn equivalent(&self, key: &Person) -> bool {
self.id == key.id && self.name == key.name
}
}

impl Comparable<Person> for PersonRef<'_> {
fn compare(&self, key: &Person) -> std::cmp::Ordering {
self.id.cmp(&key.id).then_with(|| self.name.cmp(&key.name))
}
}

impl Equivalent<PersonRef<'_>> for Person {
fn equivalent(&self, key: &PersonRef<'_>) -> bool {
self.id == key.id && self.name == key.name
}
}

impl Comparable<PersonRef<'_>> for Person {
fn compare(&self, key: &PersonRef<'_>) -> std::cmp::Ordering {
self
.id
.cmp(&key.id)
.then_with(|| self.name.as_str().cmp(key.name))
}
}

impl<'a> KeyRef<'a, Person> for PersonRef<'a> {
fn compare<Q>(&self, a: &Q) -> cmp::Ordering
where
Q: ?Sized + Ord + Comparable<Self>,
{
Comparable::compare(a, self).reverse()
}

fn compare_binary(this: &[u8], other: &[u8]) -> cmp::Ordering {
let (this_id_size, this_id) = decode_u64_varint(this).unwrap();
let (other_id_size, other_id) = decode_u64_varint(other).unwrap();

PersonRef {
id: this_id,
name: std::str::from_utf8(&this[this_id_size..]).unwrap(),
}
.cmp(&PersonRef {
id: other_id,
name: std::str::from_utf8(&other[other_id_size..]).unwrap(),
})
}
}

impl Type for Person {
type Ref<'a> = PersonRef<'a>;
type Error = dbutils::leb128::EncodeVarintError;

fn encoded_len(&self) -> usize {
encoded_u64_varint_len(self.id) + self.name.len()
}

fn encode(&self, buf: &mut [u8]) -> Result<(), Self::Error> {
let id_size = encode_u64_varint(self.id, buf)?;
buf[id_size..].copy_from_slice(self.name.as_bytes());
Ok(())
}
}

impl<'a> TypeRef<'a> for PersonRef<'a> {
fn from_slice(src: &'a [u8]) -> Self {
let (id_size, id) = decode_u64_varint(src).unwrap();
let name = std::str::from_utf8(&src[id_size..]).unwrap();
PersonRef { id, name }
}
}

fn main() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("zero_copy.wal");

let people = (0..100)
.map(|_| {
let p = Person::random();
let v = format!("My name is {}", p.name);
(p, v)
})
.collect::<Vec<_>>();

let mut wal = unsafe {
GenericOrderWal::<Person, String>::map_mut(
&path,
Options::new(),
OpenOptions::new()
.create_new(Some(1024 * 1024))
.write(true)
.read(true),
)
.unwrap()
};

// Create 100 readers
let readers = (0..100).map(|_| wal.reader()).collect::<Vec<_>>();

let people = Arc::new(people);

// Spawn 100 threads to read from the wal
let handles = readers.into_iter().enumerate().map(|(i, reader)| {
let people = people.clone();
spawn(move || loop {
let (person, hello) = &people[i];
if let Some(p) = reader.get(&people[i].0) {
assert_eq!(p.key().id, person.id);
assert_eq!(p.key().name, person.name);
assert_eq!(p.value(), hello);
break;
}
})
});

// Insert 100 people into the wal
for (p, h) in people.iter() {
wal.insert(p, h).unwrap();
}

// Wait for all threads to finish
for handle in handles {
handle.join().unwrap();
}
}

0 comments on commit 381c9e5

Please sign in to comment.