Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Port LevelDB compaction error check to check_node.

  • Loading branch information...
commit af056df5a12746d15efb960aa68f7b2a59ffd9fd 1 parent d9b7699
Daniel Reverri authored
1  .gitignore
@@ -3,3 +3,4 @@ ebin
3 3
 src/*.beam
4 4
 deps
5 5
 check_node
  6
+.eunit
168  src/check_leveldb_compaction.erl
... ...
@@ -0,0 +1,168 @@
  1
+-module(check_leveldb_compaction).
  2
+
  3
+-export([run/2]).
  4
+
  5
+run(Options, _NonOptArgs) ->
  6
+    Node = proplists:get_value(node, Options),
  7
+    KV = rpc:call(Node, application, get_all_env, [riak_kv]),
  8
+    Level = rpc:call(Node, application, get_all_env, [eleveldb]),
  9
+    Env = [{riak_kv, KV}, {eleveldb, Level}],
  10
+    DataRoots = data_roots(Env),
  11
+    case generate_command(DataRoots) of
  12
+        {error, _} ->
  13
+            {unknown, "No LevelDB paths found", []};
  14
+        Cmd ->
  15
+            run_cmd(Node, Cmd)
  16
+    end.
  17
+
  18
+run_cmd(Node, Cmd) ->
  19
+    Resp = rpc:call(Node, os, cmd, [wrap_command(Cmd)]),
  20
+    parse_resp(Resp).
  21
+
  22
+parse_resp(Resp) ->
  23
+    Lines = string:tokens(Resp, "\n"),
  24
+    ExitCode = list_to_integer(lists:nth(1, Lines)),
  25
+    Output = lists:nthtail(1, Lines),
  26
+    handle_output(ExitCode, Output).
  27
+
  28
+handle_output(0, Output) ->
  29
+    case length(Output) > 0 of
  30
+        true ->
  31
+            Errors = string:join(Output, ", "),
  32
+            {critical, "LevelDB compaction errors found: ~s", Errors};
  33
+        false ->
  34
+            {ok, "LevelDB is ok", []}
  35
+    end;
  36
+
  37
+handle_output(Err, Output) ->
  38
+    FirstLine = lists:nth(1, Output),
  39
+    {unknown, "Error code: ~B, message: ~s", [Err, FirstLine]}.
  40
+
  41
+data_roots(Env) ->
  42
+    data_roots([storage_backend(Env)], Env, []).
  43
+
  44
+data_roots([riak_kv_eleveldb_backend|BEs], Env, Acc) ->
  45
+    DataRoot = eleveldb_global_data_root(Env),
  46
+    data_roots(BEs, Env, [DataRoot|Acc]);
  47
+
  48
+data_roots([riak_cs_kv_multi_backend|BEs], Env, Acc) ->
  49
+    MoreBEs = [{BE, Options} || {_, BE, Options} <- multi_backends(Env)],
  50
+    data_roots(BEs ++ MoreBEs, Env, Acc);
  51
+
  52
+data_roots([riak_kv_multi_backend|BEs], Env, Acc) ->
  53
+    MoreBEs = [{BE, Options} || {_, BE, Options} <- multi_backends(Env)],
  54
+    data_roots(BEs ++ MoreBEs, Env, Acc);
  55
+
  56
+data_roots([{riak_kv_eleveldb_backend, Options}|BEs], Env, Acc) ->
  57
+    DataRoot = eleveldb_data_root(Options, Env),
  58
+    data_roots(BEs, Env, [DataRoot|Acc]);
  59
+
  60
+data_roots([_|BEs], Env, Acc) ->
  61
+    data_roots(BEs, Env, Acc);
  62
+
  63
+data_roots([], _, Acc) ->
  64
+    Acc.
  65
+
  66
+eleveldb_data_root(Options, Env) ->
  67
+    case proplists:get_value(data_root, Options) of
  68
+        undefined ->
  69
+            eleveldb_global_data_root(Env);
  70
+        V ->
  71
+            V
  72
+    end.
  73
+
  74
+eleveldb_global_data_root(Env) ->
  75
+    Env1 = proplists:get_value(eleveldb, Env),
  76
+    proplists:get_value(data_root, Env1).
  77
+
  78
+multi_backends(Env) ->
  79
+    Env1 = proplists:get_value(riak_kv, Env),
  80
+    proplists:get_value(multi_backend, Env1).
  81
+
  82
+storage_backend(Env) ->
  83
+    case proplists:get_value(riak_kv, Env) of
  84
+        undefined ->
  85
+            undefined;
  86
+        Env1 ->
  87
+            proplists:get_value(storage_backend, Env1)
  88
+    end.
  89
+
  90
+generate_command([]) ->
  91
+    {error, no_paths};
  92
+
  93
+generate_command(DataRoots) ->
  94
+    %% quote each root in case there are spaces in the path
  95
+    DataRoots1 = [io_lib:format("\"~s\"", [Root]) || Root <- DataRoots],
  96
+    Paths = string:join(DataRoots1, " "),
  97
+    io_lib:format("find ~s -name \"LOG\" -exec grep -l 'Compaction error' {} \\;", [Paths]).
  98
+
  99
+wrap_command(Cmd) ->
  100
+    %% os:cmd/1 does not return the exit code so we fake it the best way we can
  101
+    "O=$(" ++ Cmd ++ " 2>&1);echo $?;echo \"$O\"".    
  102
+
  103
+
  104
+-ifdef(TEST).
  105
+-include_lib("eunit/include/eunit.hrl").
  106
+
  107
+generate_command_test() ->
  108
+    Cmd = generate_command(["/data", "/data/with space"]),
  109
+    Expected = "find \"/data\" \"/data/with space\" -name \"LOG\" -exec grep -l 'Compaction error' {} \\;",
  110
+    ?assertEqual(iolist_to_binary(Expected), iolist_to_binary(Cmd)).
  111
+
  112
+critical_parse_resp_test() ->
  113
+    os:cmd("mkdir critical && echo \"Compaction error\" > critical/LOG"),
  114
+    Cmd = wrap_command(generate_command(["critical"])),
  115
+    Resp = os:cmd(Cmd),
  116
+    ?assertMatch({critical, _, _}, parse_resp(Resp)).
  117
+
  118
+ok_parse_resp_test() ->
  119
+    os:cmd("mkdir okay"),
  120
+    Cmd = wrap_command(generate_command(["okay"])),
  121
+    Resp = os:cmd(Cmd),
  122
+    ?assertMatch({ok, _, _}, parse_resp(Resp)).
  123
+
  124
+unknown_parse_resp_test() ->
  125
+    Cmd = wrap_command(generate_command(["does not exist"])),
  126
+    Resp = os:cmd(Cmd),
  127
+    ?assertMatch({unknown, _, _}, parse_resp(Resp)).
  128
+
  129
+bitcask_data_roots_test() ->
  130
+    Env = [{riak_kv, [{storage_backend, riak_kv_bitcask_backend}]}],
  131
+    ?assertEqual([], data_roots(Env)).
  132
+
  133
+eleveldb_data_roots_test() ->
  134
+    Env = [{riak_kv, [{storage_backend, riak_kv_eleveldb_backend}]},
  135
+           {eleveldb, [{data_root, "/var/lib/riak/leveldb"}]}],
  136
+    ?assertEqual(["/var/lib/riak/leveldb"], data_roots(Env)).
  137
+
  138
+cs_multi_backend_data_roots_test() ->
  139
+    Env = [{riak_kv, [{storage_backend, riak_cs_kv_multi_backend},
  140
+                      {multi_backend, [
  141
+                            {be_default, riak_kv_eleveldb_backend, [
  142
+                                    {cache_size, 47721858},
  143
+                                    {data_root, "/var/lib/riak/leveldb"},
  144
+                                    {max_open_files, 50}
  145
+                                    ]},
  146
+                            {be_blocks, riak_kv_bitcask_backend, [
  147
+                                    {data_root, "/var/lib/riak/bitcask"}
  148
+                                    ]}
  149
+                            ]}]},
  150
+           {eleveldb, [{data_root, "/var/lib/riak/leveldb"}]}],
  151
+    ?assertEqual(["/var/lib/riak/leveldb"], data_roots(Env)).
  152
+
  153
+kv_multi_backend_data_roots_test() ->
  154
+    Env = [{riak_kv, [{storage_backend, riak_cs_kv_multi_backend},
  155
+                      {multi_backend, [
  156
+                            {first_backend, riak_kv_eleveldb_backend, [
  157
+                                    {cache_size, 47721858},
  158
+                                    {data_root, "leveldb1"},
  159
+                                    {max_open_files, 50}
  160
+                                    ]},
  161
+                            {second_backend, riak_kv_eleveldb_backend, [
  162
+                                    {data_root, "leveldb2"}
  163
+                                    ]}
  164
+                            ]}]},
  165
+           {eleveldb, [{data_root, "/var/lib/riak/leveldb"}]}],
  166
+    ?assertEqual(["leveldb1", "leveldb2"], lists:sort(data_roots(Env))).
  167
+
  168
+-endif.
1  src/check_node.erl
@@ -69,6 +69,7 @@ checks() ->
69 69
         {node_up, check_node_up},
70 70
         {riak_kv_up, check_riak_kv_up},
71 71
         {file_handle_count, check_file_handle_count},
  72
+        {leveldb_compaction, check_leveldb_compaction},
72 73
         {riak_repl, check_riak_repl}
73 74
     ].
74 75
 

0 notes on commit af056df

Please sign in to comment.
Something went wrong with that request. Please try again.