summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/www/script/couch_tests.js30
-rw-r--r--src/couchdb/couch_config.erl71
-rw-r--r--src/couchdb/couch_httpd_misc_handlers.erl13
3 files changed, 82 insertions, 32 deletions
diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js
index e88c68d1..0339dda6 100644
--- a/share/www/script/couch_tests.js
+++ b/share/www/script/couch_tests.js
@@ -1857,6 +1857,36 @@ var tests = {
T(rows[(2*(i-4))+1].key == i+1);
}
T(db.view("test/single_doc").total_rows == 0);
+ },
+
+ config : function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ // test that /_config returns all the settings
+ var xhr = CouchDB.request("GET", "/_config");
+ var config = JSON.parse(xhr.responseText);
+ T(config.couchdb.database_dir);
+ T(config.httpd.port == CouchDB.port);
+ T(config.daemons.httpd);
+ T(config.httpd_global_handlers._config);
+ T(config.log.level);
+ T(config.query_servers.javascript);
+
+ // test that settings can be altered
+ xhr = CouchDB.request("PUT", "/_config/test/foo",{
+ body : "bar"
+ });
+ T(xhr.status == 200);
+ xhr = CouchDB.request("GET", "/_config/test");
+ config = JSON.parse(xhr.responseText);
+ T(config.foo == "bar");
+
+ // you can get a single key
+ xhr = CouchDB.request("GET", "/_config/test/foo");
+ T(xhr.responseText == '"bar"');
}
};
diff --git a/src/couchdb/couch_config.erl b/src/couchdb/couch_config.erl
index 8bce5718..f3b4f328 100644
--- a/src/couchdb/couch_config.erl
+++ b/src/couchdb/couch_config.erl
@@ -20,12 +20,8 @@
-include("couch_db.hrl").
-behaviour(gen_server).
--export([start_link/1, init/1,
- handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
--export([set/3, register/1, register/2,
- get/1, get/2, get/3,
- all/0, delete/2, load_ini_file/1]).
+-export([start_link/1, init/1, handle_call/3, handle_cast/2, handle_info/2,terminate/2, code_change/3]).
+-export([all/0, get/1, get/2, get/3, delete/2, set/3, register/1, register/2,load_ini_file/1]).
-record(config,
{notify_funs=[],
@@ -36,32 +32,39 @@
%% @type etstable() = integer().
-start_link(IniFiles) -> gen_server:start_link({local, ?MODULE}, ?MODULE, IniFiles, []).
+start_link(IniFiles) ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, IniFiles, []).
+all() ->
+ gen_server:call(?MODULE, all).
+get(Section) when is_binary(Section) ->
+ gen_server:call(?MODULE, {fetch, binary_to_list(Section)});
+get(Section) ->
+ gen_server:call(?MODULE, {fetch, Section}).
+get(Section, Key) when is_binary(Section) and is_binary(Key) ->
+ get(binary_to_list(Section), binary_to_list(Key), undefined);
+get(Section, Key) ->
+ get(Section, Key, undefined).
+get(Section, Key, Default) when is_binary(Section) and is_binary(Key) ->
+ gen_server:call(?MODULE, {fetch, binary_to_list(Section), binary_to_list(Key), Default});
+get(Section, Key, Default) ->
+ gen_server:call(?MODULE, {fetch, Section, Key, Default}).
+
+set(Section, Key, Value) when is_binary(Section) and is_binary(Key) ->
+ gen_server:call(?MODULE, {set, [{{binary_to_list(Section), binary_to_list(Key)}, Value}]});
set(Section, Key, Value) ->
gen_server:call(?MODULE, {set, [{{Section, Key}, Value}]}).
+delete(Section, Key) when is_binary(Section) and is_binary(Key) ->
+ gen_server:call(?MODULE, {delete, {binary_to_list(Section), binary_to_list(Key)}});
delete(Section, Key) ->
gen_server:call(?MODULE, {delete, {Section, Key}}).
-get(Section, Key) ->
- get(Section, Key, undefined).
-
-get(Section, Key, Default) ->
- case ets:lookup(?MODULE, {Section, Key}) of
- [] -> Default;
- [{_,Result}] -> Result
- end.
-
-get(Section) ->
- Matches = ets:match(?MODULE, {{Section, '$1'}, '$2'}),
- [{Key, Value} || [Key, Value] <- Matches].
-
-all() -> gen_server:call(?MODULE, all).
-
-register(Fun) -> ?MODULE:register(Fun, self()).
+register(Fun) ->
+ ?MODULE:register(Fun, self()).
-register(Fun, Pid) -> gen_server:call(?MODULE, {register, Fun, Pid}).
+register(Fun, Pid) ->
+ gen_server:call(?MODULE, {register, Fun, Pid}).
%% Private API %%
@@ -72,6 +75,20 @@ init(IniFiles) ->
[ok = load_ini_file(IniFile) || IniFile <- IniFiles],
{ok, #config{writeback_filename=lists:last(IniFiles)}}.
+handle_call(all, _From, Config) ->
+ {reply, lists:sort(ets:tab2list(?MODULE)), Config};
+
+handle_call({fetch, Section}, _From, Config) ->
+ Matches = ets:match(?MODULE, {{Section, '$1'}, '$2'}),
+ {reply, [{Key, Value} || [Key, Value] <- Matches], Config};
+
+handle_call({fetch, Section, Key, Default}, _From, Config) ->
+ Ret = case ets:lookup(?MODULE, {Section, Key}) of
+ [] -> Default;
+ [{_,Result}] -> Result
+ end,
+ {reply, Ret, Config};
+
handle_call({set, KVs}, _From, Config) ->
[ok = insert_and_commit(Config, KV) || KV <- KVs],
{reply, ok, Config};
@@ -80,16 +97,10 @@ handle_call({delete, Key}, _From, Config) ->
ets:delete(?MODULE, Key),
{reply, ok, Config};
-handle_call(all, _From, Config) ->
- {reply, lists:sort(ets:tab2list(?MODULE)), Config};
-
handle_call({register, Fun, Pid}, _From, #config{notify_funs=PidFuns}=Config) ->
erlang:monitor(process, Pid),
{reply, ok, Config#config{notify_funs=[{Pid, Fun}|PidFuns]}}.
-
-
-
%% @spec insert_and_commit(Tab::etstable(), Config::any()) -> ok
%% @doc Inserts a Key/Value pair into the ets table, writes it to the storage
%% ini file and calls all registered callback functions for Key.
diff --git a/src/couchdb/couch_httpd_misc_handlers.erl b/src/couchdb/couch_httpd_misc_handlers.erl
index 040e34de..8372c1b5 100644
--- a/src/couchdb/couch_httpd_misc_handlers.erl
+++ b/src/couchdb/couch_httpd_misc_handlers.erl
@@ -93,8 +93,17 @@ handle_uuids_req(Req) ->
% GET /_config/
% GET /_config
handle_config_req(#httpd{method='GET', path_parts=[_]}=Req) ->
- KVs = [{list_to_binary(Key), list_to_binary(Value)}
- || {Key, Value} <- couch_config:all()],
+ Grouped = lists:foldl(fun({{Section, Key}, Value}, Acc) ->
+ case dict:is_key(Section, Acc) of
+ true ->
+ dict:append(Section, {list_to_binary(Key), list_to_binary(Value)}, Acc);
+ false ->
+ dict:store(Section, [{list_to_binary(Key), list_to_binary(Value)}], Acc)
+ end
+ end, dict:new(), couch_config:all()),
+ KVs = dict:fold(fun(Section, Values, Acc) ->
+ [{list_to_binary(Section), {Values}} | Acc]
+ end, [], Grouped),
send_json(Req, 200, {KVs});
% GET /_config/Section
handle_config_req(#httpd{method='GET', path_parts=[_,Section]}=Req) ->