From 0f3bc594c57d048d329708a6c91edf5bb5be3719 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 18 Feb 2010 19:55:55 +0000 Subject: Fixes COUCHDB-640 - Reset views with invalid update seqs. If a database is restored to a previous version, and the view files are not updated appropriately they will contain data from the database after the reverted-to-update_seq. This patch checks that the update sequence recorded in a view is less than or equal to the update sequence of the database. Patch is by Filipe Manana. Execellent work once again. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@911544 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_view.erl | 16 ++++++++++++++-- src/couchdb/couch_view_group.erl | 30 +++++++++++++++++++----------- 2 files changed, 33 insertions(+), 13 deletions(-) (limited to 'src/couchdb') diff --git a/src/couchdb/couch_view.erl b/src/couchdb/couch_view.erl index f80ce434..cbbbd4ac 100644 --- a/src/couchdb/couch_view.erl +++ b/src/couchdb/couch_view.erl @@ -284,6 +284,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,6 +301,10 @@ 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( @@ -304,8 +317,7 @@ handle_cast({reset_indexes, DbName}, #server{root_dir=Root}=Server) -> end end, Names), delete_index_dir(Root, DbName), - file:delete(Root ++ "/." ++ binary_to_list(DbName) ++ "_temp"), - {noreply, Server}. + file:delete(Root ++ "/." ++ ?b2l(DbName) ++ "_temp"). handle_info({'EXIT', FromPid, Reason}, Server) -> case ets:lookup(couch_groups_by_updater, FromPid) of diff --git a/src/couchdb/couch_view_group.erl b/src/couchdb/couch_view_group.erl index 6589bc6a..8439304d 100644 --- a/src/couchdb/couch_view_group.erl +++ b/src/couchdb/couch_view_group.erl @@ -78,17 +78,25 @@ start_link(InitArgs) -> init({InitArgs, ReturnPid, Ref}) -> process_flag(trap_exit, true), case prepare_group(InitArgs, false) of - {ok, #group{db=Db, fd=Fd}=Group} -> - couch_db:monitor(Db), - Owner = self(), - Pid = spawn_link(fun()-> couch_view_updater:update(Owner, Group) end), - {ok, RefCounter} = couch_ref_counter:start([Fd]), - {ok, #group_state{ - db_name=couch_db:name(Db), - init_args=InitArgs, - updater_pid = Pid, - group=Group, - ref_counter=RefCounter}}; + {ok, #group{db=Db, fd=Fd, current_seq=Seq}=Group} -> + case Seq > couch_db:get_update_seq(Db) of + true -> + ReturnPid ! {Ref, self(), {error, invalid_view_seq}}, + ignore; + _ -> + couch_db:monitor(Db), + Owner = self(), + Pid = spawn_link( + fun()-> couch_view_updater:update(Owner, Group) end + ), + {ok, RefCounter} = couch_ref_counter:start([Fd]), + {ok, #group_state{ + db_name=couch_db:name(Db), + init_args=InitArgs, + updater_pid = Pid, + group=Group, + ref_counter=RefCounter}} + end; Error -> ReturnPid ! {Ref, self(), Error}, ignore -- cgit v1.2.3