blob: 9a2979b255ea3ae028dc2197c285808d87002086 [file] [log] [blame]
% Licensed under the Apache License, Version 2.0 (the "License"); you may not
% use this file except in compliance with the License. You may obtain a copy of
% the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
% License for the specific language governing permissions and limitations under
% the License.
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
-module(dreyfus_bookmark).
-include("dreyfus.hrl").
-include_lib("mem3/include/mem3.hrl").
-export([
update/3,
unpack/2,
pack/1,
add_missing_shards/2
]).
update(_Sort, Bookmark, []) ->
Bookmark;
update(relevance, Bookmark, [#sortable{} = Sortable | Rest]) ->
#sortable{
order = [Score, Doc],
shard = Shard
} = Sortable,
B1 = fabric_dict:store(Shard, {Score, Doc}, Bookmark),
B2 = fabric_view:remove_overlapping_shards(Shard, B1),
update(relevance, B2, Rest);
update(Sort, Bookmark, [#sortable{} = Sortable | Rest]) ->
#sortable{
order = Order,
shard = Shard
} = Sortable,
B1 = fabric_dict:store(Shard, Order, Bookmark),
B2 = fabric_view:remove_overlapping_shards(Shard, B1),
update(Sort, B2, Rest).
unpack(DbName, #index_query_args{bookmark=nil} = Args) ->
fabric_dict:init(dreyfus_util:get_shards(DbName, Args), nil);
unpack(DbName, #index_query_args{} = Args) ->
unpack(DbName, Args#index_query_args.bookmark);
unpack(DbName, Packed) when is_binary(Packed) ->
lists:map(fun({Node, Range, After}) ->
case mem3:get_shard(DbName, Node, Range) of
{ok, Shard} ->
{Shard, After};
{error, not_found} ->
PlaceHolder = #shard{
node = Node,
range = Range,
dbname = DbName,
_='_'
},
{PlaceHolder, After}
end
end, binary_to_term(couch_util:decodeBase64Url(Packed))).
pack(nil) ->
null;
pack(Workers) ->
Workers1 = [{N,R,A} || {#shard{node=N, range=R}, A} <- Workers, A =/= nil],
Bin = term_to_binary(Workers1, [compressed, {minor_version,1}]),
couch_util:encodeBase64Url(Bin).
add_missing_shards(Bookmark, LiveShards) ->
{BookmarkShards, _} = lists:unzip(Bookmark),
add_missing_shards(Bookmark, BookmarkShards, LiveShards).
add_missing_shards(Bookmark, _, []) ->
Bookmark;
add_missing_shards(Bookmark, BMShards, [H | T]) ->
Bookmark1 = case lists:keymember(H#shard.range, #shard.range, BMShards) of
true -> Bookmark;
false -> fabric_dict:store(H, nil, Bookmark)
end,
add_missing_shards(Bookmark1, BMShards, T).