summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien F. Katz <damien@apache.org>2008-09-13 17:32:46 +0000
committerDamien F. Katz <damien@apache.org>2008-09-13 17:32:46 +0000
commit58cd856811cf0e0238bcb14792711672ba687175 (patch)
tree50565ed1daa1a0966a301458f5dcb838828af478
parent48d2d8c0e97aa39eab674aea580a569d8aedd5c7 (diff)
Changes and refactorings to couch_config
git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@694989 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--share/www/script/couch_tests.js5
-rw-r--r--src/couchdb/couch_config.erl86
-rw-r--r--src/couchdb/couch_db_update_notifier_sup.erl5
-rw-r--r--src/couchdb/couch_ft_query.erl4
-rw-r--r--src/couchdb/couch_httpd.erl87
-rw-r--r--src/couchdb/couch_log.erl8
-rw-r--r--src/couchdb/couch_query_servers.erl9
-rw-r--r--src/couchdb/couch_server.erl10
-rw-r--r--src/couchdb/couch_server_sup.erl6
-rw-r--r--src/couchdb/couch_view.erl4
-rw-r--r--test/couch_config_test.erl39
11 files changed, 95 insertions, 168 deletions
diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js
index fb7b9514..57bce657 100644
--- a/share/www/script/couch_tests.js
+++ b/share/www/script/couch_tests.js
@@ -1490,6 +1490,11 @@ var tests = {
db.deleteDb();
db.createDb();
if (debug) debugger;
+
+ /*
+ purge is not to be confused with a document deletion. It removes the
+ document and all edit history from the local instance of the database.
+ */
var numDocs = 10;
diff --git a/src/couchdb/couch_config.erl b/src/couchdb/couch_config.erl
index 48386949..6822dc5c 100644
--- a/src/couchdb/couch_config.erl
+++ b/src/couchdb/couch_config.erl
@@ -23,10 +23,9 @@
-export([start_link/1, init/1,
handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
--export([store/2, register/1, register/2,
- get/1, get/2,
- lookup_match/1, lookup_match/2,
- all/0, unset/1, load_ini_file/1]).
+-export([set/3, register/1, register/2,
+ get/1, get/2, get/3,
+ all/0, delete/2, load_ini_file/1]).
-record(config,
{notify_funs=[],
@@ -39,44 +38,30 @@
start_link(IniFiles) -> gen_server:start_link({local, ?MODULE}, ?MODULE, IniFiles, []).
-%% @spec store(Key::any(), Value::any()) -> {ok, Tab::etsatable()}
-%% @doc Public API function that triggers storage of a Key/Value pair into the
-%% local ets table and writes it to the storage ini file.
-store(Key, Value) -> gen_server:call(?MODULE, {store, [{Key, Value}]}).
-
-%% @spec get(Key::any()) -> Value::any() | undefined
-%% @doc Returns the value that is stored under key::any() or undefined::atom() if no
-%% such Key exists.
-get(Key) ->
- ?MODULE:get(Key, undefined).
-
-%% @spec get(Key::any(), Default::any()) -> Value::any() | Default
-%% @doc Returns the value that is stored under key::any() or Default::any() if
-%% no such Key exists.
-get(Key, Default) ->
- fix_lookup_result(ets:lookup(?MODULE, Key), Default).
-
-%% @spec lookup_match(Key::any()) -> Value::any() | undefined:atom()
-%% @doc Lets you look for a Key's Value specifying a pattern that gets passed
-%% to ets::match(). Returns undefined::atom() if no Key is found.
-lookup_match(Key) -> gen_server:call(?MODULE, {lookup_match, Key}).
-
-%% @spec lookup_match(Key::any(), Default::any()) -> Value::any() | Default
-%% @doc Lets you look for a Key's Value specifying a pattern that gets passed
-%% to ets::match(). Returns Default::any() if no Key is found
-lookup_match(Key, Default) -> gen_server:call(?MODULE, {lookup_match, Key, Default}).
+set(Section, Key, Value) ->
+ gen_server:call(?MODULE, {set, [{{Section, Key}, Value}]}).
-all() -> gen_server:call(?MODULE, all).
+delete(Section, Key) ->
+ gen_server:call(?MODULE, {delete, {Section, Key}}).
-register(Fun) -> gen_server:call(?MODULE, {register, Fun, self()}).
+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].
-register(Fun, Pid) -> gen_server:call(?MODULE, {register, Fun, Pid}).
+all() -> gen_server:call(?MODULE, all).
-%% @spec unset(Key::any) -> ok
-%% @doc Public API call to remove the configuration entry from the internal
-%% ets table. This change is _not_ written to the storage ini file.
-unset(Key) -> gen_server:call(?MODULE, {unset, Key}).
+register(Fun) -> ?MODULE:register(Fun, self()).
+
+register(Fun, Pid) -> gen_server:call(?MODULE, {register, Fun, Pid}).
%% Private API %%
@@ -87,42 +72,23 @@ init(IniFiles) ->
[ok = load_ini_file(IniFile) || IniFile <- IniFiles],
{ok, #config{writeback_filename=lists:last(IniFiles)}}.
-%% @doc see store/2
-handle_call({store, KVs}, _From, Config) ->
+handle_call({set, KVs}, _From, Config) ->
[ok = insert_and_commit(Config, KV) || KV <- KVs],
{reply, ok, Config};
-
-%% @doc See init_value/2
-handle_call({init_value, Key, Value}, _From, Config) ->
- Reply = ets:insert(?MODULE, {Key, Value}),
- {reply, Reply, Config};
-
-%% @doc See unset/1
-handle_call({unset, Key}, _From, Config) ->
+handle_call({delete, Key}, _From, Config) ->
ets:delete(?MODULE, Key),
{reply, ok, Config};
-
-%% @doc See lookup_match/2
-handle_call({lookup_match, Key, Default}, _From, Config) ->
- {reply, fix_lookup_result(ets:match(?MODULE, Key), Default), Config};
-
handle_call(all, _From, Config) ->
{reply, lists:sort(ets:tab2list(?MODULE)), Config};
-%% @doc See register/2
handle_call({register, Fun, Pid}, _From, #config{notify_funs=PidFuns}=Config) ->
erlang:monitor(process, Pid),
{reply, ok, Config#config{notify_funs=[{Pid, Fun}|PidFuns]}}.
-fix_lookup_result([{_Key, Value}], _Default) ->
- Value;
-fix_lookup_result([], Default) ->
- Default;
-fix_lookup_result(Values, _Default) ->
- [list_to_tuple(Value) || Value <- Values].
+
%% @spec insert_and_commit(Tab::etstable(), Config::any()) -> ok
%% @doc Inserts a Key/Value pair into the ets table, writes it to the storage
@@ -130,7 +96,7 @@ fix_lookup_result(Values, _Default) ->
insert_and_commit(Config, KV) ->
true = ets:insert(?MODULE, KV),
% notify funs
- %[catch Fun(KV) || {_Pid, Fun} <- Config#config.notify_funs],
+ [catch Fun(KV) || {_Pid, Fun} <- Config#config.notify_funs],
couch_config_writer:save_to_file(KV, Config#config.writeback_filename).
%% @spec load_ini_file(IniFile::filename()) -> ok
diff --git a/src/couchdb/couch_db_update_notifier_sup.erl b/src/couchdb/couch_db_update_notifier_sup.erl
index 010533da..0662fe77 100644
--- a/src/couchdb/couch_db_update_notifier_sup.erl
+++ b/src/couchdb/couch_db_update_notifier_sup.erl
@@ -31,12 +31,11 @@ start_link() ->
init([]) ->
Self = self(),
ok = couch_config:register(
- fun({"update_notification", _}) ->
+ fun("update_notification", _) ->
exit(Self, reload_config)
end),
- UpdateNotifierExes = couch_config:lookup_match(
- {{"update_notification", '$1'}, '$2'}, []),
+ UpdateNotifierExes = couch_config:get("update_notification"),
{ok,
{{one_for_one, 10, 3600},
diff --git a/src/couchdb/couch_ft_query.erl b/src/couchdb/couch_ft_query.erl
index 9f876794..49cc374f 100644
--- a/src/couchdb/couch_ft_query.erl
+++ b/src/couchdb/couch_ft_query.erl
@@ -28,11 +28,11 @@ execute(DatabaseName, QueryString) ->
init([]) ->
ok = couch_config:register(
- fun({"search", "query_server"}) ->
+ fun("search", "query_server") ->
?MODULE:stop()
end),
- case couch_config:get({"search", "query_server"}, none) of
+ case couch_config:get("search", "query_server", none) of
none ->
{ok, none};
QueryExec ->
diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl
index 3857f40d..b30ef7ee 100644
--- a/src/couchdb/couch_httpd.erl
+++ b/src/couchdb/couch_httpd.erl
@@ -44,12 +44,13 @@ start_link() ->
% just stop if one of the config settings change. couch_server_sup
% will restart us and then we will pick up the new settings.
- BindAddress = couch_config:get({"httpd", "bind_address"}, any),
- Port = couch_config:get({"httpd", "port"}, "5984"),
- DocumentRoot = couch_config:get({"httpd", "utils_dir"}, "../../share/www"),
+ BindAddress = couch_config:get("httpd", "bind_address", any),
+ Port = couch_config:get("httpd", "port", "5984"),
+ DocumentRoot = couch_config:get("httpd", "utils_dir", "../../share/www"),
% and off we go
- Loop = fun (Req) -> apply(couch_httpd, handle_request, [Req, DocumentRoot]) end,
+ Loop = fun (Req) -> apply(couch_httpd, handle_request,
+ [Req, DocumentRoot]) end,
{ok, Pid} = mochiweb_http:start([
{loop, Loop},
{name, ?MODULE},
@@ -57,11 +58,11 @@ start_link() ->
{port, Port}
]),
ok = couch_config:register(
- fun({"httpd", "bind_address"}) ->
+ fun("httpd", "bind_address") ->
?MODULE:stop();
- ({"httpd", "port"}) ->
+ ("httpd", "port") ->
?MODULE:stop();
- ({"httpd", "utils_dir"}) ->
+ ("httpd", "utils_dir") ->
?MODULE:stop()
end, Pid),
@@ -77,13 +78,11 @@ handle_request(Req, DocumentRoot) ->
% alias HEAD to GET as mochiweb takes care of stripping the body
Method = case Req:get(method) of
'HEAD' -> 'GET';
- Other ->
- % handling of non standard HTTP verbs. Should be fixe din gen_tcp:recv()
- case Other of
- "COPY" -> 'COPY';
- "MOVE" -> 'MOVE';
- StandardMethod -> StandardMethod
- end
+
+ % handling of non standard HTTP verbs. Should be fixed in gen_tcp:recv()
+ "COPY" -> 'COPY';
+ "MOVE" -> 'MOVE';
+ StandardMethod -> StandardMethod
end,
% for the path, use the raw path with the query string and fragment
@@ -808,66 +807,42 @@ handle_config_request(_Req, Method, {config, Config}) ->
% GET /_config/Section
handle_config_request(Req, 'GET', {[Section]}) ->
- Options = [
- {[{name, list_to_binary(Option)}, {value, list_to_binary(Value)}]} ||
- {Option, Value} <-
- couch_config:lookup_match({{Section, '$1'}, '$2'}, [])
+ KVs = [
+ {list_to_binary(Key), list_to_binary(Value)} ||
+ {Key, Value} <-
+ couch_config:get(Section)
],
- send_json(Req, 200, {[
- {ok, true},
- {section, list_to_binary(Section)},
- {options, Options}
- ]});
+ send_json(Req, 200, {KVs});
-% PUT /_config/Section/Option
+% PUT /_config/Section/Key
% "value"
-handle_config_request(Req, 'PUT', {[Section, Option]}) ->
+handle_config_request(Req, 'PUT', {[Section, Key]}) ->
Value = binary_to_list(Req:recv_body()),
- ok = couch_config:store({Section, Option}, Value),
+ ok = couch_config:set(Section, Key, Value),
send_json(Req, 200, {[
- {ok, true},
- {section, list_to_binary(Section)},
- {name, list_to_binary(Option)},
- {value, list_to_binary(Value)}
+ {ok, true}
]});
-% GET /_config/Section/Option
-handle_config_request(Req, 'GET', {[Section, Option]}) ->
- case couch_config:get({Section, Option},null) of
+% GET /_config/Section/Key
+handle_config_request(Req, 'GET', {[Section, Key]}) ->
+ case couch_config:get(Section, Key, null) of
null ->
throw({not_found, unknown_config_value});
Value ->
- send_json(Req, 200, {[
- {ok, true},
- {section, list_to_binary(Section)},
- {name, list_to_binary(Option)},
- {value, list_to_binary(Value)}
- ]})
+ send_json(Req, 200, list_to_binary(Value))
end;
-% DELETE /_config/Section/Option
-handle_config_request(Req, 'DELETE', {[Section, Option]}) ->
- case couch_config:get({Section, Option}, null) of
+% DELETE /_config/Section/Key
+handle_config_request(Req, 'DELETE', {[Section, Key]}) ->
+ case couch_config:get(Section, Key, null) of
null ->
throw({not_found, unknown_config_value});
OldValue ->
- couch_config:unset({Section, Option}),
- send_json(Req, 200, {[
- {ok, true},
- {section, list_to_binary(Section)},
- {name, list_to_binary(Option)},
- {value, list_to_binary(OldValue)}
- ]})
+ couch_config:delete(Section, Key),
+ send_json(Req, 200, list_to_binary(OldValue))
end.
-% TODO:
-% POST,PUT /_config/
-% [{Key, Value}, {K2, V2}, {K3, V3}]
-%
-% POST,PUT/_config/Key?value=Value
-
-
% View request handling internals
reverse_key_default(nil) -> {};
diff --git a/src/couchdb/couch_log.erl b/src/couchdb/couch_log.erl
index 69dabbcf..3d99ae1e 100644
--- a/src/couchdb/couch_log.erl
+++ b/src/couchdb/couch_log.erl
@@ -46,14 +46,14 @@ init([]) ->
% just stop if one of the config settings change. couch_server_sup
% will restart us and then we will pick up the new settings.
ok = couch_config:register(
- fun({"log", "file"}) ->
+ fun("log", "file") ->
?MODULE:stop();
- ({"log", "level"}) ->
+ ("log", "level") ->
?MODULE:stop()
end),
- Filename = couch_config:get({"log", "file"}, "couchdb.log"),
- Level = couch_config:get({"log", "level"},"info"),
+ Filename = couch_config:get("log", "file", "couchdb.log"),
+ Level = couch_config:get("log", "level", "info"),
{ok, Fd} = file:open(Filename, [append]),
{ok, {Fd, level_integer(list_to_atom(Level))}}.
diff --git a/src/couchdb/couch_query_servers.erl b/src/couchdb/couch_query_servers.erl
index 9b1324eb..e9f309a2 100644
--- a/src/couchdb/couch_query_servers.erl
+++ b/src/couchdb/couch_query_servers.erl
@@ -35,8 +35,8 @@ readline(Port, Acc) ->
case get(query_server_timeout) of
undefined ->
Timeout = list_to_integer(couch_config:get(
- {"couchdb", "view_timeout"}, "5000")),
- put(timeout, Timeout);
+ "couchdb", "view_timeout", "5000")),
+ put(query_server_timeout, Timeout);
Timeout -> ok
end,
receive
@@ -183,12 +183,11 @@ init([]) ->
% will restart us and then we will pick up the new settings.
ok = couch_config:register(
- fun({"query_servers" ++ _, _}) ->
+ fun("query_servers" ++ _, _) ->
?MODULE:stop()
end),
- QueryServers = couch_config:lookup_match(
- {{"query_servers", '$1'}, '$2'}, []),
+ QueryServers = couch_config:get("query_servers"),
QueryServers2 =
[{list_to_binary(Lang), Path} || {Lang, Path} <- QueryServers],
diff --git a/src/couchdb/couch_server.erl b/src/couchdb/couch_server.erl
index c3630f83..04189764 100644
--- a/src/couchdb/couch_server.erl
+++ b/src/couchdb/couch_server.erl
@@ -94,13 +94,13 @@ init([]) ->
% just stop if one of the config settings change. couch_server_sup
% will restart us and then we will pick up the new settings.
- RootDir = couch_config:get({"couchdb", "database_dir"}, "."),
- MaxDbsOpen = couch_config:get({"couchdb", "max_open_databases"}, "100"),
+ RootDir = couch_config:get("couchdb", "database_dir", "."),
+ MaxDbsOpen = couch_config:get("couchdb", "max_open_databases", "100"),
Self = self(),
ok = couch_config:register(
- fun({"couchdb", "database_dir"}) ->
+ fun("couchdb", "database_dir") ->
exit(Self, config_change);
- ({"couchdb", "server_options"}) ->
+ ("couchdb", "server_options") ->
exit(Self, config_change)
end),
{ok, RegExp} = regexp:parse("^[a-z][a-z0-9\\_\\$()\\+\\-\\/]*$"),
@@ -264,7 +264,7 @@ handle_call({delete, DbName}, _From, Server) ->
{reply, Error, Server}
end;
handle_call(remote_restart, _From, Server) ->
- case couch_config:get({"couchdb", "allow_remote_restart"}, "false") of
+ case couch_config:get("couchdb", "allow_remote_restart", "false") of
"true" ->
exit(couch_server_sup, restart);
_ ->
diff --git a/src/couchdb/couch_server_sup.erl b/src/couchdb/couch_server_sup.erl
index b34db356..78ae13ed 100644
--- a/src/couchdb/couch_server_sup.erl
+++ b/src/couchdb/couch_server_sup.erl
@@ -49,7 +49,7 @@ start_server(IniFiles) ->
{ok, ConfigPid} = couch_config:start_link(IniFiles),
- LogLevel = couch_config:get({"log", "level"}, "info"),
+ LogLevel = couch_config:get("log", "level", "info"),
% announce startup
io:format("Apache CouchDB ~s (LogLevel=~s) is starting.~n", [
couch_server:get_version(),
@@ -64,7 +64,7 @@ start_server(IniFiles) ->
end,
LibDir =
- case couch_config:get({"couchdb", "util_driver_dir"}, null) of
+ case couch_config:get("couchdb", "util_driver_dir", null) of
null ->
filename:join(code:priv_dir(couch), "lib");
LibDir0 -> LibDir0
@@ -100,7 +100,7 @@ start_server(IniFiles) ->
% just restart if one of the config settings change.
couch_config:register(
- fun({"couchdb", "util_driver_dir"}) ->
+ fun("couchdb", "util_driver_dir") ->
?MODULE:stop()
end, Pid),
diff --git a/src/couchdb/couch_view.erl b/src/couchdb/couch_view.erl
index 9414e4fa..a1afe49f 100644
--- a/src/couchdb/couch_view.erl
+++ b/src/couchdb/couch_view.erl
@@ -238,10 +238,10 @@ fold(#view{btree=Btree}, StartKey, Dir, Fun, Acc) ->
init([]) ->
% read configuration settings and register for configuration changes
- RootDir = couch_config:get({"couchdb", "database_dir"}),
+ RootDir = couch_config:get("couchdb", "database_dir"),
Self = self(),
ok = couch_config:register(
- fun({"couchdb", "database_dir"})->
+ fun("couchdb", "database_dir")->
exit(Self, config_change)
end),
diff --git a/test/couch_config_test.erl b/test/couch_config_test.erl
index 7db45bd7..faacd5fc 100644
--- a/test/couch_config_test.erl
+++ b/test/couch_config_test.erl
@@ -5,45 +5,28 @@
% that run the actual tests.
couch_config_test() ->
[
- fun() -> store_tuples() end,
- fun() -> store_strings() end,
- fun() -> store_numbers() end,
- fun() -> store_tuple_key() end
+ fun() -> store_strings() end
].
% test functions
-
-% test storing different types and see if they come back
-% the same way there put in.
-store_tuples() ->
- store(key, value).
store_strings() ->
- store("key", "value").
-
-store_numbers() ->
- store("number_key", 12345).
-
-store_tuple_key() ->
- store({key, subkey}, value).
-
-
-store(Key2, Value2) ->
- Filename = "local.ini",
+ Filename = "test.ini",
file:write_file(Filename, ""),
- Key = binary_to_list(term_to_binary(Key2)),
- Value = binary_to_list(term_to_binary(Value2)),
-
- couch_config:start_link(["local.ini"]),
+ Key = "foo",
+ Value = "bar",
- couch_config:store({"test_module", Key}, Value),
- Result = couch_config:get({"test_module", Key}),
- couch_config:unset(Key),
+ {ok, Proc} = couch_config:start_link([Filename]),
- couch_config:terminate(end_of_test, ok),
+ couch_config:set("test_module", Key, Value),
+ Result = couch_config:get("test_module", Key),
+ couch_config:delete("test_module", Key),
+ exit(Proc, kill),
+ receive {'EXIT', Proc, _} -> ok end,
+
% clean up
file:delete(Filename),