diff options
Diffstat (limited to 'src/couchdb/couch_view.erl')
| -rw-r--r-- | src/couchdb/couch_view.erl | 162 |
1 files changed, 79 insertions, 83 deletions
diff --git a/src/couchdb/couch_view.erl b/src/couchdb/couch_view.erl index f80ce434..ebd7a2d4 100644 --- a/src/couchdb/couch_view.erl +++ b/src/couchdb/couch_view.erl @@ -29,11 +29,9 @@ start_link() -> gen_server:start_link({local, couch_view}, couch_view, [], []). get_temp_updater(DbName, Language, DesignOptions, MapSrc, RedSrc) -> - % make temp group - % do we need to close this db? - {ok, _Db, Group} = + {ok, Group} = couch_view_group:open_temp_group(DbName, Language, DesignOptions, MapSrc, RedSrc), - case gen_server:call(couch_view, {get_group_server, DbName, Group}) of + case gen_server:call(couch_view, {get_group_server, DbName, Group}, infinity) of {ok, Pid} -> Pid; Error -> @@ -41,11 +39,9 @@ get_temp_updater(DbName, Language, DesignOptions, MapSrc, RedSrc) -> end. get_group_server(DbName, GroupId) -> - % get signature for group case couch_view_group:open_db_group(DbName, GroupId) of - % do we need to close this db? - {ok, _Db, Group} -> - case gen_server:call(couch_view, {get_group_server, DbName, Group}) of + {ok, Group} -> + case gen_server:call(couch_view, {get_group_server, DbName, Group}, infinity) of {ok, Pid} -> Pid; Error -> @@ -80,7 +76,7 @@ cleanup_index_files(Db) -> % make unique list of group sigs Sigs = lists:map(fun(#doc{id = GroupId}) -> {ok, Info} = get_group_info(Db, GroupId), - ?b2l(proplists:get_value(signature, Info)) + ?b2l(couch_util:get_value(signature, Info)) end, [DD||DD <- DesignDocs, DD#doc.deleted == false]), FileList = list_index_files(Db), @@ -90,11 +86,12 @@ cleanup_index_files(Db) -> % filter out the ones in use DeleteFiles = [FilePath - || FilePath <- FileList, - re:run(FilePath, RegExp, [{capture, none}]) =:= nomatch], + || FilePath <- FileList, + re:run(FilePath, RegExp, [{capture, none}]) =:= nomatch], % delete unused files ?LOG_DEBUG("deleting unused view index files: ~p",[DeleteFiles]), - [file:delete(File)||File <- DeleteFiles], + RootDir = couch_config:get("couchdb", "view_index_dir"), + [couch_file:delete(RootDir,File,false)||File <- DeleteFiles], ok. list_index_files(Db) -> @@ -266,11 +263,13 @@ init([]) -> ets:new(group_servers_by_sig, [set, protected, named_table]), ets:new(couch_groups_by_updater, [set, private, named_table]), process_flag(trap_exit, true), + ok = couch_file:init_delete_dir(RootDir), {ok, #server{root_dir=RootDir}}. -terminate(Reason, _Srv) -> - couch_util:terminate_linked(Reason), +terminate(_Reason, _Srv) -> + [couch_util:shutdown_sync(Pid) || {Pid, _} <- + ets:tab2list(couch_groups_by_updater)], ok. @@ -284,6 +283,15 @@ handle_call({get_group_server, DbName, {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; @@ -292,20 +300,22 @@ handle_call({get_group_server, DbName, end. handle_cast({reset_indexes, DbName}, #server{root_dir=Root}=Server) -> + do_reset_indexes(DbName, Root), + {noreply, Server}. + +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), lists:foreach( fun({_DbName, Sig}) -> ?LOG_DEBUG("Killing update process for view group ~s. in database ~s.", [Sig, DbName]), [{_, Pid}] = ets:lookup(group_servers_by_sig, {DbName, Sig}), - exit(Pid, kill), - receive {'EXIT', Pid, _} -> - delete_from_ets(Pid, DbName, Sig) - end + couch_util:shutdown_sync(Pid), + delete_from_ets(Pid, DbName, Sig) end, Names), delete_index_dir(Root, DbName), - file:delete(Root ++ "/." ++ binary_to_list(DbName) ++ "_temp"), - {noreply, Server}. + RootDelDir = couch_config:get("couchdb", "view_index_dir"), + couch_file:delete(RootDelDir, Root ++ "/." ++ ?b2l(DbName) ++ "_temp"). handle_info({'EXIT', FromPid, Reason}, Server) -> case ets:lookup(couch_groups_by_updater, FromPid) of @@ -336,19 +346,19 @@ code_change(_OldVsn, State, _Extra) -> delete_index_dir(RootDir, DbName) -> - nuke_dir(RootDir ++ "/." ++ ?b2l(DbName) ++ "_design"). + nuke_dir(RootDir, RootDir ++ "/." ++ ?b2l(DbName) ++ "_design"). -nuke_dir(Dir) -> +nuke_dir(RootDelDir, Dir) -> case file:list_dir(Dir) of {error, enoent} -> ok; % doesn't exist {ok, Files} -> lists:foreach( fun(File)-> Full = Dir ++ "/" ++ File, - case file:delete(Full) of + case couch_file:delete(RootDelDir, Full, false) of ok -> ok; {error, eperm} -> - ok = nuke_dir(Full) + ok = nuke_dir(RootDelDir, Full) end end, Files), @@ -358,81 +368,67 @@ nuke_dir(Dir) -> % keys come back in the language of btree - tuples. less_json_ids({JsonA, IdA}, {JsonB, IdB}) -> - case JsonA == JsonB of - false -> - less_json(JsonA, JsonB); - true -> - IdA < IdB - end. - - -less_json(A, B) -> - TypeA = type_sort(A), - TypeB = type_sort(B), - if TypeA == TypeB -> - less_same_type(A, B); - true -> - TypeA < TypeB + case less_json0(JsonA, JsonB) of + 0 -> + IdA < IdB; + Result -> + Result < 0 end. -type_sort(V) when is_atom(V) -> 0; -type_sort(V) when is_integer(V) -> 1; -type_sort(V) when is_float(V) -> 1; -type_sort(V) when is_binary(V) -> 2; -type_sort(V) when is_list(V) -> 3; -type_sort({V}) when is_list(V) -> 4; -type_sort(V) when is_tuple(V) -> 5. +less_json(A,B) -> + less_json0(A,B) < 0. + +less_json0(A,A) -> 0; + +less_json0(A,B) when is_atom(A), is_atom(B) -> atom_sort(A) - atom_sort(B); +less_json0(A,_) when is_atom(A) -> -1; +less_json0(_,B) when is_atom(B) -> 1; + +less_json0(A,B) when is_number(A), is_number(B) -> A - B; +less_json0(A,_) when is_number(A) -> -1; +less_json0(_,B) when is_number(B) -> 1; +less_json0(A,B) when is_binary(A), is_binary(B) -> couch_util:collate(A,B); +less_json0(A,_) when is_binary(A) -> -1; +less_json0(_,B) when is_binary(B) -> 1; + +less_json0(A,B) when is_list(A), is_list(B) -> less_list(A,B); +less_json0(A,_) when is_list(A) -> -1; +less_json0(_,B) when is_list(B) -> 1; + +less_json0({A},{B}) when is_list(A), is_list(B) -> less_props(A,B); +less_json0({A},_) when is_list(A) -> -1; +less_json0(_,{B}) when is_list(B) -> 1. atom_sort(null) -> 1; atom_sort(false) -> 2; atom_sort(true) -> 3. - -less_same_type(A,B) when is_atom(A) -> - atom_sort(A) < atom_sort(B); -less_same_type(A,B) when is_binary(A) -> - couch_util:collate(A, B) < 0; -less_same_type({AProps}, {BProps}) -> - less_props(AProps, BProps); -less_same_type(A, B) when is_list(A) -> - less_list(A, B); -less_same_type(A, B) -> - A < B. - less_props([], [_|_]) -> - true; + -1; less_props(_, []) -> - false; + 1; less_props([{AKey, AValue}|RestA], [{BKey, BValue}|RestB]) -> case couch_util:collate(AKey, BKey) of - -1 -> true; - 1 -> false; 0 -> - case less_json(AValue, BValue) of - true -> true; - false -> - case less_json(BValue, AValue) of - true -> false; - false -> - less_props(RestA, RestB) - end - end + case less_json0(AValue, BValue) of + 0 -> + less_props(RestA, RestB); + Result -> + Result + end; + Result -> + Result end. less_list([], [_|_]) -> - true; + -1; less_list(_, []) -> - false; + 1; less_list([A|RestA], [B|RestB]) -> - case less_json(A,B) of - true -> true; - false -> - case less_json(B,A) of - true -> false; - false -> - less_list(RestA, RestB) - end + case less_json0(A,B) of + 0 -> + less_list(RestA, RestB); + Result -> + Result end. - - |
