You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2013/06/29 17:17:42 UTC

[01/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Updated Branches:
  refs/heads/1843-feature-bigcouch [created] cba2e813b


Add total_changes to view compaction status


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/de41ca78
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/de41ca78
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/de41ca78

Branch: refs/heads/1843-feature-bigcouch
Commit: de41ca78fcb0e4f5d6863cbc09654663b1785ad7
Parents: ede95d5
Author: Robert Newson <ro...@cloudant.com>
Authored: Wed Sep 5 00:15:36 2012 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:50 2013 -0500

----------------------------------------------------------------------
 src/couch_mrview/src/couch_mrview_compactor.erl | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/de41ca78/src/couch_mrview/src/couch_mrview_compactor.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview/src/couch_mrview_compactor.erl b/src/couch_mrview/src/couch_mrview_compactor.erl
index 02473e7..1a316fc 100644
--- a/src/couch_mrview/src/couch_mrview_compactor.erl
+++ b/src/couch_mrview/src/couch_mrview_compactor.erl
@@ -148,7 +148,11 @@ compact_view(View, EmptyView, BufferSize, Acc0) ->
 
 update_task(#acc{changes = Changes, total_changes = Total} = Acc, ChangesInc) ->
     Changes2 = Changes + ChangesInc,
-    couch_task_status:update([{progress, (Changes2 * 100) div Total}]),
+    couch_task_status:update([
+        {changes_done, Changes2},
+        {total_changes, Total},
+        {progress, (Changes2 * 100) div Total}
+    ]),
     Acc#acc{changes = Changes2}.
 
 


[43/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
[move] Silence some logging

If a db dies becuase its fd closed then we should avoid trying to close
the dead fd in couch_db:terminate/2.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/0c273b1e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/0c273b1e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/0c273b1e

Branch: refs/heads/1843-feature-bigcouch
Commit: 0c273b1e1258b5faadce574e4380598ae2d71493
Parents: 06475ba
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 13:09:10 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:56 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db_updater.erl | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/0c273b1e/src/couch/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl
index b8e150c..649826a 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -66,7 +66,14 @@ init({DbName, Filepath, Fd, Options}) ->
 
 
 terminate(_Reason, Db) ->
-    ok = couch_file:close(Db#db.fd),
+    % If the reason we died is becuase our fd disappeared
+    % then we don't need to try closing it again.
+    case Db#db.fd of
+        Pid when is_pid(Pid) ->
+            ok = couch_file:close(Db#db.fd);
+        _ ->
+            ok
+    end,
     couch_util:shutdown_sync(Db#db.compactor_pid),
     couch_util:shutdown_sync(Db#db.fd),
     ok.
@@ -301,7 +308,7 @@ handle_info({'EXIT', _Pid, Reason}, Db) ->
     {stop, Reason, Db};
 handle_info({'DOWN', Ref, _, _, Reason}, #db{fd_monitor=Ref, name=Name} = Db) ->
     ?LOG_ERROR("DB ~s shutting down - Fd ~p", [Name, Reason]),
-    {stop, normal, Db}.
+    {stop, normal, Db#db{fd=undefined, fd_monitor=undefined}}.
 
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.


[04/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Include view id in view compaction status

The view entry lists the current view being compacted. The value is null
when processing the id btree.

BugzID: 15494


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/c8a4db86
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/c8a4db86
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/c8a4db86

Branch: refs/heads/1843-feature-bigcouch
Commit: c8a4db864f5449a98ae8c967028fffd604ead570
Parents: 4175d06
Author: Robert Newson <ro...@cloudant.com>
Authored: Wed Nov 7 19:52:31 2012 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:50 2013 -0500

----------------------------------------------------------------------
 src/couch_mrview/src/couch_mrview_compactor.erl | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/c8a4db86/src/couch_mrview/src/couch_mrview_compactor.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview/src/couch_mrview_compactor.erl b/src/couch_mrview/src/couch_mrview_compactor.erl
index 1a316fc..6419566 100644
--- a/src/couch_mrview/src/couch_mrview_compactor.erl
+++ b/src/couch_mrview/src/couch_mrview_compactor.erl
@@ -126,12 +126,12 @@ recompact(State) ->
 
 
 %% @spec compact_view(View, EmptyView, Retry, Acc) -> {CompactView, NewAcc}
-compact_view(View, EmptyView, BufferSize, Acc0) ->
+compact_view(#mrview{id_num=VID}=View, EmptyView, BufferSize, Acc0) ->
     Fun = fun(KV, #acc{btree = Bt, kvs = Kvs, kvs_size = KvsSize} = Acc) ->
         KvsSize2 = KvsSize + ?term_size(KV),
         if KvsSize2 >= BufferSize ->
             {ok, Bt2} = couch_btree:add(Bt, lists:reverse([KV | Kvs])),
-            Acc2 = update_task(Acc, 1 + length(Kvs)),
+            Acc2 = update_task(VID, Acc, 1 + length(Kvs)),
             {ok, Acc2#acc{btree = Bt2, kvs = [], kvs_size = 0}};
         true ->
             {ok, Acc#acc{kvs = [KV | Kvs], kvs_size = KvsSize2}}
@@ -142,13 +142,18 @@ compact_view(View, EmptyView, BufferSize, Acc0) ->
     {ok, _, FinalAcc} = couch_btree:foldl(View#mrview.btree, Fun, InitAcc),
     #acc{btree = Bt3, kvs = Uncopied} = FinalAcc,
     {ok, NewBt} = couch_btree:add(Bt3, lists:reverse(Uncopied)),
-    FinalAcc2 = update_task(FinalAcc, length(Uncopied)),
+    FinalAcc2 = update_task(VID, FinalAcc, length(Uncopied)),
     {EmptyView#mrview{btree=NewBt}, FinalAcc2}.
 
 
-update_task(#acc{changes = Changes, total_changes = Total} = Acc, ChangesInc) ->
+update_task(Acc, ChangesInc) ->
+    update_task(null, Acc, ChangesInc).
+
+
+update_task(VID, #acc{changes=Changes, total_changes=Total}=Acc, ChangesInc) ->
     Changes2 = Changes + ChangesInc,
     couch_task_status:update([
+        {view, VID},
         {changes_done, Changes2},
         {total_changes, Total},
         {progress, (Changes2 * 100) div Total}


[17/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Reimplement db created events


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/c92694a6
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/c92694a6
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/c92694a6

Branch: refs/heads/1843-feature-bigcouch
Commit: c92694a6f7255860468d507885880bfc302c0b16
Parents: 05d8f16
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Jan 23 15:10:57 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:52 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_server.erl | 6 ++++++
 1 file changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/c92694a6/src/couch/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index 40dc3f9..1c74456 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -251,6 +251,12 @@ open_async(Server, From, DbName, Filepath, Options) ->
     put({async_open, DbName}, now()),
     Opener = spawn_link(fun() ->
         Res = couch_db:start_link(DbName, Filepath, Options),
+        case {Res, lists:member(create, Options)} of
+            {{ok, _Db}, true} ->
+                couch_db_update_notifier:notify({created, DbName});
+            _ ->
+                ok
+        end,
         gen_server:call(Parent, {open_result, DbName, Res}, infinity),
         unlink(Parent)
     end),


[07/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Fix handling of initial accumulator for objects

BugzID: 14798


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/b82ccc54
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/b82ccc54
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/b82ccc54

Branch: refs/heads/1843-feature-bigcouch
Commit: b82ccc54ae035e16aed1c47c99f2be04fe62df23
Parents: 98a0cfa
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Mon Dec 10 14:29:30 2012 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:51 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/b82ccc54/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index e420ce9..4e4f938 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -211,6 +211,8 @@ builtin_reduce(Re, [<<"_stats",_/binary>>|BuiltinReds], KVs, Acc) ->
 builtin_sum_rows(KVs) ->
     lists:foldl(fun([_Key, Value], Acc) -> sum_values(Value, Acc) end, 0, KVs).
 
+sum_values({Props}, 0) ->
+    {Props};
 sum_values({Props}, {AccProps}) ->
     {sum_objects(lists:sort(Props), lists:sort(AccProps))};
 sum_values(Value, Acc) when is_number(Value), is_number(Acc) ->


[28/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Reject design docs with compilation errors

If we know the language for a given design doc we'll attempt to compile
the map/reduce functions and reject updates that introduce code that
doesn't compile. We don't yet do the other types of functions because
those errors are more user visible.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/b474248c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/b474248c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/b474248c

Branch: refs/heads/1843-feature-bigcouch
Commit: b474248c6fd7f2bb5bab20225869920d87414ea7
Parents: 0861ab0
Author: Paul J. Davis <pa...@gmail.com>
Authored: Sun Mar 10 16:03:00 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:54 2013 -0500

----------------------------------------------------------------------
 etc/couchdb/default.ini.tpl.in             |  3 +++
 src/couch/src/couch_db.erl                 | 15 +++++++++--
 src/couch/src/couch_query_servers.erl      | 12 +++++++++
 src/couch_index/src/couch_index_server.erl | 28 +++++++++++++++++++-
 src/couch_mrview/src/couch_mrview.erl      | 35 +++++++++++++++++++++++++
 5 files changed, 90 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/etc/couchdb/default.ini.tpl.in
----------------------------------------------------------------------
diff --git a/etc/couchdb/default.ini.tpl.in b/etc/couchdb/default.ini.tpl.in
index 02341d3..9d9465e 100644
--- a/etc/couchdb/default.ini.tpl.in
+++ b/etc/couchdb/default.ini.tpl.in
@@ -142,6 +142,9 @@ replicator_manager={couch_replicator_manager, start_link, []}
 os_daemons={couch_os_daemons, start_link, []}
 compaction_daemon={couch_compaction_daemon, start_link, []}
 
+[indexers]
+couch_mrview = true
+
 [httpd_global_handlers]
 / = {couch_httpd_misc_handlers, handle_welcome_req, <<"Welcome">>}
 favicon.ico = {couch_httpd_misc_handlers, handle_favicon_req, "%localdatadir%/www"}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 56cb0d2..7734c7c 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -502,8 +502,11 @@ group_alike_docs([{Doc,Ref}|Rest], [Bucket|RestBuckets]) ->
        group_alike_docs(Rest, [[{Doc,Ref}]|[Bucket|RestBuckets]])
     end.
 
-validate_doc_update(#db{}=Db, #doc{id= <<"_design/",_/binary>>}, _GetDiskDocFun) ->
-    catch check_is_admin(Db);
+validate_doc_update(#db{}=Db, #doc{id= <<"_design/",_/binary>>}=Doc, _GetDiskDocFun) ->
+    case catch check_is_admin(Db) of
+        ok -> validate_ddoc(Db#db.name, Doc);
+        Error -> Error
+    end;
 validate_doc_update(#db{validate_doc_funs = undefined} = Db, Doc, Fun) ->
     ValidationFuns = load_validation_funs(Db),
     validate_doc_update(Db#db{validate_doc_funs=ValidationFuns}, Doc, Fun);
@@ -519,6 +522,14 @@ validate_doc_update(Db, Doc, GetDiskDocFun) ->
             validate_doc_update_int(Db, Doc, GetDiskDocFun)
     end.
 
+validate_ddoc(DbName, DDoc) ->
+    try
+        couch_index_server:validate(DbName, couch_doc:with_ejson_body(DDoc))
+    catch
+        throw:Error ->
+            Error
+    end.
+
 validate_doc_update_int(Db, Doc, GetDiskDocFun) ->
     DiskDoc = GetDiskDocFun(),
     JsonCtx = couch_util:json_user_ctx(Db),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index d919a85..8e4130e 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -12,6 +12,7 @@
 
 -module(couch_query_servers).
 
+-export([try_compile/4]).
 -export([start_doc_map/3, map_docs/2, map_docs_raw/2, stop_doc_map/1, raw_to_ejson/1]).
 -export([reduce/3, rereduce/3,validate_doc_update/5]).
 -export([filter_docs/5]).
@@ -65,6 +66,17 @@
 46,65,9,27,108,27,101,27,110,27,103,27,116,27,104,56,9,34,59,84,0,78,84,1,102,
 65,9,27,125,56,9,84,1,206,0,0,0,0,0,0,0>>}).
 
+
+try_compile(Proc, FunctionType, FunctionName, FunctionSource) ->
+    try
+        proc_prompt(Proc, [<<"add_fun">>, FunctionSource]),
+        ok
+    catch {compilation_error, E} ->
+        Fmt = "Compilation of the ~s function in the '~s' view failed: ~s",
+        Msg = io_lib:format(Fmt, [FunctionType, FunctionName, E]),
+        throw({compilation_error, Msg})
+    end.
+
 start_doc_map(Lang, Functions, Lib) ->
     Proc = get_os_process(Lang),
     case Lib of

http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/src/couch_index/src/couch_index_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_index/src/couch_index_server.erl b/src/couch_index/src/couch_index_server.erl
index a106f14..3d8a797 100644
--- a/src/couch_index/src/couch_index_server.erl
+++ b/src/couch_index/src/couch_index_server.erl
@@ -14,7 +14,7 @@
 -behaviour(gen_server).
 -behaviour(config_listener).
 
--export([start_link/0, get_index/4, get_index/3, get_index/2]).
+-export([start_link/0, validate/2, get_index/4, get_index/3, get_index/2]).
 -export([update_notify/1]).
 
 -export([init/1, terminate/2, code_change/3]).
@@ -35,6 +35,32 @@
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
+
+validate(DbName, DDoc) ->
+    LoadModFun = fun
+        ({ModNameList, "true"}) ->
+            try
+                [list_to_existing_atom(ModNameList)]
+            catch error:badarg ->
+                []
+            end;
+        ({_ModNameList, _Enabled}) ->
+            []
+    end,
+    ValidateFun = fun
+        (ModName, ok) ->
+            try
+                ModName:validate(DbName, DDoc)
+            catch Type:Reason ->
+                {Type, Reason}
+            end;
+        (_ModName, Error) ->
+            Error
+    end,
+    EnabledIndexers = lists:flatmap(LoadModFun, config:get("indexers")),
+    lists:foldl(ValidateFun, ok, EnabledIndexers).
+
+
 get_index(Module, <<"shards/", _/binary>>=DbName, DDoc) ->
     {Pid, Ref} = spawn_monitor(fun() ->
         exit(fabric:open_doc(mem3:dbname(DbName), DDoc, []))

http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/src/couch_mrview/src/couch_mrview.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview/src/couch_mrview.erl b/src/couch_mrview/src/couch_mrview.erl
index 20ba6d9..29b86d7 100644
--- a/src/couch_mrview/src/couch_mrview.erl
+++ b/src/couch_mrview/src/couch_mrview.erl
@@ -12,6 +12,7 @@
 
 -module(couch_mrview).
 
+-export([validate/2]).
 -export([query_all_docs/2, query_all_docs/4]).
 -export([query_view/3, query_view/4, query_view/6]).
 -export([get_info/2]).
@@ -40,6 +41,40 @@
 }).
 
 
+validate(DbName, DDoc) ->
+    GetName = fun
+        (#mrview{map_names = [Name | _]}) -> Name;
+        (#mrview{reduce_funs = [{Name, _} | _]}) -> Name;
+        (_) -> null
+    end,
+    ValidateView = fun(Proc, #mrview{def=MapSrc, reduce_funs=Reds}=View) ->
+        couch_query_servers:try_compile(Proc, map, GetName(View), MapSrc),
+        lists:foreach(fun
+            ({_RedName, <<"_", _/binary>>}) ->
+                ok;
+            ({RedName, RedSrc}) ->
+                couch_query_servers:try_compile(Proc, reduce, RedName, RedSrc)
+        end, Reds)
+    end,
+    {ok, #mrst{language=Lang, views=Views}}
+            = couch_mrview_util:ddoc_to_mrst(DbName, DDoc),
+    try Views =/= [] andalso couch_query_servers:get_os_process(Lang) of
+        false ->
+            ok;
+        Proc ->
+            try
+                lists:foreach(fun(V) -> ValidateView(Proc, V) end, Views)
+            catch Error ->
+                Error
+            after
+                couch_query_servers:ret_os_process(Proc)
+            end
+    catch {unknown_query_language, _Lang} ->
+        %% Allow users to save ddocs written in uknown languages
+        ok
+    end.
+
+
 query_all_docs(Db, Args) ->
     query_all_docs(Db, Args, fun default_cb/2, []).
 


[13/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
_key is confusing


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/403ff6b5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/403ff6b5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/403ff6b5

Branch: refs/heads/1843-feature-bigcouch
Commit: 403ff6b51cb6796c04d6efd875ccb120c3b69ff2
Parents: 3a80e08
Author: Robert Newson <ro...@cloudant.com>
Authored: Fri Jan 25 01:49:54 2013 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:52 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/403ff6b5/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index b32ed06..679d815 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -254,7 +254,7 @@ sum_arrays(_, _) ->
 builtin_stats(_, []) ->
     {[{sum,0}, {count,0}, {min,0}, {max,0}, {sumsqr,0}]};
 builtin_stats(_, [[_,First]|Rest]) ->
-    Unpacked = lists:foldl(fun([_key, Value], Acc) -> stat_values(Value, Acc) end,
+    Unpacked = lists:foldl(fun([_Key, Value], Acc) -> stat_values(Value, Acc) end,
                            build_initial_accumulator(First), Rest),
     pack_stats(Unpacked).
 


[33/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
[review] Delete dbs synchronously

For the test suite this should minimize the "file exists" errors that we
see. Theoretically maybe.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/77e7a1ff
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/77e7a1ff
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/77e7a1ff

Branch: refs/heads/1843-feature-bigcouch
Commit: 77e7a1ffb62e32b55a2cfa02847682a8b386bd5f
Parents: 6e53c8a
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 02:36:33 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:55 2013 -0500

----------------------------------------------------------------------
 share/www/script/couch.js        | 2 +-
 src/couch/src/couch_httpd_db.erl | 6 +++++-
 src/couch/src/couch_server.erl   | 6 ++++--
 3 files changed, 10 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/77e7a1ff/share/www/script/couch.js
----------------------------------------------------------------------
diff --git a/share/www/script/couch.js b/share/www/script/couch.js
index 58ad7a7..122db75 100644
--- a/share/www/script/couch.js
+++ b/share/www/script/couch.js
@@ -36,7 +36,7 @@ function CouchDB(name, httpHeaders) {
 
   // Deletes the database on the server
   this.deleteDb = function() {
-    this.last_req = this.request("DELETE", this.uri);
+    this.last_req = this.request("DELETE", this.uri + "?sync=true");
     if (this.last_req.status == 404) {
       return false;
     }

http://git-wip-us.apache.org/repos/asf/couchdb/blob/77e7a1ff/src/couch/src/couch_httpd_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_db.erl b/src/couch/src/couch_httpd_db.erl
index c70245c..50fba6c 100644
--- a/src/couch/src/couch_httpd_db.erl
+++ b/src/couch/src/couch_httpd_db.erl
@@ -220,7 +220,11 @@ create_db_req(#httpd{user_ctx=UserCtx}=Req, DbName) ->
 
 delete_db_req(#httpd{user_ctx=UserCtx}=Req, DbName) ->
     ok = couch_httpd:verify_is_server_admin(Req),
-    case couch_server:delete(DbName, [{user_ctx, UserCtx}]) of
+    Options = case couch_httpd:qs_value(Req, "sync") of
+        "true" -> [sync, {user_ctx, UserCtx}];
+        _ -> [{user_ctx, UserCtx}]
+    end,
+    case couch_server:delete(DbName, Options) of
     ok ->
         send_json(Req, 200, {[{ok, true}]});
     Error ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/77e7a1ff/src/couch/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index c23ec05..3d4a1a6 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -408,7 +408,7 @@ handle_call({create, DbName, Options}, From, Server) ->
     Error ->
         {reply, Error, Server}
     end;
-handle_call({delete, DbName, _Options}, _From, Server) ->
+handle_call({delete, DbName, Options}, _From, Server) ->
     DbNameList = binary_to_list(DbName),
     case check_dbname(Server, DbNameList) of
     ok ->
@@ -436,7 +436,9 @@ handle_call({delete, DbName, _Options}, _From, Server) ->
         end, [".compact", ".compact.data", ".compact.meta"]),
         couch_file:delete(Server#server.root_dir, FullFilepath ++ ".compact"),
 
-        case couch_file:delete(Server#server.root_dir, FullFilepath) of
+        Async = not lists:member(sync, Options),
+
+        case couch_file:delete(Server#server.root_dir, FullFilepath, Async) of
         ok ->
             couch_db_update_notifier:notify({deleted, DbName}),
             {reply, ok, Server2};


[48/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
[review] Add a remsh script


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/8f0ef8e3
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/8f0ef8e3
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/8f0ef8e3

Branch: refs/heads/1843-feature-bigcouch
Commit: 8f0ef8e3744b9d5d7ac208fdfc3ddbd87dd76588
Parents: d164628
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 21:46:30 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:57 2013 -0500

----------------------------------------------------------------------
 bin/couchdb.tpl.in |  2 +-
 bin/remsh          | 27 +++++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/8f0ef8e3/bin/couchdb.tpl.in
----------------------------------------------------------------------
diff --git a/bin/couchdb.tpl.in b/bin/couchdb.tpl.in
index 81bb8b8..709a56e 100644
--- a/bin/couchdb.tpl.in
+++ b/bin/couchdb.tpl.in
@@ -231,7 +231,7 @@ start_couchdb () {
         touch $PID_FILE
         interactive_option="+Bd -noinput"
     fi
-    command="%ERL% $interactive_option $ERL_START_OPTIONS \
+    command="%ERL% -sname couchdb $interactive_option $ERL_START_OPTIONS \
         -env ERL_LIBS $ERL_LIBS:%localerlanglibdir% -couch_ini $start_arguments -s couch"
     if test "$BACKGROUND" = "true" -a "$RECURSED" = "false"; then
         $0 $background_start_arguments -b -r $RESPAWN_TIMEOUT -p $PID_FILE \

http://git-wip-us.apache.org/repos/asf/couchdb/blob/8f0ef8e3/bin/remsh
----------------------------------------------------------------------
diff --git a/bin/remsh b/bin/remsh
new file mode 100755
index 0000000..2d06b37
--- /dev/null
+++ b/bin/remsh
@@ -0,0 +1,27 @@
+#!/usr/bin/env escript
+%%! -hidden -noshell -noinput
+
+main(_) ->
+    net_kernel:start([me(), shortnames]),
+    case net_adm:ping(couchdb()) of
+        pong ->
+            Shell = user_drv:start(['tty_sl -c -e',{couchdb(),shell,start,[]}]),
+            Ref = erlang:monitor(process, Shell),
+            receive
+                {'DOWN', Ref, _, _, _} -> ok
+            end,
+            halt(0);
+        _ ->
+            io:format("Error connection to: ~s", [couchdb()]),
+            halt(1)
+    end.
+
+
+me() ->
+    Localhost = net_adm:localhost(),
+    list_to_atom("couchdb_remsh" ++ os:getpid() ++ "@" ++ Localhost).
+
+
+couchdb() ->
+    Localhost = net_adm:localhost(),
+    list_to_atom("couchdb@" ++ Localhost).


[50/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Mention EPL of trunc_io_.erl in top-level LICENSE file


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/cba2e813
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/cba2e813
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/cba2e813

Branch: refs/heads/1843-feature-bigcouch
Commit: cba2e813bd4bb0a3eb27a357f94e9b08c05b56c4
Parents: 84a296e
Author: Robert Newson <rn...@apache.org>
Authored: Thu Jun 13 15:26:54 2013 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Thu Jun 13 15:26:54 2013 +0100

----------------------------------------------------------------------
 LICENSE | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/cba2e813/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 19490d5..7736e6e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -603,3 +603,20 @@ For the share/server/coffee-script.js file
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   OTHER DEALINGS IN THE SOFTWARE.
+
+For the src/twig/src/trunc_io.erl file
+
+  The contents of this file are subject to the Erlang Public License,
+  Version 1.1, (the "License"); you may not use this file except in
+  compliance with the License. You should have received a copy of the
+  Erlang Public License along with your Erlang distribution. If not, it can be
+  retrieved via the world wide web at http://www.erlang.org/.
+
+  Software distributed under the License is distributed on an "AS IS"
+  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+  the License for the specific language governing rights and limitations
+  under the License.
+
+  The Initial Developer of the Original Code is Corelatus AB.
+  Portions created by Corelatus are Copyright 2003, Corelatus
+  AB. All Rights Reserved.


[20/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Fix new _stats with added 'working properly' feature


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/ae6aa74b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/ae6aa74b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/ae6aa74b

Branch: refs/heads/1843-feature-bigcouch
Commit: ae6aa74b4eacb1ab43ab76a8d5cbba2bcb5e7c91
Parents: 72de049
Author: Robert Newson <ro...@cloudant.com>
Authored: Fri Jan 25 14:18:53 2013 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:53 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/ae6aa74b/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 679d815..88ab30a 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -307,9 +307,11 @@ get_number(Key, Props) ->
     case couch_util:get_value(Key, Props) of
     X when is_number(X) ->
         X;
+    undefined when is_binary(Key) ->
+        get_number(binary_to_atom(Key, latin1), Props);
     undefined ->
-        Msg = io_lib:format("user _stats input missing required field ~s",
-            [Key]),
+        Msg = io_lib:format("user _stats input missing required field ~s (~p)",
+            [Key, Props]),
         throw({invalid_value, iolist_to_binary(Msg)});
     Else ->
         Msg = io_lib:format("non-numeric _stats input received for ~s: ~w",


[22/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Remove message when adding async open listeners

This log message isn't particularly useful.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/77de003f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/77de003f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/77de003f

Branch: refs/heads/1843-feature-bigcouch
Commit: 77de003ff2fb53483d90859f07f1f1785ea26375
Parents: ae6aa74
Author: Paul J. Davis <pa...@gmail.com>
Authored: Sun Feb 10 15:04:02 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:53 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_server.erl | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/77de003f/src/couch/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index 1c74456..9f8380e 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -348,7 +348,6 @@ handle_call({open, DbName, Options}, From, Server) ->
         end;
     [#db{compactor_pid = Froms} = Db] when is_list(Froms) ->
         % icky hack of field values - compactor_pid used to store clients
-        ?LOG_INFO("adding another listener to async open for ~s", [DbName]),
         true = ets:insert(couch_dbs, Db#db{compactor_pid = [From|Froms]}),
         {noreply, Server};
     [#db{} = Db] ->


[27/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Remove reference to tally


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/409ffbcc
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/409ffbcc
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/409ffbcc

Branch: refs/heads/1843-feature-bigcouch
Commit: 409ffbccea6a1446bdc916984a5fd62c9e0c09c0
Parents: 33207af
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 17:52:46 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:54 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db_updater.erl | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/409ffbcc/src/couch/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl
index cc48ef8..4fe6073 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -829,13 +829,11 @@ sync_header(Db, NewHeader) ->
     ok = couch_file:write_header(Fd, NewHeader),
     if After -> couch_file:sync(FilePath); true -> ok end,
 
-    Db2 = Db#db{
+    Db#db{
         header=NewHeader,
         committed_update_seq=Db#db.update_seq,
         waiting_delayed_commit=nil
-    },
-    tally:update(Db2),
-    Db2.
+    }.
 
 copy_doc_attachments(#db{fd = SrcFd} = SrcDb, SrcSp, DestFd) ->
     {ok, {BodyData, BinInfos0}} = couch_db:read_doc(SrcDb, SrcSp),


[46/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
[squash] update etap tests


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/66a52955
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/66a52955
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/66a52955

Branch: refs/heads/1843-feature-bigcouch
Commit: 66a52955fd697e251647c63064b11c34ef7574a7
Parents: 86ba6db
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Mar 14 01:43:39 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:57 2013 -0500

----------------------------------------------------------------------
 src/couch_mrview/test/02-map-views.t    | 15 ++-------------
 src/couch_mrview/test/03-red-views.t    |  2 +-
 src/couch_mrview/test/04-index-info.t   | 15 ++-------------
 src/couch_mrview/test/05-collation.t    |  3 ++-
 src/couch_mrview/test/06-all-docs.t     |  2 +-
 src/couch_mrview/test/07-compact-swap.t |  2 +-
 6 files changed, 9 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/66a52955/src/couch_mrview/test/02-map-views.t
----------------------------------------------------------------------
diff --git a/src/couch_mrview/test/02-map-views.t b/src/couch_mrview/test/02-map-views.t
index 7e1ca0c..bcf4ce1 100644
--- a/src/couch_mrview/test/02-map-views.t
+++ b/src/couch_mrview/test/02-map-views.t
@@ -14,21 +14,10 @@
 % the License.
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(6),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    timer:sleep(300),
-    ok.
+    test_util:run(6, fun() -> test() end).
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
 
     {ok, Db} = couch_mrview_test_util:init_db(<<"foo">>, map),
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/66a52955/src/couch_mrview/test/03-red-views.t
----------------------------------------------------------------------
diff --git a/src/couch_mrview/test/03-red-views.t b/src/couch_mrview/test/03-red-views.t
index 6ad341b..0d11d51 100644
--- a/src/couch_mrview/test/03-red-views.t
+++ b/src/couch_mrview/test/03-red-views.t
@@ -17,7 +17,7 @@ main(_) ->
     test_util:run(4, fun() -> test() end).
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
 
     {ok, Db} = couch_mrview_test_util:init_db(<<"foo">>, red),
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/66a52955/src/couch_mrview/test/04-index-info.t
----------------------------------------------------------------------
diff --git a/src/couch_mrview/test/04-index-info.t b/src/couch_mrview/test/04-index-info.t
index 6b67b56..c86b168 100644
--- a/src/couch_mrview/test/04-index-info.t
+++ b/src/couch_mrview/test/04-index-info.t
@@ -14,23 +14,12 @@
 % the License.
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(9),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    timer:sleep(300),
-    ok.
+    test_util:run(9, fun() -> test() end).
 
 sig() -> <<"276df562b152b3c4e5d34024f62672ed">>.
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
 
     {ok, Db} = couch_mrview_test_util:init_db(<<"foo">>, map),
     couch_mrview:query_view(Db, <<"_design/bar">>, <<"baz">>),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/66a52955/src/couch_mrview/test/05-collation.t
----------------------------------------------------------------------
diff --git a/src/couch_mrview/test/05-collation.t b/src/couch_mrview/test/05-collation.t
index ac8f8bc..09878af 100644
--- a/src/couch_mrview/test/05-collation.t
+++ b/src/couch_mrview/test/05-collation.t
@@ -18,7 +18,8 @@ main(_) ->
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
+
     {ok, Db0} = couch_mrview_test_util:new_db(<<"foo">>, map),
     {ok, Db1} = couch_mrview_test_util:save_docs(Db0, docs()),
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/66a52955/src/couch_mrview/test/06-all-docs.t
----------------------------------------------------------------------
diff --git a/src/couch_mrview/test/06-all-docs.t b/src/couch_mrview/test/06-all-docs.t
index 4501aa5..a3aafa0 100644
--- a/src/couch_mrview/test/06-all-docs.t
+++ b/src/couch_mrview/test/06-all-docs.t
@@ -18,7 +18,7 @@ main(_) ->
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
 
     {ok, Db} = couch_mrview_test_util:init_db(<<"foo">>, map),
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/66a52955/src/couch_mrview/test/07-compact-swap.t
----------------------------------------------------------------------
diff --git a/src/couch_mrview/test/07-compact-swap.t b/src/couch_mrview/test/07-compact-swap.t
index 4bfe124..c1fd043 100644
--- a/src/couch_mrview/test/07-compact-swap.t
+++ b/src/couch_mrview/test/07-compact-swap.t
@@ -18,7 +18,7 @@ main(_) ->
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     {ok, Db} = couch_mrview_test_util:init_db(<<"foo">>, map, 1000),
     couch_mrview:query_view(Db, <<"_design/bar">>, <<"baz">>),
     test_swap(Db),


[18/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Throw unknown_error for non standard errors

Right now unless you throw an error with the key forbidden or
unauthorized, we throw a stack trace back at you. This will at least let
you throw a string as an error message.

Whether or not we should return unknown_error: Message or throw an error
saying invalid error format in the validate_doc_update function is
debateable.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/4fe37dee
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/4fe37dee
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/4fe37dee

Branch: refs/heads/1843-feature-bigcouch
Commit: 4fe37dee0df97d48c95df4d77171be1cce0e72b6
Parents: df41b31
Author: Russell Branca <ch...@gmail.com>
Authored: Wed Jan 23 14:03:24 2013 -0800
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:52 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/4fe37dee/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 71dcae9..5864288 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -327,7 +327,9 @@ validate_doc_update(DDoc, EditDoc, DiskDoc, Ctx, SecObj) ->
         {[{<<"forbidden">>, Message}]} ->
             throw({forbidden, Message});
         {[{<<"unauthorized">>, Message}]} ->
-            throw({unauthorized, Message})
+            throw({unauthorized, Message});
+        <<Message/binary>> ->
+            throw({unknown_error, Message})
     end.
 
 json_doc(nil) -> null;


[15/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Switch to using is_binary guard


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/0b0b6f43
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/0b0b6f43
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/0b0b6f43

Branch: refs/heads/1843-feature-bigcouch
Commit: 0b0b6f43ceadd5b11822ac5caccfcccbdab822aa
Parents: 4fe37de
Author: Russell Branca <ch...@gmail.com>
Authored: Wed Jan 23 14:14:21 2013 -0800
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:52 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/0b0b6f43/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 5864288..b32ed06 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -328,7 +328,7 @@ validate_doc_update(DDoc, EditDoc, DiskDoc, Ctx, SecObj) ->
             throw({forbidden, Message});
         {[{<<"unauthorized">>, Message}]} ->
             throw({unauthorized, Message});
-        <<Message/binary>> ->
+        Message when is_binary(Message) ->
             throw({unknown_error, Message})
     end.
 


[10/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Allow literal dot in config section names

BugzID: 15952


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/24f77c00
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/24f77c00
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/24f77c00

Branch: refs/heads/1843-feature-bigcouch
Commit: 24f77c00508611dfb59f024faed5278cf30a66da
Parents: 79dd3a9
Author: Robert Newson <ro...@cloudant.com>
Authored: Wed Dec 5 15:35:46 2012 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:51 2013 -0500

----------------------------------------------------------------------
 src/config/src/config_writer.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/24f77c00/src/config/src/config_writer.erl
----------------------------------------------------------------------
diff --git a/src/config/src/config_writer.erl b/src/config/src/config_writer.erl
index 82a2ba2..2812686 100644
--- a/src/config/src/config_writer.erl
+++ b/src/config/src/config_writer.erl
@@ -31,7 +31,7 @@ save_to_file({{Section, Key}, Value}, File) ->
     Lines = re:split(OldFileContents, "\r\n|\n|\r|\032", [{return, list}]),
 
     SectionLine = "[" ++ Section ++ "]",
-    {ok, Pattern} = re:compile(["^(", Key, "\\s*=)|\\[[a-zA-Z0-9\_-]*\\]"]),
+    {ok, Pattern} = re:compile(["^(", Key, "\\s*=)|\\[[a-zA-Z0-9\.\_-]*\\]"]),
 
     NewLines = process_file_lines(Lines, [], SectionLine, Pattern, Key, Value),
     NewFileContents = reverse_and_add_newline(strip_empty_lines(NewLines), []),


[32/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Rewrite the boot procedure for the couch app

We had a lot of historical cruft lying around from before people knew
hot OTP worked. This does some cleanup to make things a bit more tidy
through this section but we still have a long ways to go.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/33207af8
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/33207af8
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/33207af8

Branch: refs/heads/1843-feature-bigcouch
Commit: 33207af83a40b29e5a1fe93d363edc3c2f320172
Parents: 23cf4e3
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 16:13:14 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:54 2013 -0500

----------------------------------------------------------------------
 src/config/src/config.erl                       |  14 ++
 src/couch/Makefile.am                           |   5 +-
 src/couch/src/couch.app.tpl.in                  |   2 +-
 src/couch/src/couch.erl                         |  48 +++++-
 src/couch/src/couch_app.erl                     |  37 +----
 src/couch/src/couch_httpd_misc_handlers.erl     |   2 +-
 src/couch/src/couch_proc_manager.erl            |   3 +
 src/couch/src/couch_secondary_sup.erl           |   2 +-
 src/couch/src/couch_server_sup.erl              | 153 ------------------
 src/couch/src/couch_sup.erl                     | 159 +++++++++++++++++++
 .../src/couch_replicator_manager.erl            |   3 +
 11 files changed, 231 insertions(+), 197 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/config/src/config.erl
----------------------------------------------------------------------
diff --git a/src/config/src/config.erl b/src/config/src/config.erl
index 07f0489..8a94f2c 100644
--- a/src/config/src/config.erl
+++ b/src/config/src/config.erl
@@ -93,6 +93,7 @@ init(IniFiles) ->
         [_|_] -> lists:last(IniFiles);
         _ -> undefined
     end,
+    debug_config(),
     {ok, #config{write_filename=WriteFile}}.
 
 
@@ -214,3 +215,16 @@ parse_ini_file(IniFile) ->
             end
         end, {"", []}, Lines),
     {ok, ParsedIniValues}.
+
+
+debug_config() ->
+    case ?MODULE:get("log", "level") of
+        "debug" ->
+            io:format("Configuration Settings:~n", []),
+            lists:foreach(fun({{Mod, Key}, Val}) ->
+                io:format("  [~s] ~s=~p~n", [Mod, Key, Val])
+            end, lists:sort(ets:tab2list(?MODULE)));
+        _ ->
+            ok
+    end.
+

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/Makefile.am
----------------------------------------------------------------------
diff --git a/src/couch/Makefile.am b/src/couch/Makefile.am
index e87a17d..5f47bcd 100644
--- a/src/couch/Makefile.am
+++ b/src/couch/Makefile.am
@@ -70,10 +70,10 @@ source_files = \
     src/couch_query_servers.erl \
     src/couch_secondary_sup.erl \
     src/couch_server.erl \
-    src/couch_server_sup.erl \
     src/couch_stats_aggregator.erl \
     src/couch_stats_collector.erl \
     src/couch_stream.erl \
+    src/couch_sup.erl \
     src/couch_task_status.erl \
     src/couch_users_db.erl \
     src/couch_util.erl \
@@ -131,10 +131,10 @@ compiled_files = \
     ebin/couch_query_servers.beam \
     ebin/couch_secondary_sup.beam \
     ebin/couch_server.beam \
-    ebin/couch_server_sup.beam \
     ebin/couch_stats_aggregator.beam \
     ebin/couch_stats_collector.beam \
     ebin/couch_stream.beam \
+    ebin/couch_sup.beam \
     ebin/couch_task_status.beam \
     ebin/couch_users_db.beam \
     ebin/couch_util.beam \
@@ -167,7 +167,6 @@ compiled_files = \
 #     couch_rep.html \
 #     couch_rep_sup.html \
 #     couch_server.html \
-#     couch_server_sup.html \
 #     couch_stream.html \
 #     couch_util.html
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/src/couch.app.tpl.in
----------------------------------------------------------------------
diff --git a/src/couch/src/couch.app.tpl.in b/src/couch/src/couch.app.tpl.in
index 1cd0154..9b7536b 100644
--- a/src/couch/src/couch.app.tpl.in
+++ b/src/couch/src/couch.app.tpl.in
@@ -12,7 +12,7 @@
         couch_proc_manager,
         couch_secondary_services,
         couch_server,
-        couch_server_sup,
+        couch_sup,
         couch_stats_aggregator,
         couch_stats_collector,
         couch_task_status

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/src/couch.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch.erl b/src/couch/src/couch.erl
index 7d53d0c..15cffbc 100644
--- a/src/couch/src/couch.erl
+++ b/src/couch/src/couch.erl
@@ -14,18 +14,52 @@
 
 -compile(export_all).
 
+
+deps() ->
+    [
+        sasl,
+        inets,
+        os_mon,
+        crypto,
+        public_key,
+        ssl,
+        oauth,
+        ibrowse,
+        mochiweb,
+        config,
+        twig
+    ].
+
+
 start() ->
-    ok = application:start(couch).
+    catch erlang:system_flag(scheduler_bind_type, default_bind),
+    case start_apps(deps()) of
+        ok ->
+            ok = application:start(couch);
+        Else ->
+            throw(Else)
+    end.
+
 
 stop() ->
     application:stop(couch).
 
+
 restart() ->
-    case stop() of
+    init:restart().
+
+
+start_apps([]) ->
+    ok;
+start_apps([App|Rest]) ->
+    case application:start(App) of
     ok ->
-        start();
-    {error, {not_started,couch}} ->
-        start();
-    {error, Reason} ->
-        {error, Reason}
+       start_apps(Rest);
+    {error, {already_started, App}} ->
+       start_apps(Rest);
+    {error, _Reason} when App =:= public_key ->
+       % ignore on R12B5
+       start_apps(Rest);
+    {error, _Reason} ->
+       {error, {app_would_not_start, App}}
     end.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/src/couch_app.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_app.erl b/src/couch/src/couch_app.erl
index 3120a1f..d284c2b 100644
--- a/src/couch/src/couch_app.erl
+++ b/src/couch/src/couch_app.erl
@@ -18,39 +18,14 @@
 
 -export([start/2, stop/1]).
 
-start(_Type, DefaultIniFiles) ->
-    IniFiles = get_ini_files(DefaultIniFiles),
-    case start_apps([crypto, public_key, sasl, inets, oauth, ssl, ibrowse, mochiweb, os_mon]) of
-    ok ->
-        couch_server_sup:start_link(IniFiles);
-    {error, Reason} ->
-        {error, Reason}
+start(_Type, _) ->
+    case couch_sup:start_link() of
+        {ok, _} = Resp ->
+            Resp;
+        Else ->
+            throw(Else)
     end.
 
 stop(_) ->
     ok.
 
-get_ini_files(Default) ->
-    case init:get_argument(couch_ini) of
-    error ->
-        Default;
-    {ok, [[]]} ->
-        Default;
-    {ok, [Values]} ->
-        Values
-    end.
-
-start_apps([]) ->
-    ok;
-start_apps([App|Rest]) ->
-    case application:start(App) of
-    ok ->
-       start_apps(Rest);
-    {error, {already_started, App}} ->
-       start_apps(Rest);
-    {error, _Reason} when App =:= public_key ->
-       % ignore on R12B5
-       start_apps(Rest);
-    {error, _Reason} ->
-       {error, {app_would_not_start, App}}
-    end.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_misc_handlers.erl b/src/couch/src/couch_httpd_misc_handlers.erl
index e46dee3..b8f59cd 100644
--- a/src/couch/src/couch_httpd_misc_handlers.erl
+++ b/src/couch/src/couch_httpd_misc_handlers.erl
@@ -98,7 +98,7 @@ handle_restart_req(#httpd{method='POST'}=Req) ->
     couch_httpd:validate_ctype(Req, "application/json"),
     ok = couch_httpd:verify_is_server_admin(Req),
     Result = send_json(Req, 202, {[{ok, true}]}),
-    couch_server_sup:restart_core_server(),
+    couch:restart(),
     Result;
 handle_restart_req(Req) ->
     send_method_not_allowed(Req, "POST").

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_proc_manager.erl b/src/couch/src/couch_proc_manager.erl
index 6130fc9..45b334f 100644
--- a/src/couch/src/couch_proc_manager.erl
+++ b/src/couch/src/couch_proc_manager.erl
@@ -127,6 +127,9 @@ handle_cast(_Msg, State) ->
     {noreply, State}.
 
 
+handle_info(shutdown, State) ->
+    {stop, shutdown, State};
+
 handle_info({'EXIT', _, {ok, Proc0, {Client,_} = From}}, State) ->
     link(Proc0#proc.pid),
     Proc = assign_proc(State#state.tab, Client, Proc0),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/src/couch_secondary_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_secondary_sup.erl b/src/couch/src/couch_secondary_sup.erl
index 4f2d1c8..d0ed0c2 100644
--- a/src/couch/src/couch_secondary_sup.erl
+++ b/src/couch/src/couch_secondary_sup.erl
@@ -39,4 +39,4 @@ init([]) ->
         end
         || {Name, SpecStr}
         <- config:get("daemons"), SpecStr /= ""],
-    {ok, {{one_for_one, 10, 3600}, Children}}.
+    {ok, {{one_for_one, 50, 3600}, Children}}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/src/couch_server_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server_sup.erl b/src/couch/src/couch_server_sup.erl
deleted file mode 100644
index c42bcfb..0000000
--- a/src/couch/src/couch_server_sup.erl
+++ /dev/null
@@ -1,153 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(couch_server_sup).
--behaviour(supervisor).
--behaviour(config_listener).
-
-
--export([start_link/1,stop/0, restart_core_server/0]).
-
--include_lib("couch/include/couch_db.hrl").
-
-%% supervisor callbacks
--export([init/1]).
-
-% config_listener api
--export([handle_config_change/5]).
-
-start_link(IniFiles) ->
-    case whereis(couch_server_sup) of
-    undefined ->
-        start_server(IniFiles);
-    _Else ->
-        {error, already_started}
-    end.
-
-restart_core_server() ->
-    init:restart().
-
-start_server(IniFiles) ->
-    case init:get_argument(pidfile) of
-    {ok, [PidFile]} ->
-        case file:write_file(PidFile, os:getpid()) of
-        ok -> ok;
-        {error, Reason} ->
-            io:format("Failed to write PID file ~s: ~s",
-                [PidFile, file:format_error(Reason)])
-        end;
-    _ -> ok
-    end,
-
-    LogLevel = config:get("log", "level", "info"),
-    % announce startup
-    io:format("Apache CouchDB ~s (LogLevel=~s) is starting.~n", [
-        couch_server:get_version(),
-        LogLevel
-    ]),
-    case LogLevel of
-    "debug" ->
-        io:format("Configuration Settings ~p:~n", [IniFiles]),
-        [io:format("  [~s] ~s=~p~n", [Module, Variable, Value])
-            || {{Module, Variable}, Value} <- config:all()];
-    _ -> ok
-    end,
-
-    BaseChildSpecs =
-    {{one_for_one, 10, 60}, [
-        {couch_primary_services,
-            {couch_primary_sup, start_link, []},
-            permanent,
-            infinity,
-            supervisor,
-            [couch_primary_sup]},
-        {couch_secondary_services,
-            {couch_secondary_sup, start_link, []},
-            permanent,
-            infinity,
-            supervisor,
-            [couch_secondary_sup]}
-        ]},
-
-    % ensure these applications are running
-    application:start(ibrowse),
-    application:start(crypto),
-
-    {ok, Pid} = supervisor:start_link(
-        {local, couch_server_sup}, couch_server_sup, BaseChildSpecs),
-
-    ok = config:listen_for_changes(?MODULE, nil),
-
-    Ip = config:get("httpd", "bind_address"),
-    io:format("Apache CouchDB has started. Time to relax.~n"),
-    Uris = [get_uri(Name, Ip) || Name <- [couch_httpd, https]],
-    [begin
-        case Uri of
-            undefined -> ok;
-            Uri -> ?LOG_INFO("Apache CouchDB has started on ~s", [Uri])
-        end
-    end
-    || Uri <- Uris],
-    case config:get("couchdb", "uri_file", null) of 
-    null -> ok;
-    UriFile ->
-        Lines = [begin case Uri of
-            undefined -> [];
-            Uri -> io_lib:format("~s~n", [Uri])
-            end end || Uri <- Uris],
-        case file:write_file(UriFile, Lines) of
-        ok -> ok;
-        {error, Reason2} = Error ->
-            ?LOG_ERROR("Failed to write to URI file ~s: ~s",
-                [UriFile, file:format_error(Reason2)]),
-            throw(Error)
-        end
-    end,
-
-    {ok, Pid}.
-
-stop() ->
-    catch exit(whereis(couch_server_sup), normal).
-
-
-handle_config_change("daemons", _, _, _, _) ->
-    exit(whereis(couch_server_sup), shutdown),
-    remove_handler;
-handle_config_change("couchdb", "util_driver_dir", _, _, _) ->
-    [Pid] = [P || {collation_driver, P, _, _}
-        <- supervisor:which_children(couch_primary_services)],
-    Pid ! reload_driver,
-    {ok, nil};
-handle_config_change(_, _, _, _, _) ->
-    {ok, nil}.
-
-init(ChildSpecs) ->
-    {ok, ChildSpecs}.
-
-get_uri(Name, Ip) ->
-    case get_port(Name) of
-        undefined ->
-            undefined;
-        Port ->
-            io_lib:format("~s://~s:~w/", [get_scheme(Name), Ip, Port])
-    end.
-
-get_scheme(couch_httpd) -> "http";
-get_scheme(https) -> "https".
-
-get_port(Name) ->
-    try
-        mochiweb_socket_server:get(Name, port)
-    catch
-        exit:{noproc, _}->
-            undefined
-    end.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch/src/couch_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_sup.erl b/src/couch/src/couch_sup.erl
new file mode 100644
index 0000000..3508d4f
--- /dev/null
+++ b/src/couch/src/couch_sup.erl
@@ -0,0 +1,159 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(couch_sup).
+-behaviour(supervisor).
+-behaviour(config_listener).
+
+
+-export([
+    start_link/0,
+    init/1,
+    handle_config_change/5
+]).
+
+
+-include_lib("couch/include/couch_db.hrl").
+
+
+start_link() ->
+    write_pidfile(),
+    notify_starting(),
+
+    case supervisor:start_link({local, ?MODULE}, ?MODULE, []) of
+        {ok, _} = Resp ->
+            notify_started(),
+            notify_uris(),
+            write_uris(),
+            ok = config:listen_for_changes(?MODULE, nil),
+            Resp;
+        Else ->
+            notify_error(Else),
+            Else
+    end.
+
+
+init(_Args) ->
+    twig:log(info, "Starting ~s", [?MODULE]),
+    {ok, {{one_for_one,10, 60}, [
+        {
+            couch_primary_services,
+            {couch_primary_sup, start_link, []},
+            permanent,
+            infinity,
+            supervisor,
+            [couch_primary_sup]
+        },
+        {
+            couch_secondary_services,
+            {couch_secondary_sup, start_link, []},
+            permanent,
+            infinity,
+            supervisor,
+            [couch_secondary_sup]
+        }
+    ]}}.
+
+
+handle_config_change("daemons", _, _, _, _) ->
+    exit(whereis(couch_server_sup), shutdown),
+    remove_handler;
+handle_config_change("couchdb", "util_driver_dir", _, _, _) ->
+    [Pid] = [P || {collation_driver, P, _, _}
+        <- supervisor:which_children(couch_primary_services)],
+    Pid ! reload_driver,
+    {ok, nil};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
+
+notify_starting() ->
+    io:format("Apache CouchDB ~s (LogLevel=~s) is starting.~n", [
+        couch_server:get_version(),
+        config:get("log", "level", "info")
+    ]).
+
+
+notify_started() ->
+    io:format("Apache CouchDB has started. Time to relax.~n").
+
+
+notify_error(Error) ->
+    io:format("Error starting Apache CouchDB:~n~n    ~p~n~n", [Error]).
+
+
+notify_uris() ->
+    lists:foreach(fun(Uri) ->
+        ?LOG_INFO("Apache CouchDB has started on ~s", [Uri])
+    end, get_uris()).
+
+
+write_pidfile() ->
+    case init:get_argument(pidfile) of
+        {ok, [PidFile]} ->
+            write_file(PidFile, os:getpid());
+        _ ->
+            ok
+    end.
+
+
+write_uris() ->
+    case config:get("couchdb", "uri_file", null) of
+        null ->
+            ok;
+        UriFile ->
+            Lines = [io_lib:format("~s~n", [Uri]) || Uri <- get_uris()],
+            write_file(UriFile, Lines)
+    end.
+
+
+get_uris() ->
+    Ip = config:get("httpd", "bind_address"),
+    lists:flatmap(fun(Uri) ->
+        case get_uri(Uri, Ip) of
+            undefined -> [];
+            Else -> [Else]
+        end
+    end, [couch_httpd, https]).
+
+
+get_uri(Name, Ip) ->
+    case get_port(Name) of
+        undefined ->
+            undefined;
+        Port ->
+            io_lib:format("~s://~s:~w/", [get_scheme(Name), Ip, Port])
+    end.
+
+
+get_scheme(couch_httpd) -> "http";
+get_scheme(https) -> "https".
+
+
+get_port(Name) ->
+    try
+        mochiweb_socket_server:get(Name, port)
+    catch
+        exit:{noproc, _} ->
+            undefined
+    end.
+
+
+write_file(FileName, Contents) ->
+    case file:write_file(FileName, Contents) of
+        ok ->
+            ok;
+        {error, Reason} ->
+            Args = [FileName, file:format_error(Reason)],
+            io:format(standard_error, "Failed ot write ~s :: ~s", Args),
+            throw({error, Reason})
+    end.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/33207af8/src/couch_replicator/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator/src/couch_replicator_manager.erl b/src/couch_replicator/src/couch_replicator_manager.erl
index 93f0e89..c213199 100644
--- a/src/couch_replicator/src/couch_replicator_manager.erl
+++ b/src/couch_replicator/src/couch_replicator_manager.erl
@@ -226,6 +226,9 @@ handle_info(restart_config_listener, State) ->
     ok = config:listen_for_changes(?MODULE, self()),
     {noreply, State};
 
+handle_info(shutdown, State) ->
+    {stop, shutdown, State};
+
 handle_info(Msg, State) ->
     twig:log(error,"Replication manager received unexpected message ~p", [Msg]),
     {stop, {unexpected_msg, Msg}, State}.


[06/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Extend built-in _stats reduce to arrays of numbers

BugzID: 15671


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/05d8f16f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/05d8f16f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/05d8f16f

Branch: refs/heads/1843-feature-bigcouch
Commit: 05d8f16f3c28bc6226eafd2c41c2a71699940892
Parents: b82ccc5
Author: Robert Newson <ro...@cloudant.com>
Authored: Tue Dec 18 21:10:13 2012 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:51 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 91 ++++++++++++++++++------------
 1 file changed, 55 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/05d8f16f/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 4e4f938..71dcae9 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -29,6 +29,9 @@
     "structures. Objects can be arbitrarily nested, provided that the values "
     "for all fields are themselves numbers, arrays of numbers, or objects.">>).
 
+-define(STATERROR, <<"The _stats function requires that map values be numbers "
+    "or arrays of numbers.">>).
+
 % https://gist.github.com/df10284c76d85f988c3f
 -define(SUMREGEX, {re_pattern,3,0,<<69,82,67,80,194,0,0,0,8,0,0,0,5,0,0,0,3,0,
 2,0,0,0,125,2,48,0,9,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,118,97,108,
@@ -248,50 +251,58 @@ sum_arrays([X|Xs], [Y|Ys]) when is_number(X), is_number(Y) ->
 sum_arrays(_, _) ->
     throw({invalid_value, ?SUMERROR}).
 
+builtin_stats(_, []) ->
+    {[{sum,0}, {count,0}, {min,0}, {max,0}, {sumsqr,0}]};
+builtin_stats(_, [[_,First]|Rest]) ->
+    Unpacked = lists:foldl(fun([_key, Value], Acc) -> stat_values(Value, Acc) end,
+                           build_initial_accumulator(First), Rest),
+    pack_stats(Unpacked).
+
+stat_values(Value, Acc) when is_list(Value), is_list(Acc) ->
+    lists:zipwith(fun stat_values/2, Value, Acc);
+stat_values({PreRed}, Acc) when is_list(PreRed) ->
+    stat_values(unpack_stats({PreRed}), Acc);
+stat_values(Value, Acc) when is_number(Value) ->
+    stat_values({Value, 1, Value, Value, Value*Value}, Acc);
+stat_values(Value, Acc) when is_number(Acc) ->
+    stat_values(Value, {Acc, 1, Acc, Acc, Acc*Acc});
+stat_values(Value, Acc) when is_tuple(Value), is_tuple(Acc) ->
+    {Sum0, Cnt0, Min0, Max0, Sqr0} = Value,
+    {Sum1, Cnt1, Min1, Max1, Sqr1} = Acc,
+    {
+      Sum0 + Sum1,
+      Cnt0 + Cnt1,
+      erlang:min(Min0, Min1),
+      erlang:max(Max0, Max1),
+      Sqr0 + Sqr1
+    };
+stat_values(_Else, _Acc) ->
+    throw({invalid_value, ?STATERROR}).
 
-builtin_stats(reduce, [[_,First]|Rest]) ->
-    Acc0 = build_initial_accumulator(First),
-    Stats = lists:foldl(fun
-        ([_K,V], {S,C,Mi,Ma,Sq}) when is_number(V) ->
-            {S+V, C+1, erlang:min(Mi,V), erlang:max(Ma,V), Sq+(V*V)};
-        ([_K,{PreRed}], {S,C,Mi,Ma,Sq}) when is_list(PreRed) ->
-            {
-                S + get_number(<<"sum">>, PreRed),
-                C + get_number(<<"count">>, PreRed),
-                erlang:min(get_number(<<"min">>, PreRed), Mi),
-                erlang:max(get_number(<<"max">>, PreRed), Ma),
-                Sq + get_number(<<"sumsqr">>, PreRed)
-            };
-        ([_K,V], _) ->
-            Msg = io_lib:format("non-numeric _stats input: ~w", [V]),
-            throw({invalid_value, iolist_to_binary(Msg)})
-    end, Acc0, Rest),
-    {Sum, Cnt, Min, Max, Sqr} = Stats,
-    {[{sum,Sum}, {count,Cnt}, {min,Min}, {max,Max}, {sumsqr,Sqr}]};
-
-builtin_stats(rereduce, [[_,First]|Rest]) ->
-    {[{sum,Sum0}, {count,Cnt0}, {min,Min0}, {max,Max0}, {sumsqr,Sqr0}]} = First,
-    Stats = lists:foldl(fun([_K,Red], {S,C,Mi,Ma,Sq}) ->
-        {[{sum,Sum}, {count,Cnt}, {min,Min}, {max,Max}, {sumsqr,Sqr}]} = Red,
-        {Sum+S, Cnt+C, lists:min([Min, Mi]), lists:max([Max, Ma]), Sqr+Sq}
-    end, {Sum0,Cnt0,Min0,Max0,Sqr0}, Rest),
-    {Sum, Cnt, Min, Max, Sqr} = Stats,
-    {[{sum,Sum}, {count,Cnt}, {min,Min}, {max,Max}, {sumsqr,Sqr}]}.
-
+build_initial_accumulator(L) when is_list(L) ->
+    [build_initial_accumulator(X) || X <- L];
 build_initial_accumulator(X) when is_number(X) ->
     {X, 1, X, X, X*X};
 build_initial_accumulator({Props}) ->
-    {
-        get_number(<<"sum">>, Props),
-        get_number(<<"count">>, Props),
-        get_number(<<"min">>, Props),
-        get_number(<<"max">>, Props),
-        get_number(<<"sumsqr">>, Props)
-    };
+    unpack_stats({Props});
 build_initial_accumulator(Else) ->
     Msg = io_lib:format("non-numeric _stats input: ~w", [Else]),
     throw({invalid_value, iolist_to_binary(Msg)}).
 
+unpack_stats({PreRed}) when is_list(PreRed) ->
+    {
+      get_number(<<"sum">>, PreRed),
+      get_number(<<"count">>, PreRed),
+      get_number(<<"min">>, PreRed),
+      get_number(<<"max">>, PreRed),
+      get_number(<<"sumsqr">>, PreRed)
+    }.
+
+pack_stats({Sum, Cnt, Min, Max, Sqr}) ->
+    {[{<<"sum">>,Sum}, {<<"count">>,Cnt}, {<<"min">>,Min}, {<<"max">>,Max}, {<<"sumsqr">>,Sqr}]};
+pack_stats(Stats) when is_list(Stats) ->
+    lists:map(fun pack_stats/1, Stats).
+
 get_number(Key, Props) ->
     case couch_util:get_value(Key, Props) of
     X when is_number(X) ->
@@ -431,4 +442,12 @@ sum_values_test() ->
     ?assertEqual(Z, sum_values(X, Y)),
     ?assertEqual(Z, sum_values(Y, X)).
 
+stat_values_test() ->
+    ?assertEqual({1, 2, 0, 1, 1}, stat_values(1, 0)),
+    ?assertEqual({11, 2, 1, 10, 101}, stat_values(1, 10)),
+    ?assertEqual([{9, 2, 2, 7, 53},
+                  {14, 2, 3, 11, 130},
+                  {18, 2, 5, 13, 194}
+                 ], stat_values([2,3,5], [7,11,13])).
+
 -endif.


[49/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Fix up copyright headers


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/84a296e0
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/84a296e0
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/84a296e0

Branch: refs/heads/1843-feature-bigcouch
Commit: 84a296e0e13af67c80c85876a551c55f28701afc
Parents: 8f0ef8e
Author: Robert Newson <rn...@apache.org>
Authored: Thu Jun 13 13:42:11 2013 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Thu Jun 13 13:46:12 2013 +0100

----------------------------------------------------------------------
 src/chttpd/src/chttpd.app.src                     | 14 +++++++++++++-
 src/chttpd/src/chttpd_config_listener.erl         | 12 ++++++++++++
 src/chttpd/test/chttpd_delayed_response_test.erl  |  2 --
 src/chttpd/test/mock_request.erl                  |  2 --
 src/config/src/config.app.src                     | 12 ++++++++++++
 src/config/src/config_listener.erl                | 12 ++++++++++++
 src/couch_replicator/rebar.config                 |  2 --
 src/couch_replicator/src/couch_replicator_sup.erl |  2 --
 src/ddoc_cache/src/ddoc_cache.app.src             | 12 +++++++++++-
 src/ddoc_cache/src/ddoc_cache.erl                 | 12 +++++++++++-
 src/ddoc_cache/src/ddoc_cache_app.erl             | 12 +++++++++++-
 src/ddoc_cache/src/ddoc_cache_opener.erl          | 12 +++++++++++-
 src/ddoc_cache/src/ddoc_cache_sup.erl             | 12 +++++++++++-
 src/ddoc_cache/src/ddoc_cache_util.erl            | 12 ++++++++++++
 src/ets_lru/src/ets_lru.app.src                   | 12 +++++++++++-
 src/ets_lru/src/ets_lru.erl                       | 12 +++++++++++-
 src/fabric/include/fabric.hrl                     |  2 --
 src/fabric/src/fabric.app.src                     | 12 ++++++++++++
 src/fabric/src/fabric.erl                         |  2 --
 src/fabric/src/fabric_db_create.erl               |  2 --
 src/fabric/src/fabric_db_delete.erl               |  2 --
 src/fabric/src/fabric_db_doc_count.erl            |  2 --
 src/fabric/src/fabric_db_info.erl                 |  2 --
 src/fabric/src/fabric_db_meta.erl                 |  2 --
 src/fabric/src/fabric_db_update_listener.erl      |  2 --
 src/fabric/src/fabric_dict.erl                    |  2 --
 src/fabric/src/fabric_doc_attachments.erl         |  2 --
 src/fabric/src/fabric_doc_missing_revs.erl        |  2 --
 src/fabric/src/fabric_doc_open.erl                |  2 --
 src/fabric/src/fabric_doc_open_revs.erl           |  2 --
 src/fabric/src/fabric_doc_update.erl              |  2 --
 src/fabric/src/fabric_group_info.erl              |  2 --
 src/fabric/src/fabric_rpc.erl                     |  2 --
 src/fabric/src/fabric_util.erl                    |  2 --
 src/fabric/src/fabric_view.erl                    |  2 --
 src/fabric/src/fabric_view_all_docs.erl           |  2 --
 src/fabric/src/fabric_view_changes.erl            |  2 --
 src/fabric/src/fabric_view_map.erl                |  2 --
 src/fabric/src/fabric_view_reduce.erl             |  2 --
 src/mem3/include/mem3.hrl                         |  2 --
 src/mem3/src/mem3.app.src                         | 12 ++++++++++++
 src/mem3/src/mem3.erl                             |  2 --
 src/mem3/src/mem3_app.erl                         |  2 --
 src/mem3/src/mem3_httpd.erl                       |  2 --
 src/mem3/src/mem3_nodes.erl                       |  2 --
 src/mem3/src/mem3_rep.erl                         | 12 ++++++++++++
 src/mem3/src/mem3_shards.erl                      |  2 --
 src/mem3/src/mem3_sup.erl                         |  2 --
 src/mem3/src/mem3_sync.erl                        |  2 --
 src/mem3/src/mem3_sync_event.erl                  |  2 --
 src/mem3/src/mem3_sync_nodes.erl                  |  2 --
 src/mem3/src/mem3_sync_security.erl               |  2 --
 src/mem3/src/mem3_util.erl                        |  2 --
 src/mem3/test/mem3_util_test.erl                  |  2 --
 src/rexi/include/rexi.hrl                         |  2 --
 src/rexi/src/rexi.app.src                         | 12 ++++++++++++
 src/rexi/src/rexi.erl                             |  2 --
 src/rexi/src/rexi_app.erl                         |  2 --
 src/rexi/src/rexi_gov_manager.erl                 |  2 --
 src/rexi/src/rexi_governor.erl                    |  2 --
 src/rexi/src/rexi_monitor.erl                     |  2 --
 src/rexi/src/rexi_server.erl                      |  2 --
 src/rexi/src/rexi_sup.erl                         |  2 --
 src/rexi/src/rexi_utils.erl                       | 12 ++++++++++++
 src/twig/src/twig.app.src                         | 12 ++++++++++++
 src/twig/src/twig.erl                             |  2 --
 src/twig/src/twig_app.erl                         |  2 --
 src/twig/src/twig_event_handler.erl               |  2 --
 src/twig/src/twig_int.hrl                         |  2 --
 src/twig/src/twig_monitor.erl                     |  2 --
 src/twig/src/twig_sup.erl                         |  2 --
 src/twig/src/twig_util.erl                        |  2 --
 72 files changed, 210 insertions(+), 116 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/chttpd/src/chttpd.app.src
----------------------------------------------------------------------
diff --git a/src/chttpd/src/chttpd.app.src b/src/chttpd/src/chttpd.app.src
index 07ab564..d841f6c 100644
--- a/src/chttpd/src/chttpd.app.src
+++ b/src/chttpd/src/chttpd.app.src
@@ -1,4 +1,16 @@
-{application, chttpd, [
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+ {application, chttpd, [
     {description, "HTTP interface for CouchDB cluster"},
     {vsn, "%version%"},
     {modules, [

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/chttpd/src/chttpd_config_listener.erl
----------------------------------------------------------------------
diff --git a/src/chttpd/src/chttpd_config_listener.erl b/src/chttpd/src/chttpd_config_listener.erl
index 874553d..4d07b83 100644
--- a/src/chttpd/src/chttpd_config_listener.erl
+++ b/src/chttpd/src/chttpd_config_listener.erl
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 -module(chttpd_config_listener).
 -behaviour(gen_server).
 -behaviour(config_listener).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/chttpd/test/chttpd_delayed_response_test.erl
----------------------------------------------------------------------
diff --git a/src/chttpd/test/chttpd_delayed_response_test.erl b/src/chttpd/test/chttpd_delayed_response_test.erl
index f6509dd..911ef5b 100644
--- a/src/chttpd/test/chttpd_delayed_response_test.erl
+++ b/src/chttpd/test/chttpd_delayed_response_test.erl
@@ -1,5 +1,3 @@
-%% Copyright 2011 Cloudant
-%%
 %% Licensed under the Apache License, Version 2.0 (the "License"); you may not
 %% use this file except in compliance with the License. You may obtain a copy of
 %% the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/chttpd/test/mock_request.erl
----------------------------------------------------------------------
diff --git a/src/chttpd/test/mock_request.erl b/src/chttpd/test/mock_request.erl
index e1f8b0a..3edfd29 100644
--- a/src/chttpd/test/mock_request.erl
+++ b/src/chttpd/test/mock_request.erl
@@ -1,5 +1,3 @@
-%% Copyright 2011 Cloudant
-%%
 %% Licensed under the Apache License, Version 2.0 (the "License"); you may not
 %% use this file except in compliance with the License. You may obtain a copy of
 %% the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/config/src/config.app.src
----------------------------------------------------------------------
diff --git a/src/config/src/config.app.src b/src/config/src/config.app.src
index 69c665f..9b0f5f0 100644
--- a/src/config/src/config.app.src
+++ b/src/config/src/config.app.src
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 {application, config, [
     {description, "INI file configuration system for Apache CouchDB"},
     {vsn, "%version%"},

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/config/src/config_listener.erl
----------------------------------------------------------------------
diff --git a/src/config/src/config_listener.erl b/src/config/src/config_listener.erl
index d53d41a..3335b45 100644
--- a/src/config/src/config_listener.erl
+++ b/src/config/src/config_listener.erl
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 -module(config_listener).
 
 -behaviour(gen_event).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/couch_replicator/rebar.config
----------------------------------------------------------------------
diff --git a/src/couch_replicator/rebar.config b/src/couch_replicator/rebar.config
index 4af6b85..48deb03 100644
--- a/src/couch_replicator/rebar.config
+++ b/src/couch_replicator/rebar.config
@@ -1,5 +1,3 @@
-% Copyright 2011 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/couch_replicator/src/couch_replicator_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator/src/couch_replicator_sup.erl b/src/couch_replicator/src/couch_replicator_sup.erl
index 848cb13..bad9747 100644
--- a/src/couch_replicator/src/couch_replicator_sup.erl
+++ b/src/couch_replicator/src/couch_replicator_sup.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/ddoc_cache/src/ddoc_cache.app.src
----------------------------------------------------------------------
diff --git a/src/ddoc_cache/src/ddoc_cache.app.src b/src/ddoc_cache/src/ddoc_cache.app.src
index da15382..78f45de 100644
--- a/src/ddoc_cache/src/ddoc_cache.app.src
+++ b/src/ddoc_cache/src/ddoc_cache.app.src
@@ -1,4 +1,14 @@
-% Copyright 2012 Cloudant. All rights reserved.
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
 
 {application, ddoc_cache, [
     {description, "Design Document Cache"},

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/ddoc_cache/src/ddoc_cache.erl
----------------------------------------------------------------------
diff --git a/src/ddoc_cache/src/ddoc_cache.erl b/src/ddoc_cache/src/ddoc_cache.erl
index 35aa610..ec119f1 100644
--- a/src/ddoc_cache/src/ddoc_cache.erl
+++ b/src/ddoc_cache/src/ddoc_cache.erl
@@ -1,4 +1,14 @@
-% Copyright 2012 Cloudant. All rights reserved.
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
 
 -module(ddoc_cache).
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/ddoc_cache/src/ddoc_cache_app.erl
----------------------------------------------------------------------
diff --git a/src/ddoc_cache/src/ddoc_cache_app.erl b/src/ddoc_cache/src/ddoc_cache_app.erl
index 922aab6..5afa7ac 100644
--- a/src/ddoc_cache/src/ddoc_cache_app.erl
+++ b/src/ddoc_cache/src/ddoc_cache_app.erl
@@ -1,4 +1,14 @@
-% Copyright 2012 Cloudant. All rights reserved.
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
 
 -module(ddoc_cache_app).
 -behaviour(application).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/ddoc_cache/src/ddoc_cache_opener.erl
----------------------------------------------------------------------
diff --git a/src/ddoc_cache/src/ddoc_cache_opener.erl b/src/ddoc_cache/src/ddoc_cache_opener.erl
index b2bf930..e7abc9d 100644
--- a/src/ddoc_cache/src/ddoc_cache_opener.erl
+++ b/src/ddoc_cache/src/ddoc_cache_opener.erl
@@ -1,4 +1,14 @@
-% Copyright 2012 Cloudant. All rights reserved.
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
 
 -module(ddoc_cache_opener).
 -behaviour(gen_server).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/ddoc_cache/src/ddoc_cache_sup.erl
----------------------------------------------------------------------
diff --git a/src/ddoc_cache/src/ddoc_cache_sup.erl b/src/ddoc_cache/src/ddoc_cache_sup.erl
index 166f865..5ffd7e6 100644
--- a/src/ddoc_cache/src/ddoc_cache_sup.erl
+++ b/src/ddoc_cache/src/ddoc_cache_sup.erl
@@ -1,4 +1,14 @@
-% Copyright 2012 Cloudant. All rights reserved.
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
 
 -module(ddoc_cache_sup).
 -behaviour(supervisor).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/ddoc_cache/src/ddoc_cache_util.erl
----------------------------------------------------------------------
diff --git a/src/ddoc_cache/src/ddoc_cache_util.erl b/src/ddoc_cache/src/ddoc_cache_util.erl
index a725674..fb3c0b9 100644
--- a/src/ddoc_cache/src/ddoc_cache_util.erl
+++ b/src/ddoc_cache/src/ddoc_cache_util.erl
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 -module(ddoc_cache_util).
 
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/ets_lru/src/ets_lru.app.src
----------------------------------------------------------------------
diff --git a/src/ets_lru/src/ets_lru.app.src b/src/ets_lru/src/ets_lru.app.src
index 3287e88..603c5d6 100644
--- a/src/ets_lru/src/ets_lru.app.src
+++ b/src/ets_lru/src/ets_lru.app.src
@@ -1,4 +1,14 @@
-% Copyright 2012 Cloudant. All rights reserved.
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
 
 {application, ets_lru, [
     {description, "ETS Base LRU Cache"},

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/ets_lru/src/ets_lru.erl
----------------------------------------------------------------------
diff --git a/src/ets_lru/src/ets_lru.erl b/src/ets_lru/src/ets_lru.erl
index b373f89..5880bd5 100644
--- a/src/ets_lru/src/ets_lru.erl
+++ b/src/ets_lru/src/ets_lru.erl
@@ -1,4 +1,14 @@
-% Copyright 2012 Cloudant. All rights reserved.
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
 
 -module(ets_lru).
 -behavior(gen_server).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/include/fabric.hrl
----------------------------------------------------------------------
diff --git a/src/fabric/include/fabric.hrl b/src/fabric/include/fabric.hrl
index c8de0f8..94769bd 100644
--- a/src/fabric/include/fabric.hrl
+++ b/src/fabric/include/fabric.hrl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric.app.src
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric.app.src b/src/fabric/src/fabric.app.src
index 3f3b167..a3022e6 100644
--- a/src/fabric/src/fabric.app.src
+++ b/src/fabric/src/fabric.app.src
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 {application, fabric, [
     {description, "Routing and proxying layer for CouchDB cluster"},
     {vsn, "%version%"},

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric.erl b/src/fabric/src/fabric.erl
index 2899545..4b8fe4a 100644
--- a/src/fabric/src/fabric.erl
+++ b/src/fabric/src/fabric.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_db_create.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_db_create.erl b/src/fabric/src/fabric_db_create.erl
index 4f3fcae..c8f2d45 100644
--- a/src/fabric/src/fabric_db_create.erl
+++ b/src/fabric/src/fabric_db_create.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_db_delete.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_db_delete.erl b/src/fabric/src/fabric_db_delete.erl
index 6b2a434..934f95b 100644
--- a/src/fabric/src/fabric_db_delete.erl
+++ b/src/fabric/src/fabric_db_delete.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_db_doc_count.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_db_doc_count.erl b/src/fabric/src/fabric_db_doc_count.erl
index 0ef8221..dcc32aa 100644
--- a/src/fabric/src/fabric_db_doc_count.erl
+++ b/src/fabric/src/fabric_db_doc_count.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_db_info.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_db_info.erl b/src/fabric/src/fabric_db_info.erl
index b8cb605..58139e8 100644
--- a/src/fabric/src/fabric_db_info.erl
+++ b/src/fabric/src/fabric_db_info.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_db_meta.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_db_meta.erl b/src/fabric/src/fabric_db_meta.erl
index ca21b0f..78a3952 100644
--- a/src/fabric/src/fabric_db_meta.erl
+++ b/src/fabric/src/fabric_db_meta.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_db_update_listener.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_db_update_listener.erl b/src/fabric/src/fabric_db_update_listener.erl
index 7d6d878..28e5972 100644
--- a/src/fabric/src/fabric_db_update_listener.erl
+++ b/src/fabric/src/fabric_db_update_listener.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_dict.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_dict.erl b/src/fabric/src/fabric_dict.erl
index cea537c..a9d7fea 100644
--- a/src/fabric/src/fabric_dict.erl
+++ b/src/fabric/src/fabric_dict.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_doc_attachments.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_doc_attachments.erl b/src/fabric/src/fabric_doc_attachments.erl
index 54f96a3..b29e20f 100644
--- a/src/fabric/src/fabric_doc_attachments.erl
+++ b/src/fabric/src/fabric_doc_attachments.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_doc_missing_revs.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_doc_missing_revs.erl b/src/fabric/src/fabric_doc_missing_revs.erl
index 57ba90c..ec154ee 100644
--- a/src/fabric/src/fabric_doc_missing_revs.erl
+++ b/src/fabric/src/fabric_doc_missing_revs.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_doc_open.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_doc_open.erl b/src/fabric/src/fabric_doc_open.erl
index 9ec6e6d..caa389e 100644
--- a/src/fabric/src/fabric_doc_open.erl
+++ b/src/fabric/src/fabric_doc_open.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_doc_open_revs.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_doc_open_revs.erl b/src/fabric/src/fabric_doc_open_revs.erl
index f36bc9c..398a675 100644
--- a/src/fabric/src/fabric_doc_open_revs.erl
+++ b/src/fabric/src/fabric_doc_open_revs.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_doc_update.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_doc_update.erl b/src/fabric/src/fabric_doc_update.erl
index 58e6449..50c244c 100644
--- a/src/fabric/src/fabric_doc_update.erl
+++ b/src/fabric/src/fabric_doc_update.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_group_info.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_group_info.erl b/src/fabric/src/fabric_group_info.erl
index 1a0f78a..135090f 100644
--- a/src/fabric/src/fabric_group_info.erl
+++ b/src/fabric/src/fabric_group_info.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_rpc.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_rpc.erl b/src/fabric/src/fabric_rpc.erl
index f88f035..4926609 100644
--- a/src/fabric/src/fabric_rpc.erl
+++ b/src/fabric/src/fabric_rpc.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_util.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_util.erl b/src/fabric/src/fabric_util.erl
index 91db5fc..a6982f3 100644
--- a/src/fabric/src/fabric_util.erl
+++ b/src/fabric/src/fabric_util.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_view.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_view.erl b/src/fabric/src/fabric_view.erl
index 479e718..a42582b 100644
--- a/src/fabric/src/fabric_view.erl
+++ b/src/fabric/src/fabric_view.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_view_all_docs.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_view_all_docs.erl b/src/fabric/src/fabric_view_all_docs.erl
index c2b750d..1745fc4 100644
--- a/src/fabric/src/fabric_view_all_docs.erl
+++ b/src/fabric/src/fabric_view_all_docs.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_view_changes.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_view_changes.erl b/src/fabric/src/fabric_view_changes.erl
index 3cc9e8c..b0a3628 100644
--- a/src/fabric/src/fabric_view_changes.erl
+++ b/src/fabric/src/fabric_view_changes.erl
@@ -1,5 +1,3 @@
-% Copyright 2012 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_view_map.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_view_map.erl b/src/fabric/src/fabric_view_map.erl
index b6fb5ce..9403bde 100644
--- a/src/fabric/src/fabric_view_map.erl
+++ b/src/fabric/src/fabric_view_map.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/fabric/src/fabric_view_reduce.erl
----------------------------------------------------------------------
diff --git a/src/fabric/src/fabric_view_reduce.erl b/src/fabric/src/fabric_view_reduce.erl
index 9f564f2..54dcdf5 100644
--- a/src/fabric/src/fabric_view_reduce.erl
+++ b/src/fabric/src/fabric_view_reduce.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/include/mem3.hrl
----------------------------------------------------------------------
diff --git a/src/mem3/include/mem3.hrl b/src/mem3/include/mem3.hrl
index 04658bb..cb39e78 100644
--- a/src/mem3/include/mem3.hrl
+++ b/src/mem3/include/mem3.hrl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3.app.src
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3.app.src b/src/mem3/src/mem3.app.src
index 809b947..612a7fb 100644
--- a/src/mem3/src/mem3.app.src
+++ b/src/mem3/src/mem3.app.src
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 {application, mem3, [
     {description, "CouchDB Cluster Membership"},
     {vsn, "%version%"},

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3.erl b/src/mem3/src/mem3.erl
index 1b12f20..c9b4793 100644
--- a/src/mem3/src/mem3.erl
+++ b/src/mem3/src/mem3.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_app.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_app.erl b/src/mem3/src/mem3_app.erl
index bb27171..3ddfbe6 100644
--- a/src/mem3/src/mem3_app.erl
+++ b/src/mem3/src/mem3_app.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_httpd.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_httpd.erl b/src/mem3/src/mem3_httpd.erl
index 3d38d21..94196fa 100644
--- a/src/mem3/src/mem3_httpd.erl
+++ b/src/mem3/src/mem3_httpd.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_nodes.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_nodes.erl b/src/mem3/src/mem3_nodes.erl
index 39044db..ad96646 100644
--- a/src/mem3/src/mem3_nodes.erl
+++ b/src/mem3/src/mem3_nodes.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_rep.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_rep.erl b/src/mem3/src/mem3_rep.erl
index 097f2dd..09fff9c 100644
--- a/src/mem3/src/mem3_rep.erl
+++ b/src/mem3/src/mem3_rep.erl
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 -module(mem3_rep).
 
 -export([go/2, go/3, changes_enumerator/3, make_local_id/2]).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_shards.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_shards.erl b/src/mem3/src/mem3_shards.erl
index 4410ff9..2aaa35a 100644
--- a/src/mem3/src/mem3_shards.erl
+++ b/src/mem3/src/mem3_shards.erl
@@ -1,5 +1,3 @@
-% Copyright 2012 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_sup.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_sup.erl b/src/mem3/src/mem3_sup.erl
index ae38d7d..6ff688b 100644
--- a/src/mem3/src/mem3_sup.erl
+++ b/src/mem3/src/mem3_sup.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_sync.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_sync.erl b/src/mem3/src/mem3_sync.erl
index b661932..e47f6fa 100644
--- a/src/mem3/src/mem3_sync.erl
+++ b/src/mem3/src/mem3_sync.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_sync_event.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_sync_event.erl b/src/mem3/src/mem3_sync_event.erl
index 440fb8c..7a20b0b 100644
--- a/src/mem3/src/mem3_sync_event.erl
+++ b/src/mem3/src/mem3_sync_event.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_sync_nodes.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_sync_nodes.erl b/src/mem3/src/mem3_sync_nodes.erl
index 425f678..e07fd44 100644
--- a/src/mem3/src/mem3_sync_nodes.erl
+++ b/src/mem3/src/mem3_sync_nodes.erl
@@ -1,5 +1,3 @@
-% Copyright 2012 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_sync_security.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_sync_security.erl b/src/mem3/src/mem3_sync_security.erl
index 723f9b7..da112aa 100644
--- a/src/mem3/src/mem3_sync_security.erl
+++ b/src/mem3/src/mem3_sync_security.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/src/mem3_util.erl
----------------------------------------------------------------------
diff --git a/src/mem3/src/mem3_util.erl b/src/mem3/src/mem3_util.erl
index d1dc1a8..610e284 100644
--- a/src/mem3/src/mem3_util.erl
+++ b/src/mem3/src/mem3_util.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/mem3/test/mem3_util_test.erl
----------------------------------------------------------------------
diff --git a/src/mem3/test/mem3_util_test.erl b/src/mem3/test/mem3_util_test.erl
index 6d574cb..e289282 100644
--- a/src/mem3/test/mem3_util_test.erl
+++ b/src/mem3/test/mem3_util_test.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/include/rexi.hrl
----------------------------------------------------------------------
diff --git a/src/rexi/include/rexi.hrl b/src/rexi/include/rexi.hrl
index b51c5af..a2d86b2 100644
--- a/src/rexi/include/rexi.hrl
+++ b/src/rexi/include/rexi.hrl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi.app.src
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi.app.src b/src/rexi/src/rexi.app.src
index 5eb5639..c9af9d0 100644
--- a/src/rexi/src/rexi.app.src
+++ b/src/rexi/src/rexi.app.src
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 {application, rexi, [
     {description, "Lightweight RPC server"},
     {vsn, "%version%"},

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi.erl
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi.erl b/src/rexi/src/rexi.erl
index f795593..8e53dba 100644
--- a/src/rexi/src/rexi.erl
+++ b/src/rexi/src/rexi.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-% 
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi_app.erl
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi_app.erl b/src/rexi/src/rexi_app.erl
index 2dd99c2..c791d83 100644
--- a/src/rexi/src/rexi_app.erl
+++ b/src/rexi/src/rexi_app.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-% 
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi_gov_manager.erl
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi_gov_manager.erl b/src/rexi/src/rexi_gov_manager.erl
index 477be3e..4fb69e3 100644
--- a/src/rexi/src/rexi_gov_manager.erl
+++ b/src/rexi/src/rexi_gov_manager.erl
@@ -1,5 +1,3 @@
-% Copyright 2012 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi_governor.erl
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi_governor.erl b/src/rexi/src/rexi_governor.erl
index 9bbe7c9..e999470 100644
--- a/src/rexi/src/rexi_governor.erl
+++ b/src/rexi/src/rexi_governor.erl
@@ -1,5 +1,3 @@
-% Copyright 2012 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi_monitor.erl
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi_monitor.erl b/src/rexi/src/rexi_monitor.erl
index ab33fb8..7be3f0a 100644
--- a/src/rexi/src/rexi_monitor.erl
+++ b/src/rexi/src/rexi_monitor.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-% 
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi_server.erl
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi_server.erl b/src/rexi/src/rexi_server.erl
index 90e49ea..c3fc508 100644
--- a/src/rexi/src/rexi_server.erl
+++ b/src/rexi/src/rexi_server.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-% 
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi_sup.erl
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi_sup.erl b/src/rexi/src/rexi_sup.erl
index 86955a1..a8aa800 100644
--- a/src/rexi/src/rexi_sup.erl
+++ b/src/rexi/src/rexi_sup.erl
@@ -1,5 +1,3 @@
-% Copyright 2010 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/rexi/src/rexi_utils.erl
----------------------------------------------------------------------
diff --git a/src/rexi/src/rexi_utils.erl b/src/rexi/src/rexi_utils.erl
index 9950823..1b11576 100644
--- a/src/rexi/src/rexi_utils.erl
+++ b/src/rexi/src/rexi_utils.erl
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 -module(rexi_utils).
 
 -export([send/2, recv/6]).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/twig/src/twig.app.src
----------------------------------------------------------------------
diff --git a/src/twig/src/twig.app.src b/src/twig/src/twig.app.src
index 7e1da74..751375e 100644
--- a/src/twig/src/twig.app.src
+++ b/src/twig/src/twig.app.src
@@ -1,3 +1,15 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
 {application, twig, [
     {description, "Logger"},
     {vsn, git},

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/twig/src/twig.erl
----------------------------------------------------------------------
diff --git a/src/twig/src/twig.erl b/src/twig/src/twig.erl
index 6a24e6b..e62cd33 100644
--- a/src/twig/src/twig.erl
+++ b/src/twig/src/twig.erl
@@ -1,5 +1,3 @@
-% Copyright 2011 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/twig/src/twig_app.erl
----------------------------------------------------------------------
diff --git a/src/twig/src/twig_app.erl b/src/twig/src/twig_app.erl
index 209391c..e16ad58 100644
--- a/src/twig/src/twig_app.erl
+++ b/src/twig/src/twig_app.erl
@@ -1,5 +1,3 @@
-% Copyright 2011 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/twig/src/twig_event_handler.erl
----------------------------------------------------------------------
diff --git a/src/twig/src/twig_event_handler.erl b/src/twig/src/twig_event_handler.erl
index cd61b0d..d7b691b 100644
--- a/src/twig/src/twig_event_handler.erl
+++ b/src/twig/src/twig_event_handler.erl
@@ -1,5 +1,3 @@
-% Copyright 2011 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/twig/src/twig_int.hrl
----------------------------------------------------------------------
diff --git a/src/twig/src/twig_int.hrl b/src/twig/src/twig_int.hrl
index a510d40..81ef8b5 100644
--- a/src/twig/src/twig_int.hrl
+++ b/src/twig/src/twig_int.hrl
@@ -1,5 +1,3 @@
-% Copyright 2011 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/twig/src/twig_monitor.erl
----------------------------------------------------------------------
diff --git a/src/twig/src/twig_monitor.erl b/src/twig/src/twig_monitor.erl
index c32a0c6..81b04bd 100644
--- a/src/twig/src/twig_monitor.erl
+++ b/src/twig/src/twig_monitor.erl
@@ -1,5 +1,3 @@
-% Copyright 2011 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/twig/src/twig_sup.erl
----------------------------------------------------------------------
diff --git a/src/twig/src/twig_sup.erl b/src/twig/src/twig_sup.erl
index 0fe73ef..f778f0d 100644
--- a/src/twig/src/twig_sup.erl
+++ b/src/twig/src/twig_sup.erl
@@ -1,5 +1,3 @@
-% Copyright 2011 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at

http://git-wip-us.apache.org/repos/asf/couchdb/blob/84a296e0/src/twig/src/twig_util.erl
----------------------------------------------------------------------
diff --git a/src/twig/src/twig_util.erl b/src/twig/src/twig_util.erl
index b4f830c..f5442fd 100644
--- a/src/twig/src/twig_util.erl
+++ b/src/twig/src/twig_util.erl
@@ -1,5 +1,3 @@
-% Copyright 2011 Cloudant
-%
 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
 % use this file except in compliance with the License. You may obtain a copy of
 % the License at


[38/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
[squash] to somewhere, I dunno


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/19bab5cb
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/19bab5cb
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/19bab5cb

Branch: refs/heads/1843-feature-bigcouch
Commit: 19bab5cb573a6db0c5a120359f1bd490d60a690e
Parents: c535dea
Author: Robert Newson <rn...@apache.org>
Authored: Tue Mar 12 12:18:00 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:55 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db_updater.erl | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/19bab5cb/src/couch/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl
index 4fe6073..b8e150c 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -306,11 +306,11 @@ handle_info({'DOWN', Ref, _, _, Reason}, #db{fd_monitor=Ref, name=Name} = Db) ->
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
-merge_updates([[{_,#doc{id=X}}|_]=A|RestA], [[{_,#doc{id=X}}|_]=B|RestB]) ->
+merge_updates([[{_,{#doc{id=X},_}}|_]=A|RestA], [[{_,{#doc{id=X},_}}|_]=B|RestB]) ->
     [A++B | merge_updates(RestA, RestB)];
-merge_updates([[{_,#doc{id=X}}|_]|_]=A, [[{_,#doc{id=Y}}|_]|_]=B) when X < Y ->
+merge_updates([[{_,{#doc{id=X},_}}|_]|_]=A, [[{_,{#doc{id=Y},_}}|_]|_]=B) when X < Y ->
     [hd(A) | merge_updates(tl(A), B)];
-merge_updates([[{_,#doc{id=X}}|_]|_]=A, [[{_,#doc{id=Y}}|_]|_]=B) when X > Y ->
+merge_updates([[{_,{#doc{id=X},_}}|_]|_]=A, [[{_,{#doc{id=Y},_}}|_]|_]=B) when X > Y ->
     [hd(B) | merge_updates(A, tl(B))];
 merge_updates([], RestB) ->
     RestB;


[36/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Correctly (don't) track sys_db files


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/f9da28e4
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/f9da28e4
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/f9da28e4

Branch: refs/heads/1843-feature-bigcouch
Commit: f9da28e400bdc953ac1a8f08888bb5a4104adeab
Parents: 66809de
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 03:52:07 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:55 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_file.erl | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/f9da28e4/src/couch/src/couch_file.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_file.erl b/src/couch/src/couch_file.erl
index a638c32..7528091 100644
--- a/src/couch/src/couch_file.erl
+++ b/src/couch/src/couch_file.erl
@@ -23,6 +23,7 @@
 
 -record(file, {
     fd,
+    is_sys,
     eof = 0,
     db_pid
 }).
@@ -306,7 +307,7 @@ init({Filepath, Options, ReturnPid, Ref}) ->
                     ok = file:sync(Fd),
                     maybe_track_open_os_files(Options),
                     erlang:send_after(?INITIAL_WAIT, self(), maybe_close),
-                    {ok, #file{fd=Fd}};
+                    {ok, #file{fd=Fd, is_sys=lists:member(sys_db, Options)}};
                 false ->
                     ok = file:close(Fd),
                     init_status_error(ReturnPid, Ref, {error, eexist})
@@ -314,7 +315,7 @@ init({Filepath, Options, ReturnPid, Ref}) ->
             false ->
                 maybe_track_open_os_files(Options),
                 erlang:send_after(?INITIAL_WAIT, self(), maybe_close),
-                {ok, #file{fd=Fd}}
+                {ok, #file{fd=Fd, is_sys=lists:member(sys_db, Options)}}
             end;
         Error ->
             init_status_error(ReturnPid, Ref, Error)
@@ -328,7 +329,7 @@ init({Filepath, Options, ReturnPid, Ref}) ->
             maybe_track_open_os_files(Options),
             {ok, Eof} = file:position(Fd, eof),
             erlang:send_after(?INITIAL_WAIT, self(), maybe_close),
-            {ok, #file{fd=Fd, eof=Eof}};
+            {ok, #file{fd=Fd, eof=Eof, is_sys=lists:member(sys_db, Options)}};
         Error ->
             init_status_error(ReturnPid, Ref, Error)
         end
@@ -437,7 +438,7 @@ code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
 handle_info(maybe_close, File) ->
-    case is_idle() of
+    case is_idle(File) of
         true ->
             {stop, normal, File};
         false ->
@@ -446,7 +447,7 @@ handle_info(maybe_close, File) ->
     end;
 
 handle_info({'EXIT', Pid, _}, #file{db_pid=Pid}=File) ->
-    case is_idle() of
+    case is_idle(File) of
         true -> {stop, normal, File};
         false -> {noreply, File}
     end;
@@ -572,7 +573,13 @@ split_iolist([Byte | Rest], SplitAt, BeginAcc) when is_integer(Byte) ->
     split_iolist(Rest, SplitAt - 1, [Byte | BeginAcc]).
 
 
-is_idle() ->
+% System dbs aren't monitored by couch_stats_collector
+is_idle(#file{is_sys=true}) ->
+    case process_info(self(), monitored_by) of
+        {monitored_by, []} -> true;
+        _ -> false
+    end;
+is_idle(#file{is_sys=false}) ->
     case process_info(self(), monitored_by) of
         {monitored_by, []} -> true;
         {monitored_by, [_]} -> true;


[25/50] [abbrv] Major change to use the new config app

Posted by rn...@apache.org.
http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_index/src/couch_index_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_index/src/couch_index_server.erl b/src/couch_index/src/couch_index_server.erl
index 8c76a62..a106f14 100644
--- a/src/couch_index/src/couch_index_server.erl
+++ b/src/couch_index/src/couch_index_server.erl
@@ -12,13 +12,17 @@
 
 -module(couch_index_server).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
 -export([start_link/0, get_index/4, get_index/3, get_index/2]).
--export([config_change/2, update_notify/1]).
+-export([update_notify/1]).
 
 -export([init/1, terminate/2, code_change/3]).
 -export([handle_call/3, handle_cast/2, handle_info/2]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 -include_lib("couch/include/couch_db.hrl").
 
 -define(BY_SIG, couchdb_indexes_by_sig).
@@ -81,14 +85,14 @@ get_index(Module, IdxState) ->
 
 init([]) ->
     process_flag(trap_exit, true),
-    couch_config:register(fun ?MODULE:config_change/2),
+    ok = config:listen_for_changes(?MODULE, nil),
     ets:new(?BY_SIG, [protected, set, named_table]),
     ets:new(?BY_PID, [private, set, named_table]),
     ets:new(?BY_DB, [protected, bag, named_table]),
     couch_db_update_notifier:start_link(fun ?MODULE:update_notify/1),
     RootDir = couch_index_util:root_dir(),
     % Deprecation warning if it wasn't index_dir
-    case couch_config:get("couchdb", "index_dir") of
+    case config:get("couchdb", "index_dir") of
         undefined ->
             Msg = "Deprecation warning: 'view_index_dir' is now 'index_dir'",
             ?LOG_ERROR(Msg, []);
@@ -137,6 +141,12 @@ handle_cast({reset_indexes, DbName}, State) ->
     {noreply, State}.
 
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, State#st.root_dir),
+    {noreply, State};
 handle_info({'EXIT', Pid, Reason}, Server) ->
     case ets:lookup(?BY_PID, Pid) of
         [{Pid, {DbName, Sig}}] ->
@@ -158,6 +168,19 @@ code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
 
+handle_config_change("couchdb", "index_dir", RootDir, _, RootDir) ->
+    {ok, RootDir};
+handle_config_change("couchdb", "view_index_dir", RootDir, _, RootDir) ->
+    {ok, RootDir};
+handle_config_change("couchdb", "index_dir", _, _, _) ->
+    exit(whereis(couch_index_server), config_change),
+    remove_handler;
+handle_config_change("couchdb", "view_index_dir", _, _, _) ->
+    exit(whereis(couch_index_server), config_change),
+    remove_handler;
+handle_config_change(_, _, _, _, RootDir) ->
+    {ok, RootDir}.
+
 new_index({Mod, IdxState, DbName, Sig}) ->
     DDocId = Mod:get(idx_name, IdxState),
     case couch_index:start_link({Mod, IdxState}) of
@@ -197,12 +220,6 @@ rem_from_ets(DbName, Sig, DDocId, Pid) ->
     ets:delete_object(?BY_DB, {DbName, {DDocId, Sig}}).
 
 
-config_change("couchdb", "view_index_dir") ->
-    exit(whereis(?MODULE), config_change);
-config_change("couchdb", "index_dir") ->
-    exit(whereis(?MODULE), config_change).
-
-
 update_notify({deleted, DbName}) ->
     gen_server:cast(?MODULE, {reset_indexes, DbName});
 update_notify({created, DbName}) ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_index/src/couch_index_util.erl
----------------------------------------------------------------------
diff --git a/src/couch_index/src/couch_index_util.erl b/src/couch_index/src/couch_index_util.erl
index cef05f5..cf1ff75 100644
--- a/src/couch_index/src/couch_index_util.erl
+++ b/src/couch_index/src/couch_index_util.erl
@@ -19,8 +19,8 @@
 
 
 root_dir() ->
-    case couch_config:get("couchdb", "index_dir") of
-        undefined -> couch_config:get("couchdb", "view_index_dir");
+    case config:get("couchdb", "index_dir") of
+        undefined -> config:get("couchdb", "view_index_dir");
         Value -> Value
     end.
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_mrview/src/couch_mrview_compactor.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview/src/couch_mrview_compactor.erl b/src/couch_mrview/src/couch_mrview_compactor.erl
index 10fdfdc..b45d92b 100644
--- a/src/couch_mrview/src/couch_mrview_compactor.erl
+++ b/src/couch_mrview/src/couch_mrview_compactor.erl
@@ -68,7 +68,7 @@ compact(State) ->
         {progress, 0}
     ]),
 
-    BufferSize0 = couch_config:get(
+    BufferSize0 = config:get(
         "view_compaction", "keyvalue_buffer_size", "2097152"
     ),
     BufferSize = list_to_integer(BufferSize0),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_mrview/src/couch_mrview_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview/src/couch_mrview_updater.erl b/src/couch_mrview/src/couch_mrview_updater.erl
index 17b0432..99aedd0 100644
--- a/src/couch_mrview/src/couch_mrview_updater.erl
+++ b/src/couch_mrview/src/couch_mrview_updater.erl
@@ -213,8 +213,8 @@ accumulate_writes(State, W, Acc0) ->
 
 accumulate_more(NumDocIds) ->
     % check if we have enough items now
-    MinItems = couch_config:get("view_updater", "min_writer_items", "100"),
-    MinSize = couch_config:get("view_updater", "min_writer_size", "16777216"),
+    MinItems = config:get("view_updater", "min_writer_items", "100"),
+    MinSize = config:get("view_updater", "min_writer_size", "16777216"),
     {memory, CurrMem} = process_info(self(), memory),
     NumDocIds < list_to_integer(MinItems)
         andalso CurrMem < list_to_integer(MinSize).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_replicator/test/02-httpc-pool.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/02-httpc-pool.t b/src/couch_replicator/test/02-httpc-pool.t
index a7bde6c..23d7ab7 100755
--- a/src/couch_replicator/test/02-httpc-pool.t
+++ b/src/couch_replicator/test/02-httpc-pool.t
@@ -239,8 +239,8 @@ loop(Parent, Ref, Worker, Pool) ->
 
 
 spawn_pool() ->
-    Host = couch_config:get("httpd", "bind_address", "127.0.0.1"),
-    Port = couch_config:get("httpd", "port", "5984"),
+    Host = config:get("httpd", "bind_address", "127.0.0.1"),
+    Port = config:get("httpd", "port", "5984"),
     {ok, Pool} = couch_replicator_httpc_pool:start_link(
         "http://" ++ Host ++ ":5984", [{max_connections, 3}]),
     Pool.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_replicator/test/03-replication-compact.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/03-replication-compact.t b/src/couch_replicator/test/03-replication-compact.t
index 8d42d46..619d2b4 100755
--- a/src/couch_replicator/test/03-replication-compact.t
+++ b/src/couch_replicator/test/03-replication-compact.t
@@ -444,7 +444,7 @@ maybe_pause(Parent, Counter) ->
 
 db_url(DbName) ->
     iolist_to_binary([
-        "http://", couch_config:get("httpd", "bind_address", "127.0.0.1"),
+        "http://", config:get("httpd", "bind_address", "127.0.0.1"),
         ":", integer_to_list(mochiweb_socket_server:get(couch_httpd, port)),
         "/", DbName
     ]).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_replicator/test/04-replication-large-atts.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/04-replication-large-atts.t b/src/couch_replicator/test/04-replication-large-atts.t
index 5386179..caf2f67 100755
--- a/src/couch_replicator/test/04-replication-large-atts.t
+++ b/src/couch_replicator/test/04-replication-large-atts.t
@@ -66,7 +66,7 @@ test() ->
     couch_server_sup:start_link(test_util:config_files()),
     ibrowse:start(),
     crypto:start(),
-    couch_config:set("attachments", "compressible_types", "text/*", false),
+    config:set("attachments", "compressible_types", "text/*", false),
 
     Pairs = [
         {source_db_name(), target_db_name()},
@@ -227,7 +227,7 @@ att_decoded_md5(Att) ->
 
 db_url(DbName) ->
     iolist_to_binary([
-        "http://", couch_config:get("httpd", "bind_address", "127.0.0.1"),
+        "http://", config:get("httpd", "bind_address", "127.0.0.1"),
         ":", integer_to_list(mochiweb_socket_server:get(couch_httpd, port)),
         "/", DbName
     ]).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_replicator/test/05-replication-many-leaves.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/05-replication-many-leaves.t b/src/couch_replicator/test/05-replication-many-leaves.t
index 212ee99..be63d41 100755
--- a/src/couch_replicator/test/05-replication-many-leaves.t
+++ b/src/couch_replicator/test/05-replication-many-leaves.t
@@ -78,7 +78,7 @@ test() ->
     couch_server_sup:start_link(test_util:config_files()),
     ibrowse:start(),
     crypto:start(),
-    couch_config:set("replicator", "connection_timeout", "90000", false),
+    config:set("replicator", "connection_timeout", "90000", false),
 
     Pairs = [
         {source_db_name(), target_db_name()},
@@ -254,7 +254,7 @@ add_attachments(SourceDb, [{DocId, RevList} | Rest], NumAtts, IdRevsAcc) ->
 
 db_url(DbName) ->
     iolist_to_binary([
-        "http://", couch_config:get("httpd", "bind_address", "127.0.0.1"),
+        "http://", config:get("httpd", "bind_address", "127.0.0.1"),
         ":", integer_to_list(mochiweb_socket_server:get(couch_httpd, port)),
         "/", DbName
     ]).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_replicator/test/06-doc-missing-stubs.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/06-doc-missing-stubs.t b/src/couch_replicator/test/06-doc-missing-stubs.t
index e17efc9..0fffec2 100755
--- a/src/couch_replicator/test/06-doc-missing-stubs.t
+++ b/src/couch_replicator/test/06-doc-missing-stubs.t
@@ -264,7 +264,7 @@ att_decoded_md5(Att) ->
 
 db_url(DbName) ->
     iolist_to_binary([
-        "http://", couch_config:get("httpd", "bind_address", "127.0.0.1"),
+        "http://", config:get("httpd", "bind_address", "127.0.0.1"),
         ":", integer_to_list(mochiweb_socket_server:get(couch_httpd, port)),
         "/", DbName
     ]).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/001-load.t
----------------------------------------------------------------------
diff --git a/test/etap/001-load.t b/test/etap/001-load.t
index c9c2922..a5fa27f 100755
--- a/test/etap/001-load.t
+++ b/test/etap/001-load.t
@@ -22,8 +22,6 @@ main(_) ->
         couch_btree,
         couch_changes,
         couch_compress,
-        couch_config,
-        couch_config_writer,
         couch_db,
         couch_db_update_notifier,
         couch_db_update_notifier_sup,

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/002-icu-driver.t
----------------------------------------------------------------------
diff --git a/test/etap/002-icu-driver.t b/test/etap/002-icu-driver.t
index e233533..2ce47d9 100755
--- a/test/etap/002-icu-driver.t
+++ b/test/etap/002-icu-driver.t
@@ -13,7 +13,7 @@
 
 main(_) ->
     test_util:init_code_path(),
-    couch_config:start_link(test_util:config_files()),
+    application:start(config),
     etap:plan(3),
     etap:is(
         element(1, couch_drv:start_link()),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/030-doc-from-json.t
----------------------------------------------------------------------
diff --git a/test/etap/030-doc-from-json.t b/test/etap/030-doc-from-json.t
index b0c393e..79d5692 100755
--- a/test/etap/030-doc-from-json.t
+++ b/test/etap/030-doc-from-json.t
@@ -33,8 +33,8 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link(test_util:config_files()),
-    couch_config:set("attachments", "compression_level", "0", false),
+    application:start(config),
+    config:set("attachments", "compression_level", "0", false),
     ok = test_from_json_success(),
     ok = test_from_json_errors(),
     ok.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/031-doc-to-json.t
----------------------------------------------------------------------
diff --git a/test/etap/031-doc-to-json.t b/test/etap/031-doc-to-json.t
index ce950f9..e0aaf70 100755
--- a/test/etap/031-doc-to-json.t
+++ b/test/etap/031-doc-to-json.t
@@ -33,8 +33,8 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link(test_util:config_files()),
-    couch_config:set("attachments", "compression_level", "0", false),
+    application:start(config),
+    config:set("attachments", "compression_level", "0", false),
     ok = test_to_json_success(),
     ok.
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/041-uuid-gen-id.ini
----------------------------------------------------------------------
diff --git a/test/etap/041-uuid-gen-id.ini b/test/etap/041-uuid-gen-id.ini
deleted file mode 100644
index 6886efd..0000000
--- a/test/etap/041-uuid-gen-id.ini
+++ /dev/null
@@ -1,20 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one
-; or more contributor license agreements.  See the NOTICE file
-; distributed with this work for additional information
-; regarding copyright ownership.  The ASF licenses this file
-; to you under the Apache License, Version 2.0 (the
-; "License"); you may not use this file except in compliance
-; with the License.  You may obtain a copy of the License at
-;
-;   http://www.apache.org/licenses/LICENSE-2.0
-;
-; Unless required by applicable law or agreed to in writing,
-; software distributed under the License is distributed on an
-; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-; KIND, either express or implied.  See the License for the
-; specific language governing permissions and limitations
-; under the License.
-
-[uuids]
-algorithm = utc_id
-utc_id_suffix = bozo

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/041-uuid-gen-seq.ini
----------------------------------------------------------------------
diff --git a/test/etap/041-uuid-gen-seq.ini b/test/etap/041-uuid-gen-seq.ini
deleted file mode 100644
index 94cebc6..0000000
--- a/test/etap/041-uuid-gen-seq.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one
-; or more contributor license agreements.  See the NOTICE file
-; distributed with this work for additional information
-; regarding copyright ownership.  The ASF licenses this file
-; to you under the Apache License, Version 2.0 (the
-; "License"); you may not use this file except in compliance
-; with the License.  You may obtain a copy of the License at
-; 
-;   http://www.apache.org/licenses/LICENSE-2.0
-;
-; Unless required by applicable law or agreed to in writing,
-; software distributed under the License is distributed on an
-; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-; KIND, either express or implied.  See the License for the
-; specific language governing permissions and limitations
-; under the License.
-
-[uuids]
-algorithm = sequential

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/041-uuid-gen-utc.ini
----------------------------------------------------------------------
diff --git a/test/etap/041-uuid-gen-utc.ini b/test/etap/041-uuid-gen-utc.ini
deleted file mode 100644
index c2b8383..0000000
--- a/test/etap/041-uuid-gen-utc.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one
-; or more contributor license agreements.  See the NOTICE file
-; distributed with this work for additional information
-; regarding copyright ownership.  The ASF licenses this file
-; to you under the Apache License, Version 2.0 (the
-; "License"); you may not use this file except in compliance
-; with the License.  You may obtain a copy of the License at
-; 
-;   http://www.apache.org/licenses/LICENSE-2.0
-;
-; Unless required by applicable law or agreed to in writing,
-; software distributed under the License is distributed on an
-; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-; KIND, either express or implied.  See the License for the
-; specific language governing permissions and limitations
-; under the License.
-
-[uuids]
-algorithm = utc_random

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/041-uuid-gen.t
----------------------------------------------------------------------
diff --git a/test/etap/041-uuid-gen.t b/test/etap/041-uuid-gen.t
index 7234969..da1ded1 100755
--- a/test/etap/041-uuid-gen.t
+++ b/test/etap/041-uuid-gen.t
@@ -13,36 +13,19 @@
 % License for the specific language governing permissions and limitations under
 % the License.
 
-default_config() ->
-    test_util:build_file("etc/couchdb/default_dev.ini").
-
-seq_alg_config() ->
-    test_util:source_file("test/etap/041-uuid-gen-seq.ini").
-
-utc_alg_config() ->
-    test_util:source_file("test/etap/041-uuid-gen-utc.ini").
-
-utc_id_alg_config() ->
-    test_util:source_file("test/etap/041-uuid-gen-id.ini").
-
 % Run tests and wait for the gen_servers to shutdown
-run_test(IniFiles, Test) ->
-    {ok, Pid} = couch_config:start_link(IniFiles),
-    erlang:monitor(process, Pid),
+run_test(Config, Test) ->
+    lists:foreach(fun({Key, Value}) ->
+        config:set("uuids", Key, Value, false)
+    end, Config),
     couch_uuids:start(),
     Test(),
-    couch_uuids:stop(),
-    couch_config:stop(),
-    receive
-        {'DOWN', _, _, Pid, _} -> ok;
-        _Other -> etap:diag("OTHER: ~p~n", [_Other])
-    after
-        1000 -> throw({timeout_error, config_stop})
-    end.
+    couch_uuids:stop().
 
 main(_) ->
     test_util:init_code_path(),
     application:start(crypto),
+    application:start(config),
     etap:plan(9),
 
     case (catch test()) of
@@ -55,7 +38,6 @@ main(_) ->
     ok.
 
 test() ->
-
     TestUnique = fun() ->
         etap:is(
             test_unique(10000, couch_uuids:new()),
@@ -63,10 +45,10 @@ test() ->
             "Can generate 10K unique IDs"
         )
     end,
-    run_test([default_config()], TestUnique),
-    run_test([default_config(), seq_alg_config()], TestUnique),
-    run_test([default_config(), utc_alg_config()], TestUnique),
-    run_test([default_config(), utc_id_alg_config()], TestUnique),
+    run_test([{"algorithm", "random"}], TestUnique),
+    run_test([{"algorithm", "sequential"}], TestUnique),
+    run_test([{"algorithm", "utc_random"}], TestUnique),
+    run_test([{"algorithm", "utc_id"}, {"utc_id_suffix", "bozo"}], TestUnique),
 
     TestMonotonic = fun () ->
         etap:is(
@@ -75,9 +57,10 @@ test() ->
             "should produce monotonically increasing ids"
         )
     end,
-    run_test([default_config(), seq_alg_config()], TestMonotonic),
-    run_test([default_config(), utc_alg_config()], TestMonotonic),
-    run_test([default_config(), utc_id_alg_config()], TestMonotonic),
+    run_test([{"algorithm", "sequential"}], TestMonotonic),
+    run_test([{"algorithm", "utc_random"}], TestMonotonic),
+    run_test([{"algorithm", "utc_id"}, {"utc_id_suffix", "bozo"}],
+        TestMonotonic),
 
     % Pretty sure that the average of a uniform distribution is the
     % midpoint of the range. Thus, to exceed a threshold, we need
@@ -99,7 +82,7 @@ test() ->
             "should roll over every so often."
         )
     end,
-    run_test([default_config(), seq_alg_config()], TestRollOver),
+    run_test([{"algorithm", "sequential"}], TestRollOver),
 
     TestSuffix = fun() ->
         UUID = binary_to_list(couch_uuids:new()),
@@ -110,7 +93,7 @@ test() ->
             "utc_id ids should have the same suffix."
         )
     end,
-    run_test([default_config(), utc_id_alg_config()], TestSuffix).
+    run_test([{"algorithm", "utc_id"}, {"utc_id_suffix", "bozo"}], TestSuffix).
 
 test_unique(0, _) ->
     true;

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/072-cleanup.t
----------------------------------------------------------------------
diff --git a/test/etap/072-cleanup.t b/test/etap/072-cleanup.t
index 6721090..83b8a6b 100755
--- a/test/etap/072-cleanup.t
+++ b/test/etap/072-cleanup.t
@@ -103,7 +103,7 @@ delete_design_doc(DDName, Rev) ->
     couch_db:close(Db).
 
 db_url() ->
-    Addr = couch_config:get("httpd", "bind_address", "127.0.0.1"),
+    Addr = config:get("httpd", "bind_address", "127.0.0.1"),
     Port = integer_to_list(mochiweb_socket_server:get(couch_httpd, port)),
     "http://" ++ Addr ++ ":" ++ Port ++ "/" ++
         binary_to_list(?TEST_DB).
@@ -121,6 +121,6 @@ view_cleanup() ->
 
 count_index_files() ->
     % call server to fetch the index files
-    RootDir = couch_config:get("couchdb", "index_dir"),
+    RootDir = config:get("couchdb", "index_dir"),
     length(filelib:wildcard(RootDir ++ "/." ++
         binary_to_list(?TEST_DB) ++ "_design"++"/mrview/*")).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/074-doc-update-conflicts.t
----------------------------------------------------------------------
diff --git a/test/etap/074-doc-update-conflicts.t b/test/etap/074-doc-update-conflicts.t
index 09d0633..185a419 100755
--- a/test/etap/074-doc-update-conflicts.t
+++ b/test/etap/074-doc-update-conflicts.t
@@ -39,7 +39,7 @@ main(_) ->
 
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
-    couch_config:set("couchdb", "delayed_commits", "true", false),
+    config:set("couchdb", "delayed_commits", "true", false),
 
     lists:foreach(
         fun(NumClients) -> test_concurrent_doc_update(NumClients) end,

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/075-auth-cache.t
----------------------------------------------------------------------
diff --git a/test/etap/075-auth-cache.t b/test/etap/075-auth-cache.t
index 4af7aba..1b88858 100755
--- a/test/etap/075-auth-cache.t
+++ b/test/etap/075-auth-cache.t
@@ -66,14 +66,14 @@ main(_) ->
 
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
-    OrigName = couch_config:get("couch_httpd_auth", "authentication_db"),
-    couch_config:set(
+    OrigName = config:get("couch_httpd_auth", "authentication_db"),
+    config:set(
         "couch_httpd_auth", "authentication_db",
         binary_to_list(auth_db_name()), false),
 
     test_auth_db_crash(),
 
-    couch_config:set("couch_httpd_auth", "authentication_db", OrigName, false),
+    config:set("couch_httpd_auth", "authentication_db", OrigName, false),
     delete_db(auth_db_name()),
     delete_db(auth_db_2_name()),
     couch_server_sup:stop(),
@@ -136,7 +136,7 @@ test_auth_db_crash() ->
     full_commit(auth_db_name()),
 
     etap:diag("Changing the auth database"),
-    couch_config:set(
+    config:set(
         "couch_httpd_auth", "authentication_db",
         binary_to_list(auth_db_2_name()), false),
     ok = timer:sleep(500),
@@ -171,7 +171,7 @@ test_auth_db_crash() ->
             "Cached credentials have the new password"),
 
     etap:diag("Changing the auth database again"),
-    couch_config:set(
+    config:set(
         "couch_httpd_auth", "authentication_db",
         binary_to_list(auth_db_name()), false),
     ok = timer:sleep(500),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/076-file-compression.t
----------------------------------------------------------------------
diff --git a/test/etap/076-file-compression.t b/test/etap/076-file-compression.t
index 8afa599..5f75ad6 100755
--- a/test/etap/076-file-compression.t
+++ b/test/etap/076-file-compression.t
@@ -39,7 +39,7 @@ main(_) ->
 
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
-    couch_config:set("couchdb", "file_compression", "none", false),
+    config:set("couchdb", "file_compression", "none", false),
 
     create_database(),
     compact_db(),
@@ -47,7 +47,7 @@ test() ->
     DbDiskSize1 = db_disk_size(),
     ViewDiskSize1 = view_disk_size(),
 
-    couch_config:set("couchdb", "file_compression", "snappy", false),
+    config:set("couchdb", "file_compression", "snappy", false),
     compact_db(),
     compact_view(),
     DbDiskSize2 = db_disk_size(),
@@ -56,7 +56,7 @@ test() ->
     etap:is(DbDiskSize2 < DbDiskSize1, true, "Database disk size decreased"),
     etap:is(ViewDiskSize2 < ViewDiskSize1, true, "Index disk size decreased"),
 
-    couch_config:set("couchdb", "file_compression", "deflate_9", false),
+    config:set("couchdb", "file_compression", "deflate_9", false),
     compact_db(),
     compact_view(),
     DbDiskSize3 = db_disk_size(),
@@ -65,7 +65,7 @@ test() ->
     etap:is(DbDiskSize3 < DbDiskSize2, true, "Database disk size decreased again"),
     etap:is(ViewDiskSize3 < ViewDiskSize2, true, "Index disk size decreased again"),
 
-    couch_config:set("couchdb", "file_compression", "deflate_1", false),
+    config:set("couchdb", "file_compression", "deflate_1", false),
     compact_db(),
     compact_view(),
     DbDiskSize4 = db_disk_size(),
@@ -74,7 +74,7 @@ test() ->
     etap:is(DbDiskSize4 > DbDiskSize3, true, "Database disk size increased"),
     etap:is(ViewDiskSize4 > ViewDiskSize3, true, "Index disk size increased"),
 
-    couch_config:set("couchdb", "file_compression", "snappy", false),
+    config:set("couchdb", "file_compression", "snappy", false),
     compact_db(),
     compact_view(),
     DbDiskSize5 = db_disk_size(),
@@ -83,7 +83,7 @@ test() ->
     etap:is(DbDiskSize5 > DbDiskSize4, true, "Database disk size increased again"),
     etap:is(ViewDiskSize5 > ViewDiskSize4, true, "Index disk size increased again"),
 
-    couch_config:set("couchdb", "file_compression", "none", false),
+    config:set("couchdb", "file_compression", "none", false),
     compact_db(),
     compact_view(),
     DbDiskSize6 = db_disk_size(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/080-config-get-set.t
----------------------------------------------------------------------
diff --git a/test/etap/080-config-get-set.t b/test/etap/080-config-get-set.t
index 94a9cba..6e5395e 100755
--- a/test/etap/080-config-get-set.t
+++ b/test/etap/080-config-get-set.t
@@ -29,8 +29,7 @@ main(_) ->
     ok.
 
 test() ->
-    % start couch_config with default
-    couch_config:start_link([default_config()]),
+    application:start(config),
 
 
     % Check that we can get values
@@ -38,36 +37,36 @@ test() ->
 
     etap:fun_is(
         fun(List) -> length(List) > 0 end,
-        couch_config:all(),
+        config:all(),
         "Data was loaded from the INI file."
     ),
 
     etap:fun_is(
         fun(List) -> length(List) > 0 end,
-        couch_config:get("daemons"),
+        config:get("daemons"),
         "There are settings in the [daemons] section of the INI file."
     ),
 
     etap:is(
-        couch_config:get("httpd_design_handlers", "_view"),
+        config:get("httpd_design_handlers", "_view"),
         "{couch_mrview_http, handle_view_req}",
         "The {httpd_design_handlers, view} is the expected default."
     ),
 
     etap:is(
-        couch_config:get("httpd", "foo", "bar"),
+        config:get("httpd", "foo", "bar"),
         "bar",
         "Returns the default when key doesn't exist in config."
     ),
 
     etap:is(
-        couch_config:get("httpd", "foo"),
+        config:get("httpd", "foo"),
         undefined,
         "The default default is the atom 'undefined'."
     ),
 
     etap:is(
-        couch_config:get("httpd", "port", "bar"),
+        config:get("httpd", "port", "bar"),
         "5984",
         "Only returns the default when the config setting does not exist."
     ),
@@ -76,24 +75,24 @@ test() ->
     % Check that setting values works.
 
 
-    ok = couch_config:set("log", "level", "severe", false),
+    ok = config:set("log", "level", "severe", false),
 
     etap:is(
-        couch_config:get("log", "level"),
+        config:get("log", "level"),
         "severe",
         "Non persisted changes take effect."
     ),
 
     etap:is(
-        couch_config:get("new_section", "bizzle"),
+        config:get("new_section", "bizzle"),
         undefined,
         "Section 'new_section' does not exist."
     ),
 
-    ok = couch_config:set("new_section", "bizzle", "bang", false),
+    ok = config:set("new_section", "bizzle", "bang", false),
 
     etap:is(
-        couch_config:get("new_section", "bizzle"),
+        config:get("new_section", "bizzle"),
         "bang",
         "New section 'new_section' was created for a new key/value pair."
     ),
@@ -102,9 +101,9 @@ test() ->
     % Check that deleting works
 
 
-    ok = couch_config:delete("new_section", "bizzle", false),
+    ok = config:delete("new_section", "bizzle", false),
     etap:is(
-        couch_config:get("new_section", "bizzle"),
+        config:get("new_section", "bizzle"),
         undefined,
         "Deleting sets the value to \"\""
     ),
@@ -112,15 +111,15 @@ test() ->
 
     % Check ge/set/delete binary strings
 
-    ok = couch_config:set(<<"foo">>, <<"bar">>, <<"baz">>, false),
+    ok = config:set(<<"foo">>, <<"bar">>, <<"baz">>, false),
     etap:is(
-        couch_config:get(<<"foo">>, <<"bar">>),
+        config:get(<<"foo">>, <<"bar">>),
         <<"baz">>,
         "Can get and set with binary section and key values."
     ),
-    ok = couch_config:delete(<<"foo">>, <<"bar">>, false),
+    ok = config:delete(<<"foo">>, <<"bar">>, false),
     etap:is(
-        couch_config:get(<<"foo">>, <<"bar">>),
+        config:get(<<"foo">>, <<"bar">>),
         undefined,
         "Deleting with binary section/key pairs sets the value to \"\""
     ),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/081-config-override.t
----------------------------------------------------------------------
diff --git a/test/etap/081-config-override.t b/test/etap/081-config-override.t
index 01f8b4c..2d47122 100755
--- a/test/etap/081-config-override.t
+++ b/test/etap/081-config-override.t
@@ -27,10 +27,10 @@ local_config_write() ->
 
 % Run tests and wait for the config gen_server to shutdown.
 run_tests(IniFiles, Tests) ->
-    {ok, Pid} = couch_config:start_link(IniFiles),
+    application:start(config),
     erlang:monitor(process, Pid),
     Tests(),
-    couch_config:stop(),
+    config:stop(),
     receive
         {'DOWN', _, _, Pid, _} -> ok;
         _Other -> etap:diag("OTHER: ~p~n", [_Other])
@@ -58,19 +58,19 @@ test() ->
 
     CheckDefaults = fun() ->
         etap:is(
-            couch_config:get("couchdb", "max_dbs_open"),
+            config:get("couchdb", "max_dbs_open"),
             "100",
             "{couchdb, max_dbs_open} is 100 by defualt."
         ),
 
         etap:is(
-            couch_config:get("httpd","port"),
+            config:get("httpd","port"),
             "5984",
             "{httpd, port} is 5984 by default"
         ),
 
         etap:is(
-            couch_config:get("fizbang", "unicode"),
+            config:get("fizbang", "unicode"),
             undefined,
             "{fizbang, unicode} is undefined by default"
         )
@@ -83,13 +83,13 @@ test() ->
 
     CheckOverride = fun() ->
         etap:is(
-            couch_config:get("couchdb", "max_dbs_open"),
+            config:get("couchdb", "max_dbs_open"),
             "10",
             "{couchdb, max_dbs_open} was overriden with the value 10"
         ),
 
         etap:is(
-            couch_config:get("httpd", "port"),
+            config:get("httpd", "port"),
             "4895",
             "{httpd, port} was overriden with the value 4895"
         )
@@ -102,13 +102,13 @@ test() ->
 
     CheckOverride2 = fun() ->
         etap:is(
-            couch_config:get("httpd", "port"),
+            config:get("httpd", "port"),
             "80",
             "{httpd, port} is overriden with the value 80"
         ),
 
         etap:is(
-            couch_config:get("fizbang", "unicode"),
+            config:get("fizbang", "unicode"),
             "normalized",
             "{fizbang, unicode} was created by override INI file"
         )
@@ -121,7 +121,7 @@ test() ->
 
     CheckOverride3 = fun() ->
         etap:is(
-            couch_config:get("httpd", "port"),
+            config:get("httpd", "port"),
             "80",
             "{httpd, port} value was taken from the last specified INI file."
         )
@@ -142,31 +142,31 @@ test() ->
     % Open and write a value
     CheckCanWrite = fun() ->
         etap:is(
-            couch_config:get("httpd", "port"),
+            config:get("httpd", "port"),
             "5984",
             "{httpd, port} is still 5984 by default"
         ),
 
         etap:is(
-            couch_config:set("httpd", "port", "8080"),
+            config:set("httpd", "port", "8080"),
             ok,
             "Writing {httpd, port} is kosher."
         ),
 
         etap:is(
-            couch_config:get("httpd", "port"),
+            config:get("httpd", "port"),
             "8080",
             "{httpd, port} was updated to 8080 successfully."
         ),
 
         etap:is(
-            couch_config:delete("httpd", "bind_address"),
+            config:delete("httpd", "bind_address"),
             ok,
             "Deleting {httpd, bind_address} succeeds"
         ),
 
         etap:is(
-            couch_config:get("httpd", "bind_address"),
+            config:get("httpd", "bind_address"),
             undefined,
             "{httpd, bind_address} was actually deleted."
         )
@@ -178,13 +178,13 @@ test() ->
 
     CheckDidntWrite = fun() ->
         etap:is(
-            couch_config:get("httpd", "port"),
+            config:get("httpd", "port"),
             "5984",
             "{httpd, port} was not persisted to the primary INI file."
         ),
 
         etap:is(
-            couch_config:get("httpd", "bind_address"),
+            config:get("httpd", "bind_address"),
             "127.0.0.1",
             "{httpd, bind_address} was not deleted form the primary INI file."
         )
@@ -195,13 +195,13 @@ test() ->
     % Open and check we have only the persistence we expect.
     CheckDidWrite = fun() ->
         etap:is(
-            couch_config:get("httpd", "port"),
+            config:get("httpd", "port"),
             "8080",
             "{httpd, port} is still 8080 after reopening the config."
         ),
 
         etap:is(
-            couch_config:get("httpd", "bind_address"),
+            config:get("httpd", "bind_address"),
             undefined,
             "{httpd, bind_address} is still \"\" after reopening."
         )

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/082-config-register.t
----------------------------------------------------------------------
diff --git a/test/etap/082-config-register.t b/test/etap/082-config-register.t
index 191ba8f..9487887 100755
--- a/test/etap/082-config-register.t
+++ b/test/etap/082-config-register.t
@@ -29,18 +29,18 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link([default_config()]),
+    application:start(config),
 
     etap:is(
-        couch_config:get("httpd", "port"),
+        config:get("httpd", "port"),
         "5984",
         "{httpd, port} is 5984 by default."
     ),
 
-    ok = couch_config:set("httpd", "port", "4895", false),
+    ok = config:set("httpd", "port", "4895", false),
 
     etap:is(
-        couch_config:get("httpd", "port"),
+        config:get("httpd", "port"),
         "4895",
         "{httpd, port} changed to 4895"
     ),
@@ -52,22 +52,22 @@ test() ->
     end,
     SentinelPid = spawn(SentinelFunc),
 
-    couch_config:register(
+    config:register(
         fun("httpd", "port", Value) ->
             etap:is(Value, "8080", "Registered function got notification.")
         end,
         SentinelPid
     ),
 
-    ok = couch_config:set("httpd", "port", "8080", false),
+    ok = config:set("httpd", "port", "8080", false),
 
     % Implicitly checking that we *don't* call the function
     etap:is(
-        couch_config:get("httpd", "bind_address"),
+        config:get("httpd", "bind_address"),
         "127.0.0.1",
         "{httpd, bind_address} is not '0.0.0.0'"
     ),
-    ok = couch_config:set("httpd", "bind_address", "0.0.0.0", false),
+    ok = config:set("httpd", "bind_address", "0.0.0.0", false),
 
     % Ping-Pong kill process
     SentinelPid ! {ping, self()},
@@ -77,18 +77,18 @@ test() ->
         throw({timeout_error, registered_pid})
     end,
 
-    ok = couch_config:set("httpd", "port", "80", false),
+    ok = config:set("httpd", "port", "80", false),
     etap:is(
-        couch_config:get("httpd", "port"),
+        config:get("httpd", "port"),
         "80",
         "Implicitly test that the function got de-registered"
     ),
 
     % test passing of Persist flag
-    couch_config:register(
+    config:register(
         fun("httpd", _, _, Persist) ->
             etap:is(Persist, false)
         end),
-    ok = couch_config:set("httpd", "port", "80", false),
+    ok = config:set("httpd", "port", "80", false),
 
     ok.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/083-config-no-files.t
----------------------------------------------------------------------
diff --git a/test/etap/083-config-no-files.t b/test/etap/083-config-no-files.t
index 0ce38e6..3ad0905 100755
--- a/test/etap/083-config-no-files.t
+++ b/test/etap/083-config-no-files.t
@@ -27,25 +27,25 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link([]),
+    application:start(config),
 
     etap:fun_is(
         fun(KVPairs) -> length(KVPairs) == 0 end,
-        couch_config:all(),
+        config:all(),
         "No INI files specified returns 0 key/value pairs."
     ),
 
-    ok = couch_config:set("httpd", "port", "80", false),
+    ok = config:set("httpd", "port", "80", false),
 
     etap:is(
-        couch_config:get("httpd", "port"),
+        config:get("httpd", "port"),
         "80",
         "Created a new non-persisted k/v pair."
     ),
 
-    ok = couch_config:set("httpd", "bind_address", "127.0.0.1"),
+    ok = config:set("httpd", "bind_address", "127.0.0.1"),
     etap:is(
-        couch_config:get("httpd", "bind_address"),
+        config:get("httpd", "bind_address"),
         "127.0.0.1",
         "Asking for a persistent key/value pair doesn't choke."
     ),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/121-stats-aggregates.t
----------------------------------------------------------------------
diff --git a/test/etap/121-stats-aggregates.t b/test/etap/121-stats-aggregates.t
index d678aa9..92bf547 100755
--- a/test/etap/121-stats-aggregates.t
+++ b/test/etap/121-stats-aggregates.t
@@ -32,7 +32,7 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link([ini_file()]),
+    application:start(config),
     couch_stats_collector:start(),
     couch_stats_aggregator:start(cfg_file()),
     ok = test_all_empty(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/130-attachments-md5.t
----------------------------------------------------------------------
diff --git a/test/etap/130-attachments-md5.t b/test/etap/130-attachments-md5.t
index a91c9bf..12b1aba 100755
--- a/test/etap/130-attachments-md5.t
+++ b/test/etap/130-attachments-md5.t
@@ -39,7 +39,7 @@ main(_) ->
 
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
-    Addr = couch_config:get("httpd", "bind_address", any),
+    Addr = config:get("httpd", "bind_address", any),
     put(addr, Addr),
     put(port, mochiweb_socket_server:get(couch_httpd, port)),
     timer:sleep(1000),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/140-attachment-comp.t
----------------------------------------------------------------------
diff --git a/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t
index 2b082c2..6e8640d 100755
--- a/test/etap/140-attachment-comp.t
+++ b/test/etap/140-attachment-comp.t
@@ -31,14 +31,14 @@ main(_) ->
 
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
-    put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")),
+    put(addr, config:get("httpd", "bind_address", "127.0.0.1")),
     put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))),
     timer:sleep(1000),
     couch_server:delete(test_db_name(), []),
     couch_db:create(test_db_name(), []),
 
-    couch_config:set("attachments", "compression_level", "8", false),
-    couch_config:set("attachments", "compressible_types", "text/*", false),
+    config:set("attachments", "compression_level", "8", false),
+    config:set("attachments", "compressible_types", "text/*", false),
 
     create_1st_text_att(),
     create_1st_png_att(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/150-invalid-view-seq.t
----------------------------------------------------------------------
diff --git a/test/etap/150-invalid-view-seq.t b/test/etap/150-invalid-view-seq.t
index 681875a..4553b16 100755
--- a/test/etap/150-invalid-view-seq.t
+++ b/test/etap/150-invalid-view-seq.t
@@ -50,7 +50,7 @@ test() ->
     % make DB file backup
     backup_db_file(),
 
-    put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")),
+    put(addr, config:get("httpd", "bind_address", "127.0.0.1")),
     put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))),
 
     create_new_doc(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/160-vhosts.t
----------------------------------------------------------------------
diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t
index 46fdd73..4118b94 100755
--- a/test/etap/160-vhosts.t
+++ b/test/etap/160-vhosts.t
@@ -78,22 +78,22 @@ test() ->
 
     %% end boilerplate, start test
 
-    ok = couch_config:set("vhosts", "example.com", "/etap-test-db", false),
-    ok = couch_config:set("vhosts", "*.example.com",
+    ok = config:set("vhosts", "example.com", "/etap-test-db", false),
+    ok = config:set("vhosts", "*.example.com",
             "/etap-test-db/_design/doc1/_rewrite", false),
-    ok = couch_config:set("vhosts", "example.com/test", "/etap-test-db", false),
-    ok = couch_config:set("vhosts", "example1.com",
+    ok = config:set("vhosts", "example.com/test", "/etap-test-db", false),
+    ok = config:set("vhosts", "example1.com",
             "/etap-test-db/_design/doc1/_rewrite/", false),
-    ok = couch_config:set("vhosts",":appname.:dbname.example1.com",
+    ok = config:set("vhosts",":appname.:dbname.example1.com",
             "/:dbname/_design/:appname/_rewrite/", false),
-    ok = couch_config:set("vhosts", ":dbname.example1.com", "/:dbname", false),
+    ok = config:set("vhosts", ":dbname.example1.com", "/:dbname", false),
 
-    ok = couch_config:set("vhosts", "*.example2.com", "/*", false),
-    ok = couch_config:set("vhosts", "*.example2.com/test", "/*", false),
-    ok = couch_config:set("vhosts", "*/test", "/etap-test-db", false),
-    ok = couch_config:set("vhosts", "*/test1",
+    ok = config:set("vhosts", "*.example2.com", "/*", false),
+    ok = config:set("vhosts", "*.example2.com/test", "/*", false),
+    ok = config:set("vhosts", "*/test", "/etap-test-db", false),
+    ok = config:set("vhosts", "*/test1",
             "/etap-test-db/_design/doc1/_show/test", false),
-    ok = couch_config:set("vhosts", "example3.com", "/", false),
+    ok = config:set("vhosts", "example3.com", "/", false),
 
     %% reload rules
     couch_httpd_vhost:reload(),
@@ -288,12 +288,12 @@ test_vhost_request_to_root() ->
 test_vhost_request_with_oauth(Db) ->
     {ok, AuthDb} = couch_db:create(
         <<"tap_test_sec_db">>, [admin_user_ctx(), overwrite]),
-    PrevAuthDbName = couch_config:get("couch_httpd_auth", "authentication_db"),
-    couch_config:set("couch_httpd_auth", "authentication_db", "tap_test_sec_db", false),
-    couch_config:set("oauth_token_users", "otoksec1", "joe", false),
-    couch_config:set("oauth_consumer_secrets", "consec1", "foo", false),
-    couch_config:set("oauth_token_secrets", "otoksec1", "foobar", false),
-    couch_config:set("couch_httpd_auth", "require_valid_user", "true", false),
+    PrevAuthDbName = config:get("couch_httpd_auth", "authentication_db"),
+    config:set("couch_httpd_auth", "authentication_db", "tap_test_sec_db", false),
+    config:set("oauth_token_users", "otoksec1", "joe", false),
+    config:set("oauth_consumer_secrets", "consec1", "foo", false),
+    config:set("oauth_token_secrets", "otoksec1", "foobar", false),
+    config:set("couch_httpd_auth", "require_valid_user", "true", false),
 
     DDoc = couch_doc:from_json_obj({[
         {<<"_id">>, <<"_design/test">>},
@@ -308,7 +308,7 @@ test_vhost_request_with_oauth(Db) ->
     {ok, _} = couch_db:update_doc(Db, DDoc, []),
 
     RewritePath = "/etap-test-db/_design/test/_rewrite/foobar",
-    ok = couch_config:set("vhosts", "oauth-example.com", RewritePath, false),
+    ok = config:set("vhosts", "oauth-example.com", RewritePath, false),
     couch_httpd_vhost:reload(),
 
     case ibrowse:send_req(server(), [], get, [], [{host_header, "oauth-example.com"}]) of
@@ -366,6 +366,6 @@ test_vhost_request_with_oauth(Db) ->
                couch_util:to_list(Error3))
     end,
 
-    couch_config:set("couch_httpd_auth", "authentication_db", PrevAuthDbName, false),
-    couch_config:set("couch_httpd_auth", "require_valid_user", "false", false),
+    config:set("couch_httpd_auth", "authentication_db", PrevAuthDbName, false),
+    config:set("couch_httpd_auth", "require_valid_user", "false", false),
     ok = couch_server:delete(couch_db:name(AuthDb), [admin_user_ctx()]).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/170-os-daemons.t
----------------------------------------------------------------------
diff --git a/test/etap/170-os-daemons.t b/test/etap/170-os-daemons.t
index 6feaa1b..f1961a9 100755
--- a/test/etap/170-os-daemons.t
+++ b/test/etap/170-os-daemons.t
@@ -46,11 +46,11 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link(config_files()),
+    application:start(config),
     couch_os_daemons:start_link(),
 
     etap:diag("Daemons boot after configuration added."),
-    couch_config:set("os_daemons", "foo", daemon_cmd(), false),
+    config:set("os_daemons", "foo", daemon_cmd(), false),
     timer:sleep(1000),
     
     {ok, [D1]} = couch_os_daemons:info([table]),
@@ -62,7 +62,7 @@ test() ->
     check_daemon(T1, "foo"),
 
     etap:diag("Daemons stop after configuration removed."),
-    couch_config:delete("os_daemons", "foo", false),
+    config:delete("os_daemons", "foo", false),
     timer:sleep(500),
     
     {ok, []} = couch_os_daemons:info([table]),
@@ -70,8 +70,8 @@ test() ->
     etap:is(ets:tab2list(Tab2), [], "As table returns empty table."),
     
     etap:diag("Adding multiple daemons causes both to boot."),
-    couch_config:set("os_daemons", "bar", daemon_cmd(), false),
-    couch_config:set("os_daemons", "baz", daemon_cmd(), false),
+    config:set("os_daemons", "bar", daemon_cmd(), false),
+    config:set("os_daemons", "baz", daemon_cmd(), false),
     timer:sleep(500),
     {ok, Daemons} = couch_os_daemons:info([table]),
     lists:foreach(fun(D) ->
@@ -84,7 +84,7 @@ test() ->
     end, ets:tab2list(Tab3)),
     
     etap:diag("Removing one daemon leaves the other alive."),
-    couch_config:delete("os_daemons", "bar", false),
+    config:delete("os_daemons", "bar", false),
     timer:sleep(500),
     
     {ok, [D2]} = couch_os_daemons:info([table]),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/171-os-daemons-config.es
----------------------------------------------------------------------
diff --git a/test/etap/171-os-daemons-config.es b/test/etap/171-os-daemons-config.es
index b4a914e..15da0e9 100755
--- a/test/etap/171-os-daemons-config.es
+++ b/test/etap/171-os-daemons-config.es
@@ -80,6 +80,6 @@ loop({error, _Reason}) ->
 
 main([]) ->
     test_util:init_code_path(),
-    couch_config:start_link(test_util:config_files()),
+    application:start(config),
     couch_drv:start_link(),
     do_tests().

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/171-os-daemons-config.t
----------------------------------------------------------------------
diff --git a/test/etap/171-os-daemons-config.t b/test/etap/171-os-daemons-config.t
index e9dc3f3..8254c26 100755
--- a/test/etap/171-os-daemons-config.t
+++ b/test/etap/171-os-daemons-config.t
@@ -46,13 +46,13 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link(config_files()),
-    couch_config:set("log", "level", "debug", false),
+    application:start(config),
+    config:set("log", "level", "debug", false),
     couch_log:start_link(),
     couch_os_daemons:start_link(),
 
     % "foo" is a required name by this test.
-    couch_config:set("os_daemons", "foo", daemon_cmd(), false),
+    config:set("os_daemons", "foo", daemon_cmd(), false),
     timer:sleep(1000),
     
     {ok, [D1]} = couch_os_daemons:info([table]),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/172-os-daemon-errors.t
----------------------------------------------------------------------
diff --git a/test/etap/172-os-daemon-errors.t b/test/etap/172-os-daemon-errors.t
index bde5c6f..1b1fc30 100755
--- a/test/etap/172-os-daemon-errors.t
+++ b/test/etap/172-os-daemon-errors.t
@@ -55,7 +55,7 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link(config_files()),
+    application:start(config),
     couch_os_daemons:start_link(),
 
     etap:diag("Daemon not executable."),
@@ -73,14 +73,14 @@ test() ->
     ok.
 
 test_halts(Name, Cmd, Time) ->
-    couch_config:set("os_daemons", Name, Cmd ++ " 2> /dev/null", false),
+    config:set("os_daemons", Name, Cmd ++ " 2> /dev/null", false),
     timer:sleep(Time),
     {ok, [D]} = couch_os_daemons:info([table]),
     check_dead(D, Name, Cmd),
-    couch_config:delete("os_daemons", Name, false).
+    config:delete("os_daemons", Name, false).
 
 test_runs(Name, Cmd) ->
-    couch_config:set("os_daemons", Name, Cmd, false),
+    config:set("os_daemons", Name, Cmd, false),
 
     timer:sleep(1000),
     {ok, [D1]} = couch_os_daemons:info([table]),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/173-os-daemon-cfg-register.t
----------------------------------------------------------------------
diff --git a/test/etap/173-os-daemon-cfg-register.t b/test/etap/173-os-daemon-cfg-register.t
index 256ee7d..065e999 100755
--- a/test/etap/173-os-daemon-cfg-register.t
+++ b/test/etap/173-os-daemon-cfg-register.t
@@ -44,32 +44,32 @@ main(_) ->
     ok.
 
 test() ->
-    couch_config:start_link(test_util:config_files()),
+    application:start(config),
     couch_os_daemons:start_link(),
     
     DaemonCmd = daemon_cmd() ++ " 2> /dev/null",
     
     etap:diag("Booting the daemon"),
-    couch_config:set("os_daemons", daemon_name(), DaemonCmd, false),
+    config:set("os_daemons", daemon_name(), DaemonCmd, false),
     wait_for_start(10),
     {ok, [D1]} = couch_os_daemons:info([table]),
     check_daemon(D1, running),
     
     etap:diag("Daemon restarts when section changes."),
-    couch_config:set("s1", "k", "foo", false),
+    config:set("s1", "k", "foo", false),
     wait_for_restart(10),
     {ok, [D2]} = couch_os_daemons:info([table]),
     check_daemon(D2, running),
     etap:isnt(D2#daemon.kill, D1#daemon.kill, "Kill command shows restart."),
 
     etap:diag("Daemon doesn't restart for ignored section key."),
-    couch_config:set("s2", "k2", "baz", false),
+    config:set("s2", "k2", "baz", false),
     timer:sleep(1000), % Message travel time.
     {ok, [D3]} = couch_os_daemons:info([table]),
     etap:is(D3, D2, "Same daemon info after ignored config change."),
     
     etap:diag("Daemon restarts for specific section/key pairs."),
-    couch_config:set("s2", "k", "bingo", false),
+    config:set("s2", "k", "bingo", false),
     wait_for_restart(10),
     {ok, [D4]} = couch_os_daemons:info([table]),
     check_daemon(D4, running),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/180-http-proxy.t
----------------------------------------------------------------------
diff --git a/test/etap/180-http-proxy.t b/test/etap/180-http-proxy.t
index da67603..55f6aab 100755
--- a/test/etap/180-http-proxy.t
+++ b/test/etap/180-http-proxy.t
@@ -79,7 +79,7 @@ test() ->
         test_web:get_port(),
         "/\">>}"
     ]),
-    couch_config:set("httpd_global_handlers", "_test", Url, false),
+    config:set("httpd_global_handlers", "_test", Url, false),
 
     % let couch_httpd restart
     timer:sleep(100),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/200-view-group-no-db-leaks.t
----------------------------------------------------------------------
diff --git a/test/etap/200-view-group-no-db-leaks.t b/test/etap/200-view-group-no-db-leaks.t
index 350cc0b..f6ae3f0 100755
--- a/test/etap/200-view-group-no-db-leaks.t
+++ b/test/etap/200-view-group-no-db-leaks.t
@@ -65,7 +65,7 @@ main(_) ->
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
     timer:sleep(1000),
-    put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")),
+    put(addr, config:get("httpd", "bind_address", "127.0.0.1")),
     put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))),
 
     delete_db(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/201-view-group-shutdown.t
----------------------------------------------------------------------
diff --git a/test/etap/201-view-group-shutdown.t b/test/etap/201-view-group-shutdown.t
index fabedf2..fa77d89 100755
--- a/test/etap/201-view-group-shutdown.t
+++ b/test/etap/201-view-group-shutdown.t
@@ -65,8 +65,8 @@ main(_) ->
 
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
-    ok = couch_config:set("couchdb", "max_dbs_open", "3", false),
-    ok = couch_config:set("couchdb", "delayed_commits", "false", false),
+    ok = config:set("couchdb", "max_dbs_open", "3", false),
+    ok = config:set("couchdb", "delayed_commits", "false", false),
     crypto:start(),
 
     % Test that while a view group is being compacted its database can not

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/210-os-proc-pool.t
----------------------------------------------------------------------
diff --git a/test/etap/210-os-proc-pool.t b/test/etap/210-os-proc-pool.t
index d80707e..85fa9a6 100755
--- a/test/etap/210-os-proc-pool.t
+++ b/test/etap/210-os-proc-pool.t
@@ -28,7 +28,7 @@ main(_) ->
 
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
-    couch_config:set("query_server_config", "os_process_limit", "3", false),
+    config:set("query_server_config", "os_process_limit", "3", false),
 
     test_pool_full(),
     test_client_unexpected_exit(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/220-compaction-daemon.t
----------------------------------------------------------------------
diff --git a/test/etap/220-compaction-daemon.t b/test/etap/220-compaction-daemon.t
index 4c63b66..73bd5ac 100755
--- a/test/etap/220-compaction-daemon.t
+++ b/test/etap/220-compaction-daemon.t
@@ -38,7 +38,7 @@ main(_) ->
 test() ->
     couch_server_sup:start_link(test_util:config_files()),
     timer:sleep(1000),
-    put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")),
+    put(addr, config:get("httpd", "bind_address", "127.0.0.1")),
     put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))),
 
     disable_compact_daemon(),
@@ -54,9 +54,9 @@ test() ->
     {_, ViewFileSize} = get_view_frag(),
 
     % enable automatic compaction
-    ok = couch_config:set("compaction_daemon", "check_interval", "3", false),
-    ok = couch_config:set("compaction_daemon", "min_file_size", "100000", false),
-    ok = couch_config:set(
+    ok = config:set("compaction_daemon", "check_interval", "3", false),
+    ok = config:set("compaction_daemon", "min_file_size", "100000", false),
+    ok = config:set(
         "compactions",
         binary_to_list(test_db_name()),
         "[{db_fragmentation, \"70%\"}, {view_fragmentation, \"70%\"}]",
@@ -81,7 +81,7 @@ test() ->
     {_, ViewFileSize3} = get_view_frag(),
 
     % enable automatic compaction
-    ok = couch_config:set(
+    ok = config:set(
         "compactions",
         "_default",
         "[{db_fragmentation, \"70%\"}, {view_fragmentation, \"70%\"}]",
@@ -106,10 +106,10 @@ test() ->
     ok.
 
 disable_compact_daemon() ->
-    Configs = couch_config:get("compactions"),
+    Configs = config:get("compactions"),
     lists:foreach(
         fun({DbName, _}) ->
-            ok = couch_config:delete("compactions", DbName, false)
+            ok = config:delete("compactions", DbName, false)
         end,
         Configs).
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/test/etap/231-cors.t
----------------------------------------------------------------------
diff --git a/test/etap/231-cors.t b/test/etap/231-cors.t
index ad92ae9..cfc6a94 100644
--- a/test/etap/231-cors.t
+++ b/test/etap/231-cors.t
@@ -50,7 +50,7 @@ admin_user_ctx() -> {user_ctx, #user_ctx{roles=[<<"_admin">>]}}.
 
 set_admin_password(UserName, Password) ->
     Hashed = couch_passwords:hash_admin_password(Password),
-    couch_config:set("admins", UserName, Hashed, false).
+    config:set("admins", UserName, Hashed, false).
 
 cycle_db(DbName) ->
     couch_server:delete(list_to_binary(DbName), [admin_user_ctx()]),
@@ -76,8 +76,8 @@ test() ->
     test_no_headers_db(),
 
     % Now enable CORS
-    ok = couch_config:set("httpd", "enable_cors", "true", false),
-    ok = couch_config:set("cors", "origins", "http://example.com", false),
+    ok = config:set("httpd", "enable_cors", "true", false),
+    ok = config:set("cors", "origins", "http://example.com", false),
 
     %% do tests
     test_incorrect_origin_simple_request(),
@@ -91,16 +91,16 @@ test() ->
     test_preflight_with_port1(),
     test_preflight_with_scheme1(),
 
-    ok = couch_config:set("cors", "origins", "http://example.com:5984", false),
+    ok = config:set("cors", "origins", "http://example.com:5984", false),
     test_preflight_with_port2(),
 
-    ok = couch_config:set("cors", "origins", "https://example.com:5984", false),
+    ok = config:set("cors", "origins", "https://example.com:5984", false),
     test_preflight_with_scheme2(),
 
-    ok = couch_config:set("cors", "origins", "*", false),
+    ok = config:set("cors", "origins", "*", false),
     test_preflight_with_wildcard(),
 
-    ok = couch_config:set("cors", "origins", "http://example.com", false),
+    ok = config:set("cors", "origins", "http://example.com", false),
     test_case_sensitive_mismatch_of_allowed_origins(),
 
     % http://www.w3.org/TR/cors/#supports-credentials
@@ -116,14 +116,14 @@ test() ->
     % Note: The string "*" cannot be used for a resource
     % that supports credentials.
     test_db_request_credentials_header_off(),
-    ok = couch_config:set("cors", "credentials", "true", false),
+    ok = config:set("cors", "credentials", "true", false),
     test_db_request_credentials_header_on(),
     % We don’t test wildcards & credentials as that would
     % fall into the realm of validating config values
     % which we don’t do at all yet
 
     % test with vhosts
-    ok = couch_config:set("vhosts", "example.com", "/", false),
+    ok = config:set("vhosts", "example.com", "/", false),
     test_preflight_request(true),
     test_db_request(true),
     test_db_preflight_request(true),


[37/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Build chttpd_external.beam


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/c535deae
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/c535deae
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/c535deae

Branch: refs/heads/1843-feature-bigcouch
Commit: c535deae64020044477b4c2c20aec9d2affdee12
Parents: 409ffbc
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 18:02:41 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:55 2013 -0500

----------------------------------------------------------------------
 src/chttpd/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/c535deae/src/chttpd/Makefile.am
----------------------------------------------------------------------
diff --git a/src/chttpd/Makefile.am b/src/chttpd/Makefile.am
index 15ae77c..c785968 100644
--- a/src/chttpd/Makefile.am
+++ b/src/chttpd/Makefile.am
@@ -33,6 +33,7 @@ compiled_files = \
 	ebin/chttpd_app.beam \
 	ebin/chttpd_config_listener.beam \
 	ebin/chttpd_db.beam \
+	ebin/chttpd_external.beam \
 	ebin/chttpd_misc.beam \
 	ebin/chttpd_rewrite.beam \
 	ebin/chttpd_show.beam \
@@ -40,7 +41,6 @@ compiled_files = \
 
 # Conflicts in couch_db.hrl prevent us from building these
 # until after we merge the couch application
-#	ebin/chttpd_external.beam
 #	ebin/chttpd_view.beam
 
 


[05/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Disable validation for internal replication


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/4175d066
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/4175d066
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/4175d066

Branch: refs/heads/1843-feature-bigcouch
Commit: 4175d066a827a64df96d46a03976ba627146adc5
Parents: de41ca7
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Oct 25 00:41:17 2012 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:50 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db.erl | 8 ++++++++
 1 file changed, 8 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/4175d066/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 3707108..2253e62 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -512,6 +512,14 @@ validate_doc_update(#db{validate_doc_funs=[]}, _Doc, _GetDiskDocFun) ->
 validate_doc_update(_Db, #doc{id= <<"_local/",_/binary>>}, _GetDiskDocFun) ->
     ok;
 validate_doc_update(Db, Doc, GetDiskDocFun) ->
+    case get(io_priority) of
+        {internal_repl, _} ->
+            ok;
+        _ ->
+            validate_doc_update_int(Db, Doc, GetDiskDocFun)
+    end.
+
+validate_doc_update_int(Db, Doc, GetDiskDocFun) ->
     DiskDoc = GetDiskDocFun(),
     JsonCtx = couch_util:json_user_ctx(Db),
     SecObj = get_security(Db),


[40/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Update the module list


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/91b5d703
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/91b5d703
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/91b5d703

Branch: refs/heads/1843-feature-bigcouch
Commit: 91b5d7033f6c8472b6d44f5c7e3e34bf5212a45d
Parents: 004f086
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 14:11:19 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:56 2013 -0500

----------------------------------------------------------------------
 test/etap/001-load.t | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/91b5d703/test/etap/001-load.t
----------------------------------------------------------------------
diff --git a/test/etap/001-load.t b/test/etap/001-load.t
index a5fa27f..3645f53 100755
--- a/test/etap/001-load.t
+++ b/test/etap/001-load.t
@@ -18,38 +18,59 @@
 main(_) ->
     test_util:init_code_path(),
     Modules = [
+        couch,
+        couch_app,
         couch_auth_cache,
         couch_btree,
         couch_changes,
+        couch_compaction_daemon,
         couch_compress,
+        couch_config,
+        couch_config_writer,
         couch_db,
         couch_db_update_notifier,
         couch_db_update_notifier_sup,
         couch_db_updater,
         couch_doc,
+        couch_drv,
         % Fails unless couch_config gen_server is started.
         % couch_ejson_compare,
+        couch_emsort,
         couch_event_sup,
         couch_external_manager,
         couch_external_server,
         couch_file,
         couch_httpd,
+        couch_httpd_auth,
+        couch_httpd_cors,
         couch_httpd_db,
         couch_httpd_external,
         couch_httpd_misc_handlers,
+        couch_httpd_oauth,
+        couch_httpd_proxy,
         couch_httpd_rewrite,
         couch_httpd_stats_handlers,
+        couch_httpd_vhost,
         couch_key_tree,
         couch_log,
+        couch_lru,
+        couch_native_process,
+        couch_os_daemons,
         couch_os_process,
+        couch_passwords,
+        couch_primary_sup,
+        couch_proc_manager,
         couch_query_servers,
+        couch_secondary_sup,
         couch_server,
-        couch_server_sup,
         couch_stats_aggregator,
         couch_stats_collector,
         couch_stream,
+        couch_sup,
         couch_task_status,
+        couch_users_db,
         couch_util,
+        couch_uuids,
         couch_work_queue,
         json_stream_parse
     ],


[21/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Only use the ddoc cache for sharded dbs


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/72de049f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/72de049f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/72de049f

Branch: refs/heads/1843-feature-bigcouch
Commit: 72de049f6fa298e170c9aa09f90092a079043533
Parents: 403ff6b
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Jan 24 01:12:56 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:53 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db.erl | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/72de049f/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index f5953a1..5f91633 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -534,6 +534,7 @@ validate_doc_update_int(Db, Doc, GetDiskDocFun) ->
     end.
 
 
+% to be safe, spawn a middleman here
 load_validation_funs(#db{main_pid=Pid, name = <<"shards/", _/binary>>}=Db) ->
     {_, Ref} = spawn_monitor(fun() ->
         exit(ddoc_cache:open(mem3:dbname(Db#db.name), validation_funs))


[35/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
[goddamnraceconditions] Another delete after config change


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/66809de9
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/66809de9
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/66809de9

Branch: refs/heads/1843-feature-bigcouch
Commit: 66809de92e4414e64f9a8934bf8f60845a3ff079
Parents: c57ad19
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 03:19:00 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:55 2013 -0500

----------------------------------------------------------------------
 share/www/script/test/users_db_security.js | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/66809de9/share/www/script/test/users_db_security.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/users_db_security.js b/share/www/script/test/users_db_security.js
index d439fcb..1569271 100644
--- a/share/www/script/test/users_db_security.js
+++ b/share/www/script/test/users_db_security.js
@@ -79,7 +79,6 @@ couchTests.users_db_security = function(debug) {
 
   var testFun = function()
   {
-    usersDb.deleteDb();
 
     // _users db
     // a doc with a field 'password' should be hashed to 'derived_key'


[26/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Major change to use the new config app

This replaces couch_config with the config app. The config app is mostly
a direct port of couch_config to a new namespace with the addition of a
rewritten config change notification mechanism. The new change mechanism
removes the ability to register an anonymous function that breaks code
upgrades and generally cleans up the various listening patterns using a
new behavior definition.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/0861ab00
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/0861ab00
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/0861ab00

Branch: refs/heads/1843-feature-bigcouch
Commit: 0861ab00177223afdaeb10d329ab2daa79cb053e
Parents: 5df0942
Author: Robert Newson <rn...@apache.org>
Authored: Sat Mar 9 18:22:19 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:53 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch.app.tpl.in                  |  3 +-
 src/couch/src/couch.erl                         |  8 --
 src/couch/src/couch_auth_cache.erl              | 33 +++++---
 src/couch/src/couch_changes.erl                 |  2 +-
 src/couch/src/couch_compaction_daemon.erl       | 32 +++++---
 src/couch/src/couch_compress.erl                |  2 +-
 src/couch/src/couch_db.erl                      | 10 +--
 src/couch/src/couch_db_update_notifier_sup.erl  | 19 +++--
 src/couch/src/couch_db_updater.erl              | 12 +--
 src/couch/src/couch_drv.erl                     |  2 +-
 src/couch/src/couch_ejson_compare.erl           |  2 +-
 src/couch/src/couch_external_manager.erl        | 26 ++++--
 src/couch/src/couch_external_server.erl         | 22 ++++-
 src/couch/src/couch_httpd.erl                   | 85 +++++++-------------
 src/couch/src/couch_httpd_auth.erl              | 28 +++----
 src/couch/src/couch_httpd_cors.erl              |  6 +-
 src/couch/src/couch_httpd_db.erl                |  2 +-
 src/couch/src/couch_httpd_external.erl          |  2 +-
 src/couch/src/couch_httpd_misc_handlers.erl     | 18 ++---
 src/couch/src/couch_httpd_oauth.erl             | 10 +--
 src/couch/src/couch_httpd_rewrite.erl           |  4 +-
 src/couch/src/couch_httpd_vhost.erl             | 38 ++++++---
 src/couch/src/couch_log.erl                     | 51 +++++++-----
 src/couch/src/couch_os_daemons.erl              | 33 +++++---
 src/couch/src/couch_os_process.erl              |  4 +-
 src/couch/src/couch_passwords.erl               |  4 +-
 src/couch/src/couch_proc_manager.erl            |  6 +-
 src/couch/src/couch_secondary_sup.erl           |  2 +-
 src/couch/src/couch_server.erl                  | 56 +++++++++----
 src/couch/src/couch_server_sup.erl              | 53 +++++-------
 src/couch/src/couch_stats_aggregator.erl        | 27 +++++--
 src/couch/src/couch_users_db.erl                |  2 +-
 src/couch/src/couch_uuids.erl                   | 23 ++++--
 src/couch_index/src/couch_index.erl             | 26 ++++--
 src/couch_index/src/couch_index_server.erl      | 35 +++++---
 src/couch_index/src/couch_index_util.erl        |  4 +-
 src/couch_mrview/src/couch_mrview_compactor.erl |  2 +-
 src/couch_mrview/src/couch_mrview_updater.erl   |  4 +-
 src/couch_replicator/test/02-httpc-pool.t       |  4 +-
 .../test/03-replication-compact.t               |  2 +-
 .../test/04-replication-large-atts.t            |  4 +-
 .../test/05-replication-many-leaves.t           |  4 +-
 .../test/06-doc-missing-stubs.t                 |  2 +-
 test/etap/001-load.t                            |  2 -
 test/etap/002-icu-driver.t                      |  2 +-
 test/etap/030-doc-from-json.t                   |  4 +-
 test/etap/031-doc-to-json.t                     |  4 +-
 test/etap/041-uuid-gen-id.ini                   | 20 -----
 test/etap/041-uuid-gen-seq.ini                  | 19 -----
 test/etap/041-uuid-gen-utc.ini                  | 19 -----
 test/etap/041-uuid-gen.t                        | 49 ++++-------
 test/etap/072-cleanup.t                         |  4 +-
 test/etap/074-doc-update-conflicts.t            |  2 +-
 test/etap/075-auth-cache.t                      | 10 +--
 test/etap/076-file-compression.t                | 12 +--
 test/etap/080-config-get-set.t                  | 37 +++++----
 test/etap/081-config-override.t                 | 38 ++++-----
 test/etap/082-config-register.t                 | 24 +++---
 test/etap/083-config-no-files.t                 | 12 +--
 test/etap/121-stats-aggregates.t                |  2 +-
 test/etap/130-attachments-md5.t                 |  2 +-
 test/etap/140-attachment-comp.t                 |  6 +-
 test/etap/150-invalid-view-seq.t                |  2 +-
 test/etap/160-vhosts.t                          | 40 ++++-----
 test/etap/170-os-daemons.t                      | 12 +--
 test/etap/171-os-daemons-config.es              |  2 +-
 test/etap/171-os-daemons-config.t               |  6 +-
 test/etap/172-os-daemon-errors.t                |  8 +-
 test/etap/173-os-daemon-cfg-register.t          | 10 +--
 test/etap/180-http-proxy.t                      |  2 +-
 test/etap/200-view-group-no-db-leaks.t          |  2 +-
 test/etap/201-view-group-shutdown.t             |  4 +-
 test/etap/210-os-proc-pool.t                    |  2 +-
 test/etap/220-compaction-daemon.t               | 14 ++--
 test/etap/231-cors.t                            | 18 ++---
 75 files changed, 574 insertions(+), 530 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch.app.tpl.in
----------------------------------------------------------------------
diff --git a/src/couch/src/couch.app.tpl.in b/src/couch/src/couch.app.tpl.in
index f83b6f6..1cd0154 100644
--- a/src/couch/src/couch.app.tpl.in
+++ b/src/couch/src/couch.app.tpl.in
@@ -3,7 +3,6 @@
     {vsn, "@version@"},
     {modules, [@modules@]},
     {registered, [
-        couch_config,
         couch_db_update,
         couch_db_update_notifier_sup,
         couch_external_manager,
@@ -22,6 +21,6 @@
         "%localconfdir%/@defaultini@",
         "%localconfdir%/@localini@"
     ]}},
-    {applications, [kernel, stdlib, twig]},
+    {applications, [kernel, stdlib, twig, config]},
     {included_applications, [crypto, sasl, inets, oauth, ibrowse, mochiweb, os_mon]}
 ]}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch.erl b/src/couch/src/couch.erl
index c18df0b..7d53d0c 100644
--- a/src/couch/src/couch.erl
+++ b/src/couch/src/couch.erl
@@ -29,11 +29,3 @@ restart() ->
     {error, Reason} ->
         {error, Reason}
     end.
-
-reload() ->
-    case supervisor:terminate_child(couch_server_sup, couch_config) of
-    ok ->
-        supervisor:restart_child(couch_server_sup, couch_config);
-    {error, Reason} ->
-        {error, Reason}
-    end.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_auth_cache.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_auth_cache.erl b/src/couch/src/couch_auth_cache.erl
index 5f4c8f9..1650495 100644
--- a/src/couch/src/couch_auth_cache.erl
+++ b/src/couch/src/couch_auth_cache.erl
@@ -12,6 +12,7 @@
 
 -module(couch_auth_cache).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
 % public API
 -export([get_user_creds/1]).
@@ -20,6 +21,8 @@
 -export([start_link/0, init/1, handle_call/3, handle_info/2, handle_cast/2]).
 -export([code_change/3, terminate/2]).
 
+-export([handle_config_change/5]).
+
 -include_lib("couch/include/couch_db.hrl").
 -include("couch_js_functions.hrl").
 
@@ -42,7 +45,7 @@ get_user_creds(UserName) when is_list(UserName) ->
     get_user_creds(?l2b(UserName));
 
 get_user_creds(UserName) ->
-    UserCreds = case couch_config:get("admins", ?b2l(UserName)) of
+    UserCreds = case config:get("admins", ?b2l(UserName)) of
     "-hashed-" ++ HashedPwdAndSalt ->
         % the name is an admin, now check to see if there is a user doc
         % which has a matching name, salt, and password_sha
@@ -120,19 +123,12 @@ init(_) ->
     ?BY_USER = ets:new(?BY_USER, [set, protected, named_table]),
     ?BY_ATIME = ets:new(?BY_ATIME, [ordered_set, private, named_table]),
     process_flag(trap_exit, true),
-    ok = couch_config:register(
-        fun("couch_httpd_auth", "auth_cache_size", SizeList) ->
-            Size = list_to_integer(SizeList),
-            ok = gen_server:call(?MODULE, {new_max_cache_size, Size}, infinity);
-        ("couch_httpd_auth", "authentication_db", _DbName) ->
-            ok = gen_server:call(?MODULE, reinit_cache, infinity)
-        end
-    ),
+    ok = config:listen_for_changes(?MODULE, nil),
     {ok, Notifier} = couch_db_update_notifier:start_link(fun handle_db_event/1),
     State = #state{
         db_notifier = Notifier,
         max_cache_size = list_to_integer(
-            couch_config:get("couch_httpd_auth", "auth_cache_size", "50")
+            config:get("couch_httpd_auth", "auth_cache_size", "50")
         )
     },
     {ok, reinit_cache(State)}.
@@ -201,6 +197,12 @@ handle_cast({cache_hit, UserName}, State) ->
     {noreply, State}.
 
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info({'DOWN', Ref, _, _, _Reason}, #state{db_mon_ref = Ref} = State) ->
     {noreply, reinit_cache(State)}.
 
@@ -217,6 +219,15 @@ code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
 
+handle_config_change("couch_httpd_auth", "auth_cache_size", SizeList, _, _) ->
+    Size = list_to_integer(SizeList),
+    {ok, gen_server:call(?MODULE, {new_max_cache_size, Size}, infinity)};
+handle_config_change("couch_httpd_auth", "authentication_db", _DbName, _, _) ->
+    {ok, gen_server:call(?MODULE, reinit_cache, infinity)};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
+
 clear_cache(State) ->
     exec_if_auth_db(fun(AuthDb) -> catch couch_db:close(AuthDb) end),
     true = ets:delete_all_objects(?BY_USER),
@@ -226,7 +237,7 @@ clear_cache(State) ->
 
 reinit_cache(State) ->
     NewState = clear_cache(State),
-    AuthDbName = ?l2b(couch_config:get("couch_httpd_auth", "authentication_db")),
+    AuthDbName = ?l2b(config:get("couch_httpd_auth", "authentication_db")),
     true = ets:insert(?STATE, {auth_db_name, AuthDbName}),
     AuthDb = open_auth_db(),
     true = ets:insert(?STATE, {auth_db, AuthDb}),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_changes.erl b/src/couch/src/couch_changes.erl
index cbca9cb..d36b45f 100644
--- a/src/couch/src/couch_changes.erl
+++ b/src/couch/src/couch_changes.erl
@@ -258,7 +258,7 @@ get_changes_timeout(Args, Callback) ->
         feed = ResponseType
     } = Args,
     DefaultTimeout = list_to_integer(
-        couch_config:get("httpd", "changes_timeout", "60000")
+        config:get("httpd", "changes_timeout", "60000")
     ),
     case Heartbeat of
     undefined ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_compaction_daemon.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_compaction_daemon.erl b/src/couch/src/couch_compaction_daemon.erl
index b9bf969..3251d5f 100644
--- a/src/couch/src/couch_compaction_daemon.erl
+++ b/src/couch/src/couch_compaction_daemon.erl
@@ -12,14 +12,18 @@
 
 -module(couch_compaction_daemon).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
 % public API
--export([start_link/0, config_change/3]).
+-export([start_link/0]).
 
 % gen_server callbacks
 -export([init/1, handle_call/3, handle_info/2, handle_cast/2]).
 -export([code_change/3, terminate/2]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 -include_lib("couch/include/couch_db.hrl").
 
 -define(CONFIG_ETS, couch_compaction_daemon_config).
@@ -49,17 +53,13 @@ start_link() ->
 init(_) ->
     process_flag(trap_exit, true),
     ?CONFIG_ETS = ets:new(?CONFIG_ETS, [named_table, set, protected]),
-    ok = couch_config:register(fun ?MODULE:config_change/3),
+    ok = config:listen_for_changes(?MODULE, nil),
     load_config(),
     Server = self(),
     Loop = spawn_link(fun() -> compact_loop(Server) end),
     {ok, #state{loop_pid = Loop}}.
 
 
-config_change("compactions", DbName, NewValue) ->
-    ok = gen_server:cast(?MODULE, {config_update, DbName, NewValue}).
-
-
 handle_cast({config_update, DbName, deleted}, State) ->
     true = ets:delete(?CONFIG_ETS, ?l2b(DbName)),
     {noreply, State};
@@ -85,6 +85,12 @@ handle_call(Msg, _From, State) ->
     {stop, {unexpected_call, Msg}, State}.
 
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info({'EXIT', Pid, Reason}, #state{loop_pid = Pid} = State) ->
     {stop, {compaction_loop_died, Reason}, State}.
 
@@ -97,6 +103,12 @@ code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
 
+handle_config_change("compactions", DbName, Value, _, _) ->
+    {ok, gen_server:cast(?MODULE, {config_update, DbName, Value})};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
+
 compact_loop(Parent) ->
     {ok, _} = couch_server:all_databases(
         fun(DbName, Acc) ->
@@ -123,7 +135,7 @@ compact_loop(Parent) ->
         receive {Parent, have_config} -> ok end;
     false ->
         PausePeriod = list_to_integer(
-            couch_config:get("compaction_daemon", "check_interval", "300")),
+            config:get("compaction_daemon", "check_interval", "300")),
         ok = timer:sleep(PausePeriod * 1000)
     end,
     compact_loop(Parent).
@@ -295,7 +307,7 @@ can_db_compact(#config{db_frag = Threshold} = Config, Db) ->
         false ->
             false;
         true ->
-            Free = free_space(couch_config:get("couchdb", "database_dir")),
+            Free = free_space(config:get("couchdb", "database_dir")),
             case Free >= SpaceRequired of
             true ->
                 true;
@@ -364,7 +376,7 @@ check_frag(Threshold, Frag) ->
 frag(Props) ->
     FileSize = couch_util:get_value(disk_size, Props),
     MinFileSize = list_to_integer(
-        couch_config:get("compaction_daemon", "min_file_size", "131072")),
+        config:get("compaction_daemon", "min_file_size", "131072")),
     case FileSize < MinFileSize of
     true ->
         {0, FileSize};
@@ -396,7 +408,7 @@ load_config() ->
                 ok
             end
         end,
-        couch_config:get("compactions")).
+        config:get("compactions")).
 
 parse_config(DbName, ConfigString) ->
     case (catch do_parse_config(ConfigString)) of

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_compress.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_compress.erl b/src/couch/src/couch_compress.erl
index 0b9334a..6b47a7a 100644
--- a/src/couch/src/couch_compress.erl
+++ b/src/couch/src/couch_compress.erl
@@ -26,7 +26,7 @@
 
 
 get_compression_method() ->
-    case couch_config:get("couchdb", "file_compression") of
+    case config:get("couchdb", "file_compression") of
     undefined ->
         ?DEFAULT_COMPRESSION;
     Method1 ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 5f91633..56cb0d2 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -893,7 +893,7 @@ make_first_doc_on_disk(Db, Id, Pos, [{_Rev, RevValue} |_]=DocPath) ->
 set_commit_option(Options) ->
     CommitSettings = {
         [true || O <- Options, O==full_commit orelse O==delay_commit],
-        couch_config:get("couchdb", "delayed_commits", "false")
+        config:get("couchdb", "delayed_commits", "false")
     },
     case CommitSettings of
     {[true], _} ->
@@ -1016,7 +1016,7 @@ flush_att(Fd, #att{data=Data}=Att) when is_binary(Data) ->
 
 flush_att(Fd, #att{data=Fun,att_len=undefined}=Att) when is_function(Fun) ->
     MaxChunkSize = list_to_integer(
-        couch_config:get("couchdb", "attachment_stream_buffer_size", "4096")),
+        config:get("couchdb", "attachment_stream_buffer_size", "4096")),
     with_stream(Fd, Att, fun(OutputStream) ->
         % Fun(MaxChunkSize, WriterFun) must call WriterFun
         % once for each chunk of the attachment,
@@ -1067,7 +1067,7 @@ compressible_att_type(MimeType) when is_binary(MimeType) ->
     compressible_att_type(?b2l(MimeType));
 compressible_att_type(MimeType) ->
     TypeExpList = re:split(
-        couch_config:get("attachments", "compressible_types", ""),
+        config:get("attachments", "compressible_types", ""),
         "\\s*,\\s*",
         [{return, list}]
     ),
@@ -1092,12 +1092,12 @@ compressible_att_type(MimeType) ->
 % pretend that no Content-MD5 exists.
 with_stream(Fd, #att{md5=InMd5,type=Type,encoding=Enc}=Att, Fun) ->
     BufferSize = list_to_integer(
-        couch_config:get("couchdb", "attachment_stream_buffer_size", "4096")),
+        config:get("couchdb", "attachment_stream_buffer_size", "4096")),
     {ok, OutputStream} = case (Enc =:= identity) andalso
         compressible_att_type(Type) of
     true ->
         CompLevel = list_to_integer(
-            couch_config:get("attachments", "compression_level", "0")
+            config:get("attachments", "compression_level", "0")
         ),
         couch_stream:open(Fd, [{buffer_size, BufferSize},
             {encoding, gzip}, {compression_level, CompLevel}]);

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_db_update_notifier_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db_update_notifier_sup.erl b/src/couch/src/couch_db_update_notifier_sup.erl
index e7cc16c..9eb943a 100644
--- a/src/couch/src/couch_db_update_notifier_sup.erl
+++ b/src/couch/src/couch_db_update_notifier_sup.erl
@@ -21,17 +21,22 @@
 -module(couch_db_update_notifier_sup).
 
 -behaviour(supervisor).
+-behaviour(config_listener).
+
+-export([start_link/0, init/1]).
+
+% config_listener api
+-export([handle_config_change/5]).
 
--export([start_link/0, init/1, config_change/3]).
 
 start_link() ->
     supervisor:start_link({local, couch_db_update_notifier_sup},
         couch_db_update_notifier_sup, []).
 
 init([]) ->
-    ok = couch_config:register(fun ?MODULE:config_change/3),
+    ok = config:listen_for_changes(?MODULE, nil),
 
-    UpdateNotifierExes = couch_config:get("update_notification"),
+    UpdateNotifierExes = config:get("update_notification"),
 
     {ok,
         {{one_for_one, 10, 3600},
@@ -46,7 +51,7 @@ init([]) ->
 
 %% @doc when update_notification configuration changes, terminate the process
 %%      for that notifier and start a new one with the updated config
-config_change("update_notification", Id, Exe) ->
+handle_config_change("update_notification", Id, Exe, _, _) ->
     ChildSpec = {
         Id,
         {couch_db_update_notifier, start_link, [Exe]},
@@ -57,5 +62,7 @@ config_change("update_notification", Id, Exe) ->
     },
     supervisor:terminate_child(couch_db_update_notifier_sup, Id),
     supervisor:delete_child(couch_db_update_notifier_sup, Id),
-    supervisor:start_child(couch_db_update_notifier_sup, ChildSpec).
-
+    supervisor:start_child(couch_db_update_notifier_sup, ChildSpec),
+    {ok, nil};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl
index e1dc7c3..c64911e 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -40,7 +40,7 @@ init({DbName, Filepath, Fd, Options}) ->
         Header =  #db_header{},
         ok = couch_file:write_header(Fd, Header),
         % delete any old compaction files that might be hanging around
-        RootDir = couch_config:get("couchdb", "database_dir", "."),
+        RootDir = config:get("couchdb", "database_dir", "."),
         couch_file:delete(RootDir, Filepath ++ ".compact"),
         couch_file:delete(RootDir, Filepath ++ ".compact.data"),
         couch_file:delete(RootDir, Filepath ++ ".compact.meta");
@@ -92,7 +92,7 @@ handle_call(cancel_compact, _From, #db{compactor_pid = nil} = Db) ->
 handle_call(cancel_compact, _From, #db{compactor_pid = Pid} = Db) ->
     unlink(Pid),
     exit(Pid, kill),
-    RootDir = couch_config:get("couchdb", "database_dir", "."),
+    RootDir = config:get("couchdb", "database_dir", "."),
     ok = couch_file:delete(RootDir, Db#db.filepath ++ ".compact"),
     Db2 = Db#db{compactor_pid = nil},
     ok = gen_server:call(couch_server, {db_updated, Db2}, infinity),
@@ -228,7 +228,7 @@ handle_cast({compact_done, CompactFilepath}, #db{filepath=Filepath}=Db) ->
         ?LOG_DEBUG("CouchDB swapping files ~s and ~s.",
                 [Filepath, CompactFilepath]),
         ok = file:rename(CompactFilepath, Filepath ++ ".compact"),
-        RootDir = couch_config:get("couchdb", "database_dir", "."),
+        RootDir = config:get("couchdb", "database_dir", "."),
         couch_file:delete(RootDir, Filepath),
         ok = file:rename(Filepath ++ ".compact", Filepath),
         % Delete the old meta compaction file after promoting
@@ -461,7 +461,7 @@ init_db(DbName, Filepath, Fd, Header0, Options) ->
     end,
 
     {ok, FsyncOptions} = couch_util:parse_term(
-            couch_config:get("couchdb", "fsync_options",
+            config:get("couchdb", "fsync_options",
                     "[before_header, after_header, on_file_open]")),
 
     case lists:member(on_file_open, FsyncOptions) of
@@ -946,9 +946,9 @@ copy_compact(Db, NewDb0, Retry) ->
     NewDb = NewDb0#db{compression=Compression},
     TotalChanges = couch_db:count_changes_since(Db, NewDb#db.update_seq),
     BufferSize = list_to_integer(
-        couch_config:get("database_compaction", "doc_buffer_size", "524288")),
+        config:get("database_compaction", "doc_buffer_size", "524288")),
     CheckpointAfter = couch_util:to_integer(
-        couch_config:get("database_compaction", "checkpoint_after",
+        config:get("database_compaction", "checkpoint_after",
             BufferSize * 10)),
 
     EnumBySeqFun =

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_drv.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_drv.erl b/src/couch/src/couch_drv.erl
index de4d76e..7fe119a 100644
--- a/src/couch/src/couch_drv.erl
+++ b/src/couch/src/couch_drv.erl
@@ -54,7 +54,7 @@ code_change(_OldVsn, State, _Extra) ->
 
 % private API
 util_driver_dir() ->
-    case couch_config:get("couchdb", "util_driver_dir", null) of
+    case config:get("couchdb", "util_driver_dir", null) of
     null ->
         couch_util:priv_dir();
     LibDir0 ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_ejson_compare.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_ejson_compare.erl b/src/couch/src/couch_ejson_compare.erl
index 083ff42..7b000fc 100644
--- a/src/couch/src/couch_ejson_compare.erl
+++ b/src/couch/src/couch_ejson_compare.erl
@@ -18,7 +18,7 @@
 
 
 init() ->
-    LibDir = case couch_config:get("couchdb", "util_driver_dir") of
+    LibDir = case config:get("couchdb", "util_driver_dir") of
     undefined ->
         filename:join(couch_util:priv_dir(), "lib");
     LibDir0 ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_external_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_external_manager.erl b/src/couch/src/couch_external_manager.erl
index dec2880..a8cad63 100644
--- a/src/couch/src/couch_external_manager.erl
+++ b/src/couch/src/couch_external_manager.erl
@@ -12,10 +12,14 @@
 
 -module(couch_external_manager).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
--export([start_link/0, execute/2, config_change/2]).
+-export([start_link/0, execute/2]).
 -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 -include_lib("couch/include/couch_db.hrl").
 
 start_link() ->
@@ -31,15 +35,17 @@ execute(UrlName, JsonReq) ->
         couch_external_server:execute(Pid, JsonReq)
     end.
 
-config_change("external", UrlName) ->
-    gen_server:call(couch_external_manager, {config, UrlName}).
+handle_config_change("external", UrlName, _, _, _) ->
+    {ok, gen_server:call(couch_external_manager, {config, UrlName})};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
 
 % gen_server API
 
 init([]) ->
     process_flag(trap_exit, true),
     Handlers = ets:new(couch_external_manager_handlers, [set, private]),
-    couch_config:register(fun ?MODULE:config_change/2),
+    ok = config:listen_for_changes(?MODULE, nil),
     {ok, Handlers}.
 
 terminate(_Reason, Handlers) ->
@@ -52,7 +58,7 @@ terminate(_Reason, Handlers) ->
 handle_call({get, UrlName}, _From, Handlers) ->
     case ets:lookup(Handlers, UrlName) of
     [] ->
-        case couch_config:get("external", UrlName, nil) of
+        case config:get("external", UrlName, nil) of
         nil ->
             Msg = lists:flatten(
                 io_lib:format("No server configured for ~p.", [UrlName])),
@@ -94,7 +100,15 @@ handle_info({'EXIT', Pid, Reason}, Handlers) ->
     % Remove Pid from the handlers table so we don't try closing
     % it a second time in terminate/2.
     ets:match_delete(Handlers, {'_', Pid}),
-    {stop, normal, Handlers}.
+    {stop, normal, Handlers};
+
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State}.
 
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_external_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_external_server.erl b/src/couch/src/couch_external_server.erl
index a3924d0..56406bb 100644
--- a/src/couch/src/couch_external_server.erl
+++ b/src/couch/src/couch_external_server.erl
@@ -12,10 +12,14 @@
 
 -module(couch_external_server).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
 -export([start_link/2, stop/1, execute/2]).
 -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2, code_change/3]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 -include_lib("couch/include/couch_db.hrl").
 
 % External API
@@ -36,12 +40,10 @@ init([Name, Command]) ->
     ?LOG_INFO("EXTERNAL: Starting process for: ~s", [Name]),
     ?LOG_INFO("COMMAND: ~s", [Command]),
     process_flag(trap_exit, true),
-    Timeout = list_to_integer(couch_config:get("couchdb", "os_process_timeout",
+    Timeout = list_to_integer(config:get("couchdb", "os_process_timeout",
         "5000")),
     {ok, Pid} = couch_os_process:start_link(Command, [{timeout, Timeout}]),
-    couch_config:register(fun("couchdb", "os_process_timeout", NewTimeout) ->
-        couch_os_process:set_timeout(Pid, list_to_integer(NewTimeout))
-    end),
+    ok = config:listen_for_changes(?MODULE, {Name, Command, Pid}, Pid),
     {ok, {Name, Command, Pid}}.
 
 terminate(_Reason, {_Name, _Command, Pid}) ->
@@ -51,6 +53,12 @@ terminate(_Reason, {_Name, _Command, Pid}) ->
 handle_call({execute, JsonReq}, _From, {Name, Command, Pid}) ->
     {reply, couch_os_process:prompt(Pid, JsonReq), {Name, Command, Pid}}.
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, State),
+    {noreply, State};
 handle_info({'EXIT', _Pid, normal}, State) ->
     {noreply, State};
 handle_info({'EXIT', Pid, Reason}, {Name, Command, Pid}) ->
@@ -68,3 +76,9 @@ code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
 
+handle_config_change("couchdb", "os_process_timeout", NewTimeout, _, Pid) ->
+    couch_os_process:set_timeout(Pid, list_to_integer(NewTimeout)),
+    {ok, Pid};
+handle_config_change(_, _, _, _, Pid) ->
+    {ok, Pid}.
+

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd.erl b/src/couch/src/couch_httpd.erl
index 53ae47e..db90129 100644
--- a/src/couch/src/couch_httpd.erl
+++ b/src/couch/src/couch_httpd.erl
@@ -13,8 +13,7 @@
 -module(couch_httpd).
 -include_lib("couch/include/couch_db.hrl").
 
--export([start_link/0, start_link/1, stop/0, config_change/2,
-        handle_request/5]).
+-export([start_link/0, start_link/1, stop/0, handle_request/5]).
 
 -export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,qs_json_value/3]).
 -export([path/1,absolute_uri/2,body_length/1]).
@@ -35,28 +34,28 @@
 start_link() ->
     start_link(http).
 start_link(http) ->
-    Port = couch_config:get("httpd", "port", "5984"),
+    Port = config:get("httpd", "port", "5984"),
     start_link(?MODULE, [{port, Port}]);
 start_link(https) ->
-    Port = couch_config:get("ssl", "port", "6984"),
-    CertFile = couch_config:get("ssl", "cert_file", nil),
-    KeyFile = couch_config:get("ssl", "key_file", nil),
+    Port = config:get("ssl", "port", "6984"),
+    CertFile = config:get("ssl", "cert_file", nil),
+    KeyFile = config:get("ssl", "key_file", nil),
     Options = case CertFile /= nil andalso KeyFile /= nil of
         true ->
             SslOpts = [{certfile, CertFile}, {keyfile, KeyFile}],
 
             %% set password if one is needed for the cert
-            SslOpts1 = case couch_config:get("ssl", "password", nil) of
+            SslOpts1 = case config:get("ssl", "password", nil) of
                 nil -> SslOpts;
                 Password ->
                     SslOpts ++ [{password, Password}]
             end,
             % do we verify certificates ?
-            FinalSslOpts = case couch_config:get("ssl",
+            FinalSslOpts = case config:get("ssl",
                     "verify_ssl_certificates", "false") of
                 "false" -> SslOpts1;
                 "true" ->
-                    case couch_config:get("ssl",
+                    case config:get("ssl",
                             "cacert_file", nil) of
                         nil ->
                             io:format("Verify SSL certificate "
@@ -65,7 +64,7 @@ start_link(https) ->
                                 ++"missing", []),
                             throw({error, missing_cacerts});
                         CaCertFile ->
-                            Depth = list_to_integer(couch_config:get("ssl",
+                            Depth = list_to_integer(config:get("ssl",
                                     "ssl_certificate_max_depth",
                                     "1")),
                             FinalOpts = [
@@ -73,7 +72,7 @@ start_link(https) ->
                                 {depth, Depth},
                                 {verify, verify_peer}],
                             % allows custom verify fun.
-                            case couch_config:get("ssl",
+                            case config:get("ssl",
                                     "verify_fun", nil) of
                                 nil -> FinalOpts;
                                 SpecStr ->
@@ -92,40 +91,35 @@ start_link(https) ->
     end,
     start_link(https, Options).
 start_link(Name, Options) ->
-    % read config and register for configuration changes
-
-    % 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),
+    BindAddress = config:get("httpd", "bind_address", any),
     validate_bind_address(BindAddress),
     DefaultSpec = "{couch_httpd_db, handle_request}",
     DefaultFun = make_arity_1_fun(
-        couch_config:get("httpd", "default_handler", DefaultSpec)
+        config:get("httpd", "default_handler", DefaultSpec)
     ),
 
     UrlHandlersList = lists:map(
         fun({UrlKey, SpecStr}) ->
             {?l2b(UrlKey), make_arity_1_fun(SpecStr)}
-        end, couch_config:get("httpd_global_handlers")),
+        end, config:get("httpd_global_handlers")),
 
     DbUrlHandlersList = lists:map(
         fun({UrlKey, SpecStr}) ->
             {?l2b(UrlKey), make_arity_2_fun(SpecStr)}
-        end, couch_config:get("httpd_db_handlers")),
+        end, config:get("httpd_db_handlers")),
 
     DesignUrlHandlersList = lists:map(
         fun({UrlKey, SpecStr}) ->
             {?l2b(UrlKey), make_arity_3_fun(SpecStr)}
-        end, couch_config:get("httpd_design_handlers")),
+        end, config:get("httpd_design_handlers")),
 
     UrlHandlers = dict:from_list(UrlHandlersList),
     DbUrlHandlers = dict:from_list(DbUrlHandlersList),
     DesignUrlHandlers = dict:from_list(DesignUrlHandlersList),
     {ok, ServerOptions} = couch_util:parse_term(
-        couch_config:get("httpd", "server_options", "[]")),
+        config:get("httpd", "server_options", "[]")),
     {ok, SocketOptions} = couch_util:parse_term(
-        couch_config:get("httpd", "socket_options", "[]")),
+        config:get("httpd", "socket_options", "[]")),
 
     set_auth_handlers(),
 
@@ -152,44 +146,23 @@ start_link(Name, Options) ->
             {ip, BindAddress}]]),
 
     % launch mochiweb
-    {ok, Pid} = case mochiweb_http:start(FinalOptions) of
+    case mochiweb_http:start(FinalOptions) of
         {ok, MochiPid} ->
             {ok, MochiPid};
         {error, Reason} ->
             io:format("Failure to start Mochiweb: ~s~n",[Reason]),
             throw({error, Reason})
-    end,
-
-    ok = couch_config:register(fun ?MODULE:config_change/2, Pid),
-    {ok, Pid}.
+    end.
 
 
 stop() ->
     mochiweb_http:stop(couch_httpd),
     mochiweb_http:stop(https).
 
-config_change("httpd", "bind_address") ->
-    ?MODULE:stop();
-config_change("httpd", "port") ->
-    ?MODULE:stop();
-config_change("httpd", "default_handler") ->
-    ?MODULE:stop();
-config_change("httpd", "server_options") ->
-    ?MODULE:stop();
-config_change("httpd", "socket_options") ->
-    ?MODULE:stop();
-config_change("httpd", "authentication_handlers") ->
-    set_auth_handlers();
-config_change("httpd_global_handlers", _) ->
-    ?MODULE:stop();
-config_change("httpd_db_handlers", _) ->
-    ?MODULE:stop();
-config_change("ssl", _) ->
-    ?MODULE:stop().
 
 set_auth_handlers() ->
     AuthenticationSrcs = make_fun_spec_strs(
-        couch_config:get("httpd", "authentication_handlers", "")),
+        config:get("httpd", "authentication_handlers", "")),
     AuthHandlers = lists:map(
         fun(A) -> {make_arity_1_fun(A), ?l2b(A)} end, AuthenticationSrcs),
     ok = application:set_env(couch, auth_handlers, AuthHandlers).
@@ -387,7 +360,7 @@ handle_request_int(MochiReq, DefaultFun,
 authenticate_request(#httpd{user_ctx=#user_ctx{}} = Req, _AuthHandlers) ->
     Req;
 authenticate_request(#httpd{} = Req, []) ->
-    case couch_config:get("couch_httpd_auth", "require_valid_user", "false") of
+    case config:get("couch_httpd_auth", "require_valid_user", "false") of
     "true" ->
         throw({unauthorized, <<"Authentication required.">>});
     "false" ->
@@ -493,7 +466,7 @@ path(#httpd{mochi_req=MochiReq}) ->
     MochiReq:get(path).
 
 host_for_request(#httpd{mochi_req=MochiReq}) ->
-    XHost = couch_config:get("httpd", "x_forwarded_host", "X-Forwarded-Host"),
+    XHost = config:get("httpd", "x_forwarded_host", "X-Forwarded-Host"),
     case MochiReq:get_header_value(XHost) of
         undefined ->
             case MochiReq:get_header_value("Host") of
@@ -511,11 +484,11 @@ host_for_request(#httpd{mochi_req=MochiReq}) ->
 
 absolute_uri(#httpd{mochi_req=MochiReq}=Req, Path) ->
     Host = host_for_request(Req),
-    XSsl = couch_config:get("httpd", "x_forwarded_ssl", "X-Forwarded-Ssl"),
+    XSsl = config:get("httpd", "x_forwarded_ssl", "X-Forwarded-Ssl"),
     Scheme = case MochiReq:get_header_value(XSsl) of
                  "on" -> "https";
                  _ ->
-                     XProto = couch_config:get("httpd", "x_forwarded_proto", "X-Forwarded-Proto"),
+                     XProto = config:get("httpd", "x_forwarded_proto", "X-Forwarded-Proto"),
                      case MochiReq:get_header_value(XProto) of
                          %% Restrict to "https" and "http" schemes only
                          "https" -> "https";
@@ -550,7 +523,7 @@ body_length(#httpd{mochi_req=MochiReq}) ->
 
 body(#httpd{mochi_req=MochiReq, req_body=undefined}) ->
     MaxSize = list_to_integer(
-        couch_config:get("couchdb", "max_document_size", "4294967296")),
+        config:get("couchdb", "max_document_size", "4294967296")),
     MochiReq:recv_body(MaxSize);
 body(#httpd{req_body=ReqBody}) ->
     ReqBody.
@@ -753,7 +726,7 @@ initialize_jsonp(Req) ->
         CallBack ->
             try
                 % make sure jsonp is configured on (default off)
-                case couch_config:get("httpd", "allow_jsonp", "false") of
+                case config:get("httpd", "allow_jsonp", "false") of
                 "true" ->
                     validate_callback(CallBack);
                 _Else ->
@@ -848,16 +821,16 @@ error_headers(#httpd{mochi_req=MochiReq}=Req, Code, ErrorStr, ReasonStr) ->
         % this is where the basic auth popup is triggered
         case MochiReq:get_header_value("X-CouchDB-WWW-Authenticate") of
         undefined ->
-            case couch_config:get("httpd", "WWW-Authenticate", nil) of
+            case config:get("httpd", "WWW-Authenticate", nil) of
             nil ->
                 % If the client is a browser and the basic auth popup isn't turned on
                 % redirect to the session page.
                 case ErrorStr of
                 <<"unauthorized">> ->
-                    case couch_config:get("couch_httpd_auth", "authentication_redirect", nil) of
+                    case config:get("couch_httpd_auth", "authentication_redirect", nil) of
                     nil -> {Code, []};
                     AuthRedirect ->
-                        case couch_config:get("couch_httpd_auth", "require_valid_user", "false") of
+                        case config:get("couch_httpd_auth", "require_valid_user", "false") of
                         "true" ->
                             % send the browser popup header no matter what if we are require_valid_user
                             {Code, [{"WWW-Authenticate", "Basic realm=\"server\""}]};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd_auth.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_auth.erl b/src/couch/src/couch_httpd_auth.erl
index 785dd79..a747869 100644
--- a/src/couch/src/couch_httpd_auth.erl
+++ b/src/couch/src/couch_httpd_auth.erl
@@ -83,7 +83,7 @@ default_authentication_handler(Req) ->
         true ->
             Req;
         false ->
-            case couch_config:get("couch_httpd_auth", "require_valid_user", "false") of
+            case config:get("couch_httpd_auth", "require_valid_user", "false") of
                 "true" -> Req;
                 % If no admins, and no user required, then everyone is admin!
                 % Yay, admin party!
@@ -118,11 +118,11 @@ proxy_authentification_handler(Req) ->
     end.
     
 proxy_auth_user(Req) ->
-    XHeaderUserName = couch_config:get("couch_httpd_auth", "x_auth_username",
+    XHeaderUserName = config:get("couch_httpd_auth", "x_auth_username",
                                 "X-Auth-CouchDB-UserName"),
-    XHeaderRoles = couch_config:get("couch_httpd_auth", "x_auth_roles",
+    XHeaderRoles = config:get("couch_httpd_auth", "x_auth_roles",
                                 "X-Auth-CouchDB-Roles"),
-    XHeaderToken = couch_config:get("couch_httpd_auth", "x_auth_token",
+    XHeaderToken = config:get("couch_httpd_auth", "x_auth_token",
                                 "X-Auth-CouchDB-Token"),
     case header_value(Req, XHeaderUserName) of
         undefined -> nil;
@@ -132,9 +132,9 @@ proxy_auth_user(Req) ->
                 Else ->
                     [?l2b(R) || R <- string:tokens(Else, ",")]
             end,
-            case couch_config:get("couch_httpd_auth", "proxy_use_secret", "false") of
+            case config:get("couch_httpd_auth", "proxy_use_secret", "false") of
                 "true" ->
-                    case couch_config:get("couch_httpd_auth", "secret", nil) of
+                    case config:get("couch_httpd_auth", "secret", nil) of
                         nil ->
                             Req#httpd{user_ctx=#user_ctx{name=?l2b(UserName), roles=Roles}};
                         Secret ->
@@ -168,7 +168,7 @@ cookie_authentication_handler(#httpd{mochi_req=MochiReq}=Req) ->
         end,
         % Verify expiry and hash
         CurrentTime = make_cookie_time(),
-        case couch_config:get("couch_httpd_auth", "secret", nil) of
+        case config:get("couch_httpd_auth", "secret", nil) of
         nil ->
             ?LOG_DEBUG("cookie auth secret is not set",[]),
             Req;
@@ -182,7 +182,7 @@ cookie_authentication_handler(#httpd{mochi_req=MochiReq}=Req) ->
                 ExpectedHash = crypto:sha_mac(FullSecret, User ++ ":" ++ TimeStr),
                 Hash = ?l2b(HashStr),
                 Timeout = list_to_integer(
-                    couch_config:get("couch_httpd_auth", "timeout", "600")),
+                    config:get("couch_httpd_auth", "timeout", "600")),
                 ?LOG_DEBUG("timeout ~p", [Timeout]),
                 case (catch erlang:list_to_integer(TimeStr, 16)) of
                     TimeStamp when CurrentTime < TimeStamp + Timeout ->
@@ -232,10 +232,10 @@ cookie_auth_cookie(Req, User, Secret, TimeStamp) ->
         [{path, "/"}] ++ cookie_scheme(Req) ++ max_age()).
 
 ensure_cookie_auth_secret() ->
-    case couch_config:get("couch_httpd_auth", "secret", nil) of
+    case config:get("couch_httpd_auth", "secret", nil) of
         nil ->
             NewSecret = ?b2l(couch_uuids:random()),
-            couch_config:set("couch_httpd_auth", "secret", NewSecret),
+            config:set("couch_httpd_auth", "secret", NewSecret),
             NewSecret;
         Secret -> Secret
     end.
@@ -311,9 +311,9 @@ handle_session_req(#httpd{method='GET', user_ctx=UserCtx}=Req) ->
                     {roles, UserCtx#user_ctx.roles}
                 ]}},
                 {info, {[
-                    {authentication_db, ?l2b(couch_config:get("couch_httpd_auth", "authentication_db"))},
+                    {authentication_db, ?l2b(config:get("couch_httpd_auth", "authentication_db"))},
                     {authentication_handlers, [auth_name(H) || H <- couch_httpd:make_fun_spec_strs(
-                            couch_config:get("httpd", "authentication_handlers"))]}
+                            config:get("httpd", "authentication_handlers"))]}
                 ] ++ maybe_value(authenticated, UserCtx#user_ctx.handler, fun(Handler) ->
                         auth_name(?b2l(Handler))
                     end)}}
@@ -366,11 +366,11 @@ cookie_scheme(#httpd{mochi_req=MochiReq}) ->
     end.
 
 max_age() ->
-    case couch_config:get("couch_httpd_auth", "allow_persistent_cookies", "false") of
+    case config:get("couch_httpd_auth", "allow_persistent_cookies", "false") of
         "false" ->
             [];
         "true" ->
             Timeout = list_to_integer(
-                couch_config:get("couch_httpd_auth", "timeout", "600")),
+                config:get("couch_httpd_auth", "timeout", "600")),
             [{max_age, Timeout}]
     end.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd_cors.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_cors.erl b/src/couch/src/couch_httpd_cors.erl
index 5432fbd..d98357a 100644
--- a/src/couch/src/couch_httpd_cors.erl
+++ b/src/couch/src/couch_httpd_cors.erl
@@ -293,8 +293,8 @@ allow_credentials(_Origin, Host) ->
 
 
 cors_config(Host, Key, Default) ->
-    couch_config:get(cors_section(Host), Key,
-                     couch_config:get("cors", Key, Default)).
+    config:get(cors_section(Host), Key,
+                     config:get("cors", Key, Default)).
 
 cors_section(Host0) ->
     {Host, _Port} = split_host_port(Host0),
@@ -304,7 +304,7 @@ enable_cors() ->
     get_bool_config("httpd", "enable_cors", false).
 
 get_bool_config(Section, Key, Default) ->
-    case couch_config:get(Section, Key) of
+    case config:get(Section, Key) of
     undefined ->
         Default;
     "true" ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_db.erl b/src/couch/src/couch_httpd_db.erl
index 2ac4971..c70245c 100644
--- a/src/couch/src/couch_httpd_db.erl
+++ b/src/couch/src/couch_httpd_db.erl
@@ -63,7 +63,7 @@ handle_changes_req(#httpd{path_parts=[_,<<"_changes">>]}=Req, _Db) ->
     send_method_not_allowed(Req, "GET,HEAD,POST").
 
 handle_changes_req1(Req, #db{name=DbName}=Db) ->
-    AuthDbName = ?l2b(couch_config:get("couch_httpd_auth", "authentication_db")),
+    AuthDbName = ?l2b(config:get("couch_httpd_auth", "authentication_db")),
     case AuthDbName of
     DbName ->
         % in the authentication database, _changes is admin-only.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd_external.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_external.erl b/src/couch/src/couch_httpd_external.erl
index 077136d..8322dcd 100644
--- a/src/couch/src/couch_httpd_external.erl
+++ b/src/couch/src/couch_httpd_external.erl
@@ -63,7 +63,7 @@ json_req_obj(#httpd{mochi_req=Req,
     Body = case ReqBody of
         undefined ->
             MaxSize = list_to_integer(
-                couch_config:get("couchdb", "max_document_size", "4294967296")),
+                config:get("couchdb", "max_document_size", "4294967296")),
             Req:recv_body(MaxSize);
         Else -> Else
     end,

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_misc_handlers.erl b/src/couch/src/couch_httpd_misc_handlers.erl
index ff79f14..e46dee3 100644
--- a/src/couch/src/couch_httpd_misc_handlers.erl
+++ b/src/couch/src/couch_httpd_misc_handlers.erl
@@ -34,7 +34,7 @@ handle_welcome_req(#httpd{method='GET'}=Req, WelcomeMessage) ->
         {couchdb, WelcomeMessage},
         {uuid, couch_server:get_uuid()},
         {version, list_to_binary(couch_server:get_version())}
-        ] ++ case couch_config:get("vendor") of
+        ] ++ case config:get("vendor") of
         [] ->
             [];
         Properties ->
@@ -137,7 +137,7 @@ handle_config_req(#httpd{method='GET', path_parts=[_]}=Req) ->
         false ->
             dict:store(Section, [{list_to_binary(Key), list_to_binary(Value)}], Acc)
         end
-    end, dict:new(), couch_config:all()),
+    end, dict:new(), config:all()),
     KVs = dict:fold(fun(Section, Values, Acc) ->
         [{list_to_binary(Section), {Values}} | Acc]
     end, [], Grouped),
@@ -146,12 +146,12 @@ handle_config_req(#httpd{method='GET', path_parts=[_]}=Req) ->
 handle_config_req(#httpd{method='GET', path_parts=[_,Section]}=Req) ->
     ok = couch_httpd:verify_is_server_admin(Req),
     KVs = [{list_to_binary(Key), list_to_binary(Value)}
-            || {Key, Value} <- couch_config:get(Section)],
+            || {Key, Value} <- config:get(Section)],
     send_json(Req, 200, {KVs});
 % GET /_config/Section/Key
 handle_config_req(#httpd{method='GET', path_parts=[_, Section, Key]}=Req) ->
     ok = couch_httpd:verify_is_server_admin(Req),
-    case couch_config:get(Section, Key, null) of
+    case config:get(Section, Key, null) of
     null ->
         throw({not_found, unknown_config_value});
     Value ->
@@ -162,7 +162,7 @@ handle_config_req(#httpd{method=Method, path_parts=[_, Section, Key]}=Req)
       when (Method == 'PUT') or (Method == 'DELETE') ->
     ok = couch_httpd:verify_is_server_admin(Req),
     Persist = couch_httpd:header_value(Req, "X-Couch-Persist") /= "false",
-    case couch_config:get(<<"httpd">>, <<"config_whitelist">>, null) of
+    case config:get(<<"httpd">>, <<"config_whitelist">>, null) of
         null ->
             % No whitelist; allow all changes.
             handle_approved_config_req(Req, Persist);
@@ -226,8 +226,8 @@ handle_approved_config_req(#httpd{method='PUT', path_parts=[_, Section, Key]}=Re
     _ ->
         couch_httpd:json_body(Req)
     end,
-    OldValue = couch_config:get(Section, Key, ""),
-    case couch_config:set(Section, Key, ?b2l(Value), Persist) of
+    OldValue = config:get(Section, Key, ""),
+    case config:set(Section, Key, ?b2l(Value), Persist) of
     ok ->
         send_json(Req, 200, list_to_binary(OldValue));
     Error ->
@@ -235,11 +235,11 @@ handle_approved_config_req(#httpd{method='PUT', path_parts=[_, Section, Key]}=Re
     end;
 % DELETE /_config/Section/Key
 handle_approved_config_req(#httpd{method='DELETE',path_parts=[_,Section,Key]}=Req, Persist) ->
-    case couch_config:get(Section, Key, null) of
+    case config:get(Section, Key, null) of
     null ->
         throw({not_found, unknown_config_value});
     OldValue ->
-        couch_config:delete(Section, Key, Persist),
+        config:delete(Section, Key, Persist),
         send_json(Req, 200, list_to_binary(OldValue))
     end.
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd_oauth.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_oauth.erl b/src/couch/src/couch_httpd_oauth.erl
index 57799e6..8fd4c30 100644
--- a/src/couch/src/couch_httpd_oauth.erl
+++ b/src/couch/src/couch_httpd_oauth.erl
@@ -309,17 +309,17 @@ oauth_credentials_info(Token, ConsumerKey) ->
         Result;
     nil ->
         {
-            case couch_config:get("oauth_consumer_secrets", ConsumerKey) of
+            case config:get("oauth_consumer_secrets", ConsumerKey) of
             undefined -> [];
             ConsumerSecret -> [{<<"consumer_secret">>, ?l2b(ConsumerSecret)}]
             end
             ++
-            case couch_config:get("oauth_token_secrets", Token) of
+            case config:get("oauth_token_secrets", Token) of
             undefined -> [];
             TokenSecret -> [{<<"token_secret">>, ?l2b(TokenSecret)}]
             end
             ++
-            case couch_config:get("oauth_token_users", Token) of
+            case config:get("oauth_token_users", Token) of
             undefined -> [];
             User -> [{<<"username">>, ?l2b(User)}]
             end
@@ -328,7 +328,7 @@ oauth_credentials_info(Token, ConsumerKey) ->
 
 
 use_auth_db() ->
-    case couch_config:get("couch_httpd_oauth", "use_users_db", "false") of
+    case config:get("couch_httpd_oauth", "use_users_db", "false") of
     "false" ->
         nil;
     "true" ->
@@ -338,7 +338,7 @@ use_auth_db() ->
 
 
 open_auth_db() ->
-    DbName = ?l2b(couch_config:get("couch_httpd_auth", "authentication_db")),
+    DbName = ?l2b(config:get("couch_httpd_auth", "authentication_db")),
     DbOptions = [{user_ctx, #user_ctx{roles = [<<"_admin">>]}}],
     {ok, AuthDb} = couch_db:open_int(DbName, DbOptions),
     AuthDb.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd_rewrite.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_rewrite.erl b/src/couch/src/couch_httpd_rewrite.erl
index 428d30c..abd6af5 100644
--- a/src/couch/src/couch_httpd_rewrite.erl
+++ b/src/couch/src/couch_httpd_rewrite.erl
@@ -119,7 +119,7 @@ handle_rewrite_req(#httpd{
     Prefix = <<"/", (?l2b(couch_util:url_encode(DbName)))/binary, "/", DesignId/binary>>,
     QueryList = lists:map(fun decode_query_value/1, couch_httpd:qs(Req)),
 
-    MaxRewritesList = couch_config:get("httpd", "rewrite_limit", "100"),
+    MaxRewritesList = config:get("httpd", "rewrite_limit", "100"),
     MaxRewrites = list_to_integer(MaxRewritesList),
     case get(couch_rewrite_count) of
         undefined ->
@@ -438,7 +438,7 @@ path_to_list([<<>>|R], Acc, DotDotCount) ->
 path_to_list([<<"*">>|R], Acc, DotDotCount) ->
     path_to_list(R, [?MATCH_ALL|Acc], DotDotCount);
 path_to_list([<<"..">>|R], Acc, DotDotCount) when DotDotCount == 2 ->
-    case couch_config:get("httpd", "secure_rewrites", "true") of
+    case config:get("httpd", "secure_rewrites", "true") of
     "false" ->
         path_to_list(R, [<<"..">>|Acc], DotDotCount+1);
     _Else ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_httpd_vhost.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_vhost.erl b/src/couch/src/couch_httpd_vhost.erl
index 258f4eb..29fddfe 100644
--- a/src/couch/src/couch_httpd_vhost.erl
+++ b/src/couch/src/couch_httpd_vhost.erl
@@ -12,13 +12,17 @@
 
 -module(couch_httpd_vhost).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
--export([start_link/0, config_change/2, reload/0, get_state/0, dispatch_host/1]).
+-export([start_link/0, reload/0, get_state/0, dispatch_host/1]).
 -export([urlsplit_netloc/2, redirect_to_vhost/2]).
 -export([host/1, split_host_port/1]).
 
 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 -include_lib("couch/include/couch_db.hrl").
 
 -define(SEPARATOR, $\/).
@@ -237,7 +241,7 @@ bind_path(_, _) ->
 %% create vhost list from ini
 
 host(MochiReq) ->
-    XHost = couch_config:get("httpd", "x_forwarded_host",
+    XHost = config:get("httpd", "x_forwarded_host",
                              "X-Forwarded-Host"),
     case MochiReq:get_header_value(XHost) of
         undefined ->
@@ -254,7 +258,7 @@ make_vhosts() ->
                     Acc;
                 ({Vhost, Path}, Acc) ->
                     [{parse_vhost(Vhost), split_path(Path)}|Acc]
-            end, [], couch_config:get("vhosts")),
+            end, [], config:get("vhosts")),
 
     lists:reverse(lists:usort(Vhosts)).
 
@@ -327,7 +331,7 @@ make_path(Parts) ->
      "/" ++ string:join(Parts,[?SEPARATOR]).
 
 init(_) ->
-    ok = couch_config:register(fun ?MODULE:config_change/2),
+    ok = config:listen_for_changes(?MODULE, nil),
 
     %% load configuration
     {VHostGlobals, VHosts, Fun} = load_conf(),
@@ -351,6 +355,12 @@ handle_call(_Msg, _From, State) ->
 handle_cast(_Msg, State) ->
     {noreply, State}.
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info(_Info, State) ->
     {noreply, State}.
 
@@ -360,16 +370,20 @@ terminate(_Reason, _State) ->
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
-config_change("httpd", "vhost_global_handlers") ->
-    ?MODULE:reload();
-config_change("httpd", "redirect_vhost_handler") ->
-    ?MODULE:reload();
-config_change("vhosts", _) ->
-    ?MODULE:reload().
+
+handle_config_change("httpd", "vhost_global_handlers", _, _, _) ->
+    {ok, ?MODULE:reload()};
+handle_config_change("httpd", "redirect_vhost_handler", _, _, _) ->
+    {ok, ?MODULE:reload()};
+handle_config_change("vhosts", _, _, _, _) ->
+    {ok, ?MODULE:reload()};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
 
 load_conf() ->
     %% get vhost globals
-    VHostGlobals = re:split(couch_config:get("httpd",
+    VHostGlobals = re:split(config:get("httpd",
             "vhost_global_handlers",""), "\\s*,\\s*",[{return, list}]),
 
     %% build vhosts matching rules
@@ -377,7 +391,7 @@ load_conf() ->
 
     %% build vhosts handler fun
     DefaultVHostFun = "{couch_httpd_vhost, redirect_to_vhost}",
-    Fun = couch_httpd:make_arity_2_fun(couch_config:get("httpd",
+    Fun = couch_httpd:make_arity_2_fun(config:get("httpd",
             "redirect_vhost_handler", DefaultVHostFun)),
 
     {VHostGlobals, VHosts, Fun}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_log.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_log.erl b/src/couch/src/couch_log.erl
index cd4bbbb..d1aa701 100644
--- a/src/couch/src/couch_log.erl
+++ b/src/couch/src/couch_log.erl
@@ -12,6 +12,7 @@
 
 -module(couch_log).
 -behaviour(gen_event).
+-behaviour(config_listener).
 
 % public API
 -export([start_link/0, stop/0]).
@@ -24,6 +25,9 @@
 -export([init/1, handle_event/2, terminate/2, code_change/3]).
 -export([handle_info/2, handle_call/2]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 -define(LEVEL_ERROR, 4).
 -define(LEVEL_WARN, 3).
 -define(LEVEL_INFO, 2).
@@ -71,25 +75,12 @@ stop() ->
     couch_event_sup:stop(couch_log).
 
 init([]) ->
-    % read config and register for configuration changes
-
-    % 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") ->
-            ?MODULE:stop();
-        ("log", "level") ->
-            ?MODULE:stop();
-        ("log", "include_sasl") ->
-            ?MODULE:stop();
-        ("log_level_by_module", _) ->
-            ?MODULE:stop()
-        end),
-
-    Filename = couch_config:get("log", "file", "couchdb.log"),
-    Level = level_integer(list_to_atom(couch_config:get("log", "level", "info"))),
-    Sasl = couch_config:get("log", "include_sasl", "true") =:= "true",
-    LevelByModule = couch_config:get("log_level_by_module"),
+    ok = config:listen_for_changes(?MODULE, nil),
+
+    Filename = config:get("log", "file", "couchdb.log"),
+    Level = level_integer(list_to_atom(config:get("log", "level", "info"))),
+    Sasl = config:get("log", "include_sasl", "true") =:= "true",
+    LevelByModule = config:get("log_level_by_module"),
 
     case ets:info(?MODULE) of
     undefined -> ets:new(?MODULE, [named_table]);
@@ -111,6 +102,18 @@ init([]) ->
         {stop, {error, ReasonStr, Filename}}
     end.
 
+handle_config_change("log", "file", _, _, _) ->
+    ?MODULE:stop(),
+    remove_handler;
+handle_config_change("log", "level", _, _, _) ->
+    ?MODULE:stop(),
+    remove_handler;
+handle_config_change("log", "include_sasl", _, _, _) ->
+    ?MODULE:stop(),
+    remove_handler;
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
 debug_on() ->
     get_level_integer() =< ?LEVEL_DEBUG.
 
@@ -194,6 +197,12 @@ handle_call({set_level_integer, Module, NewLevel}, State) ->
     ets:insert(?MODULE, {Module, NewLevel}),
     {ok, ok, State#state{level = NewLevel}}.
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {ok, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {ok, State};
 handle_info(_Info, State) ->
     {ok, State}.
 
@@ -231,10 +240,10 @@ get_log_messages(Pid, Level, Format, Args) ->
 % |__________| 100
 
 read(Bytes, Offset) ->
-    LogFileName = couch_config:get("log", "file"),
+    LogFileName = config:get("log", "file"),
     LogFileSize = filelib:file_size(LogFileName),
     MaxChunkSize = list_to_integer(
-        couch_config:get("httpd", "log_max_chunk_size", "1000000")),
+        config:get("httpd", "log_max_chunk_size", "1000000")),
     case Bytes > MaxChunkSize of
     true ->
         throw({bad_request, "'bytes' cannot exceed " ++

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_os_daemons.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_os_daemons.erl b/src/couch/src/couch_os_daemons.erl
index 00fd7b3..3560149 100644
--- a/src/couch/src/couch_os_daemons.erl
+++ b/src/couch/src/couch_os_daemons.erl
@@ -11,12 +11,16 @@
 % the License.
 -module(couch_os_daemons).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
--export([start_link/0, info/0, info/1, config_change/2]).
+-export([start_link/0, info/0, info/1]).
 
 -export([init/1, terminate/2, code_change/3]).
 -export([handle_call/3, handle_cast/2, handle_info/2]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 -include_lib("couch/include/couch_db.hrl").
 
 -record(daemon, {
@@ -42,12 +46,9 @@ info() ->
 info(Options) ->
     gen_server:call(?MODULE, {daemon_info, Options}).
 
-config_change(Section, Key) ->
-    gen_server:cast(?MODULE, {config_change, Section, Key}).
-
 init(_) ->
     process_flag(trap_exit, true),
-    ok = couch_config:register(fun ?MODULE:config_change/2),
+    ok = config:listen_for_changes(?MODULE, nil),
     Table = ets:new(?MODULE, [protected, set, {keypos, #daemon.port}]),
     reload_daemons(Table),
     {ok, Table}.
@@ -80,6 +81,12 @@ handle_cast(Msg, Table) ->
     ?LOG_ERROR("Unknown cast message to ~p: ~p", [?MODULE, Msg]),
     {stop, error, Table}.
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info({'EXIT', Port, Reason}, Table) ->
     case ets:lookup(Table, Port) of
         [] ->
@@ -186,6 +193,12 @@ handle_info(Msg, Table) ->
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
+
+handle_config_change(Section, Key, _, _, _) ->
+    gen_server:cast(?MODULE, {config_change, Section, Key}),
+    {ok, nil}.
+
+
 % Internal API
 
 %
@@ -209,13 +222,13 @@ stop_port(#daemon{port=Port}=D) ->
 
 
 handle_port_message(#daemon{port=Port}=Daemon, [<<"get">>, Section]) ->
-    KVs = couch_config:get(Section),
+    KVs = config:get(Section),
     Data = lists:map(fun({K, V}) -> {?l2b(K), ?l2b(V)} end, KVs),
     Json = iolist_to_binary(?JSON_ENCODE({Data})),
     port_command(Port, <<Json/binary, "\n">>),
     {ok, Daemon};
 handle_port_message(#daemon{port=Port}=Daemon, [<<"get">>, Section, Key]) ->
-    Value = case couch_config:get(Section, Key, null) of
+    Value = case config:get(Section, Key, null) of
         null -> null;
         String -> ?l2b(String)
     end,
@@ -260,7 +273,7 @@ handle_log_message(Name, Msg, Level) ->
 
 reload_daemons(Table) ->
     % List of daemons we want to have running.
-    Configured = lists:sort(couch_config:get("os_daemons")),
+    Configured = lists:sort(config:get("os_daemons")),
     
     % Remove records for daemons that were halted.
     MSpecHalted = #daemon{name='$1', cmd='$2', status=halted, _='_'},
@@ -350,7 +363,7 @@ find_to_stop(_, [], Acc) ->
     Acc.
 
 should_halt(Errors) ->
-    RetryTimeCfg = couch_config:get("os_daemon_settings", "retry_time", "5"),
+    RetryTimeCfg = config:get("os_daemon_settings", "retry_time", "5"),
     RetryTime = list_to_integer(RetryTimeCfg),
 
     Now = now(),
@@ -358,7 +371,7 @@ should_halt(Errors) ->
         timer:now_diff(Now, Time) =< RetryTime * 1000000
     end, Errors),
 
-    RetryCfg = couch_config:get("os_daemon_settings", "max_retries", "3"),
+    RetryCfg = config:get("os_daemon_settings", "max_retries", "3"),
     Retries = list_to_integer(RetryCfg),
 
     {length(RecentErrors) >= Retries, RecentErrors}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_os_process.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_os_process.erl b/src/couch/src/couch_os_process.erl
index fcf9da5..c6e6520 100644
--- a/src/couch/src/couch_os_process.erl
+++ b/src/couch/src/couch_os_process.erl
@@ -178,7 +178,7 @@ pick_command1(_) ->
 init([Command, Options, PortOptions]) ->
     PrivDir = couch_util:priv_dir(),
     Spawnkiller = filename:join(PrivDir, "couchspawnkillable"),
-    V = couch_config:get("query_server_config", "os_process_idle_limit", "300"),
+    V = config:get("query_server_config", "os_process_idle_limit", "300"),
     IdleLimit = list_to_integer(V) * 1000,
     BaseProc = #os_proc{
         command=Command,
@@ -263,7 +263,7 @@ handle_info(Msg, #os_proc{idle=Idle}=OsProc) ->
     {noreply, OsProc, Idle}.
 
 code_change(_, {os_proc, Cmd, Port, W, R, Timeout} , _) ->
-    V = couch_config:get("query_server_config","os_process_idle_limit","300"),
+    V = config:get("query_server_config","os_process_idle_limit","300"),
     State = #os_proc{
         command = Cmd,
         port = Port,

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_passwords.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_passwords.erl b/src/couch/src/couch_passwords.erl
index 43f3380..d0f36cc 100644
--- a/src/couch/src/couch_passwords.erl
+++ b/src/couch/src/couch_passwords.erl
@@ -28,7 +28,7 @@ simple(Password, Salt) ->
 %% CouchDB utility functions
 -spec hash_admin_password(binary()) -> binary().
 hash_admin_password(ClearPassword) ->
-    Iterations = couch_config:get("couch_httpd_auth", "iterations", "10000"),
+    Iterations = config:get("couch_httpd_auth", "iterations", "10000"),
     Salt = couch_uuids:random(),
     DerivedKey = couch_passwords:pbkdf2(couch_util:to_binary(ClearPassword),
                                         Salt ,list_to_integer(Iterations)),
@@ -46,7 +46,7 @@ get_unhashed_admins() ->
         ({_User, _ClearPassword}) ->
             true
         end,
-    couch_config:get("admins")).
+    config:get("admins")).
 
 %% Current scheme, much stronger.
 -spec pbkdf2(binary(), binary(), integer()) -> binary().

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_proc_manager.erl b/src/couch/src/couch_proc_manager.erl
index 94946a1..6130fc9 100644
--- a/src/couch/src/couch_proc_manager.erl
+++ b/src/couch/src/couch_proc_manager.erl
@@ -100,7 +100,7 @@ handle_call(_Call, _From, State) ->
     {reply, ignored, State}.
 
 handle_cast({os_proc_idle, Pid}, #state{tab=Tab}=State) ->
-    Limit = couch_config:get("query_server_config", "os_process_soft_limit", "100"),
+    Limit = config:get("query_server_config", "os_process_soft_limit", "100"),
     case ets:lookup(Tab, Pid) of
         [#proc{client=nil}] ->
             case ets:info(Tab, size) > list_to_integer(Limit) of
@@ -225,9 +225,9 @@ new_proc(From, Lang, DDoc, DDocKey) ->
 new_proc_int(From, Lang) when is_binary(Lang) ->
     new_proc_int(From, binary_to_list(Lang));
 new_proc_int(From, Lang) when is_list(Lang) ->
-    case couch_config:get("query_servers", Lang) of
+    case config:get("query_servers", Lang) of
     undefined ->
-        case couch_config:get("native_query_servers", Lang) of
+        case config:get("native_query_servers", Lang) of
         undefined ->
             gen_server:reply(From, {unknown_query_language, Lang});
         SpecStr ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_secondary_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_secondary_sup.erl b/src/couch/src/couch_secondary_sup.erl
index 6320fd9..4f2d1c8 100644
--- a/src/couch/src/couch_secondary_sup.erl
+++ b/src/couch/src/couch_secondary_sup.erl
@@ -38,5 +38,5 @@ init([]) ->
                 [Module]}
         end
         || {Name, SpecStr}
-        <- couch_config:get("daemons"), SpecStr /= ""],
+        <- config:get("daemons"), SpecStr /= ""],
     {ok, {{one_for_one, 10, 3600}, Children}}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index 40c2d7e..c23ec05 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -12,14 +12,18 @@
 
 -module(couch_server).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
 -export([open/2,create/2,delete/2,get_version/0,get_uuid/0]).
 -export([all_databases/0, all_databases/2]).
 -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_stats/0,config_change/4]).
+-export([dev_start/0,is_admin/2,has_admins/0,get_stats/0]).
 -export([close_lru/0]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 -include_lib("couch/include/couch_db.hrl").
 
 -record(server,{
@@ -46,10 +50,10 @@ get_version() ->
     end.
 
 get_uuid() ->
-    case couch_config:get("couchdb", "uuid", nil) of
+    case config:get("couchdb", "uuid", nil) of
         nil ->
             UUID = couch_uuids:random(),
-            couch_config:set("couchdb", "uuid", ?b2l(UUID)),
+            config:set("couchdb", "uuid", ?b2l(UUID)),
             UUID;
         UUID -> ?l2b(UUID)
     end.
@@ -105,7 +109,7 @@ delete(DbName, Options) ->
 maybe_add_sys_db_callbacks(DbName, Options) when is_binary(DbName) ->
     maybe_add_sys_db_callbacks(?b2l(DbName), Options);
 maybe_add_sys_db_callbacks(DbName, Options) ->
-    case couch_config:get("replicator", "db", "_replicator") of
+    case config:get("replicator", "db", "_replicator") of
     DbName ->
         [
             {before_doc_update, fun couch_replicator_manager:before_doc_update/2},
@@ -113,7 +117,7 @@ maybe_add_sys_db_callbacks(DbName, Options) ->
             sys_db | Options
         ];
     _ ->
-        case couch_config:get("couch_httpd_auth", "authentication_db", "_users") of
+        case config:get("couch_httpd_auth", "authentication_db", "_users") of
         DbName ->
         [
             {before_doc_update, fun couch_users_db:before_doc_update/2},
@@ -139,7 +143,7 @@ check_dbname(#server{dbname_regexp=RegExp}, DbName) ->
     end.
 
 is_admin(User, ClearPwd) ->
-    case couch_config:get("admins", User) of
+    case config:get("admins", User) of
     "-hashed-" ++ HashedPwdAndSalt ->
         [HashedPwd, Salt] = string:tokens(HashedPwdAndSalt, ","),
         couch_util:to_hex(crypto:sha(ClearPwd ++ Salt)) == HashedPwd;
@@ -148,7 +152,7 @@ is_admin(User, ClearPwd) ->
     end.
 
 has_admins() ->
-    couch_config:get("admins") /= [].
+    config:get("admins") /= [].
 
 get_full_filename(Server, DbName) ->
     filename:join([Server#server.root_dir, "./" ++ DbName ++ ".couch"]).
@@ -160,7 +164,7 @@ hash_admin_passwords(Persist) ->
     lists:foreach(
         fun({User, ClearPassword}) ->
             HashedPassword = couch_passwords:hash_admin_password(ClearPassword),
-            couch_config:set("admins", User, ?b2l(HashedPassword), Persist)
+            config:set("admins", User, ?b2l(HashedPassword), Persist)
         end, couch_passwords:get_unhashed_admins()).
 
 init([]) ->
@@ -169,10 +173,10 @@ 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", "."),
+    RootDir = config:get("couchdb", "database_dir", "."),
     MaxDbsOpen = list_to_integer(
-            couch_config:get("couchdb", "max_dbs_open")),
-    ok = couch_config:register(fun ?MODULE:config_change/4),
+            config:get("couchdb", "max_dbs_open")),
+    ok = config:listen_for_changes(?MODULE, nil),
     ok = couch_file:init_delete_dir(RootDir),
     hash_admin_passwords(),
     {ok, RegExp} = re:compile(
@@ -191,13 +195,31 @@ terminate(_Reason, _Srv) ->
         nil, couch_dbs),
     ok.
 
-config_change("couchdb", "database_dir", _, _) ->
-    exit(whereis(couch_server), config_change);
-config_change("couchdb", "max_dbs_open", Max, _) ->
-    gen_server:call(couch_server, {set_max_dbs_open, list_to_integer(Max)});
-config_change("admins", _, _, Persist) ->
+handle_config_change("couchdb", "database_dir", _, _, _) ->
+    exit(whereis(couch_server), config_change),
+    remove_handler;
+handle_config_change("couchdb", "max_dbs_open", Max, _, _) ->
+    {ok, gen_server:call(couch_server,{set_max_dbs_open,list_to_integer(Max)})};
+handle_config_change("admins", _, _, Persist, _) ->
     % spawn here so couch event manager doesn't deadlock
-    spawn(fun() -> hash_admin_passwords(Persist) end).
+    {ok, spawn(fun() -> hash_admin_passwords(Persist) end)};
+handle_config_change("httpd", "authentication_handlers", _, _, _) ->
+    {ok, couch_httpd:stop()};
+handle_config_change("httpd", "bind_address", _, _, _) ->
+    {ok, couch_httpd:stop()};
+handle_config_change("httpd", "port", _, _, _) ->
+    {ok, couch_httpd:stop()};
+handle_config_change("httpd", "max_connections", _, _, _) ->
+    {ok, couch_httpd:stop()};
+handle_config_change("httpd", "default_handler", _, _, _) ->
+    {ok, couch_httpd:stop()};
+handle_config_change("httpd_global_handlers", _, _, _, _) ->
+    {ok, couch_httpd:stop()};
+handle_config_change("httpd_db_handlers", _, _, _, _) ->
+    {ok, couch_httpd:stop()};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
 
 all_databases() ->
     {ok, DbList} = all_databases(

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_server_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server_sup.erl b/src/couch/src/couch_server_sup.erl
index 528ac7c..c42bcfb 100644
--- a/src/couch/src/couch_server_sup.erl
+++ b/src/couch/src/couch_server_sup.erl
@@ -12,16 +12,19 @@
 
 -module(couch_server_sup).
 -behaviour(supervisor).
+-behaviour(config_listener).
 
 
--export([start_link/1,stop/0, couch_config_start_link_wrapper/2,
-        restart_core_server/0, config_change/2]).
+-export([start_link/1,stop/0, restart_core_server/0]).
 
 -include_lib("couch/include/couch_db.hrl").
 
 %% supervisor callbacks
 -export([init/1]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 start_link(IniFiles) ->
     case whereis(couch_server_sup) of
     undefined ->
@@ -33,14 +36,6 @@ start_link(IniFiles) ->
 restart_core_server() ->
     init:restart().
 
-couch_config_start_link_wrapper(IniFiles, FirstConfigPid) ->
-    case is_process_alive(FirstConfigPid) of
-        true ->
-            link(FirstConfigPid),
-            {ok, FirstConfigPid};
-        false -> couch_config:start_link(IniFiles)
-    end.
-
 start_server(IniFiles) ->
     case init:get_argument(pidfile) of
     {ok, [PidFile]} ->
@@ -53,9 +48,7 @@ start_server(IniFiles) ->
     _ -> ok
     end,
 
-    {ok, ConfigPid} = couch_config:start_link(IniFiles),
-
-    LogLevel = couch_config:get("log", "level", "info"),
+    LogLevel = config:get("log", "level", "info"),
     % announce startup
     io:format("Apache CouchDB ~s (LogLevel=~s) is starting.~n", [
         couch_server:get_version(),
@@ -65,18 +58,12 @@ start_server(IniFiles) ->
     "debug" ->
         io:format("Configuration Settings ~p:~n", [IniFiles]),
         [io:format("  [~s] ~s=~p~n", [Module, Variable, Value])
-            || {{Module, Variable}, Value} <- couch_config:all()];
+            || {{Module, Variable}, Value} <- config:all()];
     _ -> ok
     end,
 
     BaseChildSpecs =
-    {{one_for_one, 10, 60},
-        [{couch_config,
-            {couch_server_sup, couch_config_start_link_wrapper, [IniFiles, ConfigPid]},
-            permanent,
-            brutal_kill,
-            worker,
-            [couch_config]},
+    {{one_for_one, 10, 60}, [
         {couch_primary_services,
             {couch_primary_sup, start_link, []},
             permanent,
@@ -98,13 +85,9 @@ start_server(IniFiles) ->
     {ok, Pid} = supervisor:start_link(
         {local, couch_server_sup}, couch_server_sup, BaseChildSpecs),
 
-    % launch the icu bridge
-    % just restart if one of the config settings change.
-    couch_config:register(fun ?MODULE:config_change/2, Pid),
-
-    unlink(ConfigPid),
+    ok = config:listen_for_changes(?MODULE, nil),
 
-    Ip = couch_config:get("httpd", "bind_address"),
+    Ip = config:get("httpd", "bind_address"),
     io:format("Apache CouchDB has started. Time to relax.~n"),
     Uris = [get_uri(Name, Ip) || Name <- [couch_httpd, https]],
     [begin
@@ -114,7 +97,7 @@ start_server(IniFiles) ->
         end
     end
     || Uri <- Uris],
-    case couch_config:get("couchdb", "uri_file", null) of 
+    case config:get("couchdb", "uri_file", null) of 
     null -> ok;
     UriFile ->
         Lines = [begin case Uri of
@@ -135,13 +118,17 @@ start_server(IniFiles) ->
 stop() ->
     catch exit(whereis(couch_server_sup), normal).
 
-config_change("daemons", _) ->
-    supervisor:terminate_child(couch_server_sup, couch_secondary_services),
-    supervisor:restart_child(couch_server_sup, couch_secondary_services);
-config_change("couchdb", "util_driver_dir") ->
+
+handle_config_change("daemons", _, _, _, _) ->
+    exit(whereis(couch_server_sup), shutdown),
+    remove_handler;
+handle_config_change("couchdb", "util_driver_dir", _, _, _) ->
     [Pid] = [P || {collation_driver, P, _, _}
         <- supervisor:which_children(couch_primary_services)],
-    Pid ! reload_driver.
+    Pid ! reload_driver,
+    {ok, nil};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
 
 init(ChildSpecs) ->
     {ok, ChildSpecs}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_stats_aggregator.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_stats_aggregator.erl b/src/couch/src/couch_stats_aggregator.erl
index 6090355..416c9a0 100644
--- a/src/couch/src/couch_stats_aggregator.erl
+++ b/src/couch/src/couch_stats_aggregator.erl
@@ -12,6 +12,7 @@
 
 -module(couch_stats_aggregator).
 -behaviour(gen_server).
+-behaviour(config_listener).
 
 -export([start/0, start/1, stop/0]).
 -export([all/0, all/1, get/1, get/2, get_json/1, get_json/2, collect_sample/0]).
@@ -19,6 +20,10 @@
 -export([init/1, terminate/2, code_change/3]).
 -export([handle_call/3, handle_cast/2, handle_info/2]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
+
 -record(aggregate, {
     description = <<"">>,
     seconds = 0,
@@ -92,7 +97,7 @@ collect_sample() ->
 init(StatDescsFileName) ->
     % Create an aggregate entry for each {description, rate} pair.
     ets:new(?MODULE, [named_table, set, protected]),
-    SampleStr = couch_config:get("stats", "samples", "[0]"),
+    SampleStr = config:get("stats", "samples", "[0]"),
     {ok, Samples} = couch_util:parse_term(SampleStr),
     {ok, Descs} = file:consult(StatDescsFileName),
     lists:foreach(fun({Sect, Key, Value}) ->
@@ -105,12 +110,9 @@ init(StatDescsFileName) ->
         end, Samples)
     end, Descs),
     
-    Self = self(),
-    ok = couch_config:register(
-        fun("stats", _) -> exit(Self, config_change) end
-    ),
+    ok = config:listen_for_changes(?MODULE, nil),
     
-    Rate = list_to_integer(couch_config:get("stats", "rate", "1000")),
+    Rate = list_to_integer(config:get("stats", "rate", "1000")),
     % TODO: Add timer_start to kernel start options.
     {ok, TRef} = timer:apply_after(Rate, ?MODULE, collect_sample, []),
     {ok, {TRef, Rate}}.
@@ -156,6 +158,12 @@ handle_call(collect_sample, _, {OldTRef, SampleInterval}) ->
 handle_cast(stop, State) ->
     {stop, normal, State}.
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info(_Info, State) ->
     {noreply, State}.
 
@@ -163,6 +171,13 @@ code_change(_OldVersion, State, _Extra) ->
     {ok, State}.
 
 
+handle_config_change("stats", _, _, _, _) ->
+    exit(whereis(?MODULE), config_change),
+    remove_handler;
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
+
 new_value(incremental, Value, null) ->
     Value;
 new_value(incremental, Value, Current) ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_users_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_users_db.erl b/src/couch/src/couch_users_db.erl
index 9fe069f..76acfee 100644
--- a/src/couch/src/couch_users_db.erl
+++ b/src/couch/src/couch_users_db.erl
@@ -63,7 +63,7 @@ save_doc(#doc{body={Body}} = Doc) ->
     undefined ->
         Doc;
     ClearPassword ->
-        Iterations = list_to_integer(couch_config:get("couch_httpd_auth", "iterations", "1000")),
+        Iterations = list_to_integer(config:get("couch_httpd_auth", "iterations", "1000")),
         Salt = couch_uuids:random(),
         DerivedKey = couch_passwords:pbkdf2(ClearPassword, Salt, Iterations),
         Body0 = [{?PASSWORD_SCHEME, ?PBKDF2}, {?ITERATIONS, Iterations}|Body],

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch/src/couch_uuids.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_uuids.erl b/src/couch/src/couch_uuids.erl
index ac9b463..3065938 100644
--- a/src/couch/src/couch_uuids.erl
+++ b/src/couch/src/couch_uuids.erl
@@ -13,6 +13,7 @@
 -include_lib("couch/include/couch_db.hrl").
 
 -behaviour(gen_server).
+-behaviour(config_listener).
 
 -export([start/0, stop/0]).
 -export([new/0, random/0, utc_random/0]).
@@ -20,6 +21,9 @@
 -export([init/1, terminate/2, code_change/3]).
 -export([handle_call/3, handle_cast/2, handle_info/2]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 start() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
@@ -44,9 +48,7 @@ utc_suffix(Suffix) ->
     list_to_binary(Prefix ++ Suffix).
 
 init([]) ->
-    ok = couch_config:register(
-        fun("uuids", _) -> gen_server:cast(?MODULE, change) end
-    ),
+    ok = config:listen_for_changes(?MODULE, nil),
     {ok, state()}.
 
 terminate(_Reason, _State) ->
@@ -74,12 +76,23 @@ handle_cast(stop, State) ->
 handle_cast(_Msg, State) ->
     {noreply, State}.
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info(_Info, State) ->
     {noreply, State}.
 
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
+handle_config_change("uuids", _, _, _, _) ->
+    {ok, gen_server:cast(?MODULE, change)};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
 new_prefix() ->
     couch_util:to_hex((crypto:rand_bytes(13))).
 
@@ -87,14 +100,14 @@ inc() ->
     crypto:rand_uniform(1, 16#ffe).
 
 state() ->
-    AlgoStr = couch_config:get("uuids", "algorithm", "random"),
+    AlgoStr = config:get("uuids", "algorithm", "random"),
     case couch_util:to_existing_atom(AlgoStr) of
         random ->
             random;
         utc_random ->
             utc_random;
         utc_id ->
-            UtcIdSuffix = couch_config:get("uuids", "utc_id_suffix", ""),
+            UtcIdSuffix = config:get("uuids", "utc_id_suffix", ""),
             {utc_id, UtcIdSuffix};
         sequential ->
             {sequential, new_prefix(), inc()};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0861ab00/src/couch_index/src/couch_index.erl
----------------------------------------------------------------------
diff --git a/src/couch_index/src/couch_index.erl b/src/couch_index/src/couch_index.erl
index 483dc59..3253a32 100644
--- a/src/couch_index/src/couch_index.erl
+++ b/src/couch_index/src/couch_index.erl
@@ -12,18 +12,20 @@
 
 -module(couch_index).
 -behaviour(gen_server).
-
+-behaviour(config_listener).
 
 %% API
 -export([start_link/1, stop/1, get_state/2, get_info/1]).
 -export([trigger_update/2]).
 -export([compact/1, compact/2]).
--export([config_change/3]).
 
 %% gen_server callbacks
 -export([init/1, terminate/2, code_change/3]).
 -export([handle_call/3, handle_cast/2, handle_info/2]).
 
+% config_listener api
+-export([handle_config_change/5]).
+
 
 -include_lib("couch/include/couch_db.hrl").
 
@@ -72,12 +74,8 @@ compact(Pid, Options) ->
     end.
 
 
-config_change("query_server_config", "commit_freq", NewValue) ->
-    ok = gen_server:cast(?MODULE, {config_update, NewValue}).
-
-
 init({Mod, IdxState}) ->
-    ok = couch_config:register(fun ?MODULE:config_change/3),
+    ok = config:listen_for_changes(?MODULE, nil),
     DbName = Mod:get(db_name, IdxState),
     Resp = couch_util:with_db(DbName, fun(Db) ->
         case Mod:open(Db, IdxState) of
@@ -92,7 +90,7 @@ init({Mod, IdxState}) ->
         {ok, NewIdxState} ->
             {ok, UPid} = couch_index_updater:start_link(self(), Mod),
             {ok, CPid} = couch_index_compactor:start_link(self(), Mod),
-            Delay = couch_config:get("query_server_config", "commit_freq", "5"),
+            Delay = config:get("query_server_config", "commit_freq", "5"),
             MsDelay = 1000 * list_to_integer(Delay),
             State = #st{
                 mod=Mod,
@@ -288,6 +286,12 @@ handle_cast(_Mesg, State) ->
     {stop, unhandled_cast, State}.
 
 
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+    erlang:send_after(5000, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info(commit, #st{committed=true}=State) ->
     {noreply, State};
 handle_info(commit, State) ->
@@ -321,6 +325,12 @@ code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
 
+handle_config_change("query_server_config", "commit_freq", Val, _, _) ->
+    {ok, gen_server:cast(?MODULE, {config_update, Val})};
+handle_config_change(_, _, _, _, _) ->
+    {ok, nil}.
+
+
 maybe_restart_updater(#st{waiters=[]}) ->
     ok;
 maybe_restart_updater(#st{mod=Mod, idx_state=IdxState}=State) ->


[44/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Ignore couchdb.log


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/004f0869
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/004f0869
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/004f0869

Branch: refs/heads/1843-feature-bigcouch
Commit: 004f08692077b7d9cd8381b7e3fd0a9d3d1424f1
Parents: 0cbf6a9
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 23:42:24 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:56 2013 -0500

----------------------------------------------------------------------
 .gitignore | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/004f0869/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 1a67e25..3391f7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@ config.h.in
 config.log
 config.status
 configure
+couchdb.log
 couchdb.stderr
 couchdb.stdout
 cover/*


[47/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Fix core etap tests


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/86ba6dbe
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/86ba6dbe
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/86ba6dbe

Branch: refs/heads/1843-feature-bigcouch
Commit: 86ba6dbe513875df50f7e3e35cbd5975c38307ed
Parents: 91b5d70
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Mar 12 15:23:07 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:57 2013 -0500

----------------------------------------------------------------------
 share/www/script/test/oauth.js                  |   3 +-
 share/www/script/test/proxyauth.js              |   7 +-
 share/www/script/test/replication.js            |  20 +-
 share/www/script/test/replicator_db.js          |  11 +
 share/www/script/test/view_compaction.js        |  26 +-
 share/www/script/test/view_include_docs.js      |   2 +-
 share/www/script/test/view_update_seq.js        |  10 +-
 src/config/src/config_app.erl                   |  29 +-
 src/couch/src/couch_query_servers.erl           |  25 +-
 src/couch/src/couch_server.erl                  |   3 +-
 .../src/couch_replicator_manager.erl            | 351 ++++++++++++++-----
 test/etap/070-couch-db.t                        |   5 +-
 test/etap/071-couchdb-rapid-cycle.t             |   2 +-
 test/etap/072-cleanup.t                         |   2 +-
 test/etap/073-changes.t                         | 178 +++++-----
 test/etap/074-doc-update-conflicts.t            |  34 +-
 test/etap/075-auth-cache.t                      |   2 +-
 test/etap/076-file-compression.t                |   4 +-
 test/etap/077-couch-db-fast-db-delete-create.t  |  27 +-
 test/etap/080-config-get-set.t                  |   1 +
 test/etap/081-config-override.t                 |  14 +-
 test/etap/082-config-register.t                 |  55 ++-
 test/etap/121-stats-aggregates.t                |  13 +-
 test/etap/130-attachments-md5.t                 |   4 +-
 test/etap/140-attachment-comp.t                 |   4 +-
 test/etap/150-invalid-view-seq.t                |  19 +-
 test/etap/160-vhosts.t                          |   4 +-
 test/etap/171-os-daemons-config.t               |   4 +-
 test/etap/180-http-proxy.t                      |  14 +-
 test/etap/200-view-group-no-db-leaks.t          |   4 +-
 test/etap/201-view-group-shutdown.t             |   4 +-
 test/etap/210-os-proc-pool.t                    |   4 +-
 test/etap/220-compaction-daemon.t               |   4 +-
 test/etap/231-cors.t                            |   4 +-
 test/etap/test_util.erl.in                      |  31 +-
 35 files changed, 543 insertions(+), 381 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/share/www/script/test/oauth.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/oauth.js b/share/www/script/test/oauth.js
index 89d3779..96293f0 100644
--- a/share/www/script/test/oauth.js
+++ b/share/www/script/test/oauth.js
@@ -23,12 +23,14 @@ couchTests.oauth = function(debug) {
   var dbA = new CouchDB("test_suite_db_a", {"X-Couch-Full-Commit":"false"});
   var dbB = new CouchDB("test_suite_db_b", {"X-Couch-Full-Commit":"false"});
   var dbC = new CouchDB("test_suite_db_c", {"X-Couch-Full-Commit":"false"});
+  var dbD = new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"});
   dbA.deleteDb();
   dbA.createDb();
   dbB.deleteDb();
   dbB.createDb();
   dbC.deleteDb();
   dbC.createDb();
+  dbD.deleteDb();
 
   // Simple secret key generator
   function generateSecret(length) {
@@ -124,7 +126,6 @@ couchTests.oauth = function(debug) {
         "X-Couch-Full-Commit":"false",
         "Authorization": adminBasicAuthHeaderValue()
       });
-      usersDb.deleteDb();
         
       // Create a user
       var jasonUserDoc = CouchDB.prepareUserDoc({

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/share/www/script/test/proxyauth.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/proxyauth.js b/share/www/script/test/proxyauth.js
index 016cec5..1677a66 100644
--- a/share/www/script/test/proxyauth.js
+++ b/share/www/script/test/proxyauth.js
@@ -19,7 +19,9 @@ couchTests.proxyauth = function(debug) {
   var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
   
   if (debug) debugger;
-  
+ 
+  usersDb.deleteDb();
+
   // Simple secret key generator
   function generateSecret(length) {
     var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -33,7 +35,6 @@ couchTests.proxyauth = function(debug) {
   var secret = generateSecret(64);
   
   function TestFun() {
-    usersDb.deleteDb();
     db.deleteDb();
     db.createDb();
     
@@ -126,4 +127,4 @@ couchTests.proxyauth = function(debug) {
     TestFun
   );
   
-};
\ No newline at end of file
+};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/share/www/script/test/replication.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/replication.js b/share/www/script/test/replication.js
index fd60dd4..7e4ecc1 100644
--- a/share/www/script/test/replication.js
+++ b/share/www/script/test/replication.js
@@ -1359,17 +1359,24 @@ couchTests.replication = function(debug) {
   TEquals(true, repResult.ok);
   TEquals('string', typeof repResult._local_id);
 
-  var xhr = CouchDB.request("GET", "/_active_tasks");
-  var tasks = JSON.parse(xhr.responseText);
-
   TEquals(true, sourceDb.compact().ok);
   while (sourceDb.info().compact_running) {};
 
   TEquals(true, sourceDb.save(makeDocs(30, 31)[0]).ok);
   xhr = CouchDB.request("GET", "/_active_tasks");
 
-  var tasksAfter = JSON.parse(xhr.responseText);
-  TEquals(tasks.length, tasksAfter.length);
+  var xhr = CouchDB.request("GET", "/_active_tasks");
+  var tasks = JSON.parse(xhr.responseText);
+
+  var found_task = false;
+  for(var i = 0; i < tasks.length; i++) {
+    if(tasks[i].replication_id == repResult._local_id) {
+      found_task = true;
+      break;
+    }
+  }
+  TEquals(true, found_task);
+
   waitForSeq(sourceDb, targetDb);
   T(sourceDb.open("30") !== null);
 
@@ -1695,6 +1702,9 @@ couchTests.replication = function(debug) {
   TEquals(true, repResult.ok);
   TEquals('string', typeof repResult._local_id);
 
+  // Race conditions are awesome
+  wait(500);
+
   xhr = CouchDB.request("GET", "/_active_tasks");
   tasks = JSON.parse(xhr.responseText);
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/share/www/script/test/replicator_db.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/replicator_db.js b/share/www/script/test/replicator_db.js
index edc85f4..230acd5 100644
--- a/share/www/script/test/replicator_db.js
+++ b/share/www/script/test/replicator_db.js
@@ -240,6 +240,8 @@ couchTests.replicator_db = function(debug) {
     T(copy !== null);
     T(copy.value === 1001);
 
+    wait(250);
+
     var repDoc1 = repDb.open(repDoc._id);
     T(repDoc1 !== null);
     T(repDoc1.source === repDoc.source);
@@ -276,6 +278,8 @@ couchTests.replicator_db = function(debug) {
     // stop replication by deleting the replication document
     T(repDb.deleteDoc(repDoc1).ok);
 
+    wait(200);
+
     // add another doc to source, it will NOT be replicated to target
     var docY = {
       _id: "foo666",
@@ -498,6 +502,8 @@ couchTests.replicator_db = function(debug) {
       T(copy.value === doc.value);
     }
 
+    wait(250);
+
     repDoc1 = repDb.open("foo_dup_cont_rep_doc_1");
     T(repDoc1 !== null);
     T(repDoc1._replication_state === "triggered");
@@ -542,6 +548,8 @@ couchTests.replicator_db = function(debug) {
 
     // deleting the 1st replication document stops the replication
     T(repDb.deleteDoc(repDoc1).ok);
+    wait(wait_rep_doc); //how to remove wait?
+
     var newDoc3 = {
         _id: "foo1983",
         value: 1983
@@ -655,6 +663,7 @@ couchTests.replicator_db = function(debug) {
       "GET", "/_config/replicator/db").responseText;
 
     repDb.deleteDb();
+    repDb.createDb();
 
     var xhr = CouchDB.request("PUT", "/_config/replicator/db", {
       body : JSON.stringify(repDb.name),
@@ -807,6 +816,8 @@ couchTests.replicator_db = function(debug) {
     TEquals("joe", CouchDB.session().userCtx.name);
     TEquals(-1, CouchDB.session().userCtx.roles.indexOf("_admin"));
 
+    wait(500);
+
     var repDoc = {
       _id: "foo_rep",
       source: CouchDB.protocol + CouchDB.host + "/" + dbA.name,

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/share/www/script/test/view_compaction.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/view_compaction.js b/share/www/script/test/view_compaction.js
index 151ce93..35d6276 100644
--- a/share/www/script/test/view_compaction.js
+++ b/share/www/script/test/view_compaction.js
@@ -27,7 +27,7 @@ couchTests.view_compaction = function(debug) {
         map: "function(doc) { emit(doc._id, doc.value) }"
       },
       view2: {
-        map: "function(doc) { emit(doc._id, doc.value); }",
+        map: "function(doc) { if (typeof(doc.integer) === 'number') {emit(doc._id, doc.integer);} }",
         reduce: "function(keys, values, rereduce) { return sum(values); }"
       }
     }
@@ -38,13 +38,13 @@ couchTests.view_compaction = function(debug) {
   db.bulkSave(docs);
 
   var resp = db.view('foo/view1', {});
-  T(resp.rows.length === 10000);
+  TEquals(10000, resp.rows.length);
 
   resp = db.view('foo/view2', {});
-  T(resp.rows.length === 1);
+  TEquals(1, resp.rows.length);
 
   resp = db.designInfo("_design/foo");
-  T(resp.view_index.update_seq === 10001);
+  TEquals(10001, resp.view_index.update_seq);
 
 
   // update docs
@@ -55,13 +55,13 @@ couchTests.view_compaction = function(debug) {
 
 
   resp = db.view('foo/view1', {});
-  T(resp.rows.length === 10000);
+  TEquals(10000, resp.rows.length);
 
   resp = db.view('foo/view2', {});
-  T(resp.rows.length === 1);
+  TEquals(1, resp.rows.length);
 
   resp = db.designInfo("_design/foo");
-  T(resp.view_index.update_seq === 20001);
+  TEquals(20001, resp.view_index.update_seq);
 
 
   // update docs again...
@@ -72,13 +72,13 @@ couchTests.view_compaction = function(debug) {
 
 
   resp = db.view('foo/view1', {});
-  T(resp.rows.length === 10000);
+  TEquals(10000, resp.rows.length);
 
   resp = db.view('foo/view2', {});
-  T(resp.rows.length === 1);
+  TEquals(1, resp.rows.length);
 
   resp = db.designInfo("_design/foo");
-  T(resp.view_index.update_seq === 30001);
+  TEquals(30001, resp.view_index.update_seq);
 
   var disk_size_before_compact = resp.view_index.disk_size;
   var data_size_before_compact = resp.view_index.data_size;
@@ -97,13 +97,13 @@ couchTests.view_compaction = function(debug) {
 
 
   resp = db.view('foo/view1', {});
-  T(resp.rows.length === 10000);
+  TEquals(10000, resp.rows.length);
 
   resp = db.view('foo/view2', {});
-  T(resp.rows.length === 1);
+  TEquals(1, resp.rows.length);
 
   resp = db.designInfo("_design/foo");
-  T(resp.view_index.update_seq === 30001);
+  TEquals(30001, resp.view_index.update_seq);
   T(resp.view_index.disk_size < disk_size_before_compact);
   TEquals("number", typeof resp.view_index.data_size, "data size is a number");
   T(resp.view_index.data_size < resp.view_index.disk_size, "data size < file size");

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/share/www/script/test/view_include_docs.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/view_include_docs.js b/share/www/script/test/view_include_docs.js
index 944c910..dab79b8 100644
--- a/share/www/script/test/view_include_docs.js
+++ b/share/www/script/test/view_include_docs.js
@@ -33,7 +33,7 @@ couchTests.view_include_docs = function(debug) {
         map: "function(doc) {if(doc.link_id) { var value = {'_id':doc.link_id}; if (doc.link_rev) {value._rev = doc.link_rev}; emit(doc._id, value);}};"
       },
       summate: {
-        map:"function (doc) {emit(doc.integer, doc.integer)};",
+        map:"function (doc) { if (typeof doc.integer === 'number') {emit(doc.integer, doc.integer)};}",
         reduce:"function (keys, values) { return sum(values); };"
       }
     }

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/share/www/script/test/view_update_seq.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/view_update_seq.js b/share/www/script/test/view_update_seq.js
index 69b8c42..df92b11 100644
--- a/share/www/script/test/view_update_seq.js
+++ b/share/www/script/test/view_update_seq.js
@@ -31,7 +31,7 @@ couchTests.view_update_seq = function(debug) {
         map: "function(doc) { emit(doc.integer, doc.string) }"
       },
       summate: {
-        map:"function (doc) {emit(doc.integer, doc.integer)};",
+        map:"function (doc) { if (typeof doc.integer === 'number') { emit(doc.integer, doc.integer)}; }",
         reduce:"function (keys, values) { return sum(values); };"
       }
     }
@@ -68,12 +68,12 @@ couchTests.view_update_seq = function(debug) {
   T(resp.rows.length == 1);
   T(resp.update_seq == 101);
 
-  db.save({"id":"0"});
+  db.save({"id":"0", "integer": 1});
   resp = db.view('test/all_docs', {limit: 1,stale: "ok", update_seq:true});
   T(resp.rows.length == 1);
   T(resp.update_seq == 101);
 
-  db.save({"id":"00"});
+  db.save({"id":"00", "integer": 2});
   resp = db.view('test/all_docs',
     {limit: 1, stale: "update_after", update_seq: true});
   T(resp.rows.length == 1);
@@ -100,7 +100,7 @@ couchTests.view_update_seq = function(debug) {
   resp = db.view('test/all_docs',{update_seq:true},["0","1"]);
   T(resp.update_seq == 103);
 
-  resp = db.view('test/summate',{group:true, update_seq:true},["0","1"]);
-  T(resp.update_seq == 103);
+  resp = db.view('test/summate',{group:true, update_seq:true},[0,1]);
+  TEquals(103, resp.update_seq);
 
 };

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/src/config/src/config_app.erl
----------------------------------------------------------------------
diff --git a/src/config/src/config_app.erl b/src/config/src/config_app.erl
index 54f2433..5c5515a 100644
--- a/src/config/src/config_app.erl
+++ b/src/config/src/config_app.erl
@@ -28,14 +28,25 @@ stop(_State) ->
     ok.
 
 get_ini_files() ->
-    Etc = filename:join(code:root_dir(), "etc"),
-    Default = [filename:join(Etc,"default.ini"), filename:join(Etc,"local.ini")],
-    DefaultExists = lists:filter(fun filelib:is_file/1, Default),
+    hd([L || L <- [command_line(), env(), default()], L =/= skip]).
+
+env() ->
+    case application:get_env(config, ini_files) of
+        undefined ->
+            skip;
+        {ok, IniFiles} ->
+            IniFiles
+    end.
+
+command_line() ->
     case init:get_argument(couch_ini) of
-    error ->
-        DefaultExists;
-    {ok, [[]]} ->
-        DefaultExists;
-    {ok, [Values]} ->
-        Values
+        error ->
+            skip;
+        {ok, [IniFiles]} ->
+            IniFiles
     end.
+
+default() ->
+    Etc = filename:join(code:root_dir(), "etc"),
+    Default = [filename:join(Etc,"default.ini"), filename:join(Etc,"local.ini")],
+    lists:filter(fun filelib:is_file/1, Default).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 8e4130e..4fef028 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -26,12 +26,12 @@
 -include_lib("couch/include/couch_db.hrl").
 
 -define(SUMERROR, <<"The _sum function requires that map values be numbers, "
-    "arrays of numbers, or objects. Objects cannot be mixed with other data "
-    "structures. Objects can be arbitrarily nested, provided that the values "
+    "arrays of numbers, or objects, not '~p'. Objects cannot be mixed with other "
+    "data structures. Objects can be arbitrarily nested, provided that the values "
     "for all fields are themselves numbers, arrays of numbers, or objects.">>).
 
 -define(STATERROR, <<"The _stats function requires that map values be numbers "
-    "or arrays of numbers.">>).
+    "or arrays of numbers, not '~p'">>).
 
 % https://gist.github.com/df10284c76d85f988c3f
 -define(SUMREGEX, {re_pattern,3,0,<<69,82,67,80,194,0,0,0,8,0,0,0,5,0,0,0,3,0,
@@ -238,8 +238,8 @@ sum_values(Value, Acc) when is_number(Value), is_list(Acc) ->
     sum_arrays(Acc, [Value]);
 sum_values(Value, Acc) when is_list(Value), is_number(Acc) ->
     sum_arrays([Acc], Value);
-sum_values(_Else, _Acc) ->
-    throw({invalid_value, ?SUMERROR}).
+sum_values(Else, _Acc) ->
+    throw_sum_error(Else).
 
 sum_objects([{K1, V1} | Rest1], [{K1, V2} | Rest2]) ->
     [{K1, sum_values(V1, V2)} | sum_objects(Rest1, Rest2)];
@@ -260,8 +260,8 @@ sum_arrays([], [_|_]=Ys) ->
     Ys;
 sum_arrays([X|Xs], [Y|Ys]) when is_number(X), is_number(Y) ->
     [X+Y | sum_arrays(Xs,Ys)];
-sum_arrays(_, _) ->
-    throw({invalid_value, ?SUMERROR}).
+sum_arrays(Else, _) ->
+    throw_sum_error(Else).
 
 builtin_stats(_, []) ->
     {[{sum,0}, {count,0}, {min,0}, {max,0}, {sumsqr,0}]};
@@ -288,8 +288,8 @@ stat_values(Value, Acc) when is_tuple(Value), is_tuple(Acc) ->
       erlang:max(Max0, Max1),
       Sqr0 + Sqr1
     };
-stat_values(_Else, _Acc) ->
-    throw({invalid_value, ?STATERROR}).
+stat_values(Else, _Acc) ->
+    throw_stat_error(Else).
 
 build_initial_accumulator(L) when is_list(L) ->
     [build_initial_accumulator(X) || X <- L];
@@ -445,6 +445,13 @@ ret_os_process(Proc) ->
     catch unlink(Proc#proc.pid),
     ok.
 
+throw_sum_error(Else) ->
+    throw({invalid_value, iolist_to_binary(io_lib:format(?SUMERROR, [Else]))}).
+
+throw_stat_error(Else) ->
+    throw({invalid_value, iolist_to_binary(io_lib:format(?STATERROR, [Else]))}).
+
+
 -ifdef(TEST).
 -include_lib("eunit/include/eunit.hrl").
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/src/couch/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index 80448b1..e4de69e 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -67,7 +67,8 @@ sup_start_link() ->
     gen_server:start_link({local, couch_server}, couch_server, [], []).
 
 
-open(DbName, Options) ->
+open(DbName, Options0) ->
+    Options = maybe_add_sys_db_callbacks(DbName, Options0),
     Ctx = couch_util:get_value(user_ctx, Options, #user_ctx{}),
     case ets:lookup(couch_dbs, DbName) of
     [#db{fd=Fd, fd_monitor=Lock} = Db] when Lock =/= locked ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/src/couch_replicator/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator/src/couch_replicator_manager.erl b/src/couch_replicator/src/couch_replicator_manager.erl
index c213199..047f573 100644
--- a/src/couch_replicator/src/couch_replicator_manager.erl
+++ b/src/couch_replicator/src/couch_replicator_manager.erl
@@ -17,6 +17,7 @@
 % public API
 -export([replication_started/1, replication_completed/2, replication_error/2]).
 
+-export([before_doc_update/2, after_doc_read/2]).
 
 % gen_server callbacks
 -export([start_link/0, init/1, handle_call/3, handle_info/2, handle_cast/2]).
@@ -50,8 +51,6 @@
 }).
 
 -import(couch_util, [
-    get_value/2,
-    get_value/3,
     to_binary/1
 ]).
 
@@ -108,6 +107,9 @@ replication_error(#rep{id = {BaseId, _} = RepId}, Error) ->
     end.
 
 
+handle_config_change("replicator", "db", _, _, S) ->
+    ok = gen_server:call(S, rep_db_changed),
+    remove_handler;
 handle_config_change("replicator", "max_replication_retry_count", V, _, S) ->
     ok = gen_server:cast(S, {set_max_retries, retries_value(V)}),
     {ok, S};
@@ -124,11 +126,15 @@ init(_) ->
     Server = self(),
     ok = config:listen_for_changes(?MODULE, Server),
     ScanPid = spawn_link(fun() -> scan_all_dbs(Server) end),
+    % Automatically start node local changes feed loop
+    LocalRepDb = ?l2b(config:get("replicator", "db", "_replicator")),
+    Pid = changes_feed_loop(LocalRepDb, 0),
     {ok, #state{
         db_notifier = db_update_notifier(),
         scan_pid = ScanPid,
         max_retries = retries_value(
-            config:get("replicator", "max_replication_retry_count", "10"))
+            config:get("replicator", "max_replication_retry_count", "10")),
+        rep_start_pids = [Pid]
     }}.
 
 
@@ -137,8 +143,8 @@ handle_call({rep_db_update, DbName, {ChangeProps} = Change}, _From, State) ->
         process_update(State, DbName, Change)
     catch
     _Tag:Error ->
-        {RepProps} = get_value(doc, ChangeProps),
-        DocId = get_value(<<"_id">>, RepProps),
+        {RepProps} = get_json_value(doc, ChangeProps),
+        DocId = get_json_value(<<"_id">>, RepProps),
         rep_db_update_error(Error, DbName, DocId),
         State
     end,
@@ -180,6 +186,9 @@ handle_call({rep_db_checkpoint, DbName, EndSeq}, _From, State) ->
     true = ets:insert(?DB_TO_SEQ, {DbName, EndSeq}),
     {reply, ok, State};
 
+handle_call(rep_db_changed, _From, State) ->
+    {stop, shutdown, ok, State};
+
 handle_call(Msg, From, State) ->
     twig:log(error, "Replication manager received unexpected call ~p from ~p",
         [Msg, From]),
@@ -256,7 +265,7 @@ terminate(_Reason, State) ->
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
-changes_feed_loop(DbName, Since) ->
+changes_feed_loop(<<"shards/", _/binary>>=DbName, Since) ->
     Server = self(),
     Pid = spawn_link(
         fun() ->
@@ -286,11 +295,42 @@ changes_feed_loop(DbName, Since) ->
                 }
             )
         end),
-    Pid.
+    Pid;
+changes_feed_loop(DbName, Since) ->
+    ensure_rep_db_exists(DbName),
+    Server = self(),
+    spawn_link(fun() ->
+        UserCtx = #user_ctx{roles = [<<"_admin">>, <<"_replicator">>]},
+        DbOpenOptions = [{user_ctx, UserCtx}, sys_db],
+        {ok, Db} = couch_db:open_int(DbName, DbOpenOptions),
+        ChangesFeedFun = couch_changes:handle_changes(
+            #changes_args{
+                include_docs = true,
+                since = Since,
+                feed = "continuous",
+                timeout = infinity
+            },
+            {json_req, null},
+            Db
+        ),
+        EnumFun = fun
+        ({change, Change, _}, _) ->
+            case has_valid_rep_id(Change) of
+                true ->
+                    Msg = {rep_db_update, DbName, Change},
+                    ok = gen_server:call(Server, Msg, infinity);
+                false ->
+                    ok
+            end;
+        (_, _) ->
+            ok
+        end,
+        ChangesFeedFun(EnumFun)
+    end).
 
 
 has_valid_rep_id({Change}) ->
-    has_valid_rep_id(get_value(<<"id">>, Change));
+    has_valid_rep_id(get_json_value(<<"id">>, Change));
 has_valid_rep_id(<<?DESIGN_DOC_PREFIX, _Rest/binary>>) ->
     false;
 has_valid_rep_id(_Else) ->
@@ -299,22 +339,24 @@ has_valid_rep_id(_Else) ->
 db_update_notifier() ->
     Server = self(),
     IsReplicatorDbFun = is_replicator_db_fun(),
-    {ok, Notifier} = couch_db_update_notifier:start_link(
-        fun({updated, DbName}) ->
-            case IsReplicatorDbFun(DbName) of
-            true ->
-                ok = gen_server:call(Server, {resume_scan, mem3:dbname(DbName)}, infinity);
-            _ ->
-                ok
-            end;
-           ({deleted, DbName}) ->
-            case IsReplicatorDbFun(DbName) of
-            true ->
-                clean_up_replications(mem3:dbname(DbName));
-            _ ->
-                ok
+    {ok, Notifier} = couch_db_update_notifier:start_link(fun
+        ({Event, ShardDbName})
+                when Event == created; Event == updated; Event == deleted ->
+            DbName = mem3:dbname(ShardDbName),
+            IsRepDb = IsReplicatorDbFun(DbName),
+            case Event of
+                created when IsRepDb ->
+                    ensure_rep_ddoc_exists(DbName);
+                updated when IsRepDb ->
+                    ensure_rep_ddoc_exists(DbName),
+                    Msg = {resume_scan, DbName},
+                    ok = gen_server:call(Server, Msg, infinity);
+                deleted when IsRepDb ->
+                    clean_up_replications(DbName);
+                _ ->
+                    ok
             end;
-           (_) ->
+        (_Event) ->
             ok
         end
     ),
@@ -331,9 +373,9 @@ rescan(#state{scan_pid = ScanPid} = State) ->
     rescan(State#state{scan_pid = nil}).
 
 process_update(State, DbName, {Change}) ->
-    {RepProps} = JsonRepDoc = get_value(doc, Change),
-    DocId = get_value(<<"_id">>, RepProps),
-    case {mem3_util:owner(DbName, DocId), get_value(deleted, Change, false)} of
+    {RepProps} = JsonRepDoc = get_json_value(doc, Change),
+    DocId = get_json_value(<<"_id">>, RepProps),
+    case {is_owner(DbName, DocId), get_json_value(deleted, Change, false)} of
     {false, _} ->
         replication_complete(DbName, DocId),
         State;
@@ -341,7 +383,7 @@ process_update(State, DbName, {Change}) ->
         rep_doc_deleted(DbName, DocId),
         State;
     {true, false} ->
-        case get_value(<<"_replication_state">>, RepProps) of
+        case get_json_value(<<"_replication_state">>, RepProps) of
         undefined ->
             maybe_start_replication(State, DbName, DocId, JsonRepDoc);
         <<"triggered">> ->
@@ -359,6 +401,13 @@ process_update(State, DbName, {Change}) ->
         end
     end.
 
+
+is_owner(<<"shards/", _/binary>>=DbName, DocId) ->
+    mem3_util:owner(DbName, DocId);
+is_owner(_, _) ->
+    true.
+
+
 rep_db_update_error(Error, DbName, DocId) ->
     case Error of
     {bad_rep_doc, Reason} ->
@@ -372,13 +421,13 @@ rep_db_update_error(Error, DbName, DocId) ->
 
 
 rep_user_ctx({RepDoc}) ->
-    case get_value(<<"user_ctx">>, RepDoc) of
+    case get_json_value(<<"user_ctx">>, RepDoc) of
     undefined ->
         #user_ctx{};
     {UserCtx} ->
         #user_ctx{
-            name = get_value(<<"name">>, UserCtx, null),
-            roles = get_value(<<"roles">>, UserCtx, [])
+            name = get_json_value(<<"name">>, UserCtx, null),
+            roles = get_json_value(<<"roles">>, UserCtx, [])
         }
     end.
 
@@ -428,7 +477,7 @@ parse_rep_doc(RepDoc) ->
 
 
 maybe_tag_rep_doc(DbName, DocId, {RepProps}, RepId) ->
-    case get_value(<<"_replication_id">>, RepProps) of
+    case get_json_value(<<"_replication_id">>, RepProps) of
     RepId ->
         ok;
     _ ->
@@ -546,42 +595,26 @@ clean_up_replications(DbName) ->
 
 
 update_rep_doc(RepDbName, RepDocId, KVs) when is_binary(RepDocId) ->
-    {Pid, Ref} =
-    spawn_monitor(fun() ->
-        try
-            case fabric:open_doc(mem3:dbname(RepDbName), RepDocId, []) of
-                {ok, LatestRepDoc} ->
-                    update_rep_doc(RepDbName, LatestRepDoc, KVs);
-                _ ->
-                    ok
-            end
-        catch
+    try
+        case open_rep_doc(RepDbName, RepDocId) of
+            {ok, LastRepDoc} ->
+                update_rep_doc(RepDbName, LastRepDoc, KVs);
+            _ ->
+                ok
+        end
+    catch
         throw:conflict ->
-            % a race condition may cause an update conflict,
-            % in which cae update_rep_doc is called again to refetch
-            twig:log(error, "Conflict error when updating replication document `~s`."
-                         " Retrying.", [RepDocId]),
+            Msg = "Conflict when updating replication document `~s`. Retrying.",
+            twig:log(error, Msg, [RepDocId]),
             ok = timer:sleep(5),
-            update_rep_doc(RepDbName, RepDocId, KVs);
-        Type:Error ->
-            exit({Type, Error})
-        end
-    end),
-    receive
-    {'DOWN', Ref, process, Pid, normal} ->
-        ok;
-    {'DOWN', Ref, process, Pid, {throw, Error}} ->
-        throw(Error);
-    {'DOWN', Ref, process, Pid, {error, Error}} ->
-        erlang:error(Error)
+            update_rep_doc(RepDbName, RepDocId, KVs)
     end;
-
 update_rep_doc(RepDbName, #doc{body = {RepDocBody}} = RepDoc, KVs) ->
     NewRepDocBody = lists:foldl(
         fun({K, undefined}, Body) ->
                 lists:keydelete(K, 1, Body);
            ({<<"_replication_state">> = K, State} = KV, Body) ->
-                case get_value(K, Body) of
+                case get_json_value(K, Body) of
                 State ->
                     Body;
                 _ ->
@@ -600,9 +633,55 @@ update_rep_doc(RepDbName, #doc{body = {RepDocBody}} = RepDoc, KVs) ->
     _ ->
         % Might not succeed - when the replication doc is deleted right
         % before this update (not an error, ignore).
-        fabric:update_doc(RepDbName, RepDoc#doc{body = {NewRepDocBody}}, [?CTX])
+        save_rep_doc(RepDbName, RepDoc#doc{body = {NewRepDocBody}})
+    end.
+
+
+open_rep_doc(<<"shards/", _/binary>>=ShardDbName, DocId) ->
+    defer_call(fun() ->
+        fabric:open_doc(mem3:dbname(ShardDbName), DocId, [])
+    end);
+open_rep_doc(DbName, DocId) ->
+    {ok, Db} = couch_db:open_int(DbName, [?CTX, sys_db]),
+    try
+        couch_db:open_doc(Db, DocId, [ejson_body])
+    after
+        couch_db:close(Db)
+    end.
+
+save_rep_doc(<<"shards/", _/binary>>=DbName, Doc) ->
+    defer_call(fun() ->
+        fabric:update_doc(DbName, Doc, [?CTX])
+    end);
+save_rep_doc(DbName, Doc) ->
+    {ok, Db} = couch_db:open_int(DbName, [?CTX, sys_db]),
+    try
+        couch_db:update_doc(Db, Doc, [])
+    after
+        couch_db:close(Db)
     end.
 
+defer_call(Fun) ->
+    {Pid, Ref} = erlang:spawn_monitor(fun() ->
+        try
+            exit({exit_ok, Fun()})
+        catch
+            Type:Reason ->
+                exit({exit_err, Type, Reason})
+        end
+    end),
+    receive
+        {'DOWN', Ref, process, Pid, {exit_ok, Resp}} ->
+            Resp;
+        {'DOWN', Ref, process, Pid, {exit_err, throw, Error}} ->
+            throw(Error);
+        {'DOWN', Ref, process, Pid, {exit_err, error, Error}} ->
+            erlang:error(Error);
+        {'DOWN', Ref, process, Pid, {exit_err, exit, Error}} ->
+            exit(Error)
+    end.
+
+
 % RFC3339 timestamps.
 % Note: doesn't include the time seconds fraction (RFC3339 says it's optional).
 timestamp() ->
@@ -623,31 +702,38 @@ zone(Hr, Min) ->
     io_lib:format("-~2..0w:~2..0w", [abs(Hr), abs(Min)]).
 
 
-ensure_rep_db_exists() ->
-    DbName = ?l2b(couch_config:get("replicator", "db", "_replicator")),
-    UserCtx = #user_ctx{roles = [<<"_admin">>, <<"_replicator">>]},
-    case couch_db:open_int(DbName, [sys_db, {user_ctx, UserCtx}, nologifmissing]) of
-    {ok, Db} ->
-        Db;
-    _Error ->
-        {ok, Db} = couch_db:create(DbName, [sys_db, {user_ctx, UserCtx}])
+ensure_rep_db_exists(DbName) ->
+    Db = case couch_db:open_int(DbName, [?CTX, sys_db, nologifmissing]) of
+        {ok, Db0} ->
+            Db0;
+        _Error ->
+            {ok, Db0} = couch_db:create(DbName, [?CTX, sys_db]),
+            Db0
     end,
-    ensure_rep_ddoc_exists(Db, <<"_design/_replicator">>),
+    ensure_rep_ddoc_exists(DbName),
     {ok, Db}.
 
 
-ensure_rep_ddoc_exists(RepDb, DDocID) ->
-    case couch_db:open_doc(RepDb, DDocID, []) of
-    {ok, _Doc} ->
-        ok;
-    _ ->
-        DDoc = couch_doc:from_json_obj({[
-            {<<"_id">>, DDocID},
-            {<<"language">>, <<"javascript">>},
-            {<<"validate_doc_update">>, ?REP_DB_DOC_VALIDATE_FUN}
-        ]}),
-        {ok, _Rev} = couch_db:update_doc(RepDb, DDoc, [])
-     end.
+ensure_rep_ddoc_exists(RepDb) ->
+    DDocId = <<"_design/_replicator">>,
+    case open_rep_doc(RepDb, DDocId) of
+        {ok, _Doc} ->
+            ok;
+        _ ->
+            DDoc = couch_doc:from_json_obj({[
+                {<<"_id">>, DDocId},
+                {<<"language">>, <<"javascript">>},
+                {<<"validate_doc_update">>, ?REP_DB_DOC_VALIDATE_FUN}
+            ]}),
+            try
+                {ok, _} = save_rep_doc(RepDb, DDoc)
+            catch
+                throw:conflict ->
+                    % NFC what to do about this other than
+                    % not kill the process.
+                    ok
+            end
+    end.
 
 
 % pretty-print replication id
@@ -687,20 +773,85 @@ state_after_error(#rep_state{retries_left = Left, wait = Wait} = State) ->
         State#rep_state{retries_left = Left - 1, wait = Wait2}
     end.
 
+
+before_doc_update(#doc{id = <<?DESIGN_DOC_PREFIX, _/binary>>} = Doc, _Db) ->
+    Doc;
+before_doc_update(#doc{body = {Body}} = Doc, #db{user_ctx=UserCtx} = Db) ->
+    #user_ctx{roles = Roles, name = Name} = UserCtx,
+    case lists:member(<<"_replicator">>, Roles) of
+    true ->
+        Doc;
+    false ->
+        case couch_util:get_value(?OWNER, Body) of
+        undefined ->
+            Doc#doc{body = {?replace(Body, ?OWNER, Name)}};
+        Name ->
+            Doc;
+        Other ->
+            case (catch couch_db:check_is_admin(Db)) of
+            ok when Other =:= null ->
+                Doc#doc{body = {?replace(Body, ?OWNER, Name)}};
+            ok ->
+                Doc;
+            _ ->
+                throw({forbidden, <<"Can't update replication documents",
+                    " from other users.">>})
+            end
+        end
+    end.
+
+
+after_doc_read(#doc{id = <<?DESIGN_DOC_PREFIX, _/binary>>} = Doc, _Db) ->
+    Doc;
+after_doc_read(#doc{body = {Body}} = Doc, #db{user_ctx=UserCtx} = Db) ->
+    #user_ctx{name = Name} = UserCtx,
+    case (catch couch_db:check_is_admin(Db)) of
+    ok ->
+        Doc;
+    _ ->
+        case couch_util:get_value(?OWNER, Body) of
+        Name ->
+            Doc;
+        _Other ->
+            Source = strip_credentials(couch_util:get_value(<<"source">>,
+Body)),
+            Target = strip_credentials(couch_util:get_value(<<"target">>,
+Body)),
+            NewBody0 = ?replace(Body, <<"source">>, Source),
+            NewBody = ?replace(NewBody0, <<"target">>, Target),
+            #doc{revs = {Pos, [_ | Revs]}} = Doc,
+            NewDoc = Doc#doc{body = {NewBody}, revs = {Pos - 1, Revs}},
+            NewRevId = couch_db:new_revid(NewDoc),
+            NewDoc#doc{revs = {Pos, [NewRevId | Revs]}}
+        end
+    end.
+
+strip_credentials(Url) when is_binary(Url) ->
+    re:replace(Url,
+        "http(s)?://(?:[^:]+):[^@]+@(.*)$",
+        "http\\1://\\2",
+        [{return, binary}]);
+strip_credentials({Props}) ->
+    {lists:keydelete(<<"oauth">>, 1, Props)}.
+
 scan_all_dbs(Server) when is_pid(Server) ->
-    {ok, Db} = mem3_util:ensure_exists(
-        config:get("mem3", "shard_db", "dbs")),
+    {ok, Db} = mem3_util:ensure_exists(config:get("mem3", "shard_db", "dbs")),
     ChangesFun = couch_changes:handle_changes(#changes_args{}, nil, Db),
     IsReplicatorDbFun = is_replicator_db_fun(),
     ChangesFun(fun({change, {Change}, _}, _) ->
-        DbName = couch_util:get_value(<<"id">>, Change),
+        DbName = get_json_value(<<"id">>, Change),
         case DbName of <<"_design/", _/binary>> -> ok; _Else ->
             case couch_replicator_utils:is_deleted(Change) of
             true ->
                 ok;
             false ->
-                IsReplicatorDbFun(DbName) andalso
-                gen_server:call(Server, {resume_scan, DbName})
+                case IsReplicatorDbFun(DbName) of
+                    true ->
+                        ensure_rep_ddoc_exists(DbName),
+                        gen_server:call(Server, {resume_scan, DbName});
+                    false ->
+                        ok
+                end
             end
         end;
         (_, _) -> ok
@@ -709,6 +860,30 @@ scan_all_dbs(Server) when is_pid(Server) ->
 
 is_replicator_db_fun() ->
     {ok, RegExp} = re:compile("^([a-z][a-z0-9\\_\\$()\\+\\-\\/]*/)?_replicator$"),
-    fun(DbName) ->
-        match =:= re:run(mem3:dbname(DbName), RegExp, [{capture,none}])
+    fun
+        (<<"shards/", _/binary>>=DbName) ->
+            match =:= re:run(mem3:dbname(DbName), RegExp, [{capture,none}]);
+        (DbName) ->
+            LocalRepDb = ?l2b(config:get("replicator", "db", "_replicator")),
+            DbName == LocalRepDb
+    end.
+
+get_json_value(Key, Props) ->
+    get_json_value(Key, Props, undefined).
+
+get_json_value(Key, Props, Default) when is_atom(Key) ->
+    Ref = make_ref(),
+    case couch_util:get_value(Key, Props, Ref) of
+        Ref ->
+            couch_util:get_value(?l2b(atom_to_list(Key)), Props, Default);
+        Else ->
+            Else
+    end;
+get_json_value(Key, Props, Default) when is_binary(Key) ->
+    Ref = make_ref(),
+    case couch_util:get_value(Key, Props, Ref) of
+        Ref ->
+            couch_util:get_value(list_to_atom(?b2l(Key)), Props, Default);
+        Else ->
+            Else
     end.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/070-couch-db.t
----------------------------------------------------------------------
diff --git a/test/etap/070-couch-db.t b/test/etap/070-couch-db.t
index 787d6c6..5fa9344 100755
--- a/test/etap/070-couch-db.t
+++ b/test/etap/070-couch-db.t
@@ -22,13 +22,13 @@ main(_) ->
             etap:end_tests();
         Other ->
             etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
+            timer:sleep(1000),
             etap:bail(Other)
     end,
     ok.
 
 test() ->
-
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
 
     couch_db:create(<<"etap-test-db">>, []),
     {ok, AllDbs} = couch_server:all_databases(),
@@ -70,4 +70,5 @@ test() ->
     end, 0, lists:seq(1, 6)),
     etap:is(6, NumDeleted, "Deleted all databases."),
 
+    ok = test_util:stop_couch(),
     ok.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/071-couchdb-rapid-cycle.t
----------------------------------------------------------------------
diff --git a/test/etap/071-couchdb-rapid-cycle.t b/test/etap/071-couchdb-rapid-cycle.t
index 80b0d72..2e86483 100755
--- a/test/etap/071-couchdb-rapid-cycle.t
+++ b/test/etap/071-couchdb-rapid-cycle.t
@@ -30,7 +30,7 @@ main(_) ->
 dbname() -> <<"etap-test-db">>.
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     timer:sleep(500),
 
     couch_server:delete(dbname(), []),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/072-cleanup.t
----------------------------------------------------------------------
diff --git a/test/etap/072-cleanup.t b/test/etap/072-cleanup.t
index 83b8a6b..4792377 100755
--- a/test/etap/072-cleanup.t
+++ b/test/etap/072-cleanup.t
@@ -40,7 +40,7 @@ main(_) ->
 
 test() ->
 
-    {ok, _} = couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     couch_server:delete(?TEST_DB, []),
     timer:sleep(1000),
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/073-changes.t
----------------------------------------------------------------------
diff --git a/test/etap/073-changes.t b/test/etap/073-changes.t
index 845cd79..2e70cc4 100755
--- a/test/etap/073-changes.t
+++ b/test/etap/073-changes.t
@@ -16,6 +16,8 @@
 % target of a replication doesn't affect the replication and that the
 % replication doesn't hold their reference counters forever.
 
+-mode(compile).
+
 -record(user_ctx, {
     name = null,
     roles = [],
@@ -49,21 +51,11 @@ test_db_name() -> <<"couch_test_changes">>.
 
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(43),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    ok.
+    test_util:run(43, fun() -> test() end).
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
 
     test_by_doc_ids(),
     test_by_doc_ids_with_since(),
@@ -71,22 +63,21 @@ test() ->
     test_design_docs_only(),
     test_heartbeat(),
 
-    couch_server_sup:stop(),
     ok.
 
 
 test_by_doc_ids() ->
-    {ok, Db} = create_db(test_db_name()),
-
-    {ok, _Rev1} = save_doc(Db, {[{<<"_id">>, <<"doc1">>}]}),
-    {ok, _Rev2} = save_doc(Db, {[{<<"_id">>, <<"doc2">>}]}),
-    {ok, Rev3} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}]}),
-    {ok, _Rev4} = save_doc(Db, {[{<<"_id">>, <<"doc4">>}]}),
-    {ok, _Rev5} = save_doc(Db, {[{<<"_id">>, <<"doc5">>}]}),
-    {ok, _Rev3_2} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3}]}),
-    {ok, _Rev6} = save_doc(Db, {[{<<"_id">>, <<"doc6">>}]}),
-    {ok, _Rev7} = save_doc(Db, {[{<<"_id">>, <<"doc7">>}]}),
-    {ok, _Rev8} = save_doc(Db, {[{<<"_id">>, <<"doc8">>}]}),
+    create_db(test_db_name()),
+
+    {ok, _Rev1} = save_doc({[{<<"_id">>, <<"doc1">>}]}),
+    {ok, _Rev2} = save_doc({[{<<"_id">>, <<"doc2">>}]}),
+    {ok, Rev3} = save_doc({[{<<"_id">>, <<"doc3">>}]}),
+    {ok, _Rev4} = save_doc({[{<<"_id">>, <<"doc4">>}]}),
+    {ok, _Rev5} = save_doc({[{<<"_id">>, <<"doc5">>}]}),
+    {ok, _Rev3_2} = save_doc({[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3}]}),
+    {ok, _Rev6} = save_doc({[{<<"_id">>, <<"doc6">>}]}),
+    {ok, _Rev7} = save_doc({[{<<"_id">>, <<"doc7">>}]}),
+    {ok, _Rev8} = save_doc({[{<<"_id">>, <<"doc8">>}]}),
 
     etap:diag("Folding changes in ascending order with _doc_ids filter"),
     ChangesArgs = #changes_args{
@@ -126,21 +117,21 @@ test_by_doc_ids() ->
     etap:is(Seq2_2, 4, "Second row has seq 6"),
 
     stop(Consumer2),
-    delete_db(Db).
+    delete_db().
 
 
 test_by_doc_ids_with_since() ->
-    {ok, Db} = create_db(test_db_name()),
-
-    {ok, _Rev1} = save_doc(Db, {[{<<"_id">>, <<"doc1">>}]}),
-    {ok, _Rev2} = save_doc(Db, {[{<<"_id">>, <<"doc2">>}]}),
-    {ok, Rev3} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}]}),
-    {ok, _Rev4} = save_doc(Db, {[{<<"_id">>, <<"doc4">>}]}),
-    {ok, _Rev5} = save_doc(Db, {[{<<"_id">>, <<"doc5">>}]}),
-    {ok, Rev3_2} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3}]}),
-    {ok, _Rev6} = save_doc(Db, {[{<<"_id">>, <<"doc6">>}]}),
-    {ok, _Rev7} = save_doc(Db, {[{<<"_id">>, <<"doc7">>}]}),
-    {ok, _Rev8} = save_doc(Db, {[{<<"_id">>, <<"doc8">>}]}),
+    create_db(test_db_name()),
+
+    {ok, _Rev1} = save_doc({[{<<"_id">>, <<"doc1">>}]}),
+    {ok, _Rev2} = save_doc({[{<<"_id">>, <<"doc2">>}]}),
+    {ok, Rev3} = save_doc({[{<<"_id">>, <<"doc3">>}]}),
+    {ok, _Rev4} = save_doc({[{<<"_id">>, <<"doc4">>}]}),
+    {ok, _Rev5} = save_doc({[{<<"_id">>, <<"doc5">>}]}),
+    {ok, Rev3_2} = save_doc({[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3}]}),
+    {ok, _Rev6} = save_doc({[{<<"_id">>, <<"doc6">>}]}),
+    {ok, _Rev7} = save_doc({[{<<"_id">>, <<"doc7">>}]}),
+    {ok, _Rev8} = save_doc({[{<<"_id">>, <<"doc8">>}]}),
 
     ChangesArgs = #changes_args{
         filter = "_doc_ids",
@@ -178,7 +169,6 @@ test_by_doc_ids_with_since() ->
     stop(Consumer2),
 
     {ok, _Rev3_3} = save_doc(
-        Db,
         {[{<<"_id">>, <<"doc3">>}, {<<"_deleted">>, true}, {<<"_rev">>, Rev3_2}]}),
 
     ChangesArgs3 = #changes_args{
@@ -200,21 +190,21 @@ test_by_doc_ids_with_since() ->
 
     stop(Consumer3),
 
-    delete_db(Db).
+    delete_db().
 
 
 test_by_doc_ids_continuous() ->
-    {ok, Db} = create_db(test_db_name()),
-
-    {ok, _Rev1} = save_doc(Db, {[{<<"_id">>, <<"doc1">>}]}),
-    {ok, _Rev2} = save_doc(Db, {[{<<"_id">>, <<"doc2">>}]}),
-    {ok, Rev3} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}]}),
-    {ok, Rev4} = save_doc(Db, {[{<<"_id">>, <<"doc4">>}]}),
-    {ok, _Rev5} = save_doc(Db, {[{<<"_id">>, <<"doc5">>}]}),
-    {ok, Rev3_2} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3}]}),
-    {ok, _Rev6} = save_doc(Db, {[{<<"_id">>, <<"doc6">>}]}),
-    {ok, _Rev7} = save_doc(Db, {[{<<"_id">>, <<"doc7">>}]}),
-    {ok, _Rev8} = save_doc(Db, {[{<<"_id">>, <<"doc8">>}]}),
+    create_db(test_db_name()),
+
+    {ok, _Rev1} = save_doc({[{<<"_id">>, <<"doc1">>}]}),
+    {ok, _Rev2} = save_doc({[{<<"_id">>, <<"doc2">>}]}),
+    {ok, Rev3} = save_doc({[{<<"_id">>, <<"doc3">>}]}),
+    {ok, Rev4} = save_doc({[{<<"_id">>, <<"doc4">>}]}),
+    {ok, _Rev5} = save_doc({[{<<"_id">>, <<"doc5">>}]}),
+    {ok, Rev3_2} = save_doc({[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3}]}),
+    {ok, _Rev6} = save_doc({[{<<"_id">>, <<"doc6">>}]}),
+    {ok, _Rev7} = save_doc({[{<<"_id">>, <<"doc7">>}]}),
+    {ok, _Rev8} = save_doc({[{<<"_id">>, <<"doc8">>}]}),
 
     ChangesArgs = #changes_args{
         filter = "_doc_ids",
@@ -235,17 +225,17 @@ test_by_doc_ids_continuous() ->
     etap:is(Seq2, 6, "Second row has seq 6"),
 
     clear_rows(Consumer),
-    {ok, _Rev9} = save_doc(Db, {[{<<"_id">>, <<"doc9">>}]}),
-    {ok, _Rev10} = save_doc(Db, {[{<<"_id">>, <<"doc10">>}]}),
+    {ok, _Rev9} = save_doc({[{<<"_id">>, <<"doc9">>}]}),
+    {ok, _Rev10} = save_doc({[{<<"_id">>, <<"doc10">>}]}),
     unpause(Consumer),
     pause(Consumer),
     etap:is(get_rows(Consumer), [], "No new rows"),
 
-    {ok, Rev4_2} = save_doc(Db, {[{<<"_id">>, <<"doc4">>}, {<<"_rev">>, Rev4}]}),
-    {ok, _Rev11} = save_doc(Db, {[{<<"_id">>, <<"doc11">>}]}),
-    {ok, _Rev4_3} = save_doc(Db, {[{<<"_id">>, <<"doc4">>}, {<<"_rev">>, Rev4_2}]}),
-    {ok, _Rev12} = save_doc(Db, {[{<<"_id">>, <<"doc12">>}]}),
-    {ok, Rev3_3} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3_2}]}),
+    {ok, Rev4_2} = save_doc({[{<<"_id">>, <<"doc4">>}, {<<"_rev">>, Rev4}]}),
+    {ok, _Rev11} = save_doc({[{<<"_id">>, <<"doc11">>}]}),
+    {ok, _Rev4_3} = save_doc({[{<<"_id">>, <<"doc4">>}, {<<"_rev">>, Rev4_2}]}),
+    {ok, _Rev12} = save_doc({[{<<"_id">>, <<"doc12">>}]}),
+    {ok, Rev3_3} = save_doc({[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3_2}]}),
     unpause(Consumer),
     pause(Consumer),
 
@@ -258,7 +248,7 @@ test_by_doc_ids_continuous() ->
     etap:is(Row16#row.id, <<"doc3">>, "Second row is for doc doc3"),
 
     clear_rows(Consumer),
-    {ok, _Rev3_4} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3_3}]}),
+    {ok, _Rev3_4} = save_doc({[{<<"_id">>, <<"doc3">>}, {<<"_rev">>, Rev3_3}]}),
     unpause(Consumer),
     pause(Consumer),
     etap:is(get_rows(Consumer), [#row{seq = 17, id = <<"doc3">>}],
@@ -266,15 +256,15 @@ test_by_doc_ids_continuous() ->
 
     unpause(Consumer),
     stop(Consumer),
-    delete_db(Db).
+    delete_db().
 
 
 test_design_docs_only() ->
-    {ok, Db} = create_db(test_db_name()),
+    create_db(test_db_name()),
 
-    {ok, _Rev1} = save_doc(Db, {[{<<"_id">>, <<"doc1">>}]}),
-    {ok, _Rev2} = save_doc(Db, {[{<<"_id">>, <<"doc2">>}]}),
-    {ok, Rev3} = save_doc(Db, {[{<<"_id">>, <<"_design/foo">>}]}),
+    {ok, _Rev1} = save_doc({[{<<"_id">>, <<"doc1">>}]}),
+    {ok, _Rev2} = save_doc({[{<<"_id">>, <<"doc2">>}]}),
+    {ok, Rev3} = save_doc({[{<<"_id">>, <<"_design/foo">>}]}),
 
     ChangesArgs = #changes_args{
         filter = "_design"
@@ -292,10 +282,7 @@ test_design_docs_only() ->
 
     stop(Consumer),
 
-    {ok, Db3} = couch_db:open_int(
-        test_db_name(), [{user_ctx, #user_ctx{roles = [<<"_admin">>]}}]),
     {ok, _Rev3_2} = save_doc(
-        Db3,
         {[{<<"_id">>, <<"_design/foo">>}, {<<"_rev">>, Rev3},
             {<<"_deleted">>, true}]}),
 
@@ -303,7 +290,6 @@ test_design_docs_only() ->
 
     {Rows2, LastSeq2} = wait_finished(Consumer2),
     UpSeq2 = UpSeq + 1,
-    couch_db:close(Db3),
 
     etap:is(LastSeq2, UpSeq2, "LastSeq is same as database update seq number"),
     etap:is(length(Rows2), 1, "Received 1 changes rows"),
@@ -313,12 +299,12 @@ test_design_docs_only() ->
         "Received row with deleted ddoc"),
 
     stop(Consumer2),
-    delete_db(Db).
+    delete_db().
 
 test_heartbeat() ->
-    {ok, Db} = create_db(test_db_name()),
+    create_db(test_db_name()),
 
-    {ok, _} = save_doc(Db, {[
+    {ok, _} = save_doc({[
         {<<"_id">>, <<"_design/foo">>},
         {<<"language">>, <<"javascript">>},
             {<<"filters">>, {[
@@ -340,49 +326,53 @@ test_heartbeat() ->
     },
     Consumer = spawn_consumer(test_db_name(), ChangesArgs, {json_req, null}),
 
-    {ok, _Rev1} = save_doc(Db, {[{<<"_id">>, <<"doc1">>}]}),
+    {ok, _Rev1} = save_doc({[{<<"_id">>, <<"doc1">>}]}),
     timer:sleep(200),
-    {ok, _Rev2} = save_doc(Db, {[{<<"_id">>, <<"doc2">>}]}),
+    {ok, _Rev2} = save_doc({[{<<"_id">>, <<"doc2">>}]}),
     timer:sleep(200),
-    {ok, _Rev3} = save_doc(Db, {[{<<"_id">>, <<"doc3">>}]}),
+    {ok, _Rev3} = save_doc({[{<<"_id">>, <<"doc3">>}]}),
     timer:sleep(200),
-    {ok, _Rev4} = save_doc(Db, {[{<<"_id">>, <<"doc4">>}]}),
+    {ok, _Rev4} = save_doc({[{<<"_id">>, <<"doc4">>}]}),
     timer:sleep(200),
-    {ok, _Rev5} = save_doc(Db, {[{<<"_id">>, <<"doc5">>}]}),
+    {ok, _Rev5} = save_doc({[{<<"_id">>, <<"doc5">>}]}),
     timer:sleep(200),
-    {ok, _Rev6} = save_doc(Db, {[{<<"_id">>, <<"doc6">>}]}),
+    {ok, _Rev6} = save_doc({[{<<"_id">>, <<"doc6">>}]}),
     timer:sleep(200),
-    {ok, _Rev7} = save_doc(Db, {[{<<"_id">>, <<"doc7">>}]}),
+    {ok, _Rev7} = save_doc({[{<<"_id">>, <<"doc7">>}]}),
     timer:sleep(200),
-    {ok, _Rev8} = save_doc(Db, {[{<<"_id">>, <<"doc8">>}]}),
+    {ok, _Rev8} = save_doc({[{<<"_id">>, <<"doc8">>}]}),
     timer:sleep(200),
-    {ok, _Rev9} = save_doc(Db, {[{<<"_id">>, <<"doc9">>}]}),
+    {ok, _Rev9} = save_doc({[{<<"_id">>, <<"doc9">>}]}),
     Heartbeats = get_heartbeats(Consumer),
     etap:is(Heartbeats, 2, "Received 2 heartbeats now"),
-    {ok, _Rev10} = save_doc(Db, {[{<<"_id">>, <<"doc10">>}]}),
+    {ok, _Rev10} = save_doc({[{<<"_id">>, <<"doc10">>}]}),
     timer:sleep(200),
-    {ok, _Rev11} = save_doc(Db, {[{<<"_id">>, <<"doc11">>}]}),
+    {ok, _Rev11} = save_doc({[{<<"_id">>, <<"doc11">>}]}),
     timer:sleep(200),
-    {ok, _Rev12} = save_doc(Db, {[{<<"_id">>, <<"doc12">>}]}),
+    {ok, _Rev12} = save_doc({[{<<"_id">>, <<"doc12">>}]}),
     Heartbeats2 = get_heartbeats(Consumer),
     etap:is(Heartbeats2, 3, "Received 3 heartbeats now"),
     Rows = get_rows(Consumer),
     etap:is(length(Rows), 3, "Received 3 changes rows"),
 
-    {ok, _Rev13} = save_doc(Db, {[{<<"_id">>, <<"doc13">>}]}),
+    {ok, _Rev13} = save_doc({[{<<"_id">>, <<"doc13">>}]}),
     timer:sleep(200),
-    {ok, _Rev14} = save_doc(Db, {[{<<"_id">>, <<"doc14">>}]}),
+    {ok, _Rev14} = save_doc({[{<<"_id">>, <<"doc14">>}]}),
     timer:sleep(200),
     Heartbeats3 = get_heartbeats(Consumer),
     etap:is(Heartbeats3, 6, "Received 6 heartbeats now"),
     stop(Consumer),
-    couch_db:close(Db),
-    delete_db(Db).
+    delete_db().
+
+
+db() ->
+    {ok, Db} = couch_db:reopen(get(current_db)),
+    Db.
 
 
-save_doc(Db, Json) ->
+save_doc(Json) ->
     Doc = couch_doc:from_json_obj(Json),
-    {ok, Rev} = couch_db:update_doc(Db, Doc, []),
+    {ok, Rev} = couch_db:update_doc(db(), Doc, []),
     {ok, couch_doc:rev_to_str(Rev)}.
 
 
@@ -547,11 +537,13 @@ stop_loop(Parent, Acc) ->
 
 
 create_db(DbName) ->
-    couch_db:create(
-        DbName,
-        [{user_ctx, #user_ctx{roles = [<<"_admin">>]}}, overwrite]).
+    Options = [{user_ctx, #user_ctx{roles = [<<"_admin">>]}}, overwrite],
+    {ok, Db} = couch_db:create(DbName, Options),
+    put(current_db, Db).
 
 
-delete_db(Db) ->
-    ok = couch_server:delete(
-        couch_db:name(Db), [{user_ctx, #user_ctx{roles = [<<"_admin">>]}}]).
+delete_db() ->
+    Db = db(),
+    Options = [{user_ctx, #user_ctx{roles = [<<"_admin">>]}}],
+    ok = couch_server:delete(couch_db:name(Db), Options),
+    put(current_db, undefined).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/074-doc-update-conflicts.t
----------------------------------------------------------------------
diff --git a/test/etap/074-doc-update-conflicts.t b/test/etap/074-doc-update-conflicts.t
index 185a419..a7468e8 100755
--- a/test/etap/074-doc-update-conflicts.t
+++ b/test/etap/074-doc-update-conflicts.t
@@ -24,30 +24,19 @@ test_db_name() -> <<"couch_test_update_conflicts">>.
 
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(35),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    ok.
+    test_util:run(25, fun() -> test() end).
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     config:set("couchdb", "delayed_commits", "true", false),
 
     lists:foreach(
         fun(NumClients) -> test_concurrent_doc_update(NumClients) end,
-        [100, 500, 1000, 2000, 5000]),
+        [100, 500, 1000]),
 
     test_bulk_delete_create(),
 
-    couch_server_sup:stop(),
     ok.
 
 
@@ -120,9 +109,9 @@ test_concurrent_doc_update(NumClients) ->
 
     ok = timer:sleep(1000),
     etap:diag("Restarting the server"),
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok = timer:sleep(1000),
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
 
     {ok, Db3} = couch_db:open_int(test_db_name(), []),
     {ok, Leaves2} = couch_db:open_doc_revs(Db3, <<"foobar">>, all, []),
@@ -153,20 +142,21 @@ test_bulk_delete_create() ->
         {<<"value">>, 666}
     ]}),
 
-    {ok, Results} = couch_db:update_docs(Db, [DeletedDoc, NewDoc], []),
-    ok = couch_db:close(Db),
+    {ok, Db2} = couch_db:reopen(Db),
+    {ok, Results} = couch_db:update_docs(Db2, [DeletedDoc, NewDoc], []),
+    ok = couch_db:close(Db2),
 
     etap:is(length([ok || {ok, _} <- Results]), 2,
         "Deleted and non-deleted versions got an ok reply"),
 
     [{ok, Rev1}, {ok, Rev2}] = Results,
-    {ok, Db2} = couch_db:open_int(test_db_name(), []),
+    {ok, Db3} = couch_db:open_int(test_db_name(), []),
 
     {ok, [{ok, Doc1}]} = couch_db:open_doc_revs(
-        Db2, <<"foobar">>, [Rev1], [conflicts, deleted_conflicts]),
+        Db3, <<"foobar">>, [Rev1], [conflicts, deleted_conflicts]),
     {ok, [{ok, Doc2}]} = couch_db:open_doc_revs(
-        Db2, <<"foobar">>, [Rev2], [conflicts, deleted_conflicts]),
-    ok = couch_db:close(Db2),
+        Db3, <<"foobar">>, [Rev2], [conflicts, deleted_conflicts]),
+    ok = couch_db:close(Db3),
 
     {Doc1Props} = couch_doc:to_json_obj(Doc1, []),
     {Doc2Props} = couch_doc:to_json_obj(Doc2, []),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/075-auth-cache.t
----------------------------------------------------------------------
diff --git a/test/etap/075-auth-cache.t b/test/etap/075-auth-cache.t
index 1b88858..1c8b181 100755
--- a/test/etap/075-auth-cache.t
+++ b/test/etap/075-auth-cache.t
@@ -65,7 +65,7 @@ main(_) ->
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     OrigName = config:get("couch_httpd_auth", "authentication_db"),
     config:set(
         "couch_httpd_auth", "authentication_db",

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/076-file-compression.t
----------------------------------------------------------------------
diff --git a/test/etap/076-file-compression.t b/test/etap/076-file-compression.t
index 5f75ad6..499aae5 100755
--- a/test/etap/076-file-compression.t
+++ b/test/etap/076-file-compression.t
@@ -12,6 +12,8 @@
 % License for the specific language governing permissions and limitations under
 % the License.
 
+-mode(compile).
+
 -record(user_ctx, {
     name = null,
     roles = [],
@@ -38,7 +40,7 @@ main(_) ->
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     config:set("couchdb", "file_compression", "none", false),
 
     create_database(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/077-couch-db-fast-db-delete-create.t
----------------------------------------------------------------------
diff --git a/test/etap/077-couch-db-fast-db-delete-create.t b/test/etap/077-couch-db-fast-db-delete-create.t
index 2026698..4ba5c56 100644
--- a/test/etap/077-couch-db-fast-db-delete-create.t
+++ b/test/etap/077-couch-db-fast-db-delete-create.t
@@ -14,19 +14,8 @@
 % the License.
 
 main(_) ->
+    test_util:run(1, fun() -> test() end).
 
-    test_util:init_code_path(),
-
-    etap:plan(unknown),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            Msg = io_lib:format("Test died abnormally: ~p", [Other]),
-            etap:diag(Msg),
-            etap:bail(Msg)
-        end,
-    ok.
 
 loop(0) ->
     ok;
@@ -34,15 +23,17 @@ loop(N) ->
     ok = cycle(),
     loop(N - 1).
 
+
 cycle() ->
-    ok = couch_server:delete(<<"etap-test-db">>, []),
-    {ok, _Db} = couch_db:create(<<"etap-test-db">>, []),
+    {ok, Db} = couch_db:create(<<"etap-test-db">>, []),
+    % Dirty but only less dirty than importing the #db{} record
+    couch_file:close(element(5, Db)),
+    ok = couch_server:delete(<<"etap-test-db">>, [sync]),
     ok.
 
-test() ->
-    couch_server_sup:start_link(test_util:config_files()),
 
-    {ok, _Db} = couch_db:create(<<"etap-test-db">>, []),
+test() ->
+    test_util:start_couch(),
 
     ok = loop(1),
     ok = loop(10),
@@ -55,7 +46,5 @@ test() ->
     % ok = loop(1000000),
     % ok = loop(10000000),
 
-    ok = couch_server:delete(<<"etap-test-db">>, []),
-
     etap:is(true, true, "lots of creating and deleting of a database"),
     ok.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/080-config-get-set.t
----------------------------------------------------------------------
diff --git a/test/etap/080-config-get-set.t b/test/etap/080-config-get-set.t
index 6e5395e..d727936 100755
--- a/test/etap/080-config-get-set.t
+++ b/test/etap/080-config-get-set.t
@@ -29,6 +29,7 @@ main(_) ->
     ok.
 
 test() ->
+    application:set_env(config, ini_files, ["etc/couchdb/default_dev.ini"]),
     application:start(config),
 
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/081-config-override.t
----------------------------------------------------------------------
diff --git a/test/etap/081-config-override.t b/test/etap/081-config-override.t
index 2d47122..3a97b66 100755
--- a/test/etap/081-config-override.t
+++ b/test/etap/081-config-override.t
@@ -27,16 +27,12 @@ local_config_write() ->
 
 % Run tests and wait for the config gen_server to shutdown.
 run_tests(IniFiles, Tests) ->
-    application:start(config),
-    erlang:monitor(process, Pid),
+    application:set_env(config, ini_files, IniFiles),
+    ok = application:start(config),
     Tests(),
-    config:stop(),
-    receive
-        {'DOWN', _, _, Pid, _} -> ok;
-        _Other -> etap:diag("OTHER: ~p~n", [_Other])
-    after
-        1000 -> throw({timeout_error, config_stop})
-    end.
+    timer:sleep(1000),
+    ok = application:stop(config),
+    ok.
 
 main(_) ->
     test_util:init_code_path(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/082-config-register.t
----------------------------------------------------------------------
diff --git a/test/etap/082-config-register.t b/test/etap/082-config-register.t
index 9487887..bd09ea7 100755
--- a/test/etap/082-config-register.t
+++ b/test/etap/082-config-register.t
@@ -13,6 +13,9 @@
 % License for the specific language governing permissions and limitations under
 % the License.
 
+-mode(compile).
+-export([handle_config_change/5]).
+
 default_config() ->
     test_util:build_file("etc/couchdb/default_dev.ini").
 
@@ -29,7 +32,8 @@ main(_) ->
     ok.
 
 test() ->
-    application:start(config),
+    application:set_env(config, ini_files, ["etc/couchdb/default_dev.ini"]),
+    ok = application:start(config),
 
     etap:is(
         config:get("httpd", "port"),
@@ -45,50 +49,31 @@ test() ->
         "{httpd, port} changed to 4895"
     ),
 
-    SentinelFunc = fun() ->
-        % Ping/Pong to make sure we wait for this
-        % process to die
-        receive {ping, From} -> From ! pong end
-    end,
-    SentinelPid = spawn(SentinelFunc),
-
-    config:register(
-        fun("httpd", "port", Value) ->
-            etap:is(Value, "8080", "Registered function got notification.")
-        end,
-        SentinelPid
-    ),
+    config:listen_for_changes(?MODULE, self()),
 
     ok = config:set("httpd", "port", "8080", false),
 
+    receive
+        {"httpd", "port", Value, false} ->
+            etap:is(Value, "8080", "Registered function got notification.")
+    after
+        1000 ->
+            etap:fail("notification failed")
+    end,
+
     % Implicitly checking that we *don't* call the function
     etap:is(
         config:get("httpd", "bind_address"),
         "127.0.0.1",
         "{httpd, bind_address} is not '0.0.0.0'"
     ),
-    ok = config:set("httpd", "bind_address", "0.0.0.0", false),
 
-    % Ping-Pong kill process
-    SentinelPid ! {ping, self()},
-    receive
-        _Any -> ok
-    after 1000 ->
-        throw({timeout_error, registered_pid})
-    end,
+    Msg = receive M -> M after 500 -> nil end,
+    etap:is(Msg, nil, "yay, no notification for get"),
 
-    ok = config:set("httpd", "port", "80", false),
-    etap:is(
-        config:get("httpd", "port"),
-        "80",
-        "Implicitly test that the function got de-registered"
-    ),
+    ok.
 
-    % test passing of Persist flag
-    config:register(
-        fun("httpd", _, _, Persist) ->
-            etap:is(Persist, false)
-        end),
-    ok = config:set("httpd", "port", "80", false),
+handle_config_change(Sec, Key, Val, Persist, Pid) ->
+    Pid ! {Sec, Key, Val, Persist},
+    {ok, Pid}.
 
-    ok.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/121-stats-aggregates.t
----------------------------------------------------------------------
diff --git a/test/etap/121-stats-aggregates.t b/test/etap/121-stats-aggregates.t
index 92bf547..4436beb 100755
--- a/test/etap/121-stats-aggregates.t
+++ b/test/etap/121-stats-aggregates.t
@@ -20,19 +20,10 @@ cfg_file() ->
     test_util:source_file("test/etap/121-stats-aggregates.cfg").
 
 main(_) ->
-    test_util:init_code_path(),
-    etap:plan(17),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail()
-    end,
-    ok.
+    test_util:run(17, fun() -> test() end).
 
 test() ->
-    application:start(config),
+    config_sup:start_link([ini_file()]),
     couch_stats_collector:start(),
     couch_stats_aggregator:start(cfg_file()),
     ok = test_all_empty(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/130-attachments-md5.t
----------------------------------------------------------------------
diff --git a/test/etap/130-attachments-md5.t b/test/etap/130-attachments-md5.t
index 12b1aba..fad057e 100755
--- a/test/etap/130-attachments-md5.t
+++ b/test/etap/130-attachments-md5.t
@@ -38,7 +38,7 @@ main(_) ->
     ok.
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     Addr = config:get("httpd", "bind_address", any),
     put(addr, Addr),
     put(port, mochiweb_socket_server:get(couch_httpd, port)),
@@ -59,7 +59,7 @@ test() ->
     test_chunked_with_invalid_md5_trailer(),
 
     couch_server:delete(test_db_name(), []),
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok.
 
 test_identity_without_md5() ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/140-attachment-comp.t
----------------------------------------------------------------------
diff --git a/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t
index 6e8640d..2f77956 100755
--- a/test/etap/140-attachment-comp.t
+++ b/test/etap/140-attachment-comp.t
@@ -30,7 +30,7 @@ main(_) ->
     ok.
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     put(addr, config:get("httpd", "bind_address", "127.0.0.1")),
     put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))),
     timer:sleep(1000),
@@ -75,7 +75,7 @@ test() ->
 
     timer:sleep(3000), % to avoid mochiweb socket closed exceptions
     couch_server:delete(test_db_name(), []),
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok.
 
 db_url() ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/150-invalid-view-seq.t
----------------------------------------------------------------------
diff --git a/test/etap/150-invalid-view-seq.t b/test/etap/150-invalid-view-seq.t
index 4553b16..a2ac22c 100755
--- a/test/etap/150-invalid-view-seq.t
+++ b/test/etap/150-invalid-view-seq.t
@@ -23,23 +23,13 @@ test_db_name() ->
     <<"couch_test_invalid_view_seq">>.
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(10),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    ok.
+    test_util:run(10, fun() -> test() end).
 
 %% NOTE: since during the test we stop the server,
 %%       a huge and ugly but harmless stack trace is sent to stderr
 %%
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     timer:sleep(1000),
     delete_db(),
     create_db(),
@@ -62,7 +52,6 @@ test() ->
     query_view_after_restore_backup(),
 
     delete_db(),
-    couch_server_sup:stop(),
     ok.
 
 admin_user_ctx() ->
@@ -155,13 +144,13 @@ has_doc(DocId1, Rows) ->
     ).
 
 restore_backup_db_file() ->
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     timer:sleep(3000),
     DbFile = test_util:build_file("tmp/lib/" ++
         binary_to_list(test_db_name()) ++ ".couch"),
     ok = file:delete(DbFile),
     ok = file:rename(DbFile ++ ".backup", DbFile),
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     timer:sleep(1000),
     put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))),
     ok.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/160-vhosts.t
----------------------------------------------------------------------
diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t
index 4118b94..c83d359 100755
--- a/test/etap/160-vhosts.t
+++ b/test/etap/160-vhosts.t
@@ -41,7 +41,7 @@ main(_) ->
     ok.
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     ibrowse:start(),
     crypto:start(),
 
@@ -119,7 +119,7 @@ test() ->
     couch_db:close(Db),
     ok = couch_server:delete(couch_db:name(Db), [admin_user_ctx()]),
     timer:sleep(3000),
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
 
     ok.
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/171-os-daemons-config.t
----------------------------------------------------------------------
diff --git a/test/etap/171-os-daemons-config.t b/test/etap/171-os-daemons-config.t
index 8254c26..c8348d5 100755
--- a/test/etap/171-os-daemons-config.t
+++ b/test/etap/171-os-daemons-config.t
@@ -46,10 +46,8 @@ main(_) ->
     ok.
 
 test() ->
-    application:start(config),
+    test_util:start_couch(),
     config:set("log", "level", "debug", false),
-    couch_log:start_link(),
-    couch_os_daemons:start_link(),
 
     % "foo" is a required name by this test.
     config:set("os_daemons", "foo", daemon_cmd(), false),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/180-http-proxy.t
----------------------------------------------------------------------
diff --git a/test/etap/180-http-proxy.t b/test/etap/180-http-proxy.t
index 55f6aab..4897ad6 100755
--- a/test/etap/180-http-proxy.t
+++ b/test/etap/180-http-proxy.t
@@ -26,17 +26,7 @@ proxy() ->
 external() -> "https://www.google.com/".
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(61),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag("Test died abnormally: ~p", [Other]),
-            etap:bail("Bad return value.")
-    end,
-    ok.
+    test_util:run(61, fun() -> test() end).
 
 check_request(Name, Req, Remote, Local) ->
     case Remote of
@@ -68,7 +58,7 @@ check_request(Name, Req, Remote, Local) ->
 
 test() ->
     ExtraConfig = [test_util:source_file("test/etap/180-http-proxy.ini")],
-    couch_server_sup:start_link(test_util:config_files() ++ ExtraConfig),
+    ok = test_util:start_couch(test_util:config_files() ++ ExtraConfig),
     ibrowse:start(),
     crypto:start(),
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/200-view-group-no-db-leaks.t
----------------------------------------------------------------------
diff --git a/test/etap/200-view-group-no-db-leaks.t b/test/etap/200-view-group-no-db-leaks.t
index f6ae3f0..4cf23b1 100755
--- a/test/etap/200-view-group-no-db-leaks.t
+++ b/test/etap/200-view-group-no-db-leaks.t
@@ -63,7 +63,7 @@ main(_) ->
     ok.
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     timer:sleep(1000),
     put(addr, config:get("httpd", "bind_address", "127.0.0.1")),
     put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))),
@@ -135,7 +135,7 @@ test() ->
 
     ok = timer:sleep(1000),
     delete_db(),
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok.
 
 admin_user_ctx() ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/201-view-group-shutdown.t
----------------------------------------------------------------------
diff --git a/test/etap/201-view-group-shutdown.t b/test/etap/201-view-group-shutdown.t
index fa77d89..f374888 100755
--- a/test/etap/201-view-group-shutdown.t
+++ b/test/etap/201-view-group-shutdown.t
@@ -64,7 +64,7 @@ main(_) ->
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     ok = config:set("couchdb", "max_dbs_open", "3", false),
     ok = config:set("couchdb", "delayed_commits", "false", false),
     crypto:start(),
@@ -73,7 +73,7 @@ test() ->
     % be closed by the database LRU system.
     test_view_group_compaction(),
 
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok.
 
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/210-os-proc-pool.t
----------------------------------------------------------------------
diff --git a/test/etap/210-os-proc-pool.t b/test/etap/210-os-proc-pool.t
index 85fa9a6..20c45e4 100755
--- a/test/etap/210-os-proc-pool.t
+++ b/test/etap/210-os-proc-pool.t
@@ -27,13 +27,13 @@ main(_) ->
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     config:set("query_server_config", "os_process_limit", "3", false),
 
     test_pool_full(),
     test_client_unexpected_exit(),
 
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok.
 
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/220-compaction-daemon.t
----------------------------------------------------------------------
diff --git a/test/etap/220-compaction-daemon.t b/test/etap/220-compaction-daemon.t
index 73bd5ac..262113d 100755
--- a/test/etap/220-compaction-daemon.t
+++ b/test/etap/220-compaction-daemon.t
@@ -36,7 +36,7 @@ main(_) ->
     ok.
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
     timer:sleep(1000),
     put(addr, config:get("httpd", "bind_address", "127.0.0.1")),
     put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))),
@@ -102,7 +102,7 @@ test() ->
     etap:is(couch_db:is_idle(Db), true, "Database is idle"),
 
     delete_db(),
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok.
 
 disable_compact_daemon() ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/231-cors.t
----------------------------------------------------------------------
diff --git a/test/etap/231-cors.t b/test/etap/231-cors.t
index cfc6a94..8e13c42 100644
--- a/test/etap/231-cors.t
+++ b/test/etap/231-cors.t
@@ -63,7 +63,7 @@ test() ->
     crypto:start(),
 
     %% launch couchdb
-    couch_server_sup:start_link(test_util:config_files()),
+    ok = test_util:start_couch(),
 
     %% initialize db
     timer:sleep(1000),
@@ -152,7 +152,7 @@ test() ->
     couch_server:delete(list_to_binary(dbname2()), [admin_user_ctx()]),
 
     timer:sleep(3000),
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok.
 
 test_preflight_request() -> test_preflight_request(false).

http://git-wip-us.apache.org/repos/asf/couchdb/blob/86ba6dbe/test/etap/test_util.erl.in
----------------------------------------------------------------------
diff --git a/test/etap/test_util.erl.in b/test/etap/test_util.erl.in
index 495909c..bdb7a17 100644
--- a/test/etap/test_util.erl.in
+++ b/test/etap/test_util.erl.in
@@ -16,6 +16,7 @@
 -export([source_file/1, build_file/1, config_files/0]).
 -export([run/2]).
 -export([request/3, request/4]).
+-export([start_couch/0, start_couch/1, stop_couch/0]).
 
 srcdir() ->
     "@abs_top_srcdir@".
@@ -54,13 +55,18 @@ config_files() ->
 run(Plan, Fun) ->
     test_util:init_code_path(),
     etap:plan(Plan),
-    case (catch Fun()) of
+    try Fun() of
         ok ->
             etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally:~n~p", [Other])),
-            timer:sleep(500),
-            etap:bail(Other)
+        Else ->
+            etap:diag("Bad return:~n~p", [Else]),
+            timer:sleep(100),
+            etap:bail(Else)
+    catch Type:Reason ->
+        etap:diag("Test died: ~p~n  ~p~n  ~p~n",
+                [Type, Reason, erlang:get_stacktrace()]),
+        timer:sleep(1000),
+        etap:bail({Type, Reason})
     end,
     ok.
 
@@ -92,3 +98,18 @@ request(Url, Headers, Method, Body, N) ->
     Error ->
         Error
     end.
+
+start_couch() ->
+    start_couch(config_files()).
+
+start_couch(IniFiles) ->
+    ok = application:set_env(config, ini_files, IniFiles),
+    ok = application:start(config),
+    ok = application:start(twig),
+    ok = application:start(couch),
+    ok.
+
+stop_couch() ->
+    ok = application:stop(couch),
+    ok = application:stop(twig),
+    ok = application:stop(config).


[16/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Notify the ddoc cache when design docs change


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/df41b31a
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/df41b31a
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/df41b31a

Branch: refs/heads/1843-feature-bigcouch
Commit: df41b31ac7a703e3408672975f746ae5e62697de
Parents: c92694a
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Jan 23 15:16:29 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:52 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db_updater.erl | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/df41b31a/src/couch/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl
index 1be3e3a..e1dc7c3 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -732,11 +732,12 @@ update_docs_int(Db, DocsList, NonRepDocs, MergeConflicts, FullCommit) ->
 
     % Check if we just updated any design documents, and update the validation
     % funs if we did.
-    Db4 = case UpdatedDDocIds of
-    [] ->
-        Db3;
-    _ ->
-        refresh_validate_doc_funs(Db3)
+    Db4 = case length(UpdatedDDocIds) > 0 of
+        true ->
+            ddoc_cache:evict(Db3#db.name, UpdatedDDocIds),
+            refresh_validate_doc_funs(Db3);
+        false ->
+            Db3
     end,
 
     {ok, commit_data(Db4, not FullCommit), UpdatedDDocIds}.


[12/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Bubble missing_stub errors

If we try and replicate a doc with attachment stubs to a node that
doesn't have a previous revision of that doc then we should return a
missing_stub error instead of dying with a function_clause error.

BugzId: 15562


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/96bf7d55
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/96bf7d55
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/96bf7d55

Branch: refs/heads/1843-feature-bigcouch
Commit: 96bf7d55f8ccbb3ecc3cecd27391be7537adf319
Parents: ed80224
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Nov 13 17:25:35 2012 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:51 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db.erl | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/96bf7d55/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 67c8a49..f5953a1 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -708,7 +708,13 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI
 
                     case couch_doc:has_stubs(Doc) of
                     true ->
-                        DiskDoc = LoadPrevRevFun(),
+                        DiskDoc = case LoadPrevRevFun() of
+                            #doc{} = DiskDoc0 ->
+                                DiskDoc0;
+                            _ ->
+                                % Force a missing_stub exception
+                                couch_doc:merge_stubs(Doc, #doc{})
+                        end,
                         Doc2 = couch_doc:merge_stubs(Doc, DiskDoc),
                         GetDiskDocFun = fun() -> DiskDoc end;
                     false ->


[42/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
[squash] to somwhere Mark the dbs db as a sys_db

Not sure where


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/06475bab
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/06475bab
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/06475bab

Branch: refs/heads/1843-feature-bigcouch
Commit: 06475babece2f3dfff72df81006bd3288d63af4c
Parents: f9da28e
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 12:57:16 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:56 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_server.erl | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/06475bab/src/couch/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index 3d4a1a6..80448b1 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -125,7 +125,12 @@ maybe_add_sys_db_callbacks(DbName, Options) ->
             sys_db | Options
         ];
         _ ->
-            Options
+            case config:get("mem3", "shard_db", "dbs") of
+            DbName ->
+                [sys_db | Options];
+            _ ->
+                Options
+            end
         end
     end.
 


[24/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Update and refine comment regarding spawn

BugzID: 13179


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/987ebf78
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/987ebf78
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/987ebf78

Branch: refs/heads/1843-feature-bigcouch
Commit: 987ebf78528e5e053e08c8f791eeef8868edbf86
Parents: 977c83d
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Wed Feb 27 11:52:23 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:53 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_server.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/987ebf78/src/couch/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index 9f8380e..e8d8c49 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -196,7 +196,7 @@ config_change("couchdb", "database_dir", _, _) ->
 config_change("couchdb", "max_dbs_open", Max, _) ->
     gen_server:call(couch_server, {set_max_dbs_open, list_to_integer(Max)});
 config_change("admins", _, _, Persist) ->
-    % spawn here so couch_config doesn't try to call itself
+    % spawn here so couch event manager doesn't deadlock
     spawn(fun() -> hash_admin_passwords(Persist) end).
 
 all_databases() ->


[11/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
couchdb depends on twig


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/79dd3a90
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/79dd3a90
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/79dd3a90

Branch: refs/heads/1843-feature-bigcouch
Commit: 79dd3a90c915c6b2f44ee4ad042fc860655cd565
Parents: 96bf7d5
Author: Robert Newson <ro...@cloudant.com>
Authored: Sat Jan 5 12:39:07 2013 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:51 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch.app.tpl.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/79dd3a90/src/couch/src/couch.app.tpl.in
----------------------------------------------------------------------
diff --git a/src/couch/src/couch.app.tpl.in b/src/couch/src/couch.app.tpl.in
index dc284e4..f83b6f6 100644
--- a/src/couch/src/couch.app.tpl.in
+++ b/src/couch/src/couch.app.tpl.in
@@ -22,6 +22,6 @@
         "%localconfdir%/@defaultini@",
         "%localconfdir%/@localini@"
     ]}},
-    {applications, [kernel, stdlib]},
+    {applications, [kernel, stdlib, twig]},
     {included_applications, [crypto, sasl, inets, oauth, ibrowse, mochiweb, os_mon]}
 ]}.


[03/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
User aggregates have binary keys

BugzID: 14330


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/816bf803
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/816bf803
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/816bf803

Branch: refs/heads/1843-feature-bigcouch
Commit: 816bf803db57530cfe38e3baea3487b1f1c1ecf1
Parents: 99570a8
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Thu Aug 16 11:10:24 2012 -0400
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:50 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/816bf803/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index fb7f354..eb41e27 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -236,11 +236,11 @@ builtin_stats(reduce, [[_,First]|Rest]) ->
             {S+V, C+1, erlang:min(Mi,V), erlang:max(Ma,V), Sq+(V*V)};
         ([_K,{PreRed}], {S,C,Mi,Ma,Sq}) when is_list(PreRed) ->
             {
-                S + get_number(sum, PreRed),
-                C + get_number(count, PreRed),
-                erlang:min(get_number(min, PreRed), Mi),
-                erlang:max(get_number(max, PreRed), Ma),
-                Sq + get_number(sumsqr, PreRed)
+                S + get_number(<<"sum">>, PreRed),
+                C + get_number(<<"count">>, PreRed),
+                erlang:min(get_number(<<"min">>, PreRed), Mi),
+                erlang:max(get_number(<<"max">>, PreRed), Ma),
+                Sq + get_number(<<"sumsqr">>, PreRed)
             };
         ([_K,V], _) ->
             Msg = io_lib:format("non-numeric _stats input: ~w", [V]),
@@ -262,11 +262,11 @@ build_initial_accumulator(X) when is_number(X) ->
     {X, 1, X, X, X*X};
 build_initial_accumulator({Props}) ->
     {
-        get_number(sum, Props),
-        get_number(count, Props),
-        get_number(min, Props),
-        get_number(max, Props),
-        get_number(sumsqr, Props)
+        get_number(<<"sum">>, Props),
+        get_number(<<"count">>, Props),
+        get_number(<<"min">>, Props),
+        get_number(<<"max">>, Props),
+        get_number(<<"sumsqr">>, Props)
     };
 build_initial_accumulator(Else) ->
     Msg = io_lib:format("non-numeric _stats input: ~w", [Else]),


[23/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Middle ground on logging db openers

Rather than get too complicated with timers for each db open we'll just
silence if there's less than some smallish number of clients. And if
that threshold is exceeded we'll also log the total number of clients.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/5df09429
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/5df09429
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/5df09429

Branch: refs/heads/1843-feature-bigcouch
Commit: 5df0942935ad379a53dfd17b835b0cae497fd305
Parents: 987ebf7
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Feb 21 00:14:43 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:53 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_server.erl | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/5df09429/src/couch/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index e8d8c49..40c2d7e 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -349,6 +349,10 @@ handle_call({open, DbName, Options}, From, Server) ->
     [#db{compactor_pid = Froms} = Db] when is_list(Froms) ->
         % icky hack of field values - compactor_pid used to store clients
         true = ets:insert(couch_dbs, Db#db{compactor_pid = [From|Froms]}),
+        if length(Froms) =< 10 -> ok; true ->
+            Fmt = "~b clients waiting to open db ~s",
+            ?LOG_INFO(Fmt, [length(Froms), DbName])
+        end,
         {noreply, Server};
     [#db{} = Db] ->
         {reply, {ok, Db}, Server}


[09/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Assume success when we replicate an existing leaf

The logic in couch_db:prep_and_validate_replicated_updates/5 was broken
if we attempt to replicate a leaf that exists. The function has
explicitly commented logic that if we attempt to replicate an internal
node of the revision tree that we just ignore it and assume success.
While the logic matched the comment, what the comment should say is that
if we replicate an existing revision then we should treat is as a
successful no-op.

The way that the error manifests with the old logic is that we would try
and run make_first_doc_on_disk which reads through all previous
revisions on the edit path to find the first available revision.
Although if we had compacted then none would exist so that the
make_first_doc_on_disk function would return nil and attempt to use that
where we wanted a #doc{} in couch_doc:merge_stubs/2.

BugzId: 15562


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/ed802249
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/ed802249
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/ed802249

Branch: refs/heads/1843-feature-bigcouch
Commit: ed8022499622d1caff08d3fc6b4840a223ad0638
Parents: bcd8f73
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Nov 13 16:43:32 2012 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:51 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db.erl | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed802249/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 2253e62..67c8a49 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -682,6 +682,8 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI
             {[], AccErrors}, Bucket),
         prep_and_validate_replicated_updates(Db, RestBuckets, RestOldInfo, [ValidatedBucket | AccPrepped], AccErrors3);
     {ok, #full_doc_info{rev_tree=OldTree}} ->
+        OldLeafs = couch_key_tree:get_all_leafs_full(OldTree),
+        OldLeafsLU = [{Start, RevId} || {Start, [{RevId, _}|_]} <- OldLeafs],
         NewRevTree = lists:foldl(
             fun({NewDoc, _Ref}, AccTree) ->
                 {NewTree, _} = couch_key_tree:merge(AccTree,
@@ -694,8 +696,9 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI
         {ValidatedBucket, AccErrors3} =
         lists:foldl(
             fun({#doc{id=Id,revs={Pos, [RevId|_]}}=Doc, Ref}, {AccValidated, AccErrors2}) ->
+                IsOldLeaf = lists:member({Pos, RevId}, OldLeafsLU),
                 case dict:find({Pos, RevId}, LeafRevsFullDict) of
-                {ok, {Start, Path}} ->
+                {ok, {Start, Path}} when not IsOldLeaf ->
                     % our unflushed doc is a leaf node. Go back on the path
                     % to find the previous rev that's on disk.
 


[30/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Enable changes for cluster access

This mostly involves rewriting filter functions so that they aren't
anonymous closures. This breaks clusters when code is upgraded which is
particularly problematic for the _change feed since its a long lived
request.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/f633e54d
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/f633e54d
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/f633e54d

Branch: refs/heads/1843-feature-bigcouch
Commit: f633e54dee01d3055f6f1e8280c16a9b62937233
Parents: f8ef5e8
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 13:39:42 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:54 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_changes.erl | 393 +++++++++++++++++------------------
 1 file changed, 196 insertions(+), 197 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/f633e54d/src/couch/src/couch_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_changes.erl b/src/couch/src/couch_changes.erl
index d36b45f..4346109 100644
--- a/src/couch/src/couch_changes.erl
+++ b/src/couch/src/couch_changes.erl
@@ -18,11 +18,12 @@
     get_changes_timeout/2,
     wait_db_updated/3,
     get_rest_db_updated/1,
-    make_filter_fun/4,
-    main_only_filter/1,
-    all_docs_filter/1
+    configure_filter/4,
+    filter/3
 ]).
 
+-export([changes_enumerator/2]).
+
 % For the builtin filter _docs_ids, this is the maximum number
 % of documents for which we trigger the optimized code path.
 -define(MAX_DOC_IDS, 100).
@@ -51,8 +52,8 @@ handle_changes(Args1, Req, Db0) ->
         dir = Dir,
         since = Since
     } = Args1,
-    {FilterFun, FilterArgs} = make_filter_fun(FilterName, Style, Req, Db0),
-    Args = Args1#changes_args{filter_fun = FilterFun, filter_args = FilterArgs},
+    Filter = configure_filter(FilterName, Style, Req, Db0),
+    Args = Args1#changes_args{filter_fun = Filter},
     Start = fun() ->
         {ok, Db} = couch_db:reopen(Db0),
         StartSeq = case Dir of
@@ -120,136 +121,153 @@ get_callback_acc({Callback, _UserAcc} = Pair) when is_function(Callback, 3) ->
 get_callback_acc(Callback) when is_function(Callback, 2) ->
     {fun(Ev, Data, _) -> Callback(Ev, Data) end, ok}.
 
-make_filter_fun([$_ | _] = FilterName, Style, Req, Db) ->
-    builtin_filter_fun(FilterName, Style, Req, Db);
-make_filter_fun(_, main_only, _, _) ->
-    fun ?MODULE:main_only_filter/1;
-make_filter_fun(_, all_docs, _, _) ->
-    fun ?MODULE:all_docs_filter/1;
-make_filter_fun(FilterName, Style, Req, Db) ->
-    {os_filter_fun(FilterName, Style, Req, Db), []}.
-
-os_filter_fun(FilterName, Style, Req, Db) ->
-    case [list_to_binary(couch_httpd:unquote(Part))
-            || Part <- string:tokens(FilterName, "/")] of
-    [] ->
-        fun(_Db2, #doc_info{revs=Revs}) ->
-                builtin_results(Style, Revs)
-        end;
-    [DName, FName] ->
-        DesignId = <<"_design/", DName/binary>>,
-        DDoc = couch_httpd_db:couch_doc_open(Db, DesignId, nil, [ejson_body]),
-        % validate that the ddoc has the filter fun
-        #doc{body={Props}} = DDoc,
-        couch_util:get_nested_json_value({Props}, [<<"filters">>, FName]),
-        fun(Db2, DocInfo) ->
-            DocInfos =
-            case Style of
-            main_only ->
-                [DocInfo];
-            all_docs ->
-                [DocInfo#doc_info{revs=[Rev]}|| Rev <- DocInfo#doc_info.revs]
-            end,
-            Docs = [Doc || {ok, Doc} <- [
-                    couch_db:open_doc(Db2, DocInfo2, [deleted, conflicts])
-                        || DocInfo2 <- DocInfos]],
-            {ok, Passes} = couch_query_servers:filter_docs(
-                Req, Db2, DDoc, FName, Docs
-            ),
-            [{[{<<"rev">>, couch_doc:rev_to_str({RevPos,RevId})}]}
-                || {Pass, #doc{revs={RevPos,[RevId|_]}}}
-                <- lists:zip(Passes, Docs), Pass == true]
-        end;
-    _Else ->
-        throw({bad_request,
-            "filter parameter must be of the form `designname/filtername`"})
+
+configure_filter("_doc_ids", Style, Req, _Db) ->
+    {doc_ids, Style, get_doc_ids(Req)};
+configure_filter("_design", Style, _Req, _Db) ->
+    {design_docs, Style};
+configure_filter("_view", Style, Req, Db) ->
+    ViewName = couch_httpd:qs_value(Req, "view", ""),
+    if ViewName /= "" -> ok; true ->
+        throw({bad_request, "`view` filter parameter is not provided."})
+    end,
+    ViewNameParts = string:tokens(ViewName, "/"),
+    case [?l2b(couch_httpd:unquote(Part)) || Part <- ViewNameParts] of
+        [DName, VName] ->
+            {ok, DDoc} = open_ddoc(Db, <<"_design/", DName/binary>>),
+            check_member_exists(DDoc, [<<"views">>, VName]),
+            {view, Style, DDoc, VName};
+        [] ->
+            Msg = "`view` must be of the form `designname/viewname`",
+            throw({bad_request, Msg})
+    end;
+configure_filter([$_ | _], _Style, _Req, _Db) ->
+    throw({bad_request, "unknown builtin filter name"});
+configure_filter("", main_only, _Req, _Db) ->
+    {default, main_only};
+configure_filter("", all_docs, _Req, _Db) ->
+    {default, all_docs};
+configure_filter(FilterName, Style, Req, Db) ->
+    FilterNameParts = string:tokens(FilterName, "/"),
+    case [?l2b(couch_httpd:unquote(Part)) || Part <- FilterNameParts] of
+        [DName, FName] ->
+            {ok, DDoc} = open_ddoc(Db, <<"_design/", DName/binary>>),
+            check_member_exists(DDoc, [<<"filters">>, FName]),
+            {custom, Style, Req, DDoc, FName};
+        [] ->
+            {default, Style};
+        _Else ->
+            Msg = "`filter` must be of the form `designname/filtername`",
+            throw({bad_request, Msg})
     end.
 
-builtin_filter_fun("_doc_ids", Style, {json_req, {Props}}, _Db) ->
-    DocIds = couch_util:get_value(<<"doc_ids">>, Props),
-    {filter_docids(DocIds, Style), DocIds};
-builtin_filter_fun("_doc_ids", Style, #httpd{method='POST'}=Req, _Db) ->
+
+filter(Db, #full_doc_info{}=FDI, Filter) ->
+    filter(Db, couch_doc:to_doc_info(FDI), Filter);
+filter(_Db, DocInfo, {default, Style}) ->
+    apply_style(DocInfo, Style);
+filter(_Db, DocInfo, {doc_ids, Style, DocIds}) ->
+    case lists:member(DocInfo#doc_info.id, DocIds) of
+        true ->
+            apply_style(DocInfo, Style);
+        false ->
+            []
+    end;
+filter(_Db, DocInfo, {design_docs, Style}) ->
+    case DocInfo#doc_info.id of
+        <<"_design", _/binary>> ->
+            apply_style(DocInfo, Style);
+        _ ->
+            []
+    end;
+filter(Db, DocInfo, {view, Style, DDoc, VName}) ->
+    Docs = open_revs(Db, DocInfo, Style),
+    {ok, Passes} = couch_query_servers:filter_view(DDoc, VName, Docs),
+    filter_revs(Passes, Docs);
+filter(Db, DocInfo, {custom, Style, Req0, DDoc, FName}) ->
+    Req = case Req0 of
+        {json_req, _} -> Req0;
+        #httpd{} -> {json_req, couch_httpd_external:json_req_obj(Req0, Db)}
+    end,
+    Docs = open_revs(Db, DocInfo, Style),
+    {ok, Passes} = couch_query_servers:filter_docs(Req, Db, DDoc, FName, Docs),
+    filter_revs(Passes, Docs).
+
+
+get_doc_ids({json_req, {Props}}) ->
+    check_docids(couch_util:get_value(<<"doc_ids">>, Props));
+get_doc_ids(#httpd{method='POST'}=Req) ->
     {Props} = couch_httpd:json_body_obj(Req),
-    DocIds =  couch_util:get_value(<<"doc_ids">>, Props, nil),
-    {filter_docids(DocIds, Style), DocIds};
-builtin_filter_fun("_doc_ids", Style, #httpd{method='GET'}=Req, _Db) ->
+    check_docids(couch_util:get_value(<<"doc_ids">>, Props));
+get_doc_ids(#httpd{method='GET'}=Req) ->
     DocIds = ?JSON_DECODE(couch_httpd:qs_value(Req, "doc_ids", "null")),
-    {filter_docids(DocIds, Style), DocIds};
-builtin_filter_fun("_design", Style, _Req, _Db) ->
-    {filter_designdoc(Style), []};
-builtin_filter_fun("_view", Style, Req, Db) ->
-    ViewName = couch_httpd:qs_value(Req, "view", ""),
-    {filter_view(ViewName, Style, Db), []};
-builtin_filter_fun(_FilterName, _Style, _Req, _Db) ->
-    throw({bad_request, "unknown builtin filter name"}).
-
-main_only_filter(#doc_info{revs=[#rev_info{rev=Rev}|_]}) ->
-    [{[{<<"rev">>, couch_doc:rev_to_str(Rev)}]}].
-
-all_docs_filter(#doc_info{revs=Revs}) ->
-    [{[{<<"rev">>, couch_doc:rev_to_str(Rev)}]} || #rev_info{rev=Rev} <- Revs].
-
-filter_docids(DocIds, Style) when is_list(DocIds)->
-    fun(_Db, #doc_info{id=DocId, revs=Revs}) ->
-            case lists:member(DocId, DocIds) of
-                true ->
-                    builtin_results(Style, Revs);
-                _ -> []
-            end
+    check_docids(DocIds);
+get_doc_ids(_) ->
+    throw({bad_request, no_doc_ids_provided}).
+
+
+check_docids(DocIds) when is_list(DocIds) ->
+    lists:foreach(fun
+        (DocId) when not is_binary(DocId) ->
+            Msg = "`doc_ids` filter parameter is not a list of binaries.",
+            throw({bad_request, Msg});
+        (_) -> ok
+    end, DocIds),
+    DocIds;
+check_docids(_) ->
+    Msg = "`doc_ids` filter parameter is not a list of binaries.",
+    throw({bad_request, Msg}).
+
+
+open_ddoc(#db{name= <<"shards/", _/binary>> =ShardName}, DDocId) ->
+    {_, Ref} = spawn_monitor(fun() ->
+        exit(fabric:open_doc(mem3:dbname(ShardName), DDocId, []))
+    end),
+    receive
+        {'DOWN', Ref, _, _, {ok, _}=Response} ->
+            Response;
+        {'DOWN', Ref, _, _, Response} ->
+            throw(Response)
     end;
-filter_docids(_, _) ->
-    throw({bad_request, "`doc_ids` filter parameter is not a list."}).
-
-filter_designdoc(Style) ->
-    fun(_Db, #doc_info{id=DocId, revs=Revs}) ->
-            case DocId of
-            <<"_design", _/binary>> ->
-                    builtin_results(Style, Revs);
-                _ -> []
-            end
+open_ddoc(Db, DDocId) ->
+    case couch_db:open_doc(Db, DDocId, [ejson_body]) of
+        {ok, _} = Resp -> Resp;
+        Else -> throw(Else)
     end.
 
-filter_view("", _Style, _Db) ->
-    throw({bad_request, "`view` filter parameter is not provided."});
-filter_view(ViewName, Style, Db) ->
-    case [list_to_binary(couch_httpd:unquote(Part))
-            || Part <- string:tokens(ViewName, "/")] of
-        [] ->
-            throw({bad_request, "Invalid `view` parameter."});
-        [DName, VName] ->
-            DesignId = <<"_design/", DName/binary>>,
-            DDoc = couch_httpd_db:couch_doc_open(Db, DesignId, nil, [ejson_body]),
-            % validate that the ddoc has the filter fun
-            #doc{body={Props}} = DDoc,
-            couch_util:get_nested_json_value({Props}, [<<"views">>, VName]),
-            fun(Db2, DocInfo) ->
-                DocInfos =
-                case Style of
-                main_only ->
-                    [DocInfo];
-                all_docs ->
-                    [DocInfo#doc_info{revs=[Rev]}|| Rev <- DocInfo#doc_info.revs]
-                end,
-                Docs = [Doc || {ok, Doc} <- [
-                        couch_db:open_doc(Db2, DocInfo2, [deleted, conflicts])
-                            || DocInfo2 <- DocInfos]],
-                {ok, Passes} = couch_query_servers:filter_view(
-                    DDoc, VName, Docs
-                ),
-                [{[{<<"rev">>, couch_doc:rev_to_str({RevPos,RevId})}]}
-                    || {Pass, #doc{revs={RevPos,[RevId|_]}}}
-                    <- lists:zip(Passes, Docs), Pass == true]
-            end
-        end.
-
-builtin_results(Style, [#rev_info{rev=Rev}|_]=Revs) ->
-    case Style of
-        main_only ->
-            [{[{<<"rev">>, couch_doc:rev_to_str(Rev)}]}];
-        all_docs ->
-            [{[{<<"rev">>, couch_doc:rev_to_str(R)}]}
-                || #rev_info{rev=R} <- Revs]
-    end.
+
+check_member_exists(#doc{body={Props}}, Path) ->
+    couch_util:get_nested_json_value({Props}, Path).
+
+
+apply_style(#doc_info{revs=Revs}, main_only) ->
+    [#rev_info{rev=Rev} | _] = Revs,
+    [{[{<<"rev">>, couch_doc:rev_to_str(Rev)}]}];
+apply_style(#doc_info{revs=Revs}, all_docs) ->
+    [{[{<<"rev">>, couch_doc:rev_to_str(R)}]} || #rev_info{rev=R} <- Revs].
+
+
+open_revs(Db, DocInfo, Style) ->
+    DocInfos = case Style of
+        main_only -> [DocInfo];
+        all_docs -> [DocInfo#doc_info{revs=[R]}|| R <- DocInfo#doc_info.revs]
+    end,
+    OpenOpts = [deleted, conflicts],
+    % Relying on list comprehensions to silence errors
+    OpenResults = [couch_db:open_doc(Db, DI, OpenOpts) || DI <- DocInfos],
+    [Doc || {ok, Doc} <- OpenResults].
+
+
+filter_revs(Passes, Docs) ->
+    lists:flatmap(fun
+        ({true, #doc{revs={RevPos, [RevId | _]}}}) ->
+            RevStr = couch_doc:rev_to_str({RevPos, RevId}),
+            Change = {[{<<"rev">>, RevStr}]},
+            [Change];
+        (_) ->
+            []
+    end, lists:zip(Passes, Docs)).
+
 
 get_changes_timeout(Args, Callback) ->
     #changes_args{
@@ -292,13 +310,13 @@ build_acc(Args, Callback, UserAcc, Db, StartSeq, Prepend, Timeout, TimeoutFun) -
         conflicts = Conflicts,
         limit = Limit,
         feed = ResponseType,
-        filter_fun = FilterFun
+        filter_fun = Filter
     } = Args,
     #changes_acc{
         db = Db,
         seq = StartSeq,
         prepend = Prepend,
-        filter = FilterFun,
+        filter = Filter,
         callback = Callback,
         user_acc = UserAcc,
         resp_type = ResponseType,
@@ -311,100 +329,81 @@ build_acc(Args, Callback, UserAcc, Db, StartSeq, Prepend, Timeout, TimeoutFun) -
 
 send_changes(Args, Acc0, FirstRound) ->
     #changes_args{
-        dir = Dir,
-        filter = FilterName,
-        filter_args = FilterArgs
+        dir = Dir
     } = Args,
     #changes_acc{
         db = Db,
-        seq = StartSeq
+        seq = StartSeq,
+        filter = Filter
     } = Acc0,
-    case FirstRound of
-    true ->
-        case FilterName of
-        "_doc_ids" when length(FilterArgs) =< ?MAX_DOC_IDS ->
-            send_changes_doc_ids(
-                FilterArgs, Db, StartSeq, Dir, fun changes_enumerator/2, Acc0);
-        "_design" ->
-            send_changes_design_docs(
-                Db, StartSeq, Dir, fun changes_enumerator/2, Acc0);
+    EnumFun = fun ?MODULE:changes_enumerator/2,
+    case can_optimize(FirstRound, Filter) of
+        {true, Fun} ->
+            Fun(Db, StartSeq, Dir, EnumFun, Acc0, Filter);
         _ ->
-            couch_db:changes_since(
-                Db, StartSeq, fun changes_enumerator/2, [{dir, Dir}], Acc0)
-        end;
-    false ->
-        couch_db:changes_since(
-            Db, StartSeq, fun changes_enumerator/2, [{dir, Dir}], Acc0)
+            couch_db:changes_since(Db, StartSeq, EnumFun, [{dir, Dir}], Acc0)
     end.
 
 
-send_changes_doc_ids(DocIds, Db, StartSeq, Dir, Fun, Acc0) ->
+can_optimize(true, {doc_ids, _Style, DocIds})
+        when length(DocIds) =< ?MAX_DOC_IDS ->
+    {true, fun send_changes_doc_ids/6};
+can_optimize(true, {design_docs, _Style}) ->
+    {true, fun send_changes_design_docs/6};
+can_optimize(_, _) ->
+    false.
+
+
+send_changes_doc_ids(Db, StartSeq, Dir, Fun, Acc0, {doc_ids, _Style, DocIds}) ->
     Lookups = couch_btree:lookup(Db#db.id_tree, DocIds),
-    FullDocInfos = lists:foldl(
-        fun({ok, FDI}, Acc) ->
-            [FDI | Acc];
-        (not_found, Acc) ->
-            Acc
-        end,
-        [], Lookups),
-    send_lookup_changes(FullDocInfos, StartSeq, Dir, Db, Fun, Acc0).
+    FullInfos = lists:foldl(fun
+        ({ok, FDI}, Acc) -> [FDI | Acc];
+        (not_found, Acc) -> Acc
+    end, [], Lookups),
+    send_lookup_changes(FullInfos, StartSeq, Dir, Db, Fun, Acc0).
 
 
-send_changes_design_docs(Db, StartSeq, Dir, Fun, Acc0) ->
+send_changes_design_docs(Db, StartSeq, Dir, Fun, Acc0, {design_docs, _Style}) ->
     FoldFun = fun(FullDocInfo, _, Acc) ->
         {ok, [FullDocInfo | Acc]}
     end,
     KeyOpts = [{start_key, <<"_design/">>}, {end_key_gt, <<"_design0">>}],
-    {ok, _, FullDocInfos} = couch_btree:fold(
-        Db#db.id_tree, FoldFun, [], KeyOpts),
-    send_lookup_changes(FullDocInfos, StartSeq, Dir, Db, Fun, Acc0).
+    {ok, _, FullInfos} = couch_btree:fold(Db#db.id_tree, FoldFun, [], KeyOpts),
+    send_lookup_changes(FullInfos, StartSeq, Dir, Db, Fun, Acc0).
 
 
 send_lookup_changes(FullDocInfos, StartSeq, Dir, Db, Fun, Acc0) ->
     FoldFun = case Dir of
-    fwd ->
-        fun lists:foldl/3;
-    rev ->
-        fun lists:foldr/3
+        fwd -> fun lists:foldl/3;
+        rev -> fun lists:foldr/3
     end,
     GreaterFun = case Dir of
-    fwd ->
-        fun(A, B) -> A > B end;
-    rev ->
-        fun(A, B) -> A =< B end
+        fwd -> fun(A, B) -> A > B end;
+        rev -> fun(A, B) -> A =< B end
     end,
-    DocInfos = lists:foldl(
-        fun(FDI, Acc) ->
-            DI = couch_doc:to_doc_info(FDI),
-            case GreaterFun(DI#doc_info.high_seq, StartSeq) of
-            true ->
-                [DI | Acc];
-            false ->
-                Acc
-            end
-        end,
-        [], FullDocInfos),
+    DocInfos = lists:foldl(fun(FDI, Acc) ->
+        DI = couch_doc:to_doc_info(FDI),
+        case GreaterFun(DI#doc_info.high_seq, StartSeq) of
+            true -> [DI | Acc];
+            false -> Acc
+        end
+    end, [], FullDocInfos),
     SortedDocInfos = lists:keysort(#doc_info.high_seq, DocInfos),
     FinalAcc = try
-        FoldFun(
-            fun(DocInfo, Acc) ->
-                case Fun(DocInfo, Acc) of
+        FoldFun(fun(DocInfo, Acc) ->
+            case Fun(DocInfo, Acc) of
                 {ok, NewAcc} ->
                     NewAcc;
                 {stop, NewAcc} ->
                     throw({stop, NewAcc})
-                end
-            end,
-            Acc0, SortedDocInfos)
+            end
+        end, Acc0, SortedDocInfos)
     catch
-    throw:{stop, Acc} ->
-        Acc
+        {stop, Acc} -> Acc
     end,
     case Dir of
-    fwd ->
-        {ok, FinalAcc#changes_acc{seq = couch_db:get_update_seq(Db)}};
-    rev ->
-        {ok, FinalAcc}
+        fwd -> {ok, FinalAcc#changes_acc{seq = couch_db:get_update_seq(Db)}};
+        rev -> {ok, FinalAcc}
     end.
 
 
@@ -458,12 +457,12 @@ changes_enumerator(DocInfo, #changes_acc{resp_type = ResponseType} = Acc)
         when ResponseType =:= "continuous"
         orelse ResponseType =:= "eventsource" ->
     #changes_acc{
-        filter = FilterFun, callback = Callback,
+        filter = Filter, callback = Callback,
         user_acc = UserAcc, limit = Limit, db = Db,
         timeout = Timeout, timeout_fun = TimeoutFun
     } = Acc,
     #doc_info{high_seq = Seq} = DocInfo,
-    Results0 = FilterFun(Db, DocInfo),
+    Results0 = filter(Db, DocInfo, Filter),
     Results = [Result || Result <- Results0, Result /= null],
     %% TODO: I'm thinking this should be < 1 and not =< 1
     Go = if Limit =< 1 -> stop; true -> ok end,
@@ -484,12 +483,12 @@ changes_enumerator(DocInfo, #changes_acc{resp_type = ResponseType} = Acc)
     end;
 changes_enumerator(DocInfo, Acc) ->
     #changes_acc{
-        filter = FilterFun, callback = Callback, prepend = Prepend,
+        filter = Filter, callback = Callback, prepend = Prepend,
         user_acc = UserAcc, limit = Limit, resp_type = ResponseType, db = Db,
         timeout = Timeout, timeout_fun = TimeoutFun
     } = Acc,
     #doc_info{high_seq = Seq} = DocInfo,
-    Results0 = FilterFun(Db, DocInfo),
+    Results0 = filter(Db, DocInfo, Filter),
     Results = [Result || Result <- Results0, Result /= null],
     Go = if (Limit =< 1) andalso Results =/= [] -> stop; true -> ok end,
     case Results of


[39/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Add a config:reload/0 and HTTP trigger

Theoretically this should prevent all of those annoying test suite
failures when a test fails in with a temporary config set and fails to
undo its changes.

This works by storing the list of INI files in the config server and on
command will clear its ets table and re-read data from disk thus
clearing its cache of non-persisted values. Obviously this isn't
something that should be relied on in production settings.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/6e53c8a7
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/6e53c8a7
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/6e53c8a7

Branch: refs/heads/1843-feature-bigcouch
Commit: 6e53c8a7ee5a7f70a7492baf23c1aa383f7c5843
Parents: 19bab5c
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 01:47:34 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:55 2013 -0500

----------------------------------------------------------------------
 share/www/script/couch.js                   |  6 +++++
 src/config/src/config.erl                   | 31 ++++++++++++++++++++++--
 src/couch/src/couch_httpd_misc_handlers.erl |  7 +++++-
 test/javascript/cli_runner.js               |  1 +
 4 files changed, 42 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/6e53c8a7/share/www/script/couch.js
----------------------------------------------------------------------
diff --git a/share/www/script/couch.js b/share/www/script/couch.js
index 3deb441..58ad7a7 100644
--- a/share/www/script/couch.js
+++ b/share/www/script/couch.js
@@ -356,6 +356,12 @@ CouchDB.getVersion = function() {
   return JSON.parse(CouchDB.last_req.responseText).version;
 };
 
+CouchDB.reloadConfig = function() {
+  CouchDB.last_req = CouchDB.request("POST", "/_config/_reload");
+  CouchDB.maybeThrowError(CouchDB.last_req);
+  return JSON.parse(CouchDB.last_req.responseText);
+};
+
 CouchDB.replicate = function(source, target, rep_options) {
   rep_options = rep_options || {};
   var headers = rep_options.headers || {};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/6e53c8a7/src/config/src/config.erl
----------------------------------------------------------------------
diff --git a/src/config/src/config.erl b/src/config/src/config.erl
index 8a94f2c..f47639a 100644
--- a/src/config/src/config.erl
+++ b/src/config/src/config.erl
@@ -19,7 +19,7 @@
 -module(config).
 -behaviour(gen_server).
 
--export([start_link/1, stop/0]).
+-export([start_link/1, stop/0, reload/0]).
 -export([all/0, get/1, get/2, get/3, set/3, set/4, delete/2, delete/3]).
 -export([listen_for_changes/2]).
 -export([parse_ini_file/1]).
@@ -29,6 +29,7 @@
 
 -record(config, {
     notify_funs=[],
+    ini_files=undefined,
     write_filename=undefined
 }).
 
@@ -40,6 +41,9 @@ stop() ->
     gen_server:cast(?MODULE, stop).
 
 
+reload() ->
+    gen_server:call(?MODULE, reload).
+
 all() ->
     lists:sort(gen_server:call(?MODULE, all, infinity)).
 
@@ -94,7 +98,7 @@ init(IniFiles) ->
         _ -> undefined
     end,
     debug_config(),
-    {ok, #config{write_filename=WriteFile}}.
+    {ok, #config{ini_files=IniFiles, write_filename=WriteFile}}.
 
 
 terminate(_Reason, _State) ->
@@ -131,6 +135,29 @@ handle_call({delete, Sec, Key, Persist}, _From, Config) ->
     end,
     Event = {config_change, Sec, Key, deleted, Persist},
     gen_event:sync_notify(config_event, Event),
+    {reply, ok, Config};
+handle_call(reload, _From, Config) ->
+    DiskKVs = lists:foldl(fun(IniFile, DiskKVs0) ->
+        {ok, ParsedIniValues} = parse_ini_file(IniFile),
+        lists:foldl(fun({K, V}, DiskKVs1) ->
+            dict:store(K, V, DiskKVs1)
+        end, DiskKVs0, ParsedIniValues)
+    end, dict:new(), Config#config.ini_files),
+    % Update ets with anything we just read
+    % from disk
+    dict:fold(fun(K, V, _) ->
+        ets:insert(?MODULE, {K, V})
+    end, nil, DiskKVs),
+    % And remove anything in ets that wasn't
+    % on disk.
+    ets:foldl(fun({K, _}, _) ->
+        case dict:is_key(K, DiskKVs) of
+            true ->
+                ok;
+            false ->
+                ets:delete(?MODULE, K)
+        end
+    end, nil, ?MODULE),
     {reply, ok, Config}.
 
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/6e53c8a7/src/couch/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_misc_handlers.erl b/src/couch/src/couch_httpd_misc_handlers.erl
index b8f59cd..d57ceeb 100644
--- a/src/couch/src/couch_httpd_misc_handlers.erl
+++ b/src/couch/src/couch_httpd_misc_handlers.erl
@@ -157,6 +157,11 @@ handle_config_req(#httpd{method='GET', path_parts=[_, Section, Key]}=Req) ->
     Value ->
         send_json(Req, 200, list_to_binary(Value))
     end;
+% POST /_config/_reload - Flushes unpersisted config values from RAM
+handle_config_req(#httpd{method='POST', path_parts=[_, <<"_reload">>]}=Req) ->
+    ok = couch_httpd:verify_is_server_admin(Req),
+    ok = config:reload(),
+    send_json(Req, 200, {[{ok, true}]});
 % PUT or DELETE /_config/Section/Key
 handle_config_req(#httpd{method=Method, path_parts=[_, Section, Key]}=Req)
       when (Method == 'PUT') or (Method == 'DELETE') ->
@@ -215,7 +220,7 @@ handle_config_req(#httpd{method=Method, path_parts=[_, Section, Key]}=Req)
             end
     end;
 handle_config_req(Req) ->
-    send_method_not_allowed(Req, "GET,PUT,DELETE").
+    send_method_not_allowed(Req, "GET,PUT,POST,DELETE").
 
 % PUT /_config/Section/Key
 % "value"

http://git-wip-us.apache.org/repos/asf/couchdb/blob/6e53c8a7/test/javascript/cli_runner.js
----------------------------------------------------------------------
diff --git a/test/javascript/cli_runner.js b/test/javascript/cli_runner.js
index fcb4633..5d82a51 100644
--- a/test/javascript/cli_runner.js
+++ b/test/javascript/cli_runner.js
@@ -48,6 +48,7 @@ function T(arg1, arg2) {
 }
 
 function runTestConsole(num, name, func) {
+  CouchDB.reloadConfig();
   var passed = false;
   try {
     func();


[41/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Rewrite restartServer() for robustness

This uses an instance wide token set in the application environment to
detect when the server has restarted.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/0cbf6a9c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/0cbf6a9c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/0cbf6a9c

Branch: refs/heads/1843-feature-bigcouch
Commit: 0cbf6a9cea01eea599524bcdb77dedb322c7ade4
Parents: 0c273b1
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 14:08:43 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:56 2013 -0500

----------------------------------------------------------------------
 share/www/script/couch_test_runner.js       | 55 +++++++++++-------------
 src/couch/src/couch_httpd_misc_handlers.erl | 11 +++++
 2 files changed, 36 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/0cbf6a9c/share/www/script/couch_test_runner.js
----------------------------------------------------------------------
diff --git a/share/www/script/couch_test_runner.js b/share/www/script/couch_test_runner.js
index c04e6b1..cf5e57b 100644
--- a/share/www/script/couch_test_runner.js
+++ b/share/www/script/couch_test_runner.js
@@ -417,40 +417,35 @@ function waitForSuccess(fun, tag) {
   }
 }
 
-function waitForRestart() {
-  var waiting = true;
-  // Wait for the server to go down but don't
-  // wait too long because we might miss the
-  // the unavailable period.
-  var count = 25;
-  while (waiting && count > 0) {
-    count--;
-    try {
-      CouchDB.request("GET", "/");
-    } catch(e) {
-      waiting = false;
-    }
-  }
-  // Wait for it to come back up
-  waiting = true;
-  while (waiting) {
-    try {
-      CouchDB.request("GET", "/");
-      waiting = false;
-    } catch(e) {
-      // the request will fail until restart completes
-    }
-  }
+function getCurrentToken() {
+  var xhr = CouchDB.request("GET", "/_restart/token");
+  return JSON.parse(xhr.responseText).token;
 };
 
+
 function restartServer() {
-  var xhr;
-  try {
-    CouchDB.request("POST", "/_restart");
-  } catch(e) {
-    // this request may sometimes fail
+  var token = getCurrentToken();
+  var token_changed = false;
+  var tDelta = 5000;
+  var t0 = new Date();
+  var t1;
+
+  CouchDB.request("POST", "/_restart");
+
+  do {
+    try {
+      if(token != getCurrentToken()) {
+        token_changed = true;
+      }
+    } catch (e) {
+      // Ignore errors while the server restarts
+    }
+    t1 = new Date();
+  } while(((t1 - t0) <= tDelta) && !token_changed);
+
+  if(!token_changed) {
+    throw("Server restart failed");
   }
-  waitForRestart();
 }
 
 // legacy functions for CouchDB < 1.2.0

http://git-wip-us.apache.org/repos/asf/couchdb/blob/0cbf6a9c/src/couch/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_misc_handlers.erl b/src/couch/src/couch_httpd_misc_handlers.erl
index d57ceeb..3b2bbeb 100644
--- a/src/couch/src/couch_httpd_misc_handlers.erl
+++ b/src/couch/src/couch_httpd_misc_handlers.erl
@@ -94,6 +94,17 @@ handle_task_status_req(Req) ->
     send_method_not_allowed(Req, "GET,HEAD").
 
 
+handle_restart_req(#httpd{method='GET', path_parts=[_, <<"token">>]}=Req) ->
+    ok = couch_httpd:verify_is_server_admin(Req),
+    Token = case application:get_env(couch, instance_token) of
+        {ok, Tok} ->
+            Tok;
+        _ ->
+            Tok = erlang:phash2(make_ref()),
+            application:set_env(couch, instance_token, Tok),
+            Tok
+    end,
+    send_json(Req, 200, {[{token, Token}]});
 handle_restart_req(#httpd{method='POST'}=Req) ->
     couch_httpd:validate_ctype(Req, "application/json"),
     ok = couch_httpd:verify_is_server_admin(Req),


[14/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Fix views for node-local databases

Simple fix matches on `<<"shards/", _/binary>>` to detect if it should
use a Fabric call or open a local database.

BugzId: 14565


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/3a80e08d
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/3a80e08d
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/3a80e08d

Branch: refs/heads/1843-feature-bigcouch
Commit: 3a80e08d5776c5f98a915fcd3dec50d35e502828
Parents: 0b0b6f4
Author: Paul J. Davis <pa...@gmail.com>
Authored: Fri Aug 31 20:48:16 2012 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:52 2013 -0500

----------------------------------------------------------------------
 src/couch_index/src/couch_index_server.erl | 12 ++++++++++++
 1 file changed, 12 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/3a80e08d/src/couch_index/src/couch_index_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_index/src/couch_index_server.erl b/src/couch_index/src/couch_index_server.erl
index bd27c5c..8c76a62 100644
--- a/src/couch_index/src/couch_index_server.erl
+++ b/src/couch_index/src/couch_index_server.erl
@@ -31,6 +31,18 @@
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
+get_index(Module, <<"shards/", _/binary>>=DbName, DDoc) ->
+    {Pid, Ref} = spawn_monitor(fun() ->
+        exit(fabric:open_doc(mem3:dbname(DbName), DDoc, []))
+    end),
+    receive {'DOWN', Ref, process, Pid, {ok, Doc}} ->
+        get_index(Module, DbName, Doc, nil);
+    {'DOWN', Ref, process, Pid, Error} ->
+        Error
+    after 61000 ->
+        erlang:demonitor(Ref, [flush]),
+        {error, timeout}
+    end;
 
 get_index(Module, DbName, DDoc) ->
     get_index(Module, DbName, DDoc, nil).


[34/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Replicating existing docs bypasses validation

https://github.com/davisp/couchdb/commit/35bc88b69486a96409d9f9709209a5dacffc9174

The fact that the old test worked was a fluke. If we want to validate
all doc updates (even these that are no-ops) we should think harder
about our validation scheme.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/c57ad19f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/c57ad19f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/c57ad19f

Branch: refs/heads/1843-feature-bigcouch
Commit: c57ad19fe3a515e28465c527871248b5f9db272e
Parents: 77e7a1f
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 03:14:46 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:55 2013 -0500

----------------------------------------------------------------------
 share/www/script/test/security_validation.js | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/c57ad19f/share/www/script/test/security_validation.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/security_validation.js b/share/www/script/test/security_validation.js
index 862924a..14e5d04 100644
--- a/share/www/script/test/security_validation.js
+++ b/share/www/script/test/security_validation.js
@@ -115,6 +115,8 @@ couchTests.security_validation = function(debug) {
         {"WWW-Authenticate": "X-Couch-Test-Auth Jan Lehnardt:apple"}
       );
       // Attempt to save the design as a non-admin (in replication scenario)
+      designDoc.foo = "bar";
+      designDoc._rev = "2-642e20f96624a0aae6025b4dba0c6fb2";
       try {
         user2Db.save(designDoc, {new_edits : false});
         T(false && "Can't get here. Should have thrown an error on design doc");


[19/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Fix _sum reducer for objects with missing keys

BugzId: 17391


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/977c83d1
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/977c83d1
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/977c83d1

Branch: refs/heads/1843-feature-bigcouch
Commit: 977c83d13e57ecbca0ace0eb30eb9d59c9c52645
Parents: 77de003
Author: Mike Wallace <mi...@googlemail.com>
Authored: Mon Feb 18 16:50:47 2013 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:53 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/977c83d1/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 88ab30a..d919a85 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -232,9 +232,9 @@ sum_values(_Else, _Acc) ->
 sum_objects([{K1, V1} | Rest1], [{K1, V2} | Rest2]) ->
     [{K1, sum_values(V1, V2)} | sum_objects(Rest1, Rest2)];
 sum_objects([{K1, V1} | Rest1], [{K2, V2} | Rest2]) when K1 < K2 ->
-    [{K1, V1}, {K2, V2} | sum_objects(Rest1, Rest2)];
+    [{K1, V1} | sum_objects(Rest1, [{K2, V2} | Rest2])];
 sum_objects([{K1, V1} | Rest1], [{K2, V2} | Rest2]) when K1 > K2 ->
-    [{K2, V2}, {K1, V1} | sum_objects(Rest1, Rest2)];
+    [{K2, V2} | sum_objects([{K1, V1} | Rest1], Rest2)];
 sum_objects([], Rest) ->
     Rest;
 sum_objects(Rest, []) ->
@@ -440,9 +440,12 @@ sum_values_test() ->
     ?assertEqual(3, sum_values(1, 2)),
     ?assertEqual([2,4,6], sum_values(1, [1,4,6])),
     ?assertEqual([3,5,7], sum_values([3,2,4], [0,3,3])),
-    X = {[{<<"a">>,1}, {<<"b">>,[1,2]}, {<<"c">>, {[{<<"d">>,3}]}}]},
-    Y = {[{<<"a">>,2}, {<<"b">>,3}, {<<"c">>, {[{<<"e">>, 5}]}}]},
-    Z = {[{<<"a">>,3}, {<<"b">>,[4,2]}, {<<"c">>, {[{<<"d">>,3},{<<"e">>,5}]}}]},
+    X = {[{<<"a">>,1}, {<<"b">>,[1,2]}, {<<"c">>, {[{<<"d">>,3}]}},
+            {<<"g">>,1}]},
+    Y = {[{<<"a">>,2}, {<<"b">>,3}, {<<"c">>, {[{<<"e">>, 5}]}},
+            {<<"f">>,1}, {<<"g">>,1}]},
+    Z = {[{<<"a">>,3}, {<<"b">>,[4,2]}, {<<"c">>, {[{<<"d">>,3},{<<"e">>,5}]}},
+            {<<"f">>,1}, {<<"g">>,2}]},
     ?assertEqual(Z, sum_values(X, Y)),
     ?assertEqual(Z, sum_values(Y, X)).
 


[45/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
[squash] to etap updates


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/d164628b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/d164628b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/d164628b

Branch: refs/heads/1843-feature-bigcouch
Commit: d164628b20442f354065955bea4e8b846983ce8b
Parents: 66a5295
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Mar 14 02:06:36 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:57 2013 -0500

----------------------------------------------------------------------
 src/couch_replicator/test/02-httpc-pool.t       | 14 ++----------
 .../test/03-replication-compact.t               | 23 +++++++-------------
 .../test/04-replication-large-atts.t            | 17 +++------------
 .../test/05-replication-many-leaves.t           | 17 +++------------
 .../test/06-doc-missing-stubs.t                 | 17 +++------------
 5 files changed, 19 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/d164628b/src/couch_replicator/test/02-httpc-pool.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/02-httpc-pool.t b/src/couch_replicator/test/02-httpc-pool.t
index 23d7ab7..fc86cce 100755
--- a/src/couch_replicator/test/02-httpc-pool.t
+++ b/src/couch_replicator/test/02-httpc-pool.t
@@ -13,21 +13,11 @@
 % the License.
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(55),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    ok.
+    test_util:run(55, fun() -> test() end).
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     ibrowse:start(),
 
     test_pool_full(),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d164628b/src/couch_replicator/test/03-replication-compact.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/03-replication-compact.t b/src/couch_replicator/test/03-replication-compact.t
index 619d2b4..888d123 100755
--- a/src/couch_replicator/test/03-replication-compact.t
+++ b/src/couch_replicator/test/03-replication-compact.t
@@ -16,6 +16,8 @@
 % target of a replication doesn't affect the replication and that the
 % replication doesn't hold their reference counters forever.
 
+-mode(compile).
+
 -define(b2l(B), binary_to_list(B)).
 
 -record(user_ctx, {
@@ -66,21 +68,11 @@ target_db_name() -> <<"couch_test_rep_db_b">>.
 
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(376),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    ok.
+    test_util:run(376, fun() -> test() end).
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     ibrowse:start(),
 
     Pairs = [
@@ -112,13 +104,13 @@ test() ->
 
             delete_db(SourceDb),
             delete_db(TargetDb),
-            couch_server_sup:stop(),
+            ok = test_util:stop_couch(),
             ok = timer:sleep(1000),
-            couch_server_sup:start_link(test_util:config_files())
+            ok = test_util:start_couch()
         end,
         Pairs),
 
-    couch_server_sup:stop(),
+    ok = test_util:stop_couch(),
     ok.
 
 
@@ -284,6 +276,7 @@ compare_dbs(#db{name = SourceName}, #db{name = TargetName}) ->
 
 
 check_active_tasks(RepPid, {BaseId, Ext} = _RepId, Src, Tgt) ->
+    timer:sleep(1000),
     Source = case Src of
     {remote, NameSrc} ->
         <<(db_url(NameSrc))/binary, $/>>;

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d164628b/src/couch_replicator/test/04-replication-large-atts.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/04-replication-large-atts.t b/src/couch_replicator/test/04-replication-large-atts.t
index caf2f67..9adaead 100755
--- a/src/couch_replicator/test/04-replication-large-atts.t
+++ b/src/couch_replicator/test/04-replication-large-atts.t
@@ -49,21 +49,11 @@ target_db_name() -> <<"couch_test_rep_db_b">>.
 
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(1192),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    ok.
+    test_util:run(1192, fun() -> test() end).
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     ibrowse:start(),
     crypto:start(),
     config:set("attachments", "compressible_types", "text/*", false),
@@ -98,8 +88,7 @@ test() ->
         Pairs),
 
     delete_db(SourceDb),
-    couch_server_sup:stop(),
-    ok.
+    test_util:stop_couch().
 
 
 populate_db(Db, DocCount) ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d164628b/src/couch_replicator/test/05-replication-many-leaves.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/05-replication-many-leaves.t b/src/couch_replicator/test/05-replication-many-leaves.t
index be63d41..bd795ec 100755
--- a/src/couch_replicator/test/05-replication-many-leaves.t
+++ b/src/couch_replicator/test/05-replication-many-leaves.t
@@ -61,21 +61,11 @@ doc_num_conflicts(<<"doc3">>) -> 210.
 
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(56),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    ok.
+    test_util:run(56, fun() -> test() end).
 
 
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     ibrowse:start(),
     crypto:start(),
     config:set("replicator", "connection_timeout", "90000", false),
@@ -125,8 +115,7 @@ test() ->
         end,
         Pairs),
 
-    couch_server_sup:stop(),
-    ok.
+    test_util:stop_couch().
 
 
 populate_db(Db) ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d164628b/src/couch_replicator/test/06-doc-missing-stubs.t
----------------------------------------------------------------------
diff --git a/src/couch_replicator/test/06-doc-missing-stubs.t b/src/couch_replicator/test/06-doc-missing-stubs.t
index 0fffec2..116550c 100755
--- a/src/couch_replicator/test/06-doc-missing-stubs.t
+++ b/src/couch_replicator/test/06-doc-missing-stubs.t
@@ -52,22 +52,12 @@ target_revs_limit() -> 3.
 
 
 main(_) ->
-    test_util:init_code_path(),
-
-    etap:plan(128),
-    case (catch test()) of
-        ok ->
-            etap:end_tests();
-        Other ->
-            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
-            etap:bail(Other)
-    end,
-    ok.
+    test_util:run(128, fun() -> test() end).
 
 
 % Test motivated by COUCHDB-1365.
 test() ->
-    couch_server_sup:start_link(test_util:config_files()),
+    test_util:start_couch(),
     ibrowse:start(),
 
     Pairs = [
@@ -109,8 +99,7 @@ test() ->
         end,
         Pairs),
 
-    couch_server_sup:stop(),
-    ok.
+    test_util:stop_couch().
 
 
 populate_db(Db) ->


[08/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Extend _sum to operate on JSON Objects

A map function that emits JSON objects as values can now be used with
the builtin _sum function.  In contrast to our support for JSON arrays
(which can be freely mixed with numbers), this extension requires an
all-or-nothing approach - either emit only objects or do not emit any at
all.  Moreover, all the fields inside the object must have values that
are numbers or arrays of numbers.

TODO use proper instead of writing explicit unit test cases

BugzID: 14798


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/98a0cfa7
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/98a0cfa7
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/98a0cfa7

Branch: refs/heads/1843-feature-bigcouch
Commit: 98a0cfa798fd3a1aad03488a83ddc0f028a30cc8
Parents: 24f77c0
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Fri Dec 7 11:07:20 2012 -0800
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:51 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_query_servers.erl | 73 ++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/98a0cfa7/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index eb41e27..e420ce9 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -24,6 +24,11 @@
 
 -include_lib("couch/include/couch_db.hrl").
 
+-define(SUMERROR, <<"The _sum function requires that map values be numbers, "
+    "arrays of numbers, or objects. Objects cannot be mixed with other data "
+    "structures. Objects can be arbitrarily nested, provided that the values "
+    "for all fields are themselves numbers, arrays of numbers, or objects.">>).
+
 % https://gist.github.com/df10284c76d85f988c3f
 -define(SUMREGEX, {re_pattern,3,0,<<69,82,67,80,194,0,0,0,8,0,0,0,5,0,0,0,3,0,
 2,0,0,0,125,2,48,0,9,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,118,97,108,
@@ -204,29 +209,42 @@ builtin_reduce(Re, [<<"_stats",_/binary>>|BuiltinReds], KVs, Acc) ->
     builtin_reduce(Re, BuiltinReds, KVs, [Stats|Acc]).
 
 builtin_sum_rows(KVs) ->
-    lists:foldl(fun
-        ([_Key, Value], Acc) when is_number(Value), is_number(Acc) ->
-            Acc + Value;
-        ([_Key, Value], Acc) when is_list(Value), is_list(Acc) ->
-            sum_terms(Acc, Value);
-        ([_Key, Value], Acc) when is_number(Value), is_list(Acc) ->
-            sum_terms(Acc, [Value]);
-        ([_Key, Value], Acc) when is_list(Value), is_number(Acc) ->
-            sum_terms([Acc], Value);
-        (_Else, _Acc) ->
-            throw({invalid_value, <<"builtin _sum function requires map values to be numbers or lists of numbers">>})
-    end, 0, KVs).
-
-sum_terms([], []) ->
+    lists:foldl(fun([_Key, Value], Acc) -> sum_values(Value, Acc) end, 0, KVs).
+
+sum_values({Props}, {AccProps}) ->
+    {sum_objects(lists:sort(Props), lists:sort(AccProps))};
+sum_values(Value, Acc) when is_number(Value), is_number(Acc) ->
+    Acc + Value;
+sum_values(Value, Acc) when is_list(Value), is_list(Acc) ->
+    sum_arrays(Acc, Value);
+sum_values(Value, Acc) when is_number(Value), is_list(Acc) ->
+    sum_arrays(Acc, [Value]);
+sum_values(Value, Acc) when is_list(Value), is_number(Acc) ->
+    sum_arrays([Acc], Value);
+sum_values(_Else, _Acc) ->
+    throw({invalid_value, ?SUMERROR}).
+
+sum_objects([{K1, V1} | Rest1], [{K1, V2} | Rest2]) ->
+    [{K1, sum_values(V1, V2)} | sum_objects(Rest1, Rest2)];
+sum_objects([{K1, V1} | Rest1], [{K2, V2} | Rest2]) when K1 < K2 ->
+    [{K1, V1}, {K2, V2} | sum_objects(Rest1, Rest2)];
+sum_objects([{K1, V1} | Rest1], [{K2, V2} | Rest2]) when K1 > K2 ->
+    [{K2, V2}, {K1, V1} | sum_objects(Rest1, Rest2)];
+sum_objects([], Rest) ->
+    Rest;
+sum_objects(Rest, []) ->
+    Rest.
+
+sum_arrays([], []) ->
     [];
-sum_terms([_|_]=Xs, []) ->
+sum_arrays([_|_]=Xs, []) ->
     Xs;
-sum_terms([], [_|_]=Ys) ->
+sum_arrays([], [_|_]=Ys) ->
     Ys;
-sum_terms([X|Xs], [Y|Ys]) when is_number(X), is_number(Y) ->
-    [X+Y | sum_terms(Xs,Ys)];
-sum_terms(_, _) ->
-    throw({invalid_value, <<"builtin _sum function requires map values to be numbers or lists of numbers">>}).
+sum_arrays([X|Xs], [Y|Ys]) when is_number(X), is_number(Y) ->
+    [X+Y | sum_arrays(Xs,Ys)];
+sum_arrays(_, _) ->
+    throw({invalid_value, ?SUMERROR}).
 
 
 builtin_stats(reduce, [[_,First]|Rest]) ->
@@ -397,3 +415,18 @@ ret_os_process(Proc) ->
     true = gen_server:call(couch_proc_manager, {ret_proc, Proc}, infinity),
     catch unlink(Proc#proc.pid),
     ok.
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+sum_values_test() ->
+    ?assertEqual(3, sum_values(1, 2)),
+    ?assertEqual([2,4,6], sum_values(1, [1,4,6])),
+    ?assertEqual([3,5,7], sum_values([3,2,4], [0,3,3])),
+    X = {[{<<"a">>,1}, {<<"b">>,[1,2]}, {<<"c">>, {[{<<"d">>,3}]}}]},
+    Y = {[{<<"a">>,2}, {<<"b">>,3}, {<<"c">>, {[{<<"e">>, 5}]}}]},
+    Z = {[{<<"a">>,3}, {<<"b">>,[4,2]}, {<<"c">>, {[{<<"d">>,3},{<<"e">>,5}]}}]},
+    ?assertEqual(Z, sum_values(X, Y)),
+    ?assertEqual(Z, sum_values(Y, X)).
+
+-endif.


[29/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Introduce a #leaf{} record in revision trees

This is substantially based on work by Bob Dionne (a452a4a) to introduce
the data size calculations at Cloudant. There's quite a bit of conflict
in code and actual behavior between this work and what Filipe wrote for
CouchDB. This new record should ease the transition of merging both
behaviors.

An important thing to note is that this record is only ever in RAM and
not written to disk so we don't have to worry about record upgrades
though we will have to maintain upgrade info that Filipe and Bob both
introduced (which is fairly straightforward).


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/f8ef5e83
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/f8ef5e83
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/f8ef5e83

Branch: refs/heads/1843-feature-bigcouch
Commit: f8ef5e83f6dd5b8d57fffa3fe241ad39825cbeff
Parents: b474248
Author: Robert Newson <rn...@apache.org>
Authored: Sun Mar 10 16:12:28 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:54 2013 -0500

----------------------------------------------------------------------
 src/couch/include/couch_db.hrl     |  9 ++++++++
 src/couch/src/couch_db.erl         | 22 ++++++------------
 src/couch/src/couch_db_updater.erl | 40 ++++++++++++++-------------------
 src/couch/src/couch_doc.erl        | 13 ++++++-----
 src/couch/src/couch_util.erl       | 11 +++++++++
 5 files changed, 52 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/f8ef5e83/src/couch/include/couch_db.hrl
----------------------------------------------------------------------
diff --git a/src/couch/include/couch_db.hrl b/src/couch/include/couch_db.hrl
index 77006e4..61a59f7 100644
--- a/src/couch/include/couch_db.hrl
+++ b/src/couch/include/couch_db.hrl
@@ -23,6 +23,8 @@
 
 -define(b2l(V), binary_to_list(V)).
 -define(l2b(V), list_to_binary(V)).
+-define(i2b(V), couch_util:integer_to_boolean(V)).
+-define(b2i(V), couch_util:boolean_to_integer(V)).
 -define(term_to_bin(T), term_to_binary(T, [{minor_version, 1}])).
 -define(term_size(T),
     try
@@ -271,3 +273,10 @@
     stop_fun
 }).
 
+-record(leaf,  {
+    deleted,
+    ptr,
+    seq,
+    size = nil
+}).
+

http://git-wip-us.apache.org/repos/asf/couchdb/blob/f8ef5e83/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 7734c7c..e4e8cca 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -580,7 +580,7 @@ prep_and_validate_update(Db, #doc{id=Id,revs={RevStart, Revs}}=Doc,
     case Revs of
     [PrevRev|_] ->
         case dict:find({RevStart, PrevRev}, LeafRevsDict) of
-        {ok, {Deleted, DiskSp, DiskRevs}} ->
+        {ok, {#leaf{deleted=Deleted, ptr=DiskSp}, DiskRevs}} ->
             case couch_doc:has_stubs(Doc) of
             true ->
                 DiskDoc = make_doc(Db, Id, Deleted, DiskSp, DiskRevs),
@@ -643,12 +643,8 @@ prep_and_validate_updates(Db, [DocBucket|RestBuckets],
         AllowConflict, AccPrepped, AccErrors) ->
     Leafs = couch_key_tree:get_all_leafs(OldRevTree),
     LeafRevsDict = dict:from_list([
-        begin
-            Deleted = element(1, LeafVal),
-            Sp = element(2, LeafVal),
-            {{Start, RevId}, {Deleted, Sp, Revs}}
-        end ||
-        {LeafVal, {Start, [RevId | _]} = Revs} <- Leafs
+        {{Start, RevId}, {Leaf, Revs}} ||
+        {Leaf, {Start, [RevId | _]} = Revs} <- Leafs
     ]),
     {PreppedBucket, AccErrors3} = lists:foldl(
         fun({Doc, Ref}, {Docs2Acc, AccErrors2}) ->
@@ -895,9 +891,7 @@ make_first_doc_on_disk(Db, Id, Pos, [{_Rev, #doc{}} | RestPath]) ->
     make_first_doc_on_disk(Db, Id, Pos-1, RestPath);
 make_first_doc_on_disk(Db, Id, Pos, [{_Rev, ?REV_MISSING}|RestPath]) ->
     make_first_doc_on_disk(Db, Id, Pos - 1, RestPath);
-make_first_doc_on_disk(Db, Id, Pos, [{_Rev, RevValue} |_]=DocPath) ->
-    IsDel = element(1, RevValue),
-    Sp = element(2, RevValue),
+make_first_doc_on_disk(Db, Id, Pos, [{_Rev, #leaf{deleted=IsDel, ptr=Sp}} |_]=DocPath) ->
     Revs = [Rev || {Rev, _} <- DocPath],
     make_doc(Db, Id, IsDel, Sp, {Pos, Revs}).
 
@@ -1243,9 +1237,7 @@ open_doc_revs_int(Db, IdRevs, Options) ->
                     ?REV_MISSING ->
                         % we have the rev in our list but know nothing about it
                         {{not_found, missing}, {Pos, Rev}};
-                    RevValue ->
-                        IsDeleted = element(1, RevValue),
-                        SummaryPtr = element(2, RevValue),
+                    #leaf{deleted=IsDeleted, ptr=SummaryPtr} ->
                         {ok, make_doc(Db, Id, IsDeleted, SummaryPtr, FoundRevPath)}
                     end
                 end, FoundRevs),
@@ -1297,8 +1289,8 @@ doc_meta_info(#doc_info{high_seq=Seq,revs=[#rev_info{rev=Rev}|RestInfo]}, RevTre
         [{revs_info, Pos, lists:map(
             fun({Rev1, ?REV_MISSING}) ->
                 {Rev1, missing};
-            ({Rev1, RevValue}) ->
-                case element(1, RevValue) of
+            ({Rev1, Leaf}) ->
+                case Leaf#leaf.deleted of
                 true ->
                     {Rev1, deleted};
                 false ->

http://git-wip-us.apache.org/repos/asf/couchdb/blob/f8ef5e83/src/couch/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl
index c64911e..cc48ef8 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -158,10 +158,8 @@ handle_call({purge_docs, IdRevs}, _From, Db) ->
     {DocInfoToUpdate, NewSeq} = lists:mapfoldl(
         fun(#full_doc_info{rev_tree=Tree}=FullInfo, SeqAcc) ->
             Tree2 = couch_key_tree:map_leafs(
-                fun(_RevId, LeafVal) ->
-                    IsDeleted = element(1, LeafVal),
-                    BodyPointer = element(2, LeafVal),
-                    {IsDeleted, BodyPointer, SeqAcc + 1}
+                fun(_RevId, Leaf) ->
+                    Leaf#leaf{seq=SeqAcc+1}
                 end, Tree),
             {FullInfo#full_doc_info{rev_tree=Tree2}, SeqAcc + 1}
         end, LastSeq, FullDocInfoToUpdate),
@@ -340,37 +338,35 @@ rev_tree(DiskTree) ->
     couch_key_tree:mapfold(fun
         (_RevId, {IsDeleted, BodyPointer, UpdateSeq}, leaf, _Acc) ->
             % pre 1.2 format, will be upgraded on compaction
-            {{IsDeleted == 1, BodyPointer, UpdateSeq, nil}, nil};
+            {#leaf{deleted=?i2b(IsDeleted), ptr=BodyPointer, seq=UpdateSeq}, nil};
         (_RevId, {IsDeleted, BodyPointer, UpdateSeq}, branch, Acc) ->
-            {{IsDeleted == 1, BodyPointer, UpdateSeq, nil}, Acc};
+            {#leaf{deleted=?i2b(IsDeleted), ptr=BodyPointer, seq=UpdateSeq}, Acc};
         (_RevId, {IsDeleted, BodyPointer, UpdateSeq, Size}, leaf, Acc) ->
             Acc2 = sum_leaf_sizes(Acc, Size),
-            {{IsDeleted == 1, BodyPointer, UpdateSeq, Size}, Acc2};
+            {#leaf{deleted=?i2b(IsDeleted), ptr=BodyPointer, seq=UpdateSeq, size=Size}, Acc2};
         (_RevId, {IsDeleted, BodyPointer, UpdateSeq, Size}, branch, Acc) ->
-            {{IsDeleted == 1, BodyPointer, UpdateSeq, Size}, Acc};
+            {#leaf{deleted=?i2b(IsDeleted), ptr=BodyPointer, seq=UpdateSeq, size=Size}, Acc};
         (_RevId, ?REV_MISSING, _Type, Acc) ->
             {?REV_MISSING, Acc}
-    end, DiskTree).
+    end, 0, DiskTree).
 
 disk_tree(RevTree) ->
     couch_key_tree:map(fun
         (_RevId, ?REV_MISSING) ->
             ?REV_MISSING;
-        (_RevId, {IsDeleted, BodyPointer, UpdateSeq}) ->
-            {if IsDeleted -> 1; true -> 0 end, BodyPointer, UpdateSeq, nil};
-        (_RevId, {IsDeleted, BodyPointer, UpdateSeq, Size}) ->
-            {if IsDeleted -> 1; true -> 0 end, BodyPointer, UpdateSeq, Size}
+        (_RevId, #leaf{deleted=IsDeleted, ptr=BodyPointer, seq=UpdateSeq, size=Size}) ->
+            {?b2i(IsDeleted), BodyPointer, UpdateSeq, Size}
     end, RevTree).
 
 btree_by_seq_split(#full_doc_info{id=Id, update_seq=Seq, deleted=Del, rev_tree=T}) ->
-    {Seq, {Id, if Del -> 1; true -> 0 end, disk_tree(T)}}.
+    {Seq, {Id, ?b2i(Del), disk_tree(T)}}.
 
 btree_by_seq_join(Seq, {Id, Del, DiskTree}) when is_integer(Del) ->
     {RevTree, LeafsSize} = rev_tree(DiskTree),
     #full_doc_info{
         id = Id,
         update_seq = Seq,
-        deleted = (Del == 1),
+        deleted = ?i2b(Del),
         rev_tree = RevTree,
         leafs_size = LeafsSize
     };
@@ -388,14 +384,14 @@ btree_by_seq_join(KeySeq, {Id, RevInfos, DeletedRevInfos}) ->
 
 btree_by_id_split(#full_doc_info{id=Id, update_seq=Seq,
         deleted=Deleted, rev_tree=Tree}) ->
-    {Id, {Seq, if Deleted -> 1; true -> 0 end, disk_tree(Tree)}}.
+    {Id, {Seq, ?b2i(Deleted), disk_tree(Tree)}}.
 
 btree_by_id_join(Id, {HighSeq, Deleted, DiskTree}) ->
     {Tree, LeafsSize} = rev_tree(DiskTree),
     #full_doc_info{
         id = Id,
         update_seq = HighSeq,
-        deleted = (Deleted == 1),
+        deleted = ?i2b(Deleted),
         rev_tree = Tree,
         leafs_size = LeafsSize
     }.
@@ -573,7 +569,8 @@ flush_trees(#db{fd = Fd} = Db,
                 TotalSize = lists:foldl(
                     fun(#att{att_len = L}, A) -> A + L end,
                     SummarySize, Value#doc.atts),
-                NewValue = {IsDeleted, NewSummaryPointer, UpdateSeq, TotalSize},
+                NewValue = #leaf{deleted=IsDeleted, ptr=NewSummaryPointer,
+                                 seq=UpdateSeq, size=TotalSize},
                 case Type of
                 leaf ->
                     {NewValue, Acc + TotalSize};
@@ -899,10 +896,7 @@ copy_docs(Db, #db{fd = DestFd} = NewDb, MixedInfos, Retry) ->
             Info#full_doc_info{rev_tree=couch_key_tree:map(
                 fun(_, _, branch) ->
                     ?REV_MISSING;
-                (_Rev, LeafVal, leaf) ->
-                    IsDel = element(1, LeafVal),
-                    Sp = element(2, LeafVal),
-                    Seq = element(3, LeafVal),
+                (_Rev, #leaf{ptr=Sp}=Leaf, leaf) ->
                     {_Body, AttsInfo} = Summary = copy_doc_attachments(
                         Db, Sp, DestFd),
                     SummaryChunk = make_doc_summary(NewDb, Summary),
@@ -911,7 +905,7 @@ copy_docs(Db, #db{fd = DestFd} = NewDb, MixedInfos, Retry) ->
                     TotalLeafSize = lists:foldl(
                         fun({_, _, _, AttLen, _, _, _, _}, S) -> S + AttLen end,
                         SummarySize, AttsInfo),
-                    {IsDel, Pos, Seq, TotalLeafSize}
+                    Leaf#leaf{ptr=Pos, size=TotalLeafSize}
                 end, RevTree)}
         end, NewInfos0),
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/f8ef5e83/src/couch/src/couch_doc.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_doc.erl b/src/couch/src/couch_doc.erl
index bcf79d2..6f2ca9b 100644
--- a/src/couch/src/couch_doc.erl
+++ b/src/couch/src/couch_doc.erl
@@ -330,7 +330,10 @@ max_seq(Tree, UpdateSeq) ->
             {_Deleted, _DiskPos, OldTreeSeq} ->
                 % Older versions didn't track data sizes.
                 erlang:max(MaxOldSeq, OldTreeSeq);
-            {_Deleted, _DiskPos, OldTreeSeq, _Size} ->
+            {_Deleted, _DiskPos, OldTreeSeq, _Size} -> % necessary clause?
+                % Older versions didn't store #leaf records.
+                erlang:max(MaxOldSeq, OldTreeSeq);
+            #leaf{seq=OldTreeSeq} ->
                 erlang:max(MaxOldSeq, OldTreeSeq);
             _ ->
                 MaxOldSeq
@@ -341,11 +344,11 @@ max_seq(Tree, UpdateSeq) ->
 to_doc_info_path(#full_doc_info{id=Id,rev_tree=Tree,update_seq=FDISeq}) ->
     RevInfosAndPath = [
         {#rev_info{
-            deleted = element(1, LeafVal),
-            body_sp = element(2, LeafVal),
-            seq = element(3, LeafVal),
+            deleted = Leaf#leaf.deleted,
+            body_sp = Leaf#leaf.ptr,
+            seq = Leaf#leaf.seq,
             rev = {Pos, RevId}
-        }, Path} || {LeafVal, {Pos, [RevId | _]} = Path} <-
+        }, Path} || {Leaf, {Pos, [RevId | _]} = Path} <-
             couch_key_tree:get_all_leafs(Tree)
     ],
     SortedRevInfosAndPath = lists:sort(

http://git-wip-us.apache.org/repos/asf/couchdb/blob/f8ef5e83/src/couch/src/couch_util.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_util.erl b/src/couch/src/couch_util.erl
index 3556d36..d09211a 100644
--- a/src/couch/src/couch_util.erl
+++ b/src/couch/src/couch_util.erl
@@ -29,6 +29,7 @@
 -export([encode_doc_id/1]).
 -export([with_db/2]).
 -export([rfc1123_date/0, rfc1123_date/1]).
+-export([integer_to_boolean/1, boolean_to_integer/1]).
 
 -include_lib("couch/include/couch_db.hrl").
 
@@ -487,3 +488,13 @@ month(9) -> "Sep";
 month(10) -> "Oct";
 month(11) -> "Nov";
 month(12) -> "Dec".
+
+integer_to_boolean(1) ->
+    true;
+integer_to_boolean(0) ->
+    false.
+
+boolean_to_integer(true) ->
+    1;
+boolean_to_integer(false) ->
+    0.


[31/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
No need to specify Erlang ebin paths

Now that we have a proper OTP application structure we don't have to
list each path to start CouchDB.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/23cf4e3d
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/23cf4e3d
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/23cf4e3d

Branch: refs/heads/1843-feature-bigcouch
Commit: 23cf4e3dcdf13872e6fe620e40463d5072d1ed96
Parents: f633e54
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 16:13:38 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:54 2013 -0500

----------------------------------------------------------------------
 utils/Makefile.am | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/23cf4e3d/utils/Makefile.am
----------------------------------------------------------------------
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 4477156..eb8ec43 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -23,13 +23,7 @@ run: ../bin/couchdb.tpl
 	    -e "s|%bindir%|$(abs_top_builddir)/bin|g" \
 	    -e "s|%defaultini%|default_dev.ini|g" \
 	    -e "s|%localini%|local_dev.ini|g" \
-	    -e "s|%localerlanglibdir%|$(abs_top_builddir)\/src \
-			-pa $(abs_top_builddir)\/src\/couchdb \
-			-pa $(abs_top_builddir)\/src\/ejson \
-			-pa $(abs_top_builddir)\/src\/oauth \
-			-pa $(abs_top_builddir)\/src\/ibrowse \
-			-pa $(abs_top_builddir)\/src\/mochiweb \
-			-pa $(abs_top_builddir)\/src\/snappy|g" \
+	    -e "s|%localerlanglibdir%|$(abs_top_builddir)\/src|g" \
 	    -e "s|%localconfdir%|$(abs_top_builddir)/etc/couchdb|g" \
 	    -e "s|%localstatelogdir%|$(abs_top_builddir)/tmp/log|g" \
 	    -e "s|%localstatelibdir%|$(abs_top_builddir)/tmp/lib|g" \


[02/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Posted by rn...@apache.org.
Move macro definition to module for appup sanity

BugzID: 14553


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/ede95d58
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/ede95d58
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/ede95d58

Branch: refs/heads/1843-feature-bigcouch
Commit: ede95d58bf0c335cecc411651b9155c57bdfc5eb
Parents: 816bf80
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Fri Aug 31 13:28:03 2012 -0400
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:50 2013 -0500

----------------------------------------------------------------------
 src/couch/src/couch_db.erl | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/ede95d58/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index daa96d8..3707108 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -33,6 +33,8 @@
 
 -include_lib("couch/include/couch_db.hrl").
 
+-define(VALID_DB_NAME, "^[a-z][a-z0-9\\_\\$()\\+\\-\\/]*$").
+
 start_link(DbName, Filepath, Options) ->
     case open_db_file(Filepath, Options) of
     {ok, Fd} ->