Skip to content

Commit

Permalink
First working version
Browse files Browse the repository at this point in the history
  • Loading branch information
carstein committed Jan 23, 2023
0 parents commit 498b4d2
Show file tree
Hide file tree
Showing 13 changed files with 385 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
25 changes: 25 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "cargo",
"command": "build",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
},
"label": "rust: cargo build"
},
{
"type": "cargo",
"command": "run",
"problemMatcher": [
"$rustc"
],
"label": "rust: cargo run"
}
]
}
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "quick_kv"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## Future development

**Update**
Add support for update command

**Metadata**
Serialize and deserialize metadata on start

**Add cache**
- on read create cache (no size limit)
- invalidate cache on write (all of it)

**Better cache**
- invalidate single cache entry
- cache limit - remove least access element on read

**Remove elements**
Add support for delete command
Set of free blocks
Write use one of the free blocks
25 changes: 25 additions & 0 deletions create_pages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env python3

import sys

page_size = 1024
filename = "page.db"

def generate_page(value):
b = []
pattern = 0x41 + value

for i in range(page_size):
b.append(chr(pattern))

return ''.join(b)

def main():
with open(filename, "w") as fh:

for x in range(0, 20):
fh.write(generate_page(x))


if __name__ == "__main__":
sys.exit(main())
11 changes: 11 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(Debug)]
pub enum Error {
NamespaceNotFound,
FileTooSmall,
InvalidValueLen,
PageReadOverflow,
KeyNotFound,
ValueToLarge,
DataFileSeek,
DataFileWrite
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod storage;
mod page;
mod metadata;
mod error;
40 changes: 40 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use quick_kv::storage::Storage;


fn main() {
let namespace = String::from("test");
let mut storage = Storage::new(namespace);

let values = [
("test1", vec![0x41; 8]),
("test2", vec![0x42; 12]),
("test3", vec![0x43; 1020]),
("test4", vec![0x44; 16]),
];

for (key, value) in values {
storage.write(&String::from(key), &value).unwrap();
}

let keys = [
"test1",
"test2",
"test3",
"test4",
"test5"
];

for key in keys {
let value = match storage.read(&String::from(key)) {
Ok(v) => v,
Err(e) => {
// Handle error
eprintln!("[{:?}] Key \"{}\" not found", e, &key);
return;
}
};

println!("Value read: 0x{:x} times {}", value[0], value.len());
}

}
92 changes: 92 additions & 0 deletions src/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use std::collections::HashMap;

const PAGE_SIZE: u64 = 1024;

#[derive(Debug, Clone, Copy)]
pub struct Location {
offset: u64,
length: u64,
}

#[derive(Debug)]
pub struct Metadata {
index: HashMap<String, Location>,
pub write_cursor: u64,
}


impl Location {
pub fn new(offset:u64, length:u64) -> Location {
Location {
offset,
length
}
}

pub fn get_offset(self) -> u64 {
self.offset
}

pub fn len(self) -> u64 {
self.length
}

pub fn get_page_offset(self) -> u64 {
// zero out last 10 bits
self.offset & !(PAGE_SIZE - 1)
}

pub fn get_relative_offset(self) -> u64 {
// keep last 10 bits
self.offset & !(PAGE_SIZE - 1)
}
}

impl Metadata {
pub fn new(namespace: String) -> Metadata {
// if file exist, deserialize metadata
// otherwise, create empty one

Metadata {
index: HashMap::new(),
write_cursor: 0,
}
}

pub fn get_write_cursor(&self) -> u64 {
self.write_cursor
}

pub fn update_write_cursor(&mut self, new_cursor: u64) {
self.write_cursor = new_cursor;
}

pub fn get_item_location(&self, key: &String) -> Option<&Location> {
self.index.get(key)
}

pub fn set_item_location(&mut self, name: &String, location: Location) {
self.index.insert(name.to_owned(), location);
}
}


#[cfg(test)]
mod tests {
use super::*;

#[test]
fn page_offset() {
let location_1 = Location {
offset: 536,
length: 10
};
let location_2 = Location {
offset: 1536,
length: 10
};

assert_eq!(location_1.get_page_offset(), 0);
assert_eq!(location_2.get_page_offset(), 1024);
}
}
25 changes: 25 additions & 0 deletions src/page.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

pub const PAGE_SIZE: u64 = 1024;

#[derive(Debug)]
pub struct Page {
offset: u64,
access_count: usize,
pub data: Vec<u8>,
}

impl Page {
pub fn new() -> Page {
Page {
offset: 0,
access_count: 0,
data: Vec::with_capacity(PAGE_SIZE as usize),
}
}
}

impl Default for Page {
fn default() -> Self {
Page::new()
}
}
Loading

0 comments on commit 498b4d2

Please sign in to comment.