元々 kumofs は configure 時にストレージを選択できるようになっていて、本体部分とストレージ部分が API によりある程度分離されています。なので独自にストレージを作成することもそんなに難しくなくできると思います。
ストレージ部には21個の関数が必要です。関数は src/storage/interface.h で定義されています。
以下、各関数について説明します。関数名の「xxxxx」は通常ストレージ固有の名前を指定します。たとえば kumofs 標準のストレージである Tokyo Cabinet の Hash の場合は tchdb となっています。
嘘書いてあるかもしれないので、あまり信じない方がいいと思います。
ストレージ層に渡されるキーとデータはクライアントから指定されたものそのままではなく、kumofs 管理用のヘッダがついています。キーのヘッダは 8バイト、データのヘッダは 10バイトです。詳しくは doc/doc.ja.md の FAQ データベースファイルのフォーマットを見てください。
create
static void* kumo_xxxxx_create(void)
初期化。kumo-server 起動時に呼ばれます。
戻り値は任意のポインタです。これ以外の関数の呼び出し時に data として渡されるものです。
NULL を返すと初期化に失敗したことを表し、kumo-server は終了します。
free
static void kumo_xxxxx_free(void* data)
kumo-server 終了時に呼ばれます。
open
static bool kumo_xxxxx_open(void* data, const char* path)
kumo-server が attach された時に呼ばれます。
path は kumo-server の -s オプションで指定されたファイル名です。
close
static void kumo_xxxxx_close(void* data)
kumo-server 終了時に呼ばれます。
get
static const char* kumo_xxxxx_get(void* data, const char* key, uint32_t keylen, uint32_t* result_vallen, msgpack_zone* zone)
データを取り出します。
key, keylen はキーの値と長さを示します。
戻り値で取り出したデータの値のポインタを返します。データが見つからなかった場合、処理に失敗した場合は NULL を返します。
result_vallen はデータの長さを返すポインタです。
データが不要になった場合の処理は次のように登録します。
msgpack_zone_push_finalizer(zone, 関数名, 関数に渡す引数);
msgpack_zone_push_finalizer() が 0 を返した場合は登録に失敗しているので、kumo_xxxxx_get() も NULL を返す必要があります。
データを格納したメモリを malloc() で獲得し、ポインタ val で保持している場合の処理は、通常次のようになります。
if (!msgpack_zone_push_finalizer(zone, free, val)) { free(val); return NULL; }
get_header
static int32_t kumo_xxxxx_get_header(void* data, const char* key, uint32_t keylen, char* result_val, uint32_t vallen)
kumo_xxxxx_get() と同じく値を取り出しますが、返すデータの最大長が指定されています。
key, keylen はキーの値と長さを示します。
取り出した値は result_val に入ります。result_val の大きさは vallen で指定されています。
戻り値は result_val に書き込んだデータの長さです。データが見つからなかった場合は -1 を返します。
set
static bool kumo_xxxxx_set(void* data, const char* key, uint32_t keylen, const char* val, uint32_t vallen)
キーとデータを格納します。
key, keylen はキーの値と長さを示します。
val, vallen はデータの値と長さを示します。
成功した場合 true, 失敗した場合 false を返します。
del
static bool kumo_xxxxx_del(void* data, const char* key, uint32_t keylen, kumo_storage_casproc proc, void* casdata)
キーとデータを削除します。
key, keylen はキーの値と長さを示します。
proc と casdata はCAS処理のために使用されます。
指定されたキーが存在する場合、「proc(casdata, 既存データ値, 既存データ長)」を呼び出します。
proc が true を返した場合データを削除して true を返します。
proc が false を返した場合はデータを削除せずに false を返します。
update
static bool kumo_xxxxx_update(void* data, const char* key, uint32_t keylen, const char* val, uint32_t vallen, kumo_storage_casproc proc, void* casdata)
キーに対応するデータを更新します。
key, keylen はキーの値と長さを示します。
val, vallen はデータの値と長さを示します。
proc と casdata はCAS処理のために使用されます。
指定されたキーが存在しない場合データを登録します。
指定されたキーが存在する場合、「proc(casdata, 既存データ値, 既存データ長)」を呼び出します。
proc が true を返した場合データを更新して true を返します。
proc が false を返した場合はデータを更新せずに false を返します。
rnum
static uint64_t kumo_xxxxx_rnum(void* data)
ストレージ内の全データの数を返します。
backup
static bool kumo_xxxxx_backup(void* data, const char* dstpath)
kumoctl backup 時に呼ばれます。
dstpath はバックアップ先のファイル名です。
成功した場合は true, 失敗した場合は false を返します。
error
static const char* kumo_xxxxx_error(void* data)
エラーメッセージを返します。
for_each
static int kumo_xxxxx_for_each(void* data, void* user, int (*func)(void* user, void* iterator_data))
ストレージの全データを順番に指定された関数 func に渡します。
func の第一引数は user をそのまま渡します。
func の第二引数は1件のデータを表すポインタで kumo_xxxxx_iterator_ で始まる関数に渡されます。
iterator_key
static const char* kumo_xxxxx_iterator_key(void* iterator_data)
iterator_data からキー値のポインタを取り出します。
iterator_val
static const char* kumo_xxxxx_iterator_val(void* iterator_data)
iterator_data からデータ値のポインタを取り出します。
iterator_keylen
static size_t kumo_xxxxx_iterator_keylen(void* iterator_data)
iterator_data からキーの長さを取り出します。
iterator_vallen
static size_t kumo_xxxxx_iterator_vallen(void* iterator_data)
iterator_data からデータの長さを取り出します。
iterator_release_key
static const char* kumo_xxxxx_iterator_release_key(void* iterator_data, msgpack_zone* zone)
iterator_data からキー値のポインタを取り出します。
メモリ管理をイテレータから zone に移します。キー値のメモリ解放は msgpack_zone_push_finalizer() で zone にまかせます。イテレータ側でメモリを解放してはいけません。
実際にはこの関数は kumofs では使用されていないように見えます。
iterator_release_val
static const char* kumo_xxxxx_iterator_release_val(void* iterator_data, msgpack_zone* zone)
iterator_data からデータ値のポインタを取り出します。
メモリ管理をイテレータから zone に移します。データ値のメモリ解放は msgpack_zone_push_finalizer() で zone にまかせます。イテレータ側でメモリを解放してはいけません。
実際にはこの関数は kumofs では使用されていないように見えます。
iterator_del
static bool kumo_xxxxx_iterator_del(void* iterator_data, kumo_storage_casproc proc, void* casdata)
iterator_data が示すデータを削除します。
成功した場合は true, 失敗した場合は false を返します。
proc, casdata は kumo_xxxxx_del() と同様です。
iterator_del_force
static bool kumo_xxxxx_iterator_del_force(void* iterator_data)
iterator_data が示すデータを削除します。
kumo_storage_init
上記各関数のポインタが入ってる kumofs_storage_op 構造体のポインタを返します。kumo-server 起動時に呼ばれます。以降のストレージ処理はこの構造体のメンバ関数を通して処理されます。
次のように使用します。
static kumo_storage_op kumo_xxxxx_op = { kumo_xxxxx_create, kumo_xxxxx_free, kumo_xxxxx_open, kumo_xxxxx_close, kumo_xxxxx_get, kumo_xxxxx_get_header, kumo_xxxxx_set, kumo_xxxxx_del, kumo_xxxxx_update, NULL, kumo_xxxxx_rnum, kumo_xxxxx_backup, kumo_xxxxx_error, kumo_xxxxx_for_each, kumo_xxxxx_iterator_key, kumo_xxxxx_iterator_val, kumo_xxxxx_iterator_keylen, kumo_xxxxx_iterator_vallen, kumo_xxxxx_iterator_release_key, kumo_xxxxx_iterator_release_val, kumo_xxxxx_iterator_del, kumo_xxxxx_iterator_del_force, }; kumo_storage_op kumo_storage_init(void) { return kumo_xxxxx_op; }