summaryrefslogtreecommitdiff
path: root/apps/couch/src/couch_view.erl
diff options
context:
space:
mode:
Diffstat (limited to 'apps/couch/src/couch_view.erl')
-rw-r--r--apps/couch/src/couch_view.erl89
1 files changed, 60 insertions, 29 deletions
diff --git a/apps/couch/src/couch_view.erl b/apps/couch/src/couch_view.erl
index 6093d69d..05174245 100644
--- a/apps/couch/src/couch_view.erl
+++ b/apps/couch/src/couch_view.erl
@@ -55,11 +55,22 @@ get_group_server(DbName, GroupId) ->
get_group(Db, GroupId, Stale) ->
MinUpdateSeq = case Stale of
ok -> 0;
+ update_after -> 0;
_Else -> couch_db:get_update_seq(Db)
end,
- couch_view_group:request_group(
- get_group_server(couch_db:name(Db), GroupId),
- MinUpdateSeq).
+ GroupPid = get_group_server(couch_db:name(Db), GroupId),
+ Result = couch_view_group:request_group(GroupPid, MinUpdateSeq),
+ case Stale of
+ update_after ->
+ % best effort, process might die
+ spawn(fun() ->
+ LastSeq = couch_db:get_update_seq(Db),
+ couch_view_group:request_group(GroupPid, LastSeq)
+ end);
+ _ ->
+ ok
+ end,
+ Result.
get_temp_group(Db, Language, DesignOptions, MapSrc, RedSrc) ->
couch_view_group:request_group(
@@ -82,13 +93,18 @@ cleanup_index_files(Db) ->
FileList = list_index_files(Db),
- % regex that matches all ddocs
- RegExp = "("++ string:join(Sigs, "|") ++")",
+ DeleteFiles =
+ if length(Sigs) =:= 0 ->
+ FileList;
+ true ->
+ % regex that matches all ddocs
+ RegExp = "("++ string:join(Sigs, "|") ++")",
% filter out the ones in use
- DeleteFiles = [FilePath
- || FilePath <- FileList,
- re:run(FilePath, RegExp, [{capture, none}]) =:= nomatch],
+ [FilePath || FilePath <- FileList,
+ re:run(FilePath, RegExp, [{capture, none}]) =:= nomatch]
+ end,
+
% delete unused files
?LOG_DEBUG("deleting unused view index files: ~p",[DeleteFiles]),
RootDir = couch_config:get("couchdb", "view_index_dir"),
@@ -277,36 +293,42 @@ terminate(_Reason, _Srv) ->
ok.
-handle_call({get_group_server, DbName,
- #group{name=GroupId,sig=Sig}=Group}, _From, #server{root_dir=Root}=Server) ->
+handle_call({get_group_server, DbName, #group{sig=Sig}=Group}, From,
+ #server{root_dir=Root}=Server) ->
case ets:lookup(group_servers_by_sig, {DbName, Sig}) of
[] ->
- ?LOG_DEBUG("Spawning new group server for view group ~s in database ~s.",
- [GroupId, DbName]),
- case (catch couch_view_group:start_link({Root, DbName, Group})) of
- {ok, NewPid} ->
- add_to_ets(NewPid, DbName, Sig),
- {reply, {ok, NewPid}, Server};
- {error, invalid_view_seq} ->
- do_reset_indexes(DbName, Root),
- case (catch couch_view_group:start_link({Root, DbName, Group})) of
- {ok, NewPid} ->
- add_to_ets(NewPid, DbName, Sig),
- {reply, {ok, NewPid}, Server};
- Error ->
- {reply, Error, Server}
- end;
- Error ->
- {reply, Error, Server}
- end;
+ spawn_monitor(fun() -> new_group(Root, DbName, Group) end),
+ ets:insert(group_servers_by_sig, {{DbName, Sig}, [From]}),
+ {noreply, Server};
+ [{_, WaitList}] when is_list(WaitList) ->
+ ets:insert(group_servers_by_sig, {{DbName, Sig}, [From | WaitList]}),
+ {noreply, Server};
[{_, ExistingPid}] ->
{reply, {ok, ExistingPid}, Server}
- end.
+ end;
+
+handle_call({reset_indexes, DbName}, _From, #server{root_dir=Root}=Server) ->
+ do_reset_indexes(DbName, Root),
+ {reply, ok, Server}.
handle_cast({reset_indexes, DbName}, #server{root_dir=Root}=Server) ->
do_reset_indexes(DbName, Root),
{noreply, Server}.
+new_group(Root, DbName, #group{name=GroupId, sig=Sig} = Group) ->
+ ?LOG_DEBUG("Spawning new group server for view group ~s in database ~s.",
+ [GroupId, DbName]),
+ case (catch couch_view_group:start_link({Root, DbName, Group})) of
+ {ok, NewPid} ->
+ unlink(NewPid),
+ exit({DbName, Sig, {ok, NewPid}});
+ {error, invalid_view_seq} ->
+ ok = gen_server:call(couch_view, {reset_indexes, DbName}),
+ new_group(Root, DbName, Group);
+ Error ->
+ exit({DbName, Sig, Error})
+ end.
+
do_reset_indexes(DbName, Root) ->
% shutdown all the updaters and clear the files, the db got changed
Names = ets:lookup(couch_groups_by_db, DbName),
@@ -333,6 +355,15 @@ handle_info({'EXIT', FromPid, Reason}, Server) ->
[{_, {DbName, GroupId}}] ->
delete_from_ets(FromPid, DbName, GroupId)
end,
+ {noreply, Server};
+
+handle_info({'DOWN', _, _, _, {DbName, Sig, Reply}}, Server) ->
+ [{_, WaitList}] = ets:lookup(group_servers_by_sig, {DbName, Sig}),
+ [gen_server:reply(From, Reply) || From <- WaitList],
+ case Reply of {ok, NewPid} ->
+ link(NewPid),
+ add_to_ets(NewPid, DbName, Sig);
+ _ -> ok end,
{noreply, Server}.
config_change("couchdb", "view_index_dir") ->