summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/couchdb/default.ini.tpl.in2
-rw-r--r--share/www/script/couch_tests.js33
-rw-r--r--src/couchdb/couch_db.hrl8
-rw-r--r--src/couchdb/couch_file_stats.erl2
-rw-r--r--src/couchdb/couch_httpd_misc_handlers.erl14
-rw-r--r--src/couchdb/couch_server.erl55
-rw-r--r--src/couchdb/couch_view.erl4
7 files changed, 83 insertions, 35 deletions
diff --git a/etc/couchdb/default.ini.tpl.in b/etc/couchdb/default.ini.tpl.in
index e3600a9a..d16b1e71 100644
--- a/etc/couchdb/default.ini.tpl.in
+++ b/etc/couchdb/default.ini.tpl.in
@@ -7,6 +7,7 @@ database_dir = %localstatelibdir%
util_driver_dir = %couchprivlibdir%
max_document_size = 4294967296 ; 4 GB
view_timeout = 5000 ; 5 seconds
+max_dbs_open = 100
[httpd]
port = 5984
@@ -39,6 +40,7 @@ favicon.ico = {couch_httpd_misc_handlers, handle_favicon_req, "%localdatadir%/ww
_utils = {couch_httpd_misc_handlers, handle_utils_dir_req, "%localdatadir%/www"}
_all_dbs = {couch_httpd_misc_handlers, handle_all_dbs_req}
+_stats = {couch_httpd_misc_handlers, handle_stats_req}
_config = {couch_httpd_misc_handlers, handle_config_req}
_replicate = {couch_httpd_misc_handlers, handle_replicate_req}
_uuids = {couch_httpd_misc_handlers, handle_uuids_req}
diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js
index de4f03db..dbdc27ce 100644
--- a/share/www/script/couch_tests.js
+++ b/share/www/script/couch_tests.js
@@ -2860,7 +2860,38 @@ var tests = {
// Now delete document
T(user2Db.deleteDoc(doc).ok);
});
- }
+ },
+
+
+ max_dbs_open : function(debug) {
+ if (debug) debugger;
+ restartServer();
+ var max = 5;
+ run_on_modified_server(
+ [{section: "couchdb",
+ key: "max_dbs_open",
+ value: max.toString()}],
+
+ function () {
+ for(var i=0; i<max*2; i++) {
+ var db = new CouchDB("test_suite_db"+ i);
+ db.deleteDb();
+ db.createDb();
+ }
+
+ var stats = JSON.parse(CouchDB.request("GET", "/_stats").responseText);
+ T(stats.dbs_open == max);
+
+
+ for(var i=0; i<max*2; i++) {
+ var db = new CouchDB("test_suite_db"+ i);
+ db.deleteDb();
+ }
+
+ var stats = JSON.parse(CouchDB.request("GET", "/_stats").responseText);
+ T(stats.dbs_open == 0);
+ })
+ },
};
function makeDocs(start, end, templateDoc) {
diff --git a/src/couchdb/couch_db.hrl b/src/couchdb/couch_db.hrl
index 238025a2..d22d09c7 100644
--- a/src/couchdb/couch_db.hrl
+++ b/src/couchdb/couch_db.hrl
@@ -177,14 +177,6 @@
reduce_funs=[]
}).
--record(server,{
- root_dir = [],
- dbname_regexp,
- max_dbs_open=100,
- current_dbs_open=0,
- start_time=""
- }).
-
-record(index_header,
{seq=0,
purge_seq=0,
diff --git a/src/couchdb/couch_file_stats.erl b/src/couchdb/couch_file_stats.erl
index 90ed973e..5e7d550b 100644
--- a/src/couchdb/couch_file_stats.erl
+++ b/src/couchdb/couch_file_stats.erl
@@ -30,7 +30,7 @@ track_file(Fd) ->
get_stats() ->
#stats{opened=Opened,closed=Closed}=gen_server:call(couch_file_stats,get),
- {ok, [{opened,Opened}, {closed,Closed}]}.
+ [{files_open,Opened-Closed}, {files_closed,Closed}].
start_link() ->
diff --git a/src/couchdb/couch_httpd_misc_handlers.erl b/src/couchdb/couch_httpd_misc_handlers.erl
index c9a56c5c..5a1f6ee4 100644
--- a/src/couchdb/couch_httpd_misc_handlers.erl
+++ b/src/couchdb/couch_httpd_misc_handlers.erl
@@ -12,9 +12,9 @@
-module(couch_httpd_misc_handlers).
--export([handle_welcome_req/2,handle_favicon_req/2,handle_utils_dir_req/2,handle_all_dbs_req/1,
- handle_replicate_req/1,handle_restart_req/1,handle_uuids_req/1,
- handle_config_req/1]).
+-export([handle_welcome_req/2,handle_favicon_req/2,handle_utils_dir_req/2,
+ handle_all_dbs_req/1,handle_replicate_req/1,handle_restart_req/1,
+ handle_uuids_req/1,handle_config_req/1,handle_stats_req/1]).
-export([increment_update_seq_req/2]).
@@ -31,8 +31,7 @@
handle_welcome_req(#httpd{method='GET'}=Req, WelcomeMessage) ->
send_json(Req, {[
{couchdb, WelcomeMessage},
- {version, list_to_binary(couch_server:get_version())},
- {start_time, list_to_binary(couch_server:get_start_time())}
+ {version, list_to_binary(couch_server:get_version())}
]});
handle_welcome_req(Req, _) ->
send_method_not_allowed(Req, "GET,HEAD").
@@ -62,6 +61,11 @@ handle_all_dbs_req(#httpd{method='GET'}=Req) ->
handle_all_dbs_req(Req) ->
send_method_not_allowed(Req, "GET,HEAD").
+handle_stats_req(#httpd{method='GET'}=Req) ->
+ ok = couch_httpd:verify_is_server_admin(Req),
+ send_json(Req, {couch_server:get_stats() ++ couch_file_stats:get_stats()});
+handle_stats_req(Req) ->
+ send_method_not_allowed(Req, "GET,HEAD").
handle_replicate_req(#httpd{user_ctx=UserCtx,method='POST'}=Req) ->
{Props} = couch_httpd:json_body(Req),
diff --git a/src/couchdb/couch_server.erl b/src/couchdb/couch_server.erl
index c576fc55..69cfa36c 100644
--- a/src/couchdb/couch_server.erl
+++ b/src/couchdb/couch_server.erl
@@ -18,10 +18,18 @@
-export([open/2,create/2,delete/2,all_databases/0,get_version/0]).
-export([init/1, handle_call/3,sup_start_link/0]).
-export([handle_cast/2,code_change/3,handle_info/2,terminate/2]).
--export([dev_start/0,is_admin/2,has_admins/0,get_start_time/0]).
+-export([dev_start/0,is_admin/2,has_admins/0,get_stats/0]).
-include("couch_db.hrl").
+-record(server,{
+ root_dir = [],
+ dbname_regexp,
+ max_dbs_open=100,
+ dbs_open=0,
+ start_time=""
+ }).
+
start() ->
start(["default.ini"]).
@@ -55,9 +63,10 @@ get_version() ->
"0.0.0"
end.
-get_start_time() ->
- {ok, #server{start_time=Time}} = gen_server:call(couch_server, get_server),
- Time.
+get_stats() ->
+ {ok, #server{start_time=Time,dbs_open=Open}} =
+ gen_server:call(couch_server, get_server),
+ [{start_time, ?l2b(Time)}, {dbs_open, Open}].
sup_start_link() ->
gen_server:start_link({local, couch_server}, couch_server, [], []).
@@ -124,16 +133,19 @@ init([]) ->
RootDir = couch_config:get("couchdb", "database_dir", "."),
MaxDbsOpen = list_to_integer(
- couch_config:get("couchdb", "max_open_databases", "100")),
+ couch_config:get("couchdb", "max_dbs_open")),
Self = self(),
ok = couch_config:register(
fun("couchdb", "database_dir") ->
- exit(Self, config_change);
- ("couchdb", "server_options") ->
exit(Self, config_change)
end),
ok = couch_config:register(
- fun("admins", _) ->
+ fun("couchdb", "max_dbs_open", Max) ->
+ gen_server:call(couch_server,
+ {set_max_dbs_open, list_to_integer(Max)})
+ end),
+ ok = couch_config:register(
+ fun("admins") ->
hash_admin_passwords()
end),
hash_admin_passwords(),
@@ -164,13 +176,13 @@ all_databases() ->
{ok, Filenames}.
-maybe_close_lru_db(#server{current_dbs_open=NumOpen, max_dbs_open=MaxOpen}=Server)
+maybe_close_lru_db(#server{dbs_open=NumOpen, max_dbs_open=MaxOpen}=Server)
when NumOpen < MaxOpen ->
{ok, Server};
-maybe_close_lru_db(#server{current_dbs_open=NumOpen}=Server) ->
+maybe_close_lru_db(#server{dbs_open=NumOpen}=Server) ->
% must free up the lru db.
case try_close_lru(now()) of
- ok -> {ok, Server#server{current_dbs_open=NumOpen-1}};
+ ok -> {ok, Server#server{dbs_open=NumOpen-1}};
Error -> Error
end.
@@ -203,6 +215,8 @@ try_close_lru(StartTime) ->
end
end.
+handle_call({set_max_dbs_open, Max}, _From, Server) ->
+ {reply, ok, Server#server{max_dbs_open=Max}};
handle_call(get_server, _From, Server) ->
{reply, {ok, Server}, Server};
handle_call({open, DbName, Options}, _From, Server) ->
@@ -220,9 +234,9 @@ handle_call({open, DbName, Options}, _From, Server) ->
true = ets:insert(couch_dbs_by_name, {DbName, {MainPid, LruTime}}),
true = ets:insert(couch_dbs_by_pid, {MainPid, DbName}),
true = ets:insert(couch_dbs_by_lru, {LruTime, DbName}),
- DbsOpen = Server2#server.current_dbs_open + 1,
+ DbsOpen = Server2#server.dbs_open + 1,
{reply, {ok, MainPid},
- Server2#server{current_dbs_open=DbsOpen}};
+ Server2#server{dbs_open=DbsOpen}};
Error ->
{reply, Error, Server2}
end;
@@ -255,10 +269,10 @@ handle_call({create, DbName, Options}, _From, Server) ->
{DbName, {MainPid, LruTime}}),
true = ets:insert(couch_dbs_by_pid, {MainPid, DbName}),
true = ets:insert(couch_dbs_by_lru, {LruTime, DbName}),
- DbsOpen = Server2#server.current_dbs_open + 1,
+ DbsOpen = Server2#server.dbs_open + 1,
couch_db_update_notifier:notify({created, DbName}),
{reply, {ok, MainPid},
- Server2#server{current_dbs_open=DbsOpen}};
+ Server2#server{dbs_open=DbsOpen}};
Error ->
{reply, Error, Server2}
end;
@@ -285,8 +299,7 @@ handle_call({delete, DbName, _Options}, _From, Server) ->
true = ets:delete(couch_dbs_by_name, DbName),
true = ets:delete(couch_dbs_by_pid, Pid),
true = ets:delete(couch_dbs_by_lru, LruTime),
- DbsOpen = Server#server.current_dbs_open - 1,
- Server#server{current_dbs_open=DbsOpen}
+ Server#server{dbs_open=Server#server.dbs_open - 1}
end,
case file:delete(FullFilepath) of
ok ->
@@ -306,13 +319,15 @@ handle_cast(Msg, _Server) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
-
-handle_info({'EXIT', Pid, _Reason}, #server{current_dbs_open=DbsOpen}=Server) ->
+
+handle_info({'EXIT', _Pid, config_change}, _Server) ->
+ exit(kill);
+handle_info({'EXIT', Pid, _Reason}, #server{dbs_open=DbsOpen}=Server) ->
[{Pid, DbName}] = ets:lookup(couch_dbs_by_pid, Pid),
[{DbName, {Pid, LruTime}}] = ets:lookup(couch_dbs_by_name, DbName),
true = ets:delete(couch_dbs_by_pid, Pid),
true = ets:delete(couch_dbs_by_name, DbName),
true = ets:delete(couch_dbs_by_lru, LruTime),
- {noreply, Server#server{current_dbs_open=DbsOpen-1}};
+ {noreply, Server#server{dbs_open=DbsOpen-1}};
handle_info(Info, _Server) ->
exit({unknown_message, Info}).
diff --git a/src/couchdb/couch_view.erl b/src/couchdb/couch_view.erl
index 5065b731..ce41dd23 100644
--- a/src/couchdb/couch_view.erl
+++ b/src/couchdb/couch_view.erl
@@ -20,6 +20,10 @@
extract_map_view/1]).
-include("couch_db.hrl").
+
+
+-record(server,{
+ root_dir = []}).
start_link() ->
gen_server:start_link({local, couch_view}, couch_view, [], []).