This is an automated email from the ASF dual-hosted git repository. vatamane pushed a commit to branch merge-3.4.3 in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 0588c4ac227ab76896ac6e3dd9a368cdafafc276 Author: Nick Vatamaniuc <[email protected]> AuthorDate: Wed Jan 15 17:35:51 2025 -0500 Remove idle check timeout 7 years ago we added an idle-check timeout to force idle system shard to close [1]. It seemed like a relevant setting for Cloudant, where at the time we had a large number of open `_replicator` dbs per server. However, at Cloudant we only enabled it once, it failed as it closed too many shards too quickly, and then they had to be re-opened, which added extra load, we disabled ran with `infinity` ever since. We also never documented it anywhere so let's remove it. [1] https://github.com/apache/couchdb-couch/pull/236 --- src/couch/src/couch_bt_engine.erl | 5 -- src/couch/src/couch_db_engine.erl | 14 ----- src/couch/src/couch_db_updater.erl | 91 +++++++------------------------ src/couch/src/couch_file.erl | 10 ---- src/couch/test/eunit/couch_file_tests.erl | 10 ---- 5 files changed, 20 insertions(+), 110 deletions(-) diff --git a/src/couch/src/couch_bt_engine.erl b/src/couch/src/couch_bt_engine.erl index db5df074f..ad84e0db8 100644 --- a/src/couch/src/couch_bt_engine.erl +++ b/src/couch/src/couch_bt_engine.erl @@ -30,8 +30,6 @@ decref/1, monitored_by/1, - last_activity/1, - get_compacted_seq/1, get_del_doc_count/1, get_disk_version/1, @@ -212,9 +210,6 @@ monitored_by(St) -> [] end. -last_activity(#st{fd = Fd}) -> - couch_file:last_read(Fd). - get_compacted_seq(#st{header = Header}) -> couch_bt_engine_header:get(Header, compacted_seq). diff --git a/src/couch/src/couch_db_engine.erl b/src/couch/src/couch_db_engine.erl index 052a527e3..54f2c1482 100644 --- a/src/couch/src/couch_db_engine.erl +++ b/src/couch/src/couch_db_engine.erl @@ -180,14 +180,6 @@ -callback decref(DbHandle :: db_handle()) -> ok. -callback monitored_by(DbHande :: db_handle()) -> [pid()]. -% This is called in the context of couch_db_updater:handle_info/2 -% and should return the timestamp of the last activity of -% the database. If a storage has no notion of activity or the -% value would be hard to report its ok to just return the -% result of os:timestamp/0 as this will just disable idle -% databases from automatically closing. --callback last_activity(DbHandle :: db_handle()) -> erlang:timestamp(). - % All of the get_* functions may be called from many % processes concurrently. @@ -673,8 +665,6 @@ decref/1, monitored_by/1, - last_activity/1, - get_engine/1, get_compacted_seq/1, get_del_doc_count/1, @@ -791,10 +781,6 @@ monitored_by(#db{} = Db) -> #db{engine = {Engine, EngineState}} = Db, Engine:monitored_by(EngineState). -last_activity(#db{} = Db) -> - #db{engine = {Engine, EngineState}} = Db, - Engine:last_activity(EngineState). - get_engine(#db{} = Db) -> #db{engine = {Engine, _}} = Db, Engine. diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl index d1b4c1d2d..3f6c8886d 100644 --- a/src/couch/src/couch_db_updater.erl +++ b/src/couch/src/couch_db_updater.erl @@ -19,7 +19,6 @@ -include_lib("couch/include/couch_db.hrl"). -include("couch_db_int.hrl"). --define(IDLE_LIMIT_DEFAULT, 61000). % 10 GiB -define(DEFAULT_MAX_PARTITION_SIZE, 16#280000000). @@ -34,7 +33,6 @@ init({Engine, DbName, FilePath, Options0}) -> erlang:put(io_priority, {db_update, DbName}), - update_idle_limit_from_config(), DefaultSecObj = default_security_object(DbName), Options = [{default_security_object, DefaultSecObj} | Options0], try @@ -51,7 +49,7 @@ init({Engine, DbName, FilePath, Options0}) -> % couch_db:validate_doc_update, which loads them lazily. NewDb = Db#db{main_pid = self()}, proc_lib:init_ack({ok, NewDb}), - gen_server:enter_loop(?MODULE, [], NewDb, idle_limit()) + gen_server:enter_loop(?MODULE, [], NewDb) catch throw:InitError -> proc_lib:init_ack(InitError) @@ -63,39 +61,39 @@ terminate(Reason, Db) -> ok. handle_call(get_db, _From, Db) -> - {reply, {ok, Db}, Db, idle_limit()}; + {reply, {ok, Db}, Db}; handle_call(start_compact, _From, Db) -> - {noreply, NewDb, _Timeout} = handle_cast(start_compact, Db), - {reply, {ok, NewDb#db.compactor_pid}, NewDb, idle_limit()}; + {noreply, NewDb} = handle_cast(start_compact, Db), + {reply, {ok, NewDb#db.compactor_pid}, NewDb}; handle_call(compactor_pid, _From, #db{compactor_pid = Pid} = Db) -> - {reply, Pid, Db, idle_limit()}; + {reply, Pid, Db}; handle_call(cancel_compact, _From, #db{compactor_pid = nil} = Db) -> - {reply, ok, Db, idle_limit()}; + {reply, ok, Db}; handle_call(cancel_compact, _From, #db{compactor_pid = Pid} = Db) -> unlink(Pid), exit(Pid, kill), couch_server:delete_compaction_files(Db#db.name), Db2 = Db#db{compactor_pid = nil}, ok = couch_server:db_updated(Db2), - {reply, ok, Db2, idle_limit()}; + {reply, ok, Db2}; handle_call({set_security, NewSec}, _From, #db{} = Db) -> {ok, NewDb} = couch_db_engine:set_security(Db, NewSec), NewSecDb = commit_data(NewDb#db{ security = NewSec }), ok = couch_server:db_updated(NewSecDb), - {reply, ok, NewSecDb, idle_limit()}; + {reply, ok, NewSecDb}; handle_call({set_revs_limit, Limit}, _From, Db) -> {ok, Db2} = couch_db_engine:set_revs_limit(Db, Limit), Db3 = commit_data(Db2), ok = couch_server:db_updated(Db3), - {reply, ok, Db3, idle_limit()}; + {reply, ok, Db3}; handle_call({set_purge_infos_limit, Limit}, _From, Db) -> {ok, Db2} = couch_db_engine:set_purge_infos_limit(Db, Limit), ok = couch_server:db_updated(Db2), - {reply, ok, Db2, idle_limit()}; + {reply, ok, Db2}; handle_call({purge_docs, [], _}, _From, Db) -> - {reply, {ok, []}, Db, idle_limit()}; + {reply, {ok, []}, Db}; handle_call({purge_docs, PurgeReqs0, Options}, _From, Db) -> % Filter out any previously applied updates during % internal replication @@ -116,11 +114,11 @@ handle_call({purge_docs, PurgeReqs0, Options}, _From, Db) -> ) end, {ok, NewDb, Replies} = purge_docs(Db, PurgeReqs), - {reply, {ok, Replies}, NewDb, idle_limit()}; + {reply, {ok, Replies}, NewDb}; handle_call(Msg, From, Db) -> case couch_db_engine:handle_db_updater_call(Msg, From, Db) of {reply, Resp, NewDb} -> - {reply, Resp, NewDb, idle_limit()}; + {reply, Resp, NewDb}; Else -> Else end. @@ -128,7 +126,7 @@ handle_call(Msg, From, Db) -> handle_cast({load_validation_funs, ValidationFuns}, Db) -> Db2 = Db#db{validate_doc_funs = ValidationFuns}, ok = couch_server:db_updated(Db2), - {noreply, Db2, idle_limit()}; + {noreply, Db2}; handle_cast(start_compact, Db) -> case Db#db.compactor_pid of nil -> @@ -146,16 +144,14 @@ handle_cast(start_compact, Db) -> couch_log:Level("Starting compaction for db \"~s\" at ~p", Args), {ok, Db2} = couch_db_engine:start_compaction(Db), ok = couch_server:db_updated(Db2), - {noreply, Db2, idle_limit()}; + {noreply, Db2}; _ -> % compact currently running, this is a no-op - {noreply, Db, idle_limit()} + {noreply, Db} end; handle_cast({compact_done, _Engine, CompactInfo}, #db{} = OldDb) -> {ok, NewDb} = couch_db_engine:finish_compaction(OldDb, CompactInfo), {noreply, NewDb}; -handle_cast(wakeup, Db) -> - {noreply, Db, idle_limit()}; handle_cast(Msg, #db{name = Name} = Db) -> couch_log:error( "Database `~s` updater received unexpected cast: ~p", @@ -213,40 +209,20 @@ handle_info( false -> Db2 end, - {noreply, Db3, hibernate_if_no_idle_limit()} + {noreply, Db3, hibernate} catch throw:retry -> [catch (ClientPid ! {retry, self()}) || ClientPid <- Clients], - {noreply, Db, hibernate_if_no_idle_limit()} + {noreply, Db, hibernate} end; handle_info({'EXIT', _Pid, normal}, Db) -> - {noreply, Db, idle_limit()}; + {noreply, Db}; handle_info({'EXIT', _Pid, Reason}, Db) -> {stop, Reason, Db}; -handle_info(timeout, #db{name = DbName} = Db) -> - IdleLimitMSec = update_idle_limit_from_config(), - case couch_db:is_idle(Db) of - true -> - LastActivity = couch_db_engine:last_activity(Db), - DtMSec = timer:now_diff(os:timestamp(), LastActivity) div 1000, - MSecSinceLastActivity = max(0, DtMSec), - case MSecSinceLastActivity > IdleLimitMSec of - true -> - ok = couch_server:close_db_if_idle(DbName); - false -> - ok - end; - false -> - ok - end, - % Send a message to wake up and then hibernate. Hibernation here is done to - % force a thorough garbage collection. - gen_server:cast(self(), wakeup), - {noreply, Db, hibernate}; handle_info(Msg, Db) -> case couch_db_engine:handle_db_updater_info(Msg, Db) of {noreply, NewDb} -> - {noreply, NewDb, idle_limit()}; + {noreply, NewDb}; Else -> Else end. @@ -942,33 +918,6 @@ default_security_object(_DbName) -> [] end. -% These functions rely on using the process dictionary. This is -% usually frowned upon however in this case it is done to avoid -% changing to a different server state record. Once PSE (Pluggable -% Storage Engine) code lands this should be moved to the #db{} record. -update_idle_limit_from_config() -> - Default = integer_to_list(?IDLE_LIMIT_DEFAULT), - IdleLimit = - case config:get("couchdb", "idle_check_timeout", Default) of - "infinity" -> - infinity; - Milliseconds -> - list_to_integer(Milliseconds) - end, - put(idle_limit, IdleLimit), - IdleLimit. - -idle_limit() -> - get(idle_limit). - -hibernate_if_no_idle_limit() -> - case idle_limit() of - infinity -> - hibernate; - Timeout when is_integer(Timeout) -> - Timeout - end. - -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). diff --git a/src/couch/src/couch_file.erl b/src/couch/src/couch_file.erl index 02b2412f3..9c2a7a1d8 100644 --- a/src/couch/src/couch_file.erl +++ b/src/couch/src/couch_file.erl @@ -44,7 +44,6 @@ -export([append_terms/2, append_terms/3]). -export([write_header/2, read_header/1]). -export([delete/2, delete/3, nuke_dir/2, init_delete_dir/1]). --export([last_read/1]). % gen_server callbacks -export([init/1, terminate/2, format_status/2]). @@ -400,16 +399,11 @@ init_status_error(ReturnPid, Ref, Error) -> ReturnPid ! {Ref, self(), Error}, ignore. -last_read(Fd) when is_pid(Fd) -> - Now = os:timestamp(), - couch_util:process_dict_get(Fd, read_timestamp, Now). - % server functions init({Filepath, Options, ReturnPid, Ref}) -> OpenOptions = file_open_options(Options), IsSys = lists:member(sys_db, Options), - update_read_timestamp(), case lists:member(create, Options) of true -> filelib:ensure_dir(Filepath), @@ -489,7 +483,6 @@ terminate(_Reason, #file{fd = Fd}) -> handle_call(close, _From, #file{fd = Fd} = File) -> {stop, normal, file:close(Fd), File#file{fd = nil}}; handle_call({pread_iolists, PosL}, _From, File) -> - update_read_timestamp(), LocNums1 = [{Pos, 4} || Pos <- PosL], DataSizes = read_multi_raw_iolists_int(File, LocNums1), MapFun = fun({LenIoList, NextPos}) -> @@ -868,9 +861,6 @@ is_idle(#file{is_sys = false}) -> process_info(Pid) -> couch_util:process_dict_get(Pid, couch_file_fd). -update_read_timestamp() -> - put(read_timestamp, os:timestamp()). - %% in event of a partially successful write. reset_eof(#file{} = File) -> {ok, Eof} = file:position(File#file.fd, eof), diff --git a/src/couch/test/eunit/couch_file_tests.erl b/src/couch/test/eunit/couch_file_tests.erl index 36b2a61a1..df4caa714 100644 --- a/src/couch/test/eunit/couch_file_tests.erl +++ b/src/couch/test/eunit/couch_file_tests.erl @@ -95,7 +95,6 @@ read_write_test_() -> ?TDEF_FE(should_catch_pread_failure), ?TDEF_FE(should_truncate), ?TDEF_FE(should_set_db_pid), - ?TDEF_FE(should_update_last_read_time), ?TDEF_FE(should_open_read_only), ?TDEF_FE(should_apply_overwrite_create_option), ?TDEF_FE(should_error_on_creation_if_exists), @@ -245,15 +244,6 @@ should_set_db_pid(Fd) -> ), ?assertNot(is_process_alive(Fd)). -should_update_last_read_time(Fd) -> - {ok, Pos, _} = couch_file:append_term(Fd, foo), - ReadTs1 = couch_file:last_read(Fd), - ?assertMatch({_, _, _}, ReadTs1), - {ok, foo} = couch_file:pread_term(Fd, Pos), - ReadTs2 = couch_file:last_read(Fd), - ?assertMatch({_, _, _}, ReadTs2), - ?assert(ReadTs2 > ReadTs1). - should_open_read_only(Fd) -> {_, Path} = couch_file:process_info(Fd), {ok, Pos, _} = couch_file:append_term(Fd, foo),
