/src/dreyfus/src/dreyfus_bookmark.erl

https://github.com/apache/couchdb · Erlang · 90 lines · 63 code · 15 blank · 12 comment · 1 complexity · 2999f2c1c6085cc949576ecb67267638 MD5 · raw file

  1. % Licensed under the Apache License, Version 2.0 (the "License"); you may not
  2. % use this file except in compliance with the License. You may obtain a copy of
  3. % the License at
  4. %
  5. % http://www.apache.org/licenses/LICENSE-2.0
  6. %
  7. % Unless required by applicable law or agreed to in writing, software
  8. % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. % License for the specific language governing permissions and limitations under
  11. % the License.
  12. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  13. -module(dreyfus_bookmark).
  14. -include("dreyfus.hrl").
  15. -include_lib("mem3/include/mem3.hrl").
  16. -export([
  17. update/3,
  18. unpack/2,
  19. pack/1,
  20. add_missing_shards/2
  21. ]).
  22. update(_Sort, Bookmark, []) ->
  23. Bookmark;
  24. update(relevance, Bookmark, [#sortable{} = Sortable | Rest]) ->
  25. #sortable{
  26. order = [Score, Doc],
  27. shard = Shard
  28. } = Sortable,
  29. B1 = fabric_dict:store(Shard, {Score, Doc}, Bookmark),
  30. B2 = fabric_view:remove_overlapping_shards(Shard, B1),
  31. update(relevance, B2, Rest);
  32. update(Sort, Bookmark, [#sortable{} = Sortable | Rest]) ->
  33. #sortable{
  34. order = Order,
  35. shard = Shard
  36. } = Sortable,
  37. B1 = fabric_dict:store(Shard, Order, Bookmark),
  38. B2 = fabric_view:remove_overlapping_shards(Shard, B1),
  39. update(Sort, B2, Rest).
  40. unpack(DbName, #index_query_args{bookmark=nil} = Args) ->
  41. fabric_dict:init(dreyfus_util:get_shards(DbName, Args), nil);
  42. unpack(DbName, #index_query_args{} = Args) ->
  43. unpack(DbName, Args#index_query_args.bookmark);
  44. unpack(DbName, Packed) when is_binary(Packed) ->
  45. lists:map(fun({Node, Range, After}) ->
  46. case mem3:get_shard(DbName, Node, Range) of
  47. {ok, Shard} ->
  48. {Shard, After};
  49. {error, not_found} ->
  50. PlaceHolder = #shard{
  51. node = Node,
  52. range = Range,
  53. dbname = DbName,
  54. _='_'
  55. },
  56. {PlaceHolder, After}
  57. end
  58. end, binary_to_term(couch_util:decodeBase64Url(Packed))).
  59. pack(nil) ->
  60. null;
  61. pack(Workers) ->
  62. Workers1 = [{N,R,A} || {#shard{node=N, range=R}, A} <- Workers, A =/= nil],
  63. Bin = term_to_binary(Workers1, [compressed, {minor_version,1}]),
  64. couch_util:encodeBase64Url(Bin).
  65. add_missing_shards(Bookmark, LiveShards) ->
  66. {BookmarkShards, _} = lists:unzip(Bookmark),
  67. add_missing_shards(Bookmark, BookmarkShards, LiveShards).
  68. add_missing_shards(Bookmark, _, []) ->
  69. Bookmark;
  70. add_missing_shards(Bookmark, BMShards, [H | T]) ->
  71. Bookmark1 = case lists:keymember(H#shard.range, #shard.range, BMShards) of
  72. true -> Bookmark;
  73. false -> fabric_dict:store(H, nil, Bookmark)
  74. end,
  75. add_missing_shards(Bookmark1, BMShards, T).