Skip to content

Instantly share code, notes, and snippets.

@angrycub
Created March 20, 2014 15:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angrycub/9666947 to your computer and use it in GitHub Desktop.
Save angrycub/9666947 to your computer and use it in GitHub Desktop.
escript bitcask hintcheck
#!/usr/bin/env escript -f
%% -*- erlang -*-
-define(OFFSETFIELD, 64).
-define(TSTAMPFIELD, 32).
-define(KEYSIZEFIELD, 16).
-define(TOTALSIZEFIELD, 32).
-define(HINTHEADSIZE, 18). %%(?TSTAMPFIELD + ?KEYSIZEFIELD + ?TOTALSIZEFIELD + ?OFFSETFIELD)/8
%% Please export ERL_LIBS=<riak>/lib where riak is probably /usr/lib/riak for package installs
%% Note: this script is designed for Riak 0.14.2 on Debian/Ubuntu
main([Root]) ->
case file:list_dir(filename:absname(Root)) of
{ok, VnodeDirs} ->
[ check_bitcask(filename:absname(Dir, Root)) || Dir <- VnodeDirs];
{error, Reason} ->
io:format("Couldn't list dir ~s: ~w~n", [Root, Reason]),
halt(1)
end;
main(_) ->
usage().
check_bitcask(Dir) ->
io:format("== Checking Bitcask Directory ~s ==~n", [Dir]),
case file:list_dir(Dir) of
{ok, Files} ->
[ scan(filename:absname(F, Dir)) || F <- Files,
filename:extension(F) =:= ".hint"];
{error, Reason} ->
io:format("\tCouldn't list dir ~s: ~w~n", [Dir, Reason])
end.
usage() ->
io:format("usage: bitcaskhintcheck <bitcask-data-root>\n"),
halt(1).
key(<<>>) -> "Hintfile CRC";
key(B) ->
case catch binary_to_term(B) of
K={_,_} -> K;
_ -> "Error decoding key"
end.
read_hint(Fd) ->
case file:read(Fd,?HINTHEADSIZE) of
{ok,
<<Tstamp:?TSTAMPFIELD/integer,
KeySz:?KEYSIZEFIELD/integer,
_TotalSz:?TOTALSIZEFIELD/integer,
Offset:?OFFSETFIELD/integer>>
} ->
case file:read(Fd,KeySz) of
{ok, Key} ->
io:format("Key: ~p Timestamp: ~p Offset: ~b~n",[key(Key),Tstamp,Offset]);
eof -> {error, eof};
{error, Reason} -> {error, Reason};
O -> {error, {unexpected, O}}
end;
eof -> {error, eof};
{error, Reason} -> {error, Reason};
O -> {error, {unexpected, O}}
end.
scan(Filename) when is_list(Filename) ->
{ok, F} = file:open(Filename,[read,raw,binary]),
read_all(F,start).
read_all(_Fd,{error,Reason}) ->
io:format("Stopping due to {error,~p}~n",[Reason]);
read_all(_Fd,eof) ->
io:format("Done~n");
read_all(Fd,_) ->
read_all(Fd,read_hint(Fd)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment