-
Notifications
You must be signed in to change notification settings - Fork 14
Getting Started
Yuya Uezato edited this page Oct 19, 2018
·
7 revisions
組み込みKVSであるCannyLSを実際にRustから呼び出して利用する。
CannyLSはcratesで公開済みであり、cargoを経由して簡単に利用できる。 次のように作業用ディレクトリを作成し
$ cargo new cannyls_wks
$ cd cannyls_wks
cannyls_wks$ ls .
Cargo.toml src
Cargo.toml
の[dependencies]
にcannyls = "0.9.0"
を追加する。
これは例えば次のようになる:
[package]
name = "cannyls_wks"
version = "0.1.0"
authors = ["yuuya uezato <[email protected]>"]
[dependencies]
cannyls = "0.9.0" # <-- 追加
src/main.rs
を次のようにする:
extern crate cannyls;
use cannyls::lump::{LumpData, LumpId};
use cannyls::nvm::FileNvm;
use cannyls::storage::Storage;
fn main() {
// Storageモジュールが利用するファイルを demo.lusf という名前で作成する
// このファイルは最大で 1MB を利用する
// cf. https://docs.rs/cannyls/0.9.0/cannyls/nvm/struct.FileNvm.html
let file: FileNvm = FileNvm::create("demo.lusf", 1_000_000).unwrap();
// 作成したファイル `file` をCannyLSのストレージとして使えるようにする
// cf. https://docs.rs/cannyls/0.9.0/cannyls/storage/struct.Storage.html
let mut storage: Storage<FileNvm> = Storage::create(file).unwrap();
// CannyLSでは、keyは `LumpId` と呼ばれる構造体
// cf. https://docs.rs/cannyls/0.9.0/cannyls/lump/struct.LumpId.html
// ここでは数0からLumpIdを一つ作成する
let lump_id: LumpId = LumpId::new(0);
// CannyLSでは、valueは `LumpData` と呼ばれる構造体
// cf. https://docs.rs/cannyls/0.9.0/cannyls/lump/struct.LumpData.html
// ここでは文字列 `"Hello, CannyLS"` からLumpDataを一つ作成する
let lump_data: LumpData = LumpData::new(Vec::from("Hello, CannyLS")).unwrap();
// 作ったLumpIdとLumpDataを作成したストレージにputする
let result: bool = storage.put(&lump_id, &lump_data).unwrap();
if !result {
// データのputに成功したならば、`result==true`なのでここには来ない
panic!("put failed for some reason...");
}
println!("Put succeeded!");
// key=`lump_id`を用いてputしたLumpDataを取得する
let stored_data: Option<LumpData> = storage.get(&lump_id).unwrap();
if let Some(data) = stored_data {
// keyに対応するデータが存在した場合の処理
println!("Dumping the obtained data:\n {:?}", data);
let byte_data: &[u8] = data.as_bytes();
let string_data: &str = std::str::from_utf8(byte_data).unwrap();
println!("{}", string_data);
assert_eq!(string_data, "Hello, CannyLS");
} else {
// keyに対応するデータが存在しない場合の処理
panic!("CannyLS failed to find your data");
}
}
cannyls_wks$ cargo run
Put succeeded!
Dumping the obtained data:
LumpData { block_size: Some(BlockSize(512)), bytes: [72, 101, 108, 108, 111, 44, 32, 67, 97, 110, 110, 121, 76, 83] }
Hello, CannyLS
実行すると cannyls_wks/demo.lusf
ファイルが出来る。このファイルはrm
コマンドなどで削除して良い。
CannyLSの実装上の中心的な構造体として、上でも用いたStorage
構造体がある。
この構造体については、Storage構造体のドキュメントを参考にされたい。
上で用いなかったメソッドのうちで分かりやすいものに、ストレージのメタ情報を取得するための
Storage::header
や、ストレージに入っているデータ一覧を返す
Storage::list
などもある。
KaNiLSという、 CannyLSのStorageモジュールの公開メソッドを組み合わせたコマンドラインツールが参考になる。
CannyLSに限らず、大規模なサービスの中でKVSを用いると、複数のスレッドで一つのストレージを扱いたくなる。
Rust流の作法ではArc<Mutex<...>>
としてmutex lockを用いた方法もあるが、CannyLSではDeviceモジュールというより良いStorage構造体
を管理する方法を提供している。
extern crate cannyls;
extern crate futures;
use cannyls::device::DeviceBuilder;
use cannyls::lump::{LumpData, LumpId};
use cannyls::nvm::FileNvm;
use cannyls::storage::Storage;
use futures::Future;
use std::{thread, time};
fn wait<E, F: Future<Error = E>>(mut f: F) -> Result<(), E> {
while !(f.poll())?.is_ready() {}
Ok(())
}
fn main() {
let file = FileNvm::create("demo.lusf", 1_000_000_000).unwrap();
let storage = Storage::create(file).unwrap();
let device = DeviceBuilder::new().spawn(|| Ok(storage));
let d = device.handle();
let _ = wait(d.request().wait_for_running().list()); // デバイスの起動を待機
let data = LumpData::new(vec![42; 1_000_000]).unwrap();
for i in 0..10 {
let lump_id = LumpId::new(i);
let future0 = d.request().put(lump_id, data.clone());
wait(future0).unwrap();
}
// thread::sleep(time::Duration::from_secs(3));
}
$ cargo run
$ kanils List --storage demo.lusf
there are no lumps
……?