Как использовать bitcask как самостоятельный - PullRequest
1 голос
/ 29 января 2012

(редактировать: я скучаю по репутации, чтобы создать тег bitcask, так что ...)

( tl; dr => bitcask: get / 2 не работает и поднимает badargв bitcask_nifs: keydir_get_int)

Я хотел бы знать, как правильно использовать bitcask без riak.

Сначала я пытался это:

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

Это двавызовы вызывают ту же ошибку: badarg с erlang: размер / 1

Проблема в том, что erlang: size / 1 принимает только двоичные файлы или кортежи.Итак, я пытался это:

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

Затем появилась новая ошибка badarg, с erlang: crc32 и значением, которое я хочу сохранить.

Итак, теперь я использую этот код, ведро - это атомимя зарегистрированного сервера gen_server, который сохраняет дескриптор в своем состоянии.cask_wrapper - код для этих gen_servers.Приведенный ниже код является доступом к этим серверам.

-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 в каждом вызове хорошей практикой, или это медленно?Мне придется преобразовать обратно в термины Эрланга значения, которые я получаю.

В данный момент операция 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

Я не могу понять, почему это не работает, и был бы признателен за помощь.

Спасибо

1 Ответ

1 голос
/ 31 января 2012

Bitcask ожидает, что ключ и значение являются двоичными (как вы уже заметили).Я действительно не знаю, насколько быстрым является term_to_binary / binary_to_term, но на самом деле нет никакого способа обойти это, если вы хотите хранить термины на диске.Конечно, вы можете свернуть свой собственный код для преобразования ваших ключей и значений в / из двоичных файлов, но я сомневаюсь, что он будет значительно быстрее встроенных функций и, конечно, менее гибким.Но в конце дня вы должны измерить профиль вашего приложения и решить, является ли term_to_binary / binary_to_term горячей точкой в ​​вашей общей системе.Я был бы очень удивлен, если это имеет место в любом реальном приложении, где данные должны быть записаны на диск.

Теперь об ошибке при вызове sr_db: get / 2.Вы дважды оборачиваете ключ в кортеж {get, Key}, один раз внутри sr_db: get / 2, а другой раз в cask_wrapper: get / 2, но вы разворачиваете его только один раз, сопоставляя в cask_wrapper: handle_call / 3.Вы можете сразу же обнаружить это в отчете об ошибках в этих двух строках:

** Последнее сообщение было {get, {get, << 131,97,3 >>}}

и

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

...