| % 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). |