/src/rabbit_msg_store_toke_index.erl

https://github.com/rabbitmq/rabbitmq-toke · Erlang · 100 lines · 67 code · 18 blank · 15 comment · 2 complexity · 12bcbcbebaa10a799bdebdb01b67333f MD5 · raw file

  1. %% The contents of this file are subject to the Mozilla Public License
  2. %% Version 1.1 (the "License"); you may not use this file except in
  3. %% compliance with the License. You may obtain a copy of the License
  4. %% at http://www.mozilla.org/MPL/
  5. %%
  6. %% Software distributed under the License is distributed on an "AS IS"
  7. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  8. %% the License for the specific language governing rights and
  9. %% limitations under the License.
  10. %%
  11. %% The Original Code is RabbitMQ.
  12. %%
  13. %% The Initial Developer of the Original Code is GoPivotal, Inc.
  14. %% Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
  15. %%
  16. -module(rabbit_msg_store_toke_index).
  17. -behaviour(rabbit_msg_store_index).
  18. -include_lib("rabbit_common/include/rabbit_msg_store.hrl").
  19. -rabbit_boot_step({rabbit_toke,
  20. [{description, "Tokyo Cabinet for rabbit_msg_store"},
  21. {mfa, {application, set_env,
  22. [rabbit, msg_store_index_module, ?MODULE]}},
  23. {enables, recovery}]}).
  24. -export([new/1, recover/1,
  25. lookup/2, insert/2, update/2, update_fields/3, delete/2,
  26. delete_object/2, clean_up_temporary_reference_count_entries_without_file/1, terminate/1]).
  27. -define(FILENAME, "msg_store_toke.tch").
  28. new(Dir) ->
  29. {Toke, Path} = init(Dir),
  30. ok = toke_drv:open(Toke, Path, [read, write, create, truncate, no_lock]),
  31. Toke.
  32. recover(Dir) ->
  33. {Toke, Path} = init(Dir),
  34. case toke_drv:open(Toke, Path, [read, write, no_lock]) of
  35. ok -> {ok, Toke};
  36. Err -> {error, Err}
  37. end.
  38. init(Dir) ->
  39. {ok, Toke} = toke_drv:start_link(),
  40. ok = toke_drv:new(Toke),
  41. ok = toke_drv:set_cache(Toke, 1000000),
  42. ok = toke_drv:set_df_unit(Toke, 0),
  43. ok = toke_drv:tune(Toke, 40000000, -1, 15, [large]),
  44. {Toke, filename:join(Dir, ?FILENAME)}.
  45. lookup(Key, Toke) -> %% Key is MsgId which is binary already
  46. case toke_drv:get(Toke, Key) of
  47. not_found -> not_found;
  48. Entry -> #msg_location {} = binary_to_term(Entry)
  49. end.
  50. insert(Obj = #msg_location { msg_id = MsgId }, Toke) ->
  51. ok = toke_drv:insert_async(Toke, MsgId, term_to_binary(Obj)).
  52. update(Obj, Toke) ->
  53. insert(Obj, Toke).
  54. update_fun({Position, NewValue}, ObjAcc) ->
  55. setelement(Position, ObjAcc, NewValue).
  56. update_fields(Key, Updates, Toke) ->
  57. Fun = fun (ObjBin) ->
  58. Obj = #msg_location {} = binary_to_term(ObjBin),
  59. term_to_binary(
  60. case is_list(Updates) of
  61. true -> lists:foldl(fun update_fun/2, Obj, Updates);
  62. false -> update_fun(Updates, Obj)
  63. end)
  64. end,
  65. ok = toke_drv:update_atomically(Toke, Key, Fun).
  66. delete(Key, Toke) ->
  67. ok = toke_drv:delete(Toke, Key).
  68. delete_object(Obj = #msg_location { msg_id = MsgId }, Toke) ->
  69. ok = toke_drv:delete_if_value_eq(Toke, MsgId, term_to_binary(Obj)).
  70. clean_up_temporary_reference_count_entries_without_file(Toke) ->
  71. DeleteMe = toke_drv:fold(
  72. fun (Key, Obj, Acc) ->
  73. case (binary_to_term(Obj))#msg_location.file of
  74. undefined -> [Key | Acc];
  75. _ -> Acc
  76. end
  77. end, [], Toke),
  78. [ok = toke_drv:delete(Toke, Key) || Key <- DeleteMe],
  79. ok.
  80. terminate(Toke) ->
  81. ok = toke_drv:close(Toke),
  82. ok = toke_drv:stop(Toke).