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
13-module(couch_spatial_index).
14
15
16-export([get/2]).
17-export([init/2, open/2, close/1, reset/1, delete/1]).
18-export([start_update/3, purge/4, process_doc/3, finish_update/1, commit/1]).
19-export([compact/3, swap_compacted/2]).
20
21
22-include("couch_spatial.hrl").
23
24
25get(Property, State) ->
26    case Property of
27        db_name ->
28            State#spatial_state.db_name;
29        idx_name ->
30            State#spatial_state.idx_name;
31        signature ->
32            State#spatial_state.sig;
33        update_seq ->
34            State#spatial_state.update_seq;
35        purge_seq ->
36            State#spatial_state.purge_seq;
37        update_options ->
38            %Opts = State#spatual_state.design_options,
39            % NOTE vmx 2012-10-19: Not supported at the moment
40            %IncDesign = couch_util:get_value(<<"include_design">>, Opts, false),
41            %LocalSeq = couch_util:get_value(<<"local_seq">>, Opts, false),
42            %if IncDesign -> [include_design]; true -> [] end
43            %    ++ if LocalSeq -> [local_seq]; true -> [] end;
44            [];
45        info ->
46            #spatial_state{
47                fd = Fd,
48                sig = Sig,
49                language = Lang,
50                update_seq = UpdateSeq,
51                purge_seq = PurgeSeq
52            } = State,
53            {ok, Size} = couch_file:bytes(Fd),
54            {ok, [
55                {signature, list_to_binary(couch_index_util:hexsig(Sig))},
56                {language, Lang},
57                {disk_size, Size},
58                {update_seq, UpdateSeq},
59                {purge_seq, PurgeSeq}
60            ]};
61        Other ->
62            throw({unknown_index_property, Other})
63    end.
64
65
66init(Db, DDoc) ->
67    couch_spatial_util:ddoc_to_spatial_state(couch_db:name(Db), DDoc).
68
69
70open(Db, State) ->
71    #spatial_state{
72        db_name=DbName,
73        sig=Sig
74    } = State,
75    IndexFName = couch_spatial_util:index_file(DbName, Sig),
76    case couch_spatial_util:open_file(IndexFName) of
77        {ok, Fd} ->
78            NewState = case (catch couch_file:read_header(Fd)) of
79                {ok, {Sig, Header}} ->
80                    % Matching view signatures.
81                    couch_spatial_util:init_state(Db, Fd, State, Header);
82                _ ->
83                    couch_spatial_util:reset_index(Db, Fd, State)
84            end,
85            {ok, RefCounter} = couch_ref_counter:start([Fd]),
86            {ok, NewState#spatial_state{ref_counter=RefCounter}};
87        Error ->
88            (catch couch_spatial_util:delete_files(DbName, Sig)),
89            Error
90    end.
91
92
93close(State) ->
94    couch_file:close(State#spatial_state.fd).
95
96
97delete(State) ->
98    #spatial_state{
99        fd=Fd,
100        db_name=DbName,
101        sig=Sig
102    } = State,
103    couch_file:close(Fd),
104    catch couch_spatial_util:delete_files(DbName, Sig).
105
106
107reset(State) ->
108    #spatial_state{
109        fd=Fd,
110        db_name=DbName
111    } = State,
112    couch_util:with_db(DbName, fun(Db) ->
113        NewState = couch_spatial_util:reset_index(Db, Fd, State),
114        {ok, NewState}
115    end).
116
117
118start_update(PartialDest, State, NumChanges) ->
119    couch_spatial_updater:start_update(PartialDest, State, NumChanges).
120
121
122purge(_Db, _PurgeSeq, _PurgedIdRevs, _State) ->
123    throw("purge on spatial views isn't supported").
124
125
126process_doc(Doc, Seq, State) ->
127    couch_spatial_updater:process_doc(Doc, Seq, State).
128
129
130finish_update(State) ->
131    couch_spatial_updater:finish_update(State).
132
133
134commit(State) ->
135    #spatial_state{
136        sig=Sig,
137        fd=Fd
138    } = State,
139    Header = {Sig, couch_spatial_util:make_header(State)},
140    couch_file:write_header(Fd, Header).
141
142
143compact(Db, State, Opts) ->
144    couch_spatial_compactor:compact(Db, State, Opts).
145
146
147swap_compacted(OldState, NewState) ->
148    couch_spatial_compactor:swap_compacted(OldState, NewState).
149