1

(編集:ビットキャスクタグを作成するという評判が恋しいので...)

tl; dr => bitcask:get / 2が機能せず、bitcask_nifs:keydir_get_intでbadargが発生します)

正しい方法でriakを使わずにbitcaskを使用する方法を知りたいです。

まず、私はこれを試していました:

bitcask:put(Handle, 3, {this, is, data}).
bitcask:get(Handle, 3).

この2つの呼び出しで同じエラーが発生します:badarg with erlang:size / 1

問題はerlang:size/1がバイナリまたはタプルのみを受け入れることです。だから私はこれを試していました:

bitcask:put(Handle, {thing, 3}, {this, is, data}).
bitcask:get(Handle, {thing, 3}).

erlang:crc32と保存したい値を含む新しいbadargエラー。

だから今私はこのコードを使用します、バケットはハンドルをその状態に保つ登録されたgen_serverのアトム名です。cask_wrapperは、これらのgen_serversのコードです。以下のコードは、これらのgenサーバーへのアクセスです。

-module(sr_db).
...
get(Type, Key) when not is_binary(Key) ->
    ?MODULE:get(Type, term_to_binary(Key));
get(Type, Key) ->
    Bucket = type2bucket(Type),
    cask_wrapper:get(Bucket, {get, Key}).

put(Type, Key, Data) when not is_binary(Key) ->
    ?MODULE:put(Type, term_to_binary(Key), Data);

put(Type, Key, Data) when not is_binary(Data) ->
    ?MODULE:put(Type, Key, term_to_binary(Data));

put(Type, Key, Data) ->
    Bucket = type2bucket(Type),
    cask_wrapper:put(Bucket, Key, Data),
    ok.
%% syncput(Type, Key, Data) -> call au lieu de cast

type2bucket(user) -> users_cask.

私はこのコードを次のように使用します:

sr_db:get(user, 3).
%% then a call is made to cask_wrapper:get(users_cask, {get, 3}).

cask_wrapper関数があります

get(Bucket, Key) ->
    gen_server:call(Bucket, {get, Key}).

handle_call({get, Key}, _From, State) ->
    Fetch = bitcask:get(State#state.handle, Key),
    {reply, Fetch, State}.

put関数でも同じメカニズムを使用しています。(ただし、gen_server:castを使用)

私の最初の質問は:すべての呼び出しでterm_to_binary変換を行うのは良い習慣ですか、それとも遅いですか?フェッチした値をerlang用語に変換し直す必要があります。

現時点では、put操作は「ok」を返します。できます。ただし、get操作はまだ機能しません。これはエラーです:

=ERROR REPORT==== 29-Jan-2012::20:21:24 ===
** Generic server users_cask terminating
** Last message in was {get,{get,<<131,97,3>>}}
** When Server state == {state,#Ref<0.0.0.353>}
** Reason for termination ==
** {badarg,[{bitcask_nifs,keydir_get_int,[<<>>,{get,<<131,97,3>>}]},
            {bitcask_nifs,keydir_get,2},
            {bitcask,get,3},
            {cask_wrapper,handle_call,3},
            {gen_server,handle_msg,5},
            {proc_lib,init_p_do_apply,3}]}
Bitcask dir : "/home/niahoo/src/skyraiders/priv/bitcasks/users"
options : [read_write]** exception exit: {{badarg,
                        [{bitcask_nifs,keydir_get_int,
                             [<<>>,{get,<<131,97,3>>}]},
                         {bitcask_nifs,keydir_get,2},
                         {bitcask,get,3},
                         {cask_wrapper,handle_call,3},
                         {gen_server,handle_msg,5},
                         {proc_lib,init_p_do_apply,3}]},
                    {gen_server,call,[users_cask,{get,{get,<<131,97,3>>}}]}}
     in function  gen_server:call/2

なぜそれが機能しないのか理解できず、助けていただければ幸いです。

ありがとうございました

4

1 に答える 1

1

Bitcaskは、キーと値の両方がバイナリであることを期待しています(すでにお気づきのとおり)。term_to_binary / binary_to_termの速度はよくわかりませんが、用語をディスクに保存したい場合は、それを回避する方法はありません。もちろん、独自のコードをロールして、キーと値をバイナリとの間で変換することもできますが、組み込み関数よりも大幅に高速で、柔軟性が低いことは間違いありません。しかし、1日の終わりに、アプリケーションのプロファイルを測定し、term_to_binary/binary_to_termがシステム全体のホットスポットであるかどうかを判断する必要があります。データをディスクに書き込む必要がある実際のアプリケーションの場合は、非常に驚​​きます。

ここで、sr_db:get/2を呼び出すときのエラーについて説明します。キーを{get、Key}タプル内で2回、sr_db:get / 2内で1回、cask_wrapper:get / 2内でもう1回ラップしていますが、cask_wrapper:handle_call / 3で照合することにより、1回だけアンラップします。これは、次の2行のエラーレポートですぐにわかります。

**最後のメッセージは{get、{get、<<131,97,3>>}}でした

{gen_server、call、[users_cask、{get、{get、<< 131,97,3 >>}}]}}

于 2012-01-31T11:33:20.000 に答える