changeset 521:c819897ec8fc

Add kvserver example Just for fun
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 23 Feb 2020 22:59:01 +0100
parents b339b1817b84
children f4bbb33b6b4c
files Cargo.toml examples/kvserver/.hgignore examples/kvserver/Cargo.toml examples/kvserver/README.md examples/kvserver/src/main.rs
diffstat 5 files changed, 82 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Cargo.toml	Sat Feb 22 23:29:55 2020 +0100
+++ b/Cargo.toml	Sun Feb 23 22:59:01 2020 +0100
@@ -28,5 +28,5 @@
 path = "src/benches/maps_bench.rs"
 
 [workspace]
-members = ["examples/write-a-lot", "examples/leveldb-tool", "examples/word-analyze"]
+members = ["examples/write-a-lot", "examples/leveldb-tool", "examples/word-analyze", "examples/kvserver"]
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/kvserver/.hgignore	Sun Feb 23 22:59:01 2020 +0100
@@ -0,0 +1,1 @@
+^target/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/kvserver/Cargo.toml	Sun Feb 23 22:59:01 2020 +0100
@@ -0,0 +1,11 @@
+[package]
+name = "kvserver"
+version = "0.1.0"
+authors = ["Lewin Bormann <lewin@lewin-bormann.info>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+canteen = "0.5"
+rusty-leveldb = { path = "../../" }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/kvserver/README.md	Sun Feb 23 22:59:01 2020 +0100
@@ -0,0 +1,10 @@
+# kvserver
+
+A simplistic Key/Value HTTP server using rusty-leveldb.
+
+It is not multi-threaded, and achieves around 13'000 ops per second (both
+fetching and storing keys) on my somewhat old `Intel(R) Xeon(R) CPU E5-1650 v2 @
+3.50GHz` using `ab`.
+
+For comparison, writing of random keys directly (in-process) usually happens at
+300'000 keys per second.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/kvserver/src/main.rs	Sun Feb 23 22:59:01 2020 +0100
@@ -0,0 +1,59 @@
+use canteen;
+use rusty_leveldb;
+
+struct KVService {
+    db: rusty_leveldb::DB,
+}
+
+static mut STORAGE_SERVICE: Option<std::sync::Mutex<KVService>> = None;
+
+impl KVService {
+    fn handle_get(&mut self, req: &canteen::Request) -> canteen::Response {
+        let key: String = req.get("key");
+
+        let val = self.db.get(key.as_bytes());
+
+        let mut rp = canteen::Response::new();
+
+        rp.set_status(200);
+        rp.set_content_type("text/plain");
+
+        if let Some(val) = val {
+            rp.append(val);
+        } else {
+            rp.set_status(404);
+        }
+        rp
+    }
+    fn handle_put(&mut self, req: &canteen::Request) -> canteen::Response {
+        let mut rp = canteen::Response::new();
+        let key: String = req.get("key");
+        let val = &req.payload;
+
+        self.db.put(key.as_bytes(), val.as_ref()).unwrap();
+
+        rp.set_status(200);
+        rp.set_content_type("text/plain");
+        rp
+    }
+}
+
+fn get_key_fn(rq: &canteen::Request) -> canteen::Response {
+    unsafe { STORAGE_SERVICE.as_ref().unwrap().lock().unwrap().handle_get(rq) }
+}
+
+fn put_key_fn(rq: &canteen::Request) -> canteen::Response {
+    unsafe { STORAGE_SERVICE.as_ref().unwrap().lock().unwrap().handle_put(rq) }
+}
+
+fn main() {
+    let db = rusty_leveldb::DB::open("httpdb", rusty_leveldb::Options::default()).unwrap();
+    let service = KVService { db: db };
+    unsafe { STORAGE_SERVICE = Some(std::sync::Mutex::new(service)) };
+
+    let mut ct = canteen::Canteen::new();
+    ct.add_route("/kvs/get/<str:key>", &[canteen::Method::Get], get_key_fn);
+    ct.add_route("/kvs/put/<str:key>", &[canteen::Method::Put, canteen::Method::Post], put_key_fn);
+    ct.bind("0.0.0.0:8080");
+    ct.run()
+}