Replying the question *"2. how they're subsequently mutated/abused over the
_config REST API?*". Does it means the codepath of the _config rest api? If
it is, the excellent explanation of Jan on the codepath of PUT /DB/DocID
will help to better understand other rest api, such as the _config.
The five API related to _config as below,
GET /_config
GET /_config/section
GET /_config/section/key
PUT /_config/section/key
DELETE /_config/section/key
Check the section [httpd_global_handlers] in default.ini
_config = {couch_httpd_misc_handlers, handle_config_req}
Moving to the couch_httpd_misc_handlers:handle_config_req/1. All five
_config apis are implemented here. By checking the code we can learn that
all five apis require the server admin role.
For both PUT and DELETE /_config/section/key, needing to check the
config_whitelist, if there is no config_whitelist, move to the function
couch_httpd_misc_handlers:handle_approved_config_req/2 to handle,
Regards & Thanks!
Binbin
2012/11/19 Binbin Wang <[email protected]>
> Hi Dave,
>
> Nice homework! Replying the question "1. how are configs loaded at startup
> in CouchDB?"
>
> Referring to the current master,
> commit-d9566c831d002be16f866f0065a905bc23773cf9
>
> Assuming we use the script ../couchdb/bin/couchdb -i to launch the couchdb
> service
> *command="/opt/couchdb/erlang/bin/erl $interactive_option
> $ERL_START_OPTIONS \*
> * -env ERL_LIBS /opt/couchdb/couchdb/lib/couchdb/erlang/lib -couch_ini
> $start_arguments -s couch"*
>
> `*eval $command* -pidfile $PID_FILE -heart \
> >> $STDOUT_FILE 2>> $STDERR_FILE` || true
>
> The script execute the $command to launch the couchdb service, moving to
> the couch.erl
> couch.erl
> 17 start() ->
> *18 ok = application:start(couch).*
>
> Let's checking the couch application in couch.app
> 1 {application, couch, [
> 2 {description, "@package_name@"},
> 3 {vsn, "@version@"},
> 4 {modules, [@modules@]},
> 5 {registered, [
> 6 couch_config,
> 7 couch_db_update,
> 8 couch_db_update_notifier_sup,
> 9 couch_external_manager,
> 10 couch_httpd,
> 11 couch_log,
> 12 couch_primary_services,
> 13 couch_query_servers,
> 14 couch_secondary_services,
> 15 couch_server,
> 16 couch_server_sup,
> 17 couch_stats_aggregator,
> 18 couch_stats_collector,
> 19 couch_task_status
> 20 ]},
> * 21 {mod, {couch_app, [*
> * 22 "%localconfdir%/@defaultini@",*
> * 23 "%localconfdir%/@localini@"*
> * 24 ]}},*
> 25 {applications, [kernel, stdlib]},
> 26 {included_applications, [crypto, sasl, inets, oauth, ibrowse,
> mochiweb, os_mon]}
> 27 ]}.
>
> Check the line 21, 22, 23, 24, moving to the module couch_app.erl,
> 21 start(_Type, DefaultIniFiles) ->
> 22 *IniFiles = get_ini_files(DefaultIniFiles),*
> 23 case start_apps([crypto, public_key, sasl, inets, oauth, ssl,
> ibrowse, mochiweb, os_mon]) of
> 24 ok ->
> 25 *couch_server_sup:start_link(IniFiles);*
> 26 {error, Reason} ->
> 27 {error, Reason}
> 28 end.
>
> In my case, the IniFiles is actually,
>
> ["/opt/couchdb/couchdb/etc/couchdb/default.ini","/opt/couchdb/couchdb/etc/couchdb/local.ini"]
>
> Move to the couch_server_sup.erl
> 25 start_link(IniFiles) ->
> 26 case whereis(couch_server_sup) of
> 27 undefined ->
> 28 * start_server(IniFiles);*
> 29 _Else ->
> 30 {error, already_started}
> 31 end.
>
> 44 start_server(IniFiles) ->
> ...
> * 56 {ok, ConfigPid} = couch_config:start_link(IniFiles),*
> ...
>
> the question *"1. how are configs loaded at startup in CouchDB?"* can be
> learned here.
> line 56 spawn the couchdb config process, return the config process pid -
> ConfigPid
>
> Let's move to the couch_config to dig more, and then back to the
> couch_server_sub:start_server/1 later
>
> couch_config.erl
> 39 start_link(IniFiles) ->
> 40 gen_server:start_link({local, ?MODULE}, ?MODULE, IniFiles, []).
>
> 94 init(IniFiles) ->
> * 95 ets:new(?MODULE, [named_table, set, protected]),*
> 96 try
> 97 lists:map(fun(IniFile) ->
> * 98 {ok, ParsedIniValues} = parse_ini_file(IniFile),*
> * 99 ets:insert(?MODULE, ParsedIniValues)*
> 100 end, IniFiles),
> 101 WriteFile = case IniFiles of
> 102 [_|_] -> lists:last(IniFiles);
> 103 _ -> undefined
> 104 end,
> 105 {ok, #config{write_filename = WriteFile}}
> 106 catch _Tag:Error ->
> 107 {stop, Error}
> 108 end.
>
> The configuration in default.ini and local.ini are transformed into ets
> table. The function couch_config:parse_ini_file/1 is actually to read the
> file and parse the configs in the files.
>
> Let's back to the couch_server_sub:start_server/1,
> 72 BaseChildSpecs =
> 73 {{one_for_all, 10, 3600},
> 74 [{*couch_config,*
> 75 * {couch_server_sup, couch_config_start_link_wrapper,
> [IniFiles, ConfigPid]},*
> 76 permanent,
> 77 brutal_kill,
> 78 * worker,*
> 79 [couch_config]},
> 80 {couch_primary_services,
> 81 {couch_primary_sup, start_link, []},
> 82 permanent,
> 83 infinity,
> 84 supervisor,
> 85 [couch_primary_sup]},
> 86 {couch_secondary_services,
> 87 {couch_secondary_sup, start_link, []},
> 88 permanent,
> 89 infinity,
> 90 supervisor,
> 91 [couch_secondary_sup]}
> 92 ]},
>
> * 98 {ok, Pid} = supervisor:start_link(*
> * 99 {local, couch_server_sup}, couch_server_sup, BaseChildSpecs),
> *
>
> line 73~79, here the couch_config is actually a *child worker process* of
> the couch_serer_sub (root in couchdb). The ConfigPid is actually the return
> config process pid in line-56. Let's check the
> couch_config_start_link_wrapper, which will link the config process pid if
> it is alive, otherwise start the config process.
>
> 36 couch_config_start_link_wrapper(IniFiles, FirstConfigPid) ->
> 37 case is_process_alive(FirstConfigPid) of
> 38 true ->
> * 39 link(FirstConfigPid),*
> 40 {ok, FirstConfigPid};
> * 41 false -> couch_config:start_link(IniFiles)*
> 42 end.
>
> Regards & Thanks!
> Binbin
>
>
> 2012/11/17 Dave Cottlehuber <[email protected]>
>
>> Many thanks for all replies on my other thread!
>>
>> Erlang is amazing, and CouchDB obviously, but there's a big hurdle between
>> the handful of erlang books, and real-world expert development.
>>
>> My (selfish!) original intent of asking for this list to be created was
>> to use CouchDB as a convenient playground / reference point for improving
>> my erlangz, and ultimately end up with some contributable code. And I
>> hope that this approach will be a great thing for many of us in the
>> same situation, and in the long term, also grow our community &
>> committers too.
>>
>> So I am *really* keen for this to be as much of a group approach as
>> possible,
>> and spend time reviewing other's solutions etc, more so than just hacking
>> away in a closet. We could set up a shared git repo if you all like, or
>> just swap patches/gists over email. Whatever works.
>>
>> If you like the approach, the first one I suggest is about configuration,
>> and we
>> can check back in a week. I'd be rapt if this works out and others
>> propose some topics along the way too.
>>
>> Homework :-)
>>
>> 1. how are configs loaded at startup in CouchDB?
>> 2. how they're subsequently mutated/abused over the _config REST API?
>> 3. how are these events managed elsewhere e.g. in couch httpd when IP
>> changes?
>> 4. compare with the sys.config approach used in OTP [1]
>> 5. can you see a way to have the best of both worlds?
>>
>> I'll send my findings through early next week.
>>
>> A+
>> Dave
>>
>> [1]:
>> http://www.erlang.org/doc/design_principles/applications.html#id74029
>>
>
>
>
> --
> Wang.bupt
>
--
Wang.bupt