From 58cd856811cf0e0238bcb14792711672ba687175 Mon Sep 17 00:00:00 2001 From: "Damien F. Katz" Date: Sat, 13 Sep 2008 17:32:46 +0000 Subject: Changes and refactorings to couch_config git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@694989 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_config.erl | 86 +++++++++------------------ src/couchdb/couch_db_update_notifier_sup.erl | 5 +- src/couchdb/couch_ft_query.erl | 4 +- src/couchdb/couch_httpd.erl | 87 ++++++++++------------------ src/couchdb/couch_log.erl | 8 +-- src/couchdb/couch_query_servers.erl | 9 ++- src/couchdb/couch_server.erl | 10 ++-- src/couchdb/couch_server_sup.erl | 6 +- src/couchdb/couch_view.erl | 4 +- 9 files changed, 79 insertions(+), 140 deletions(-) (limited to 'src/couchdb') 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), -- cgit v1.2.3