kumofs ストレージ API

kumofs のストレージのAPIについて調べてみました。

元々 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;
}