summaryrefslogtreecommitdiff
path: root/src/couch_views/src/couch_views_updater.erl
blob: defdb6ba62d39475c681f0625214de8bbfba2219 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
% 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.
-module(couch_views_updater).

-export([
    index/6
]).


-include_lib("couch/include/couch_db.hrl").
-include_lib("couch_views/include/couch_views.hrl").

% If the doc revision doesn't not match the NewRevId passed here we can ignore
% the document since it is then a conflict document and it doesn't need
% to be indexed.
index(Db, #doc{id = Id, revs = Revs} = Doc, _NewWinner, _OldWinner, NewRevId,
        Seq) ->
    try
        {Depth, [FirstRev | _]} = Revs,
        DocRev = {Depth, FirstRev},
        if DocRev /= NewRevId -> ok; true ->
            index_int(Db, Doc, Seq)
        end
    catch
        error:{erlfdb_error, ErrCode} when is_integer(ErrCode) ->
            Stack = erlang:get_stacktrace(),
            DbName = fabric2_db:name(Db),
            couch_log:error("Mango index erlfdb error Db ~s Doc ~p ~p",
                [DbName, Id, ErrCode]),
            erlang:raise(error, {erlfdb_error, ErrCode}, Stack);
        Error:Reason ->
            DbName = fabric2_db:name(Db),
            couch_log:error("Mango index error for Db ~s Doc ~p ~p ~p",
                [DbName, Id, Error, Reason])
    end.


% Check if design doc is an interactive index and kick off background worker
% to build the new index up to the creation_vs
index_int(Db, #doc{id = <<?DESIGN_DOC_PREFIX, _/binary>>,
        deleted = false} = DDoc, Seq) ->
    DbName = fabric2_db:name(Db),

    case couch_views_ddoc:is_interactive(DDoc) of
        true ->
            {ok, Mrst} = couch_views_util:ddoc_to_mrst(DbName, DDoc),
            case couch_views_fdb:get_creation_vs(Db, Mrst) of
                not_found ->
                    couch_views_fdb:new_interactive_index(Db, Mrst, Seq),
                    {ok, _} = couch_views_jobs:build_view_async(Db, Mrst);
                _ ->
                    ok
            end;
        false ->
            ok
    end,
    write_doc(Db, DDoc);


index_int(Db, #doc{} = Doc, _Seq) ->
    write_doc(Db, Doc).


write_doc(Db, #doc{deleted = Deleted} = Doc) ->
    DbName = fabric2_db:name(Db),
    DDocs = couch_views_ddoc:get_interactive_list(Db),

    Result0 = [#{
        id => Doc#doc.id,
        results => [],
        deleted => Deleted,
        doc => Doc
    }],

    %% Interactive updates do not update the views update_seq
    State = #{
        last_seq => false
    },

    lists:foreach(fun(DDoc) ->
        {ok, Mrst0} = couch_views_util:ddoc_to_mrst(DbName, DDoc),
        Mrst1 = couch_views_trees:open(Db, Mrst0),

        case should_index_doc(Doc, Mrst1) of
            true ->
                {Mrst2, Result1} = couch_views_indexer:map_docs(Mrst1, Result0),
                DocNumber = couch_views_indexer:write_docs(Db, Mrst2,
                    Result1, State),
                couch_views_plugin:after_interactive_write(Db, Mrst2,
                    Result1, DocNumber),
                couch_eval:release_map_context(Mrst2#mrst.qserver);
            false ->
                ok
        end
    end, DDocs).


should_index_doc(<<?DESIGN_DOC_PREFIX, _/binary>>, Mrst) ->
    lists:keymember(<<"include_design">>, 1, Mrst#mrst.design_opts);

should_index_doc(_,  _) ->
    true.