/2011/riak-core-the-vnode/rts/src/rts_stat_vnode.erl

https://github.com/oier/try-try-try · Erlang · 135 lines · 97 code · 29 blank · 9 comment · 0 complexity · f75f967169b54db46325995444571d3a MD5 · raw file

  1. %% @doc A vnode to handle get & put commands for stat data. The vnode
  2. %% requests will be hashed on Client and StatName and will use a
  3. %% coordinator to enforce N/R/W values.
  4. -module(rts_stat_vnode).
  5. -behaviour(riak_core_vnode).
  6. -include("rts.hrl").
  7. -include_lib("riak_core/include/riak_core_vnode.hrl").
  8. -export([start_vnode/1,
  9. init/1,
  10. terminate/2,
  11. handle_command/3,
  12. is_empty/1,
  13. delete/1,
  14. handle_handoff_command/3,
  15. handoff_starting/2,
  16. handoff_cancelled/1,
  17. handoff_finished/2,
  18. handle_handoff_data/2,
  19. encode_handoff_item/2]).
  20. -export([
  21. get/2,
  22. set/3,
  23. incr/2,
  24. incrby/3,
  25. append/3,
  26. sadd/3
  27. ]).
  28. -record(state, {partition, stats}).
  29. -define(MASTER, rts_stat_vnode_master).
  30. -define(sync(PrefList, Command, Master),
  31. riak_core_vnode_master:sync_command(PrefList, Command, Master)).
  32. %%%===================================================================
  33. %%% API
  34. %%%===================================================================
  35. start_vnode(I) ->
  36. riak_core_vnode_master:get_vnode_pid(I, ?MODULE).
  37. get(IdxNode, StatName) ->
  38. ?sync(IdxNode, {get, StatName}, ?MASTER).
  39. set(IdxNode, StatName, Val) ->
  40. ?sync(IdxNode, {set, StatName, Val}, ?MASTER).
  41. incr(IdxNode, StatName) ->
  42. ?sync(IdxNode, {incr, StatName}, ?MASTER).
  43. incrby(IdxNode, StatName, Val) ->
  44. ?sync(IdxNode, {incrby, StatName, Val}, ?MASTER).
  45. append(IdxNode, StatName, Val) ->
  46. ?sync(IdxNode, {append, StatName, Val}, ?MASTER).
  47. sadd(IdxNode, StatName, Val) ->
  48. ?sync(IdxNode, {sadd, StatName, Val}, ?MASTER).
  49. %%%===================================================================
  50. %%% Callbacks
  51. %%%===================================================================
  52. init([Partition]) ->
  53. {ok, #state { partition=Partition, stats=dict:new() }}.
  54. handle_command({get, StatName}, _Sender, #state{stats=Stats}=State) ->
  55. Reply =
  56. case dict:find(StatName, Stats) of
  57. error ->
  58. not_found;
  59. Found ->
  60. Found
  61. end,
  62. {reply, Reply, State};
  63. handle_command({set, StatName, Val}, _Sender, #state{stats=Stats0}=State) ->
  64. Stats = dict:store(StatName, Val, Stats0),
  65. {reply, ok, State#state{stats=Stats}};
  66. handle_command({incr, StatName}, _Sender, #state{stats=Stats0}=State) ->
  67. Stats = dict:update_counter(StatName, 1, Stats0),
  68. {reply, ok, State#state{stats=Stats}};
  69. handle_command({incrby, StatName, Val}, _Sender, #state{stats=Stats0}=State) ->
  70. Stats = dict:update_counter(StatName, Val, Stats0),
  71. {reply, ok, State#state{stats=Stats}};
  72. handle_command({append, StatName, Val}, _Sender, #state{stats=Stats0}=State) ->
  73. Stats = try dict:append(StatName, Val, Stats0)
  74. catch _:_ -> dict:store(StatName, [Val], Stats0)
  75. end,
  76. {reply, ok, State#state{stats=Stats}};
  77. handle_command({sadd, StatName, Val}, _Sender, #state{stats=Stats0}=State) ->
  78. F = fun(S) ->
  79. sets:add_element(Val, S)
  80. end,
  81. Stats = dict:update(StatName, F, sets:from_list([Val]), Stats0),
  82. {reply, ok, State#state{stats=Stats}}.
  83. handle_handoff_command(?FOLD_REQ{foldfun=Fun, acc0=Acc0}, _Sender, State) ->
  84. Acc = dict:fold(Fun, Acc0, State#state.stats),
  85. {reply, Acc, State}.
  86. handoff_starting(_TargetNode, _State) ->
  87. {true, _State}.
  88. handoff_cancelled(State) ->
  89. {ok, State}.
  90. handoff_finished(_TargetNode, State) ->
  91. {ok, State}.
  92. handle_handoff_data(Data, #state{stats=Stats0}=State) ->
  93. {StatName, Val} = binary_to_term(Data),
  94. Stats = dict:store(StatName, Val, Stats0),
  95. {reply, ok, State#state{stats=Stats}}.
  96. encode_handoff_item(StatName, Val) ->
  97. term_to_binary({StatName,Val}).
  98. is_empty(State) ->
  99. case dict:size(State#state.stats) of
  100. 0 -> {true, State};
  101. _ -> {false, State}
  102. end.
  103. delete(State) ->
  104. {ok, State}.
  105. terminate(_Reason, _State) ->
  106. ok.