You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2014/02/10 21:22:23 UTC

[01/50] couch commit: updated refs/heads/import to 09c6556

Updated Branches:
  refs/heads/import [created] 09c655604


Extend built-in _stats reduce to arrays of numbers

BugzID: 15671


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

Branch: refs/heads/import
Commit: ab02c8c23a30a4cc798c4c8b25ada2388d172f12
Parents: e5e5880
Author: Robert Newson <ro...@cloudant.com>
Authored: Tue Dec 18 21:10:13 2012 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:23 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/ab02c8c2/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index 4e4f938..71dcae9 100644
--- a/src/couch_query_servers.erl
+++ b/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.


[25/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/78df1c1c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/78df1c1c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/78df1c1c

Branch: refs/heads/import
Commit: 78df1c1cb10975a98d5acccb4948d88713648f32
Parents: 4fcb3b1
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 12:57:16 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/78df1c1c/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index 3d4a1a6..80448b1 100644
--- a/src/couch_server.erl
+++ b/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.
 


[36/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
git describe --always


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

Branch: refs/heads/import
Commit: b51ea9797774ea62dc5dede02867b15c61eee6f2
Parents: a100a82
Author: Robert Newson <rn...@apache.org>
Authored: Mon Feb 3 20:48:22 2014 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 rebar.config.script | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/b51ea979/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index 238f897..b92bde1 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -17,7 +17,7 @@ CouchJSName = case os:type() of
     _ ->
         "couchjs"
 end,
-Version = string:strip(os:cmd("git describe"), right, $\n),
+Version = string:strip(os:cmd("git describe --always"), right, $\n),
 
 %% build config.h
 ConfigH = [


[34/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Build icu_driver


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

Branch: refs/heads/import
Commit: a64fe6592fc2b758fb2f7b7dc43312fafd8b5ecf
Parents: d05eb31
Author: Robert Newson <rn...@apache.org>
Authored: Mon Feb 3 13:42:58 2014 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 rebar.config.script | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a64fe659/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index a0e1345..43c9a61 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -48,21 +48,26 @@ end,
 CFLAGS1 = CFLAGS0 ++ " -DWITHOUT_CURL",
 
 PortEnv = [
+    {"DRV_CFLAGS",  "$DRV_CFLAGS -DPIC -O2 -fno-common"},
+    {"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -lpthread"},
     {"CFLAGS", "$CFLAGS -Wall -c -g -O2 " ++ CFLAGS1},
     {"LDFLAGS", LDFLAGS}],
 
 CouchJSSpec = [{filename:join(["priv", CouchJSName]),
                 ["priv/couch_js/{help,http,main,utf8,util}.c"]}],
 SpawnSpec = [{"priv/couchspawnkillable", ["priv/spawnkillable/*.c"]}],
+IcuSpec = [{"priv/couch_icu_driver.so", ["priv/icu_driver/*.c"]}],
+
+BaseSpecs = CouchJSSpec ++ IcuSpec,
 
 PortSpecs = case os:type() of
     {win32, _} ->
-        CouchJSSpec ++ SpawnSpec;
+        BaseSpecs ++ SpawnSpec;
     _ ->
         {ok, _} = file:copy("priv/spawnkillable/couchspawnkillable.sh",
                             "priv/couchspawnkillable"),
         os:cmd("chmod +x priv/couchspawnkillable"),
-        CouchJSSpec
+        BaseSpecs
 end,
 
 [{port_env, PortEnv},


[19/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: 78a4f420af66a902c2ab152af4c22014ee289911
Parents: 1d952f0
Author: Robert Newson <ro...@cloudant.com>
Authored: Fri Jan 25 01:49:54 2013 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/78a4f420/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index b32ed06..679d815 100644
--- a/src/couch_query_servers.erl
+++ b/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).
 


[32/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/7047b891
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/7047b891
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/7047b891

Branch: refs/heads/import
Commit: 7047b891e2afac8a55ea56792ca5cca27449333f
Parents: 78df1c1
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 13:09:10 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/7047b891/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index b8e150c..649826a 100644
--- a/src/couch_db_updater.erl
+++ b/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}.


[16/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: 1d952f01741240edf6935f10e73a4d5657f4e829
Parents: af1f7e9
Author: Russell Branca <ch...@gmail.com>
Authored: Wed Jan 23 14:14:21 2013 -0800
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/1d952f01/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index 5864288..b32ed06 100644
--- a/src/couch_query_servers.erl
+++ b/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.
 


[22/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/8c561b49
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/8c561b49
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/8c561b49

Branch: refs/heads/import
Commit: 8c561b49e02615d0b7af443c59f74fa2d9b92104
Parents: 4b7044a
Author: Paul J. Davis <pa...@gmail.com>
Authored: Sun Feb 10 15:04:02 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/8c561b49/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index 1c74456..9f8380e 100644
--- a/src/couch_server.erl
+++ b/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] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: f37ad2b1b65e50c18064b54f7e13f6dc79bfc954
Parents: 7474dfe
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 17:52:46 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f37ad2b1/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index cc48ef8..4fe6073 100644
--- a/src/couch_db_updater.erl
+++ b/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),


[41/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Build with rebar


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

Branch: refs/heads/import
Commit: 6c8c480ee7a579624c942cd24a3c0e5791a85986
Parents: 74e907a
Author: Robert Newson <rn...@apache.org>
Authored: Wed Dec 18 14:04:59 2013 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 Makefile.am                   | 204 -------------------------------------
 priv/Makefile.am              | 159 -----------------------------
 priv/stat_descriptions.cfg    |  50 +++++++++
 priv/stat_descriptions.cfg.in |  50 ---------
 rebar.config                  |  11 ++
 src/couch.app.src             |  22 ++++
 src/couch.app.tpl.in          |  26 -----
 7 files changed, 83 insertions(+), 439 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/6c8c480e/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 9a656f7..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,204 +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.
-
-SUBDIRS = priv
-
-# devdocdir = $(localdocdir)/developer/couchdb
-couchlibdir = $(localerlanglibdir)/couch-$(version)
-couchincludedir = $(couchlibdir)/include
-couchebindir = $(couchlibdir)/ebin
-
-couchinclude_DATA = include/couch_db.hrl src/couch_js_functions.hrl
-couchebin_DATA = $(compiled_files)
-
-# dist_devdoc_DATA = $(doc_base) $(doc_modules)
-
-CLEANFILES = $(compiled_files) $(doc_base)
-
-# CLEANFILES = $(doc_modules) edoc-info
-
-source_files = \
-    src/couch.erl \
-    src/couch_app.erl \
-    src/couch_auth_cache.erl \
-    src/couch_btree.erl \
-    src/couch_changes.erl \
-    src/couch_compaction_daemon.erl \
-    src/couch_compress.erl \
-    src/couch_config.erl \
-    src/couch_config_writer.erl \
-    src/couch_db.erl \
-    src/couch_db_update_notifier.erl \
-    src/couch_db_update_notifier_sup.erl \
-    src/couch_doc.erl \
-    src/couch_drv.erl \
-    src/couch_ejson_compare.erl \
-    src/couch_emsort.erl \
-    src/couch_event_sup.erl \
-    src/couch_external_manager.erl \
-    src/couch_external_server.erl \
-    src/couch_file.erl \
-    src/couch_httpd.erl \
-    src/couch_httpd_db.erl \
-    src/couch_httpd_auth.erl \
-    src/couch_httpd_cors.erl \
-    src/couch_httpd_oauth.erl \
-    src/couch_httpd_external.erl \
-    src/couch_httpd_misc_handlers.erl \
-    src/couch_httpd_proxy.erl \
-    src/couch_httpd_rewrite.erl \
-    src/couch_httpd_stats_handlers.erl \
-    src/couch_httpd_vhost.erl \
-    src/couch_key_tree.erl \
-    src/couch_log.erl \
-	src/couch_lru.erl \
-    src/couch_native_process.erl \
-    src/couch_os_daemons.erl \
-    src/couch_os_process.erl \
-    src/couch_passwords.erl \
-    src/couch_primary_sup.erl \
-	src/couch_proc_manager.erl \
-    src/couch_query_servers.erl \
-    src/couch_secondary_sup.erl \
-    src/couch_server.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 \
-    src/couch_uuids.erl \
-    src/couch_db_updater.erl \
-    src/couch_work_queue.erl
-
-EXTRA_DIST = \
-	$(source_files) \
-	include/couch_db.hrl \
-	src/couch_js_functions.hrl
-
-compiled_files = \
-    ebin/couch.app \
-    ebin/couch.beam \
-    ebin/couch_app.beam \
-    ebin/couch_auth_cache.beam \
-    ebin/couch_btree.beam \
-    ebin/couch_changes.beam \
-    ebin/couch_compaction_daemon.beam \
-    ebin/couch_compress.beam \
-    ebin/couch_config.beam \
-    ebin/couch_config_writer.beam \
-    ebin/couch_db.beam \
-    ebin/couch_db_update_notifier.beam \
-    ebin/couch_db_update_notifier_sup.beam \
-    ebin/couch_doc.beam \
-    ebin/couch_drv.beam \
-    ebin/couch_ejson_compare.beam \
-    ebin/couch_emsort.beam \
-    ebin/couch_event_sup.beam \
-    ebin/couch_external_manager.beam \
-    ebin/couch_external_server.beam \
-    ebin/couch_file.beam \
-    ebin/couch_httpd.beam \
-    ebin/couch_httpd_db.beam \
-    ebin/couch_httpd_auth.beam \
-    ebin/couch_httpd_oauth.beam \
-    ebin/couch_httpd_cors.beam \
-    ebin/couch_httpd_proxy.beam \
-    ebin/couch_httpd_external.beam \
-    ebin/couch_httpd_misc_handlers.beam \
-    ebin/couch_httpd_rewrite.beam \
-    ebin/couch_httpd_stats_handlers.beam \
-    ebin/couch_httpd_vhost.beam \
-    ebin/couch_key_tree.beam \
-    ebin/couch_log.beam \
-	ebin/couch_lru.beam \
-    ebin/couch_native_process.beam \
-    ebin/couch_os_daemons.beam \
-    ebin/couch_os_process.beam \
-    ebin/couch_passwords.beam \
-    ebin/couch_primary_sup.beam \
-	ebin/couch_proc_manager.beam \
-    ebin/couch_query_servers.beam \
-    ebin/couch_secondary_sup.beam \
-    ebin/couch_server.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 \
-    ebin/couch_uuids.beam \
-    ebin/couch_db_updater.beam \
-    ebin/couch_work_queue.beam
-
-# doc_base = \
-#     erlang.png \
-#     index.html \
-#     modules-frame.html \
-#     overview-summary.html \
-#     packages-frame.html \
-#     stylesheet.css
-
-# doc_modules = \
-#     couch_btree.html \
-#     couch_config.html \
-#     couch_config_writer.html \
-#     couch_db.html \
-#     couch_db_update_notifier.html \
-#     couch_db_update_notifier_sup.html \
-#     couch_doc.html \
-#     couch_event_sup.html \
-#     couch_file.html \
-#     couch_httpd.html \
-#     couch_key_tree.html \
-#     couch_log.html \
-#     couch_query_servers.html \
-#     couch_rep.html \
-#     couch_rep_sup.html \
-#     couch_server.html \
-#     couch_stream.html \
-#     couch_util.html
-
-if WINDOWS
-ebin/couch.app: src/couch.app.tpl
-	@mkdir -p ebin/
-	modules=`find ./src -name "*.erl" \! -name ".*" -exec basename {} .erl \; | tr '\n' ',' | sed "s/,$$//"`; \
-	sed -e "s|%package_name%|@package_name@|g" \
-			-e "s|%version%|@version@|g" \
-			-e "s|@modules@|$$modules|g" \
-			-e "s|%localconfdir%|../etc/couchdb|g" \
-			-e "s|@defaultini@|default.ini|g" \
-			-e "s|@localini@|local.ini|g" > \
-	$@ < $<
-else
-ebin/couch.app: src/couch.app.tpl
-	@mkdir -p ebin/
-	modules=`{ find ./src -name "*.erl" \! -name ".*" -exec basename {} .erl \; | tr '\n' ','; echo ''; } | sed "s/,$$//"`; \
-	sed -e "s|%package_name%|@package_name@|g" \
-			-e "s|%version%|@version@|g" \
-			-e "s|@modules@|$$modules|g" \
-			-e "s|%localconfdir%|@localconfdir@|g" \
-			-e "s|@defaultini@|default.ini|g" \
-			-e "s|@localini@|local.ini|g" > \
-	$@ < $<
-endif
-
-# $(dist_devdoc_DATA): edoc-info
-
-# $(ERL) -noshell -run edoc_run files [\"$<\"]
-
-ebin/%.beam: src/%.erl include/couch_db.hrl src/couch_js_functions.hrl
-	@mkdir -p ebin/
-	$(ERLC) -I$(top_srcdir)/src -o ebin/ $(ERLC_FLAGS) ${TEST} $<;
-

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/6c8c480e/priv/Makefile.am
----------------------------------------------------------------------
diff --git a/priv/Makefile.am b/priv/Makefile.am
deleted file mode 100644
index ced9bec..0000000
--- a/priv/Makefile.am
+++ /dev/null
@@ -1,159 +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.
-
-MAKE_SAFE = $(MAKE)
-
-couchlibdir = $(localerlanglibdir)/couch-$(version)
-couchprivdir = $(couchlibdir)/priv
-couchprivlibdir = $(couchlibdir)/priv/lib
-man1dir = $(mandir)/man1
-
-man_file = couchjs.1
-
-if BUILD_MAN
-man_file_build = $(man_file)
-else
-man_file_build =
-endif
-
-BUILT_SOURCES = $(man_file_build)
-
-EXTRA_DIST = \
-	spawnkillable/couchspawnkillable.sh \
-	stat_descriptions.cfg.in \
-	couch_ejson_compare/erl_nif_compat.h \
-	couch_js/sm170.c \
-	couch_js/sm180.c \
-	couch_js/sm185.c \
-	$(man_file_build)
-
-CLEANFILES = $(man_file_build) stat_descriptions.cfg
-
-couchprivlib_LTLIBRARIES = couch_icu_driver.la
-if USE_EJSON_COMPARE_NIF
-couchprivlib_LTLIBRARIES += couch_ejson_compare.la
-couch_ejson_compare_la_SOURCES = couch_ejson_compare/couch_ejson_compare.c
-couch_ejson_compare_la_CPPFLAGS = -D_BSD_SOURCE $(ICU_CPPFLAGS) $(ERLANG_FLAGS)
-couch_ejson_compare_la_LDFLAGS = -module -avoid-version
-couch_ejson_compare_la_LIBADD = $(ICU_LIBS)
-if WINDOWS
-couch_ejson_compare_la_LDFLAGS += -no-undefined
-endif
-endif
-couch_icu_driver_la_SOURCES = icu_driver/couch_icu_driver.c
-couch_icu_driver_la_LDFLAGS = -module -avoid-version
-couch_icu_driver_la_CPPFLAGS = $(ICU_CPPFLAGS) $(ERLANG_FLAGS)
-couch_icu_driver_la_LIBADD = $(ICU_LIBS)
-
-if WINDOWS
-couch_icu_driver_la_LDFLAGS += -no-undefined
-couch_icu_driver_so_name = couch_icu_driver.dll
-else
-couch_icu_driver_so_name = couch_icu_driver.so
-endif
-
-$(couch_icu_driver_so_name): couch_icu_driver.la
-	cp .libs/$(couch_icu_driver_so_name) $@
-
-all: $(couch_icu_driver_so_name)
-
-COUCHJS_SRCS = \
-	couch_js/help.h \
-	couch_js/http.c \
-	couch_js/http.h \
-	couch_js/main.c \
-	couch_js/utf8.c \
-	couch_js/utf8.h \
-	couch_js/util.h \
-	couch_js/util.c
-
-locallibbin_PROGRAMS = couchjs
-couchjs_SOURCES = $(COUCHJS_SRCS)
-couchjs_CFLAGS = -g -Wall -Werror -D_BSD_SOURCE $(CURL_CFLAGS) $(JS_CFLAGS)
-couchjs_LDADD = $(CURL_LIBS) $(JS_LIBS)
-
-couchpriv_DATA = stat_descriptions.cfg
-couchpriv_PROGRAMS = couchspawnkillable
-
-# Depend on source files so distributed man pages are not rebuilt for end user.
-
-$(man_file): $(COUCHJS_SRCS)
-	$(MAKE_SAFE) -f Makefile couchjs; \
-	$(top_srcdir)/build-aux/missing --run \
-	    help2man \
-	        --no-info \
-	        --help-option="-h" \
-	        --version-option="-V" \
-	        --name="$(package_name) JavaScript interpreter" \
-	        ./couchjs --output $@
-
-install-data-local:
-	if test -s $(man_file); then \
-	    if test `cat $(man_file) | wc -l` -gt 1; then \
-	        $(INSTALL) -d $(DESTDIR)$(man1dir); \
-	        $(INSTALL_DATA) $(man_file) $(DESTDIR)$(man1dir)/$(man_file); \
-	    fi \
-	fi
-
-%.cfg: %.cfg.in
-	cp $< $@
-
-if WINDOWS
-couchspawnkillable_SOURCES = spawnkillable/couchspawnkillable_win.c
-endif
-
-if !WINDOWS
-couchspawnkillable: spawnkillable/couchspawnkillable.sh
-	cp $< $@
-	chmod +x $@
-endif
-
-# libtool and automake have defeated markh.  For each of our executables
-# we end up with 2 copies - one directly in the 'target' folder (eg, 'priv')
-# and another - the correct one - in .libs.  The former doesn't work but is
-# what gets installed for 'couchspawnkillable' - but the correct one for
-# couchjs.exe *does* get copied.  *shrug*  So just clobber it with the
-# correct one as the last step. See bug COUCHDB-439
-install-data-hook:
-	if test -f "$(DESTDIR)$(couchprivlibdir)/couch_icu_driver"; then \
-	    rm -f "$(DESTDIR)$(couchprivlibdir)/couch_icu_driver.so"; \
-	    cd "$(DESTDIR)$(couchprivlibdir)" && \
-	        $(LN_S) couch_icu_driver couch_icu_driver.so; \
-	fi
-	if test -f "$(DESTDIR)$(couchprivlibdir)/couch_ejson_compare_nif"; then \
-	    rm -f "$(DESTDIR)$(couchprivlibdir)/couch_ejson_compare_nif.so"; \
-	    cd "$(DESTDIR)$(couchprivlibdir)" && \
-	        $(LN_S) couch_ejson_compare_nif couch_ejson_compare_nif.so; \
-	fi
-if WINDOWS
-	$(INSTALL) $(ICU_BIN)/icuuc*.dll $(bindir)
-	$(INSTALL) $(ICU_BIN)/icudt*.dll $(bindir)
-	$(INSTALL) $(ICU_BIN)/icuin*.dll $(bindir)
-	$(INSTALL) $(JS_LIB_BINARY) $(bindir)
-	$(INSTALL) .libs/couchspawnkillable.exe \
-		"$(DESTDIR)$(couchprivdir)/couchspawnkillable.exe"
-endif
-
-uninstall-local:
-	rm -f $(DESTDIR)$(man1dir)/$(man_file)
-	if test -f "$(DESTDIR)$(couchprivlibdir)/couch_erl_driver"; then \
-	    rm -f "$(DESTDIR)$(couchprivlibdir)/couch_erl_driver.so"; \
-	fi
-
-distcheck-hook:
-	if test ! -s $(man_file); then \
-	    $(top_srcdir)/build-aux/dist-error $(man_file); \
-	else \
-	    if test ! `cat $(man_file) | wc -l` -gt 1; then \
-	        $(top_srcdir)/build-aux/dist-error $(man_file); \
-	    fi \
-	fi

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/6c8c480e/priv/stat_descriptions.cfg
----------------------------------------------------------------------
diff --git a/priv/stat_descriptions.cfg b/priv/stat_descriptions.cfg
new file mode 100644
index 0000000..b80d768
--- /dev/null
+++ b/priv/stat_descriptions.cfg
@@ -0,0 +1,50 @@
+%% 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.
+
+% Style guide for descriptions: Start with a lowercase letter & do not add
+% a trailing full-stop / period
+% Please keep this in alphabetical order
+
+{couchdb, database_writes, "number of times a database was changed"}.
+{couchdb, database_reads, "number of times a document was read from a database"}.
+{couchdb, open_databases, "number of open databases"}.
+{couchdb, open_os_files, "number of file descriptors CouchDB has open"}.
+{couchdb, request_time, "length of a request inside CouchDB without MochiWeb"}.
+{couchdb, auth_cache_hits, "number of authentication cache hits"}.
+{couchdb, auth_cache_misses, "number of authentication cache misses"}.
+
+{httpd, bulk_requests, "number of bulk requests"}.
+{httpd, requests, "number of HTTP requests"}.
+{httpd, temporary_view_reads, "number of temporary view reads"}.
+{httpd, view_reads, "number of view reads"}.
+{httpd, clients_requesting_changes, "number of clients for continuous _changes"}.
+
+{httpd_request_methods, 'COPY', "number of HTTP COPY requests"}.
+{httpd_request_methods, 'DELETE', "number of HTTP DELETE requests"}.
+{httpd_request_methods, 'GET', "number of HTTP GET requests"}.
+{httpd_request_methods, 'HEAD', "number of HTTP HEAD requests"}.
+{httpd_request_methods, 'POST', "number of HTTP POST requests"}.
+{httpd_request_methods, 'PUT', "number of HTTP PUT requests"}.
+
+{httpd_status_codes, '200', "number of HTTP 200 OK responses"}.
+{httpd_status_codes, '201', "number of HTTP 201 Created responses"}.
+{httpd_status_codes, '202', "number of HTTP 202 Accepted responses"}.
+{httpd_status_codes, '301', "number of HTTP 301 Moved Permanently responses"}.
+{httpd_status_codes, '304', "number of HTTP 304 Not Modified responses"}.
+{httpd_status_codes, '400', "number of HTTP 400 Bad Request responses"}.
+{httpd_status_codes, '401', "number of HTTP 401 Unauthorized responses"}.
+{httpd_status_codes, '403', "number of HTTP 403 Forbidden responses"}.
+{httpd_status_codes, '404', "number of HTTP 404 Not Found responses"}.
+{httpd_status_codes, '405', "number of HTTP 405 Method Not Allowed responses"}.
+{httpd_status_codes, '409', "number of HTTP 409 Conflict responses"}.
+{httpd_status_codes, '412', "number of HTTP 412 Precondition Failed responses"}.
+{httpd_status_codes, '500', "number of HTTP 500 Internal Server Error responses"}.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/6c8c480e/priv/stat_descriptions.cfg.in
----------------------------------------------------------------------
diff --git a/priv/stat_descriptions.cfg.in b/priv/stat_descriptions.cfg.in
deleted file mode 100644
index b80d768..0000000
--- a/priv/stat_descriptions.cfg.in
+++ /dev/null
@@ -1,50 +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.
-
-% Style guide for descriptions: Start with a lowercase letter & do not add
-% a trailing full-stop / period
-% Please keep this in alphabetical order
-
-{couchdb, database_writes, "number of times a database was changed"}.
-{couchdb, database_reads, "number of times a document was read from a database"}.
-{couchdb, open_databases, "number of open databases"}.
-{couchdb, open_os_files, "number of file descriptors CouchDB has open"}.
-{couchdb, request_time, "length of a request inside CouchDB without MochiWeb"}.
-{couchdb, auth_cache_hits, "number of authentication cache hits"}.
-{couchdb, auth_cache_misses, "number of authentication cache misses"}.
-
-{httpd, bulk_requests, "number of bulk requests"}.
-{httpd, requests, "number of HTTP requests"}.
-{httpd, temporary_view_reads, "number of temporary view reads"}.
-{httpd, view_reads, "number of view reads"}.
-{httpd, clients_requesting_changes, "number of clients for continuous _changes"}.
-
-{httpd_request_methods, 'COPY', "number of HTTP COPY requests"}.
-{httpd_request_methods, 'DELETE', "number of HTTP DELETE requests"}.
-{httpd_request_methods, 'GET', "number of HTTP GET requests"}.
-{httpd_request_methods, 'HEAD', "number of HTTP HEAD requests"}.
-{httpd_request_methods, 'POST', "number of HTTP POST requests"}.
-{httpd_request_methods, 'PUT', "number of HTTP PUT requests"}.
-
-{httpd_status_codes, '200', "number of HTTP 200 OK responses"}.
-{httpd_status_codes, '201', "number of HTTP 201 Created responses"}.
-{httpd_status_codes, '202', "number of HTTP 202 Accepted responses"}.
-{httpd_status_codes, '301', "number of HTTP 301 Moved Permanently responses"}.
-{httpd_status_codes, '304', "number of HTTP 304 Not Modified responses"}.
-{httpd_status_codes, '400', "number of HTTP 400 Bad Request responses"}.
-{httpd_status_codes, '401', "number of HTTP 401 Unauthorized responses"}.
-{httpd_status_codes, '403', "number of HTTP 403 Forbidden responses"}.
-{httpd_status_codes, '404', "number of HTTP 404 Not Found responses"}.
-{httpd_status_codes, '405', "number of HTTP 405 Method Not Allowed responses"}.
-{httpd_status_codes, '409', "number of HTTP 409 Conflict responses"}.
-{httpd_status_codes, '412', "number of HTTP 412 Precondition Failed responses"}.
-{httpd_status_codes, '500', "number of HTTP 500 Internal Server Error responses"}.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/6c8c480e/rebar.config
----------------------------------------------------------------------
diff --git a/rebar.config b/rebar.config
new file mode 100644
index 0000000..def6879
--- /dev/null
+++ b/rebar.config
@@ -0,0 +1,11 @@
+{port_specs, [{"priv/couch_icu_driver.so", ["priv/icu_driver/couch_icu_driver.c"]}]}.
+
+{port_env, [
+  {"DRV_CFLAGS",  "$DRV_CFLAGS -DPIC -O2 -fno-common"},
+  {"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -lpthread"},
+  {"linux", "DRV_LDFLAGS", "$DRV_LDFLAGS -lcrypt"},
+  {"freebsd", "DRV_CFLAGS", "$DRV_CFLAGS -I/usr/local/include"},
+  {"freebsd", "DRV_LDFLAGS", "$DRV_LDFLAGS -L/usr/local/lib"},
+  {"solaris", "DRV_CFLAGS", "$DRV_CFLAGS -I/opt/local/include"},
+  {"solaris", "DRV_LDFLAGS", "$DRV_LDFLAGS -L/opt/local/lib"}
+]}.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/6c8c480e/src/couch.app.src
----------------------------------------------------------------------
diff --git a/src/couch.app.src b/src/couch.app.src
new file mode 100644
index 0000000..bb1e527
--- /dev/null
+++ b/src/couch.app.src
@@ -0,0 +1,22 @@
+{application, couch, [
+    {description, "Apache CouchDB"},
+    {vsn, git},
+    {registered, [
+        couch_db_update,
+        couch_db_update_notifier_sup,
+        couch_external_manager,
+        couch_httpd,
+        couch_log,
+        couch_primary_services,
+        couch_proc_manager,
+        couch_secondary_services,
+        couch_server,
+        couch_sup,
+        couch_stats_aggregator,
+        couch_stats_collector,
+        couch_task_status
+    ]},
+    {mod, {couch_app, []}},
+    {applications, [kernel, stdlib, crypto, sasl, inets, oauth, ibrowse,
+        mochiweb, ssl, twig]}
+]}.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/6c8c480e/src/couch.app.tpl.in
----------------------------------------------------------------------
diff --git a/src/couch.app.tpl.in b/src/couch.app.tpl.in
deleted file mode 100644
index 9b7536b..0000000
--- a/src/couch.app.tpl.in
+++ /dev/null
@@ -1,26 +0,0 @@
-{application, couch, [
-    {description, "@package_name@"},
-    {vsn, "@version@"},
-    {modules, [@modules@]},
-    {registered, [
-        couch_db_update,
-        couch_db_update_notifier_sup,
-        couch_external_manager,
-        couch_httpd,
-        couch_log,
-        couch_primary_services,
-        couch_proc_manager,
-        couch_secondary_services,
-        couch_server,
-        couch_sup,
-        couch_stats_aggregator,
-        couch_stats_collector,
-        couch_task_status
-    ]},
-    {mod, {couch_app, [
-        "%localconfdir%/@defaultini@",
-        "%localconfdir%/@localini@"
-    ]}},
-    {applications, [kernel, stdlib, twig, config]},
-    {included_applications, [crypto, sasl, inets, oauth, ibrowse, mochiweb, os_mon]}
-]}.


[42/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Avoid unnecessary linkage with per-port env


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

Branch: refs/heads/import
Commit: c3116d79c025ed5624829b601ede5d1b5149e59e
Parents: ad08d25
Author: Robert Newson <rn...@apache.org>
Authored: Tue Feb 4 12:54:48 2014 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 rebar.config.script | 43 ++++++++++++++-----------------------------
 1 file changed, 14 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/c3116d79/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index a4f72ec..9053485 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -35,33 +35,21 @@ ConfigH = [
 ConfigSrc = [["#define ", K, " ", V, $\n] || {K, V} <- ConfigH],
 ok = file:write_file("priv/couch_js/config.h", ConfigSrc),
 
-
-JSLIBS = "-lmozjs185",
-{CFLAGS0, LDFLAGS} = case os:type() of
-    {unix, darwin} ->
-        {"-DXP_UNIX -I/usr/local/include/js", JSLIBS};
-    {unix, linux} ->
-        {"-DXP_UNIX -I/usr/include/js", JSLIBS ++ " -lm"};
-    {unix, _} ->
-        {"-DXP_UNIX -I/usr/local/include/js", JSLIBS ++ " -lm"};
-    _ ->
-        {"-DXP_WIN -I/usr/include/js", JSLIBS}
-end,
-CFLAGS1 = CFLAGS0 ++ " -DWITHOUT_CURL",
-
-
-PortEnv = [
-    {"DRV_CFLAGS",  "$DRV_CFLAGS -DPIC -O2 -fno-common"},
-    {"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -lpthread"},
-    {"CFLAGS", "$CFLAGS -Wall -c -g -O2 " ++ CFLAGS1},
-    {"LDFLAGS", LDFLAGS}
-],
-
+JS_LDFLAGS = "-lmozjs185 -DWITHOUTCURL",
+CouchJSSrc = ["priv/couch_js/{help,http,main,utf8,util}.c"],
 
 BaseSpecs = [
-    {CouchJSPath, ["priv/couch_js/{help,http,main,utf8,util}.c"]},
-    {"priv/couch_icu_driver.so", ["priv/icu_driver/*.c"]},
-    {"priv/couch_ejson_compare.so", ["priv/couch_ejson_compare/*.c"]}
+        %% couchjs
+        {"darwin", CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", "-DXP_UNIX -I/usr/local/include/js"}, {"LDFLAGS", JS_LDFLAGS}]}]},
+        {"linux",  CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", "-DXP_UNIX -I/usr/include/js"}, {"LDFLAGS", JS_LDFLAGS ++ " -lm"}]}]},
+        {"unix",   CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", "-DXP_UNIX -I/usr/local/include/js}"}, {"LDFLAGS", JS_LDFLAGS ++ " -lm"}]}]},
+        {"win32",  CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", "-DXP_WIN -I/usr/include/js"}, {"LDFLAGS", JS_LDFLAGS}]}]},
+        % ICU
+        {"", "priv/couch_icu_driver.so", ["priv/icu_driver/*.c"], [{env, [
+            {"DRV_CFLAGS",  "$DRV_CFLAGS -DPIC -O2 -fno-common"},
+            {"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -lpthread"}]}]},
+        % ejson_compare
+        {"priv/couch_ejson_compare.so", ["priv/couch_ejson_compare/*.c"]}
 ],
 
 SpawnSpec = [
@@ -79,7 +67,4 @@ PortSpecs = case os:type() of
 end,
 
 
-[
-    {port_env, PortEnv},
-    {port_specs, PortSpecs}
-].
+[{port_specs, PortSpecs}].


[10/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/22fdbe2e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/22fdbe2e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/22fdbe2e

Branch: refs/heads/import
Commit: 22fdbe2e4c8c4372fadfd714cf45211bfdd5cff3
Parents: a7d1663
Author: Paul J. Davis <pa...@gmail.com>
Authored: Sun Mar 10 16:03:00 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

----------------------------------------------------------------------
 src/couch_db.erl            | 15 +++++++++++++--
 src/couch_query_servers.erl | 12 ++++++++++++
 2 files changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/22fdbe2e/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 56cb0d2..7734c7c 100644
--- a/src/couch_db.erl
+++ b/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-couch/blob/22fdbe2e/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index d919a85..8e4130e 100644
--- a/src/couch_query_servers.erl
+++ b/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


[49/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Add dbs and nodes to the system dbs lists

These are the internal database names used by BigCouch for storing
cluster information.


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

Branch: refs/heads/import
Commit: f8c23352480c46bf4982daf5a95a468a0a1f5292
Parents: 68f9777
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Feb 6 22:38:25 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Thu Feb 6 22:38:25 2014 -0600

----------------------------------------------------------------------
 src/couch_server.erl | 50 +++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f8c23352/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index e4de69e..64c87ef 100644
--- a/src/couch_server.erl
+++ b/src/couch_server.erl
@@ -110,29 +110,33 @@ 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 config:get("replicator", "db", "_replicator") of
-    DbName ->
-        [
-            {before_doc_update, fun couch_replicator_manager:before_doc_update/2},
-            {after_doc_read, fun couch_replicator_manager:after_doc_read/2},
-            sys_db | Options
-        ];
-    _ ->
-        case config:get("couch_httpd_auth", "authentication_db", "_users") of
-        DbName ->
-        [
-            {before_doc_update, fun couch_users_db:before_doc_update/2},
-            {after_doc_read, fun couch_users_db:after_doc_read/2},
-            sys_db | Options
-        ];
-        _ ->
-            case config:get("mem3", "shard_db", "dbs") of
-            DbName ->
-                [sys_db | Options];
-            _ ->
-                Options
-            end
-        end
+    ReplicatorDbName = config:get("replicator", "db", "_replicator"),
+    ReplicatorDbOptions = [
+        {before_doc_update, fun couch_replicator_manager:before_doc_update/2},
+        {after_doc_read, fun couch_replicator_manager:after_doc_read/2},
+        sys_db
+    ] ++ Options,
+    UsersDbName = config:get("couch_httpd_auth", "authentication_db", "_users"),
+    UsersDbOptions = [
+        {before_doc_update, fun couch_users_db:before_doc_update/2},
+        {after_doc_read, fun couch_users_db:after_doc_read/2},
+        sys_db
+    ] ++ Options,
+    DbsDbName = config:get("mem3", "shard_db", "dbs"),
+    DbsDbOptions = [sys_db | Options],
+    NodesDbName = config:get("mem3", "node_db", "nodes"),
+    NodesDbOptions = [sys_db | Options],
+    KnownSysDbs = [
+        {ReplicatorDbName, ReplicatorDbOptions},
+        {UsersDbName, UsersDbOptions},
+        {DbsDbName, DbsDbOptions},
+        {NodesDbName, NodesDbOptions}
+    ],
+    case lists:keyfind(DbName, 1, KnownSysDbs) of
+        {DbName, SysOptions} ->
+            SysOptions;
+        false ->
+            Options
     end.
 
 check_dbname(#server{dbname_regexp=RegExp}, DbName) ->


[06/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/5a2ec4f5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/5a2ec4f5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/5a2ec4f5

Branch: refs/heads/import
Commit: 5a2ec4f50cbac04d8572cde13a118b3d0341fad6
Parents: f8fb11a
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Fri Dec 7 11:07:20 2012 -0800
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:23 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/5a2ec4f5/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index eb41e27..e420ce9 100644
--- a/src/couch_query_servers.erl
+++ b/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.


[14/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/af1f7e96
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/af1f7e96
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/af1f7e96

Branch: refs/heads/import
Commit: af1f7e965a47f6e0f436eef7d69f6c75dd2bab3d
Parents: 207708a
Author: Russell Branca <ch...@gmail.com>
Authored: Wed Jan 23 14:03:24 2013 -0800
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/af1f7e96/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index 71dcae9..5864288 100644
--- a/src/couch_query_servers.erl
+++ b/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;


[24/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/1a8d72c5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/1a8d72c5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/1a8d72c5

Branch: refs/heads/import
Commit: 1a8d72c53184be4c3994ed16891a25f27e681466
Parents: cadc7e6
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 01:47:34 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/1a8d72c5/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_misc_handlers.erl b/src/couch_httpd_misc_handlers.erl
index b8f59cd..d57ceeb 100644
--- a/src/couch_httpd_misc_handlers.erl
+++ b/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"


[39/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Do you even build


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

Branch: refs/heads/import
Commit: ad08d25dc9525a2ed454071d060144ab21deb8d4
Parents: dd17921
Author: Robert Newson <rn...@apache.org>
Authored: Mon Feb 3 23:02:52 2014 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 rebar.config.script | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/ad08d25d/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index bbc8400..a4f72ec 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -59,7 +59,7 @@ PortEnv = [
 
 
 BaseSpecs = [
-    {CouchJSPath, ["priv/couch_js/*.c"]},
+    {CouchJSPath, ["priv/couch_js/{help,http,main,utf8,util}.c"]},
     {"priv/couch_icu_driver.so", ["priv/icu_driver/*.c"]},
     {"priv/couch_ejson_compare.so", ["priv/couch_ejson_compare/*.c"]}
 ],


[18/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: 4b7044a0c0aee6f304c5a8c4e00a197bd0ba7c77
Parents: c3bc116
Author: Robert Newson <ro...@cloudant.com>
Authored: Fri Jan 25 14:18:53 2013 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/4b7044a0/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index 679d815..88ab30a 100644
--- a/src/couch_query_servers.erl
+++ b/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",


[43/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Make sure that we don't destroy the current CONFIG

Found this by looking at other example rebar.config.script examples. We
want to be sure we aren't accidentally removing configuration values
from the global CONIFG value.


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

Branch: refs/heads/import
Commit: cee3471cf033d847c9e6fe40f5aecd6e48628f38
Parents: c3116d7
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Feb 4 20:22:42 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 21:05:33 2014 -0600

----------------------------------------------------------------------
 rebar.config.script | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/cee3471c/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index 9053485..8e7c8e6 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -66,5 +66,9 @@ PortSpecs = case os:type() of
         BaseSpecs
 end,
 
+AddConfig = [{port_specs, PortSpecs}].
+
+lists:foldl(fun({K, V}, CfgAcc) ->
+    lists:keystore(K, 1, CfgAcc, {K, V})
+end, CONFIG, AddConfig).
 
-[{port_specs, PortSpecs}].


[45/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Ignore built files


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

Branch: refs/heads/import
Commit: 331d549a48874bc44177d4a9001ba152bae5b11c
Parents: 783326a
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Feb 4 22:09:10 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 22:09:10 2014 -0600

----------------------------------------------------------------------
 .gitignore | 7 +++++++
 1 file changed, 7 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/331d549a/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e5bb133
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+*.o
+*.so
+ebin/
+
+priv/couch_js/config.h
+priv/couchjs
+priv/couchspawnkillable


[29/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: cadc7e6305c3b5487dd007436de36fc4499f65d9
Parents: f37ad2b
Author: Robert Newson <rn...@apache.org>
Authored: Tue Mar 12 12:18:00 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/cadc7e63/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index 4fe6073..b8e150c 100644
--- a/src/couch_db_updater.erl
+++ b/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;


[28/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/7474dfe5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/7474dfe5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/7474dfe5

Branch: refs/heads/import
Commit: 7474dfe5531871baad403248fbc7b81aece77d63
Parents: e09b807
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 16:13:14 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/7474dfe5/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
index 63c557e..9a656f7 100644
--- a/Makefile.am
+++ b/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-couch/blob/7474dfe5/src/couch.app.tpl.in
----------------------------------------------------------------------
diff --git a/src/couch.app.tpl.in b/src/couch.app.tpl.in
index 1cd0154..9b7536b 100644
--- a/src/couch.app.tpl.in
+++ b/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-couch/blob/7474dfe5/src/couch.erl
----------------------------------------------------------------------
diff --git a/src/couch.erl b/src/couch.erl
index 7d53d0c..15cffbc 100644
--- a/src/couch.erl
+++ b/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-couch/blob/7474dfe5/src/couch_app.erl
----------------------------------------------------------------------
diff --git a/src/couch_app.erl b/src/couch_app.erl
index 3120a1f..d284c2b 100644
--- a/src/couch_app.erl
+++ b/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-couch/blob/7474dfe5/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_misc_handlers.erl b/src/couch_httpd_misc_handlers.erl
index e46dee3..b8f59cd 100644
--- a/src/couch_httpd_misc_handlers.erl
+++ b/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-couch/blob/7474dfe5/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index 6130fc9..45b334f 100644
--- a/src/couch_proc_manager.erl
+++ b/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-couch/blob/7474dfe5/src/couch_secondary_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_secondary_sup.erl b/src/couch_secondary_sup.erl
index 4f2d1c8..d0ed0c2 100644
--- a/src/couch_secondary_sup.erl
+++ b/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-couch/blob/7474dfe5/src/couch_server_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_server_sup.erl b/src/couch_server_sup.erl
deleted file mode 100644
index c42bcfb..0000000
--- a/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-couch/blob/7474dfe5/src/couch_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_sup.erl b/src/couch_sup.erl
new file mode 100644
index 0000000..3508d4f
--- /dev/null
+++ b/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.


[37/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Build couch_ejson_compare


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

Branch: refs/heads/import
Commit: a100a825da722e9b40d202e09d61f67136565138
Parents: a64fe65
Author: Robert Newson <rn...@apache.org>
Authored: Mon Feb 3 13:51:36 2014 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 rebar.config.script | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a100a825/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index 43c9a61..238f897 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -57,8 +57,9 @@ CouchJSSpec = [{filename:join(["priv", CouchJSName]),
                 ["priv/couch_js/{help,http,main,utf8,util}.c"]}],
 SpawnSpec = [{"priv/couchspawnkillable", ["priv/spawnkillable/*.c"]}],
 IcuSpec = [{"priv/couch_icu_driver.so", ["priv/icu_driver/*.c"]}],
+CompareSpec = [{"priv/couch_ejson_compare.so", ["priv/couch_ejson_compare/*.c"]}],
 
-BaseSpecs = CouchJSSpec ++ IcuSpec,
+BaseSpecs = CouchJSSpec ++ IcuSpec ++ CompareSpec,
 
 PortSpecs = case os:type() of
     {win32, _} ->


[21/50] couch commit: updated refs/heads/import to 09c6556

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

BugzId: 17391


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

Branch: refs/heads/import
Commit: 1b8cae98cffeac09e3cb888ff593cb494f6c0976
Parents: 8c561b4
Author: Mike Wallace <mi...@googlemail.com>
Authored: Mon Feb 18 16:50:47 2013 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/1b8cae98/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index 88ab30a..d919a85 100644
--- a/src/couch_query_servers.erl
+++ b/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)).
 


[02/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/4cc61f1b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/4cc61f1b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/4cc61f1b

Branch: refs/heads/import
Commit: 4cc61f1ba02d87b7190f5c014b93dd21cf5a5503
Parents: 5718463
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Nov 13 16:43:32 2012 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:23 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/4cc61f1b/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 2253e62..67c8a49 100644
--- a/src/couch_db.erl
+++ b/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.
 


[31/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: 4fcb3b157da7b25b7137cb24c7e66aff6e5cbfe5
Parents: 68d60f0
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 03:52:07 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/4fcb3b15/src/couch_file.erl
----------------------------------------------------------------------
diff --git a/src/couch_file.erl b/src/couch_file.erl
index a638c32..7528091 100644
--- a/src/couch_file.erl
+++ b/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;


[33/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/7035788d
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/7035788d
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/7035788d

Branch: refs/heads/import
Commit: 7035788d280b1ec4fe8d8406a558194043ae4c8d
Parents: 7047b89
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 14:08:43 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_misc_handlers.erl | 11 +++++++++++
 1 file changed, 11 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/7035788d/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_misc_handlers.erl b/src/couch_httpd_misc_handlers.erl
index d57ceeb..3b2bbeb 100644
--- a/src/couch_httpd_misc_handlers.erl
+++ b/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),


[17/50] couch commit: updated refs/heads/import to 09c6556

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

BugzID: 13179


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

Branch: refs/heads/import
Commit: 14d1dd27e887fecc59f72e5e05f9f0b56ade08e2
Parents: 1b8cae9
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Wed Feb 27 11:52:23 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/14d1dd27/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index 9f8380e..e8d8c49 100644
--- a/src/couch_server.erl
+++ b/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() ->


[23/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: 74e907afa6ff6ff4895023c5b5363e4177303396
Parents: 7035788
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Mar 12 15:23:07 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

----------------------------------------------------------------------
 src/couch_query_servers.erl | 25 ++++++++++++++++---------
 src/couch_server.erl        |  3 ++-
 2 files changed, 18 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/74e907af/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index 8e4130e..4fef028 100644
--- a/src/couch_query_servers.erl
+++ b/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-couch/blob/74e907af/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index 80448b1..e4de69e 100644
--- a/src/couch_server.erl
+++ b/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 ->


[04/50] couch commit: updated refs/heads/import to 09c6556

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

BugzID: 14553


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

Branch: refs/heads/import
Commit: ee7998df5a394ad3cbfe82b621c24792de40b464
Parents: ea800ea
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Fri Aug 31 13:28:03 2012 -0400
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:23 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/ee7998df/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index daa96d8..3707108 100644
--- a/src/couch_db.erl
+++ b/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} ->


[48/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
No longer use conditional imports for main.c

Dropping support for versions of SpiderMonkey other than 1.8.5 means we
don't need to bother with the conditional import.


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

Branch: refs/heads/import
Commit: 68f97778257cffe9ea6dc02202fec71cd25e53e0
Parents: 91ae53e
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Feb 4 22:23:26 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 22:25:04 2014 -0600

----------------------------------------------------------------------
 priv/couch_js/main.c  | 423 +++++++++++++++++++++++++++++++++++++++++++-
 priv/couch_js/sm185.c | 431 ---------------------------------------------
 rebar.config.script   |   2 +-
 3 files changed, 418 insertions(+), 438 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/68f97778/priv/couch_js/main.c
----------------------------------------------------------------------
diff --git a/priv/couch_js/main.c b/priv/couch_js/main.c
index 209bb02..1f1bb1d 100644
--- a/priv/couch_js/main.c
+++ b/priv/couch_js/main.c
@@ -10,12 +10,423 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <jsapi.h>
 #include "config.h"
+#include "http.h"
+#include "utf8.h"
+#include "util.h"
+
+
+#define SETUP_REQUEST(cx) \
+    JS_SetContextThread(cx); \
+    JS_BeginRequest(cx);
+#define FINISH_REQUEST(cx) \
+    JS_EndRequest(cx); \
+    JS_ClearContextThread(cx);
+
+
+static JSClass global_class = {
+    "GlobalClass",
+    JSCLASS_GLOBAL_FLAGS,
+    JS_PropertyStub,
+    JS_PropertyStub,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub,
+    JS_FinalizeStub,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+static JSBool
+req_ctor(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSBool ret;
+    JSObject* obj = JS_NewObjectForConstructor(cx, vp);
+    if(!obj) {
+        JS_ReportError(cx, "Failed to create CouchHTTP instance.\n");
+        return JS_FALSE;
+    }
+    ret = http_ctor(cx, obj);
+    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
+    return ret;
+}
+
+
+static void 
+req_dtor(JSContext* cx, JSObject* obj)
+{
+    http_dtor(cx, obj);
+}
+
+
+static JSBool
+req_open(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 2) {
+        ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
+    } else if(argc == 3) {
+        ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.open");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_set_hdr(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 2) {
+        ret = http_set_hdr(cx, obj, argv[0], argv[1]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_send(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 1) {
+        ret = http_send(cx, obj, argv[0]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.send");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_status(JSContext* cx, JSObject* obj, jsid pid, jsval* vp)
+{
+    int status = http_status(cx, obj);
+    if(status < 0)
+        return JS_FALSE;
+
+    JS_SET_RVAL(cx, vp, INT_TO_JSVAL(status));
+    return JS_TRUE;
+}
+
+
+static JSBool
+base_url(JSContext *cx, JSObject* obj, jsid pid, jsval* vp)
+{
+    couch_args *args = (couch_args*)JS_GetContextPrivate(cx);
+    return http_uri(cx, obj, args, &JS_RVAL(cx, vp));
+}
+
+
+static JSBool
+evalcx(JSContext *cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    JSString* str;
+    JSObject* sandbox;
+    JSObject* global;
+    JSContext* subcx;
+    JSCrossCompartmentCall* call = NULL;
+    const jschar* src;
+    size_t srclen;
+    jsval rval;
+    JSBool ret = JS_FALSE;
+    char *name = NULL;
+
+    sandbox = NULL;
+    if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) {
+        return JS_FALSE;
+    }
+
+    subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L);
+    if(!subcx) {
+        JS_ReportOutOfMemory(cx);
+        return JS_FALSE;
+    }
+
+    SETUP_REQUEST(subcx);
+
+    src = JS_GetStringCharsAndLength(cx, str, &srclen);
+
+    // Re-use the compartment associated with the main context,
+    // rather than creating a new compartment */
+    global = JS_GetGlobalObject(cx);
+    if(global == NULL) goto done;
+    call = JS_EnterCrossCompartmentCall(subcx, global);
+
+    if(!sandbox) {
+        sandbox = JS_NewGlobalObject(subcx, &global_class);
+        if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) {
+            goto done;
+        }
+    }
+
+    if(argc > 2) {
+        name = enc_string(cx, argv[2], NULL);
+    }
+
+    if(srclen == 0) {
+        JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox));
+    } else {
+        JS_EvaluateUCScript(subcx, sandbox, src, srclen, name, 1, &rval);
+        JS_SET_RVAL(cx, vp, rval);
+    }
+    
+    ret = JS_TRUE;
+
+done:
+    if(name) JS_free(cx, name);
+    JS_LeaveCrossCompartmentCall(call);
+    FINISH_REQUEST(subcx);
+    JS_DestroyContext(subcx);
+    return ret;
+}
+
+
+static JSBool
+gc(JSContext* cx, uintN argc, jsval* vp)
+{
+    JS_GC(cx);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
+
+
+static JSBool
+print(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    couch_print(cx, argc, argv);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
 
-#if defined(SM185)
-#include "sm185.c"
-#elif defined(SM180)
-#include "sm180.c"
-#else
-#include "sm170.c"
+
+static JSBool
+quit(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    int exit_code = 0;
+    JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
+    exit(exit_code);
+}
+
+
+static JSBool
+readline(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSString* line;
+
+    /* GC Occasionally */
+    JS_MaybeGC(cx);
+
+    line = couch_readline(cx, stdin);
+    if(line == NULL) return JS_FALSE;
+
+    JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(line));
+    return JS_TRUE;
+}
+
+
+static JSBool
+seal(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    JSObject *target;
+    JSBool deep = JS_FALSE;
+    JSBool ret;
+
+    if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+        return JS_FALSE;
+
+    if(!target) {
+        JS_SET_RVAL(cx, vp, JSVAL_VOID);
+        return JS_TRUE;
+    }
+
+    
+    ret = deep ? JS_DeepFreezeObject(cx, target) : JS_FreezeObject(cx, target);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+JSClass CouchHTTPClass = {
+    "CouchHTTP",
+    JSCLASS_HAS_PRIVATE
+        | JSCLASS_CONSTRUCT_PROTOTYPE
+        | JSCLASS_HAS_RESERVED_SLOTS(2),
+    JS_PropertyStub,
+    JS_PropertyStub,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub,
+    req_dtor,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+JSPropertySpec CouchHTTPProperties[] = {
+    {"status", 0, JSPROP_READONLY, req_status, NULL},
+    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
+    {0, 0, 0, 0, 0}
+};
+
+
+JSFunctionSpec CouchHTTPFunctions[] = {
+    JS_FS("_open", req_open, 3, 0),
+    JS_FS("_setRequestHeader", req_set_hdr, 2, 0),
+    JS_FS("_send", req_send, 1, 0),
+    JS_FS_END
+};
+
+
+static JSFunctionSpec global_functions[] = {
+    JS_FS("evalcx", evalcx, 0, 0),
+    JS_FS("gc", gc, 0, 0),
+    JS_FS("print", print, 0, 0),
+    JS_FS("quit", quit, 0, 0),
+    JS_FS("readline", readline, 0, 0),
+    JS_FS("seal", seal, 0, 0),
+    JS_FS_END
+};
+
+
+int
+main(int argc, const char* argv[])
+{
+    JSRuntime* rt = NULL;
+    JSContext* cx = NULL;
+    JSObject* global = NULL;
+    JSCrossCompartmentCall *call = NULL;
+    JSObject* klass = NULL;
+    JSSCRIPT_TYPE script;
+    JSString* scriptsrc;
+    const jschar* schars;
+    size_t slen;
+    jsval sroot;
+    jsval result;
+    int i;
+
+    couch_args* args = couch_parse_args(argc, argv);
+
+    rt = JS_NewRuntime(64L * 1024L * 1024L);
+    if(rt == NULL)
+        return 1;
+
+    cx = JS_NewContext(rt, args->stack_size);
+    if(cx == NULL)
+        return 1;
+
+    JS_SetErrorReporter(cx, couch_error);
+    JS_ToggleOptions(cx, JSOPTION_XML);
+    JS_SetOptions(cx, JSOPTION_METHODJIT);
+#ifdef JSOPTION_TYPE_INFERENCE
+    JS_SetOptions(cx, JSOPTION_TYPE_INFERENCE);
 #endif
+    JS_SetContextPrivate(cx, args);
+    
+    SETUP_REQUEST(cx);
+
+    global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
+    if(global == NULL)
+        return 1;
+
+    call = JS_EnterCrossCompartmentCall(cx, global);
+
+    JS_SetGlobalObject(cx, global);
+    
+    if(!JS_InitStandardClasses(cx, global))
+        return 1;
+
+    if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
+        return 1;
+ 
+    if(args->use_http) {
+        http_check_enabled();
+
+        klass = JS_InitClass(
+            cx, global,
+            NULL,
+            &CouchHTTPClass, req_ctor,
+            0,
+            CouchHTTPProperties, CouchHTTPFunctions,
+            NULL, NULL
+        );
+
+        if(!klass)
+        {
+            fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
+            exit(2);
+        }
+    } 
+
+    for(i = 0 ; args->scripts[i] ; i++) {
+        // Convert script source to jschars.
+        scriptsrc = couch_readfile(cx, args->scripts[i]);
+        if(!scriptsrc)
+            return 1;
+
+        schars = JS_GetStringCharsAndLength(cx, scriptsrc, &slen);
+
+        // Root it so GC doesn't collect it.
+        sroot = STRING_TO_JSVAL(scriptsrc);
+        if(JS_AddValueRoot(cx, &sroot) != JS_TRUE) {
+            fprintf(stderr, "Internal root error.\n");
+            return 1;
+        }
+
+        // Compile and run
+        script = JS_CompileUCScript(cx, global, schars, slen,
+                                    args->scripts[i], 1);
+        if(!script) {
+            fprintf(stderr, "Failed to compile script.\n");
+            return 1;
+        }
+
+        if(JS_ExecuteScript(cx, global, script, &result) != JS_TRUE) {
+            fprintf(stderr, "Failed to execute script.\n");
+            return 1;
+        }
+
+        // Warning message if we don't remove it.
+        JS_RemoveValueRoot(cx, &sroot);
+
+        // Give the GC a chance to run.
+        JS_MaybeGC(cx);
+    }
+
+    JS_LeaveCrossCompartmentCall(call);
+    FINISH_REQUEST(cx);
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/68f97778/priv/couch_js/sm185.c
----------------------------------------------------------------------
diff --git a/priv/couch_js/sm185.c b/priv/couch_js/sm185.c
deleted file mode 100644
index bfee023..0000000
--- a/priv/couch_js/sm185.c
+++ /dev/null
@@ -1,431 +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.
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <jsapi.h>
-#include "http.h"
-#include "utf8.h"
-#include "util.h"
-
-
-#define SETUP_REQUEST(cx) \
-    JS_SetContextThread(cx); \
-    JS_BeginRequest(cx);
-#define FINISH_REQUEST(cx) \
-    JS_EndRequest(cx); \
-    JS_ClearContextThread(cx);
-
-
-static JSClass global_class = {
-    "GlobalClass",
-    JSCLASS_GLOBAL_FLAGS,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_StrictPropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
-};
-
-
-static JSBool
-req_ctor(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSBool ret;
-    JSObject* obj = JS_NewObjectForConstructor(cx, vp);
-    if(!obj) {
-        JS_ReportError(cx, "Failed to create CouchHTTP instance.\n");
-        return JS_FALSE;
-    }
-    ret = http_ctor(cx, obj);
-    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
-    return ret;
-}
-
-
-static void 
-req_dtor(JSContext* cx, JSObject* obj)
-{
-    http_dtor(cx, obj);
-}
-
-
-static JSBool
-req_open(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSObject* obj = JS_THIS_OBJECT(cx, vp);
-    jsval* argv = JS_ARGV(cx, vp);
-    JSBool ret = JS_FALSE;
-
-    if(argc == 2) {
-        ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
-    } else if(argc == 3) {
-        ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.open");
-    }
-
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return ret;
-}
-
-
-static JSBool
-req_set_hdr(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSObject* obj = JS_THIS_OBJECT(cx, vp);
-    jsval* argv = JS_ARGV(cx, vp);
-    JSBool ret = JS_FALSE;
-
-    if(argc == 2) {
-        ret = http_set_hdr(cx, obj, argv[0], argv[1]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
-    }
-
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return ret;
-}
-
-
-static JSBool
-req_send(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSObject* obj = JS_THIS_OBJECT(cx, vp);
-    jsval* argv = JS_ARGV(cx, vp);
-    JSBool ret = JS_FALSE;
-
-    if(argc == 1) {
-        ret = http_send(cx, obj, argv[0]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.send");
-    }
-
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return ret;
-}
-
-
-static JSBool
-req_status(JSContext* cx, JSObject* obj, jsid pid, jsval* vp)
-{
-    int status = http_status(cx, obj);
-    if(status < 0)
-        return JS_FALSE;
-
-    JS_SET_RVAL(cx, vp, INT_TO_JSVAL(status));
-    return JS_TRUE;
-}
-
-
-static JSBool
-base_url(JSContext *cx, JSObject* obj, jsid pid, jsval* vp)
-{
-    couch_args *args = (couch_args*)JS_GetContextPrivate(cx);
-    return http_uri(cx, obj, args, &JS_RVAL(cx, vp));
-}
-
-
-static JSBool
-evalcx(JSContext *cx, uintN argc, jsval* vp)
-{
-    jsval* argv = JS_ARGV(cx, vp);
-    JSString* str;
-    JSObject* sandbox;
-    JSObject* global;
-    JSContext* subcx;
-    JSCrossCompartmentCall* call = NULL;
-    const jschar* src;
-    size_t srclen;
-    jsval rval;
-    JSBool ret = JS_FALSE;
-    char *name = NULL;
-
-    sandbox = NULL;
-    if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) {
-        return JS_FALSE;
-    }
-
-    subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L);
-    if(!subcx) {
-        JS_ReportOutOfMemory(cx);
-        return JS_FALSE;
-    }
-
-    SETUP_REQUEST(subcx);
-
-    src = JS_GetStringCharsAndLength(cx, str, &srclen);
-
-    // Re-use the compartment associated with the main context,
-    // rather than creating a new compartment */
-    global = JS_GetGlobalObject(cx);
-    if(global == NULL) goto done;
-    call = JS_EnterCrossCompartmentCall(subcx, global);
-
-    if(!sandbox) {
-        sandbox = JS_NewGlobalObject(subcx, &global_class);
-        if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) {
-            goto done;
-        }
-    }
-
-    if(argc > 2) {
-        name = enc_string(cx, argv[2], NULL);
-    }
-
-    if(srclen == 0) {
-        JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox));
-    } else {
-        JS_EvaluateUCScript(subcx, sandbox, src, srclen, name, 1, &rval);
-        JS_SET_RVAL(cx, vp, rval);
-    }
-    
-    ret = JS_TRUE;
-
-done:
-    if(name) JS_free(cx, name);
-    JS_LeaveCrossCompartmentCall(call);
-    FINISH_REQUEST(subcx);
-    JS_DestroyContext(subcx);
-    return ret;
-}
-
-
-static JSBool
-gc(JSContext* cx, uintN argc, jsval* vp)
-{
-    JS_GC(cx);
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return JS_TRUE;
-}
-
-
-static JSBool
-print(JSContext* cx, uintN argc, jsval* vp)
-{
-    jsval* argv = JS_ARGV(cx, vp);
-    couch_print(cx, argc, argv);
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return JS_TRUE;
-}
-
-
-static JSBool
-quit(JSContext* cx, uintN argc, jsval* vp)
-{
-    jsval* argv = JS_ARGV(cx, vp);
-    int exit_code = 0;
-    JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
-    exit(exit_code);
-}
-
-
-static JSBool
-readline(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSString* line;
-
-    /* GC Occasionally */
-    JS_MaybeGC(cx);
-
-    line = couch_readline(cx, stdin);
-    if(line == NULL) return JS_FALSE;
-
-    JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(line));
-    return JS_TRUE;
-}
-
-
-static JSBool
-seal(JSContext* cx, uintN argc, jsval* vp)
-{
-    jsval* argv = JS_ARGV(cx, vp);
-    JSObject *target;
-    JSBool deep = JS_FALSE;
-    JSBool ret;
-
-    if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
-        return JS_FALSE;
-
-    if(!target) {
-        JS_SET_RVAL(cx, vp, JSVAL_VOID);
-        return JS_TRUE;
-    }
-
-    
-    ret = deep ? JS_DeepFreezeObject(cx, target) : JS_FreezeObject(cx, target);
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return ret;
-}
-
-
-JSClass CouchHTTPClass = {
-    "CouchHTTP",
-    JSCLASS_HAS_PRIVATE
-        | JSCLASS_CONSTRUCT_PROTOTYPE
-        | JSCLASS_HAS_RESERVED_SLOTS(2),
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_StrictPropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    req_dtor,
-    JSCLASS_NO_OPTIONAL_MEMBERS
-};
-
-
-JSPropertySpec CouchHTTPProperties[] = {
-    {"status", 0, JSPROP_READONLY, req_status, NULL},
-    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
-    {0, 0, 0, 0, 0}
-};
-
-
-JSFunctionSpec CouchHTTPFunctions[] = {
-    JS_FS("_open", req_open, 3, 0),
-    JS_FS("_setRequestHeader", req_set_hdr, 2, 0),
-    JS_FS("_send", req_send, 1, 0),
-    JS_FS_END
-};
-
-
-static JSFunctionSpec global_functions[] = {
-    JS_FS("evalcx", evalcx, 0, 0),
-    JS_FS("gc", gc, 0, 0),
-    JS_FS("print", print, 0, 0),
-    JS_FS("quit", quit, 0, 0),
-    JS_FS("readline", readline, 0, 0),
-    JS_FS("seal", seal, 0, 0),
-    JS_FS_END
-};
-
-
-int
-main(int argc, const char* argv[])
-{
-    JSRuntime* rt = NULL;
-    JSContext* cx = NULL;
-    JSObject* global = NULL;
-    JSCrossCompartmentCall *call = NULL;
-    JSObject* klass = NULL;
-    JSSCRIPT_TYPE script;
-    JSString* scriptsrc;
-    const jschar* schars;
-    size_t slen;
-    jsval sroot;
-    jsval result;
-    int i;
-
-    couch_args* args = couch_parse_args(argc, argv);
-
-    rt = JS_NewRuntime(64L * 1024L * 1024L);
-    if(rt == NULL)
-        return 1;
-
-    cx = JS_NewContext(rt, args->stack_size);
-    if(cx == NULL)
-        return 1;
-
-    JS_SetErrorReporter(cx, couch_error);
-    JS_ToggleOptions(cx, JSOPTION_XML);
-    JS_SetOptions(cx, JSOPTION_METHODJIT);
-#ifdef JSOPTION_TYPE_INFERENCE
-    JS_SetOptions(cx, JSOPTION_TYPE_INFERENCE);
-#endif
-    JS_SetContextPrivate(cx, args);
-    
-    SETUP_REQUEST(cx);
-
-    global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
-    if(global == NULL)
-        return 1;
-
-    call = JS_EnterCrossCompartmentCall(cx, global);
-
-    JS_SetGlobalObject(cx, global);
-    
-    if(!JS_InitStandardClasses(cx, global))
-        return 1;
-
-    if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
-        return 1;
- 
-    if(args->use_http) {
-        http_check_enabled();
-
-        klass = JS_InitClass(
-            cx, global,
-            NULL,
-            &CouchHTTPClass, req_ctor,
-            0,
-            CouchHTTPProperties, CouchHTTPFunctions,
-            NULL, NULL
-        );
-
-        if(!klass)
-        {
-            fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
-            exit(2);
-        }
-    } 
-
-    for(i = 0 ; args->scripts[i] ; i++) {
-        // Convert script source to jschars.
-        scriptsrc = couch_readfile(cx, args->scripts[i]);
-        if(!scriptsrc)
-            return 1;
-
-        schars = JS_GetStringCharsAndLength(cx, scriptsrc, &slen);
-
-        // Root it so GC doesn't collect it.
-        sroot = STRING_TO_JSVAL(scriptsrc);
-        if(JS_AddValueRoot(cx, &sroot) != JS_TRUE) {
-            fprintf(stderr, "Internal root error.\n");
-            return 1;
-        }
-
-        // Compile and run
-        script = JS_CompileUCScript(cx, global, schars, slen,
-                                    args->scripts[i], 1);
-        if(!script) {
-            fprintf(stderr, "Failed to compile script.\n");
-            return 1;
-        }
-
-        if(JS_ExecuteScript(cx, global, script, &result) != JS_TRUE) {
-            fprintf(stderr, "Failed to execute script.\n");
-            return 1;
-        }
-
-        // Warning message if we don't remove it.
-        JS_RemoveValueRoot(cx, &sroot);
-
-        // Give the GC a chance to run.
-        JS_MaybeGC(cx);
-    }
-
-    JS_LeaveCrossCompartmentCall(call);
-    FINISH_REQUEST(cx);
-    JS_DestroyContext(cx);
-    JS_DestroyRuntime(rt);
-    JS_ShutDown();
-
-    return 0;
-}

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/68f97778/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index 88483e8..7221d0f 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -49,7 +49,7 @@ ok = file:write_file("priv/couch_js/config.h", ConfigSrc),
         {"", "-lmozjs185"}
 end,
 
-CouchJSSrc = ["priv/couch_js/{help,http,main,utf8,util}.c"],
+CouchJSSrc = ["priv/couch_js/*.c"],
 
 BaseSpecs = [
         %% couchjs


[38/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Build couchjs

We've dropped all but SpiderMonkey 1.8.5 support for this release.


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

Branch: refs/heads/import
Commit: d05eb31699297d95559f50eab7d7aeca132cead0
Parents: 295602b
Author: Robert Newson <rn...@apache.org>
Authored: Thu Jan 30 18:50:18 2014 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 priv/couch_js/sm170.c | 398 --------------------------------------------
 priv/couch_js/sm180.c | 407 ---------------------------------------------
 rebar.config          |  11 --
 rebar.config.script   |  69 ++++++++
 4 files changed, 69 insertions(+), 816 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/d05eb316/priv/couch_js/sm170.c
----------------------------------------------------------------------
diff --git a/priv/couch_js/sm170.c b/priv/couch_js/sm170.c
deleted file mode 100644
index 4a18d8f..0000000
--- a/priv/couch_js/sm170.c
+++ /dev/null
@@ -1,398 +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.
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <jsapi.h>
-#include "http.h"
-#include "utf8.h"
-#include "util.h"
-
-
-#ifdef JS_THREADSAFE
-#define SETUP_REQUEST(cx) \
-    JS_SetContextThread(cx); \
-    JS_BeginRequest(cx);
-#define FINISH_REQUEST(cx) \
-    JS_EndRequest(cx); \
-    JS_ClearContextThread(cx);
-#else
-#define SETUP_REQUEST(cx)
-#define FINISH_REQUEST(cx)
-#endif
-
-
-static JSBool
-req_ctor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    return http_ctor(cx, obj);
-}
-
-
-static void 
-req_dtor(JSContext* cx, JSObject* obj)
-{
-    http_dtor(cx, obj);
-}
-
-
-static JSBool
-req_open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    JSBool ret = JS_FALSE;
-
-    if(argc == 2) {
-        ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
-    } else if(argc == 3) {
-        ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.open");
-    }
-
-    *rval = JSVAL_VOID;
-    return ret;
-}
-
-
-static JSBool
-req_set_hdr(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    JSBool ret = JS_FALSE;
-    if(argc == 2) {
-        ret = http_set_hdr(cx, obj, argv[0], argv[1]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
-    }
-
-    *rval = JSVAL_VOID;
-    return ret;
-}
-
-
-static JSBool
-req_send(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    JSBool ret = JS_FALSE;
-    if(argc == 1) {
-        ret = http_send(cx, obj, argv[0]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.send");
-    }
-
-    *rval = JSVAL_VOID;
-    return ret;
-}
-
-
-static JSBool
-req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* rval)
-{
-    int status = http_status(cx, obj);
-    if(status < 0)
-        return JS_FALSE;
-
-    if(INT_FITS_IN_JSVAL(status)) {
-        *rval = INT_TO_JSVAL(status);
-        return JS_TRUE;
-    } else {
-        JS_ReportError(cx, "Invalid HTTP status.");
-        return JS_FALSE;
-    }
-}
-
-
-static JSBool
-base_url(JSContext *cx, JSObject* obj, jsval idval, jsval* rval)
-{
-    couch_args *args = (couch_args*)JS_GetContextPrivate(cx);
-    return http_uri(cx, obj, args, rval);
-}
-
-
-static JSBool
-evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-    JSString *str;
-    JSObject *sandbox;
-    JSContext *subcx;
-    const jschar *src;
-    size_t srclen;
-    JSBool ret = JS_FALSE;
-    char *name = NULL;
-
-    sandbox = NULL;
-    if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) {
-        return JS_FALSE;
-    }
-
-    subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L);
-    if(!subcx) {
-        JS_ReportOutOfMemory(cx);
-        return JS_FALSE;
-    }
-
-    SETUP_REQUEST(subcx);
-
-    src = JS_GetStringChars(str);
-    srclen = JS_GetStringLength(str);
-
-    if(!sandbox) {
-        sandbox = JS_NewObject(subcx, NULL, NULL, NULL);
-        if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) {
-            goto done;
-        }
-    }
-
-    if(argc > 2) {
-      name = enc_string(cx, argv[2], NULL);
-    }
-
-    if(srclen == 0) {
-        *rval = OBJECT_TO_JSVAL(sandbox);
-    } else {
-        JS_EvaluateUCScript(subcx, sandbox, src, srclen, name, 1, rval);
-    }
-    
-    ret = JS_TRUE;
-
-done:
-    if(name) JS_free(cx, name);
-    FINISH_REQUEST(subcx);
-    JS_DestroyContext(subcx);
-    return ret;
-}
-
-
-static JSBool
-gc(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    JS_GC(cx);
-    *rval = JSVAL_VOID;
-    return JS_TRUE;
-}
-
-
-static JSBool
-print(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    couch_print(cx, argc, argv);
-    *rval = JSVAL_VOID;
-    return JS_TRUE;
-}
-
-
-static JSBool
-quit(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    int exit_code = 0;
-    JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
-    exit(exit_code);
-}
-
-
-static JSBool
-readline(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    JSString* line;
-
-    /* GC Occasionally */
-    JS_MaybeGC(cx);
-
-    line = couch_readline(cx, stdin);
-    if(line == NULL) return JS_FALSE;
-
-    *rval = STRING_TO_JSVAL(line);
-    return JS_TRUE;
-}
-
-
-static JSBool
-seal(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    JSObject *target;
-    JSBool deep = JS_FALSE;
-
-    if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
-        return JS_FALSE;
-
-    if(!target) {
-        *rval = JSVAL_VOID;
-        return JS_TRUE;
-    }
-
-    if(JS_SealObject(cx, target, deep) != JS_TRUE)
-        return JS_FALSE;
-
-    *rval = JSVAL_VOID;
-    return JS_TRUE;
-}
-
-
-JSClass CouchHTTPClass = {
-    "CouchHTTP",
-    JSCLASS_HAS_PRIVATE
-        | JSCLASS_CONSTRUCT_PROTOTYPE
-        | JSCLASS_HAS_RESERVED_SLOTS(2),
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    req_dtor,
-    JSCLASS_NO_OPTIONAL_MEMBERS
-};
-
-
-JSPropertySpec CouchHTTPProperties[] = {
-    {"status", 0, JSPROP_READONLY, req_status, NULL},
-    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
-    {0, 0, 0, 0, 0}
-};
-
-
-JSFunctionSpec CouchHTTPFunctions[] = {
-    {"_open", req_open, 3, 0, 0},
-    {"_setRequestHeader", req_set_hdr, 2, 0, 0},
-    {"_send", req_send, 1, 0, 0},
-    {0, 0, 0, 0, 0}
-};
-
-
-static JSClass global_class = {
-    "GlobalClass",
-    JSCLASS_GLOBAL_FLAGS,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
-};
-
-
-static JSFunctionSpec global_functions[] = {
-    {"evalcx", evalcx, 0, 0, 0},
-    {"gc", gc, 0, 0, 0},
-    {"print", print, 0, 0, 0},
-    {"quit", quit, 0, 0, 0},
-    {"readline", readline, 0, 0, 0},
-    {"seal", seal, 0, 0, 0},
-    {0, 0, 0, 0, 0}
-};
-
-
-int
-main(int argc, const char* argv[])
-{
-    JSRuntime* rt = NULL;
-    JSContext* cx = NULL;
-    JSObject* global = NULL;
-    JSObject* klass = NULL;
-    JSScript* script;
-    JSString* scriptsrc;
-    jschar* schars;
-    size_t slen;
-    jsval sroot;
-    jsval result;
-    int i;
-
-    couch_args* args = couch_parse_args(argc, argv);
-    
-    rt = JS_NewRuntime(64L * 1024L * 1024L);
-    if(rt == NULL)
-        return 1;
-
-    cx = JS_NewContext(rt, args->stack_size);
-    if(cx == NULL)
-        return 1;
-
-    JS_SetErrorReporter(cx, couch_error);
-    JS_ToggleOptions(cx, JSOPTION_XML);
-    JS_SetContextPrivate(cx, args);
-    
-    SETUP_REQUEST(cx);
-
-    global = JS_NewObject(cx, &global_class, NULL, NULL);
-    if(global == NULL)
-        return 1;
-
-    JS_SetGlobalObject(cx, global);
-    
-    if(!JS_InitStandardClasses(cx, global))
-        return 1;
-
-    if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
-        return 1;
- 
-    if(args->use_http) {
-        http_check_enabled();
-
-        klass = JS_InitClass(
-            cx, global,
-            NULL,
-            &CouchHTTPClass, req_ctor,
-            0,
-            CouchHTTPProperties, CouchHTTPFunctions,
-            NULL, NULL
-        );
-
-        if(!klass)
-        {
-            fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
-            exit(2);
-        }
-    } 
-
-    for (i = 0 ; args->scripts[i] ; i++) {
-        // Convert script source to jschars.
-        scriptsrc = couch_readfile(cx, args->scripts[i]);
-        if(!scriptsrc)
-            return 1;
-
-        schars = JS_GetStringChars(scriptsrc);
-        slen = JS_GetStringLength(scriptsrc);
-
-        // Root it so GC doesn't collect it.
-        sroot = STRING_TO_JSVAL(scriptsrc);
-        if(JS_AddRoot(cx, &sroot) != JS_TRUE) {
-            fprintf(stderr, "Internal root error.\n");
-            return 1;
-        }
-
-        // Compile and run
-        script = JS_CompileUCScript(cx, global, schars, slen,
-                                    args->scripts[i], 1);
-        if(!script) {
-            fprintf(stderr, "Failed to compile script.\n");
-            return 1;
-        }
-
-        JS_ExecuteScript(cx, global, script, &result);
-
-        // Warning message if we don't remove it.
-        JS_RemoveRoot(cx, &sroot);
-    }
-
-    FINISH_REQUEST(cx);
-    JS_DestroyContext(cx);
-    JS_DestroyRuntime(rt);
-    JS_ShutDown();
-
-    return 0;
-}

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/d05eb316/priv/couch_js/sm180.c
----------------------------------------------------------------------
diff --git a/priv/couch_js/sm180.c b/priv/couch_js/sm180.c
deleted file mode 100644
index 9ffd1df..0000000
--- a/priv/couch_js/sm180.c
+++ /dev/null
@@ -1,407 +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.
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <jsapi.h>
-#include "http.h"
-#include "utf8.h"
-#include "util.h"
-
-
-#define SETUP_REQUEST(cx) \
-    JS_SetContextThread(cx); \
-    JS_BeginRequest(cx);
-#define FINISH_REQUEST(cx) \
-    JS_EndRequest(cx); \
-    JS_ClearContextThread(cx);
-
-
-static JSBool
-req_ctor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
-    return http_ctor(cx, obj);
-}
-
-
-static void 
-req_dtor(JSContext* cx, JSObject* obj)
-{
-    http_dtor(cx, obj);
-}
-
-
-static JSBool
-req_open(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSObject* obj = JS_THIS_OBJECT(cx, vp);
-    jsval* argv = JS_ARGV(cx, vp);
-    JSBool ret = JS_FALSE;
-
-    if(argc == 2) {
-        ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
-    } else if(argc == 3) {
-        ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.open");
-    }
-
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return ret;
-}
-
-
-static JSBool
-req_set_hdr(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSObject* obj = JS_THIS_OBJECT(cx, vp);
-    jsval* argv = JS_ARGV(cx, vp);
-    JSBool ret = JS_FALSE;
-
-    if(argc == 2) {
-        ret = http_set_hdr(cx, obj, argv[0], argv[1]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
-    }
-
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return ret;
-}
-
-
-static JSBool
-req_send(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSObject* obj = JS_THIS_OBJECT(cx, vp);
-    jsval* argv = JS_ARGV(cx, vp);
-    JSBool ret = JS_FALSE;
-
-    if(argc == 1) {
-        ret = http_send(cx, obj, argv[0]);
-    } else {
-        JS_ReportError(cx, "Invalid call to CouchHTTP.send");
-    }
-
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return ret;
-}
-
-
-static JSBool
-req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
-{
-    int status = http_status(cx, obj);
-    if(status < 0)
-        return JS_FALSE;
-
-    if(INT_FITS_IN_JSVAL(status)) {
-        JS_SET_RVAL(cx, vp, INT_TO_JSVAL(status));
-        return JS_TRUE;
-    } else {
-        JS_ReportError(cx, "Invalid HTTP status.");
-        return JS_FALSE;
-    }
-}
-
-
-static JSBool
-base_url(JSContext *cx, JSObject* obj, jsid pid, jsval* vp)
-{
-    couch_args *args = (couch_args*)JS_GetContextPrivate(cx);
-    return http_uri(cx, obj, args, &JS_RVAL(cx, vp));
-}
-
-
-static JSBool
-evalcx(JSContext *cx, uintN argc, jsval* vp)
-{
-    jsval* argv = JS_ARGV(cx, vp);
-    JSString *str;
-    JSObject *sandbox;
-    JSContext *subcx;
-    const jschar *src;
-    size_t srclen;
-    jsval rval;
-    JSBool ret = JS_FALSE;
-    char *name = NULL;
-
-    sandbox = NULL;
-    if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) {
-        return JS_FALSE;
-    }
-
-    subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L);
-    if(!subcx) {
-        JS_ReportOutOfMemory(cx);
-        return JS_FALSE;
-    }
-
-    SETUP_REQUEST(subcx);
-
-    src = JS_GetStringChars(str);
-    srclen = JS_GetStringLength(str);
-
-    if(!sandbox) {
-        sandbox = JS_NewObject(subcx, NULL, NULL, NULL);
-        if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) {
-            goto done;
-        }
-    }
-
-    if(argc > 2) {
-      name = enc_string(cx, argv[2], NULL);
-    }
-
-    if(srclen == 0) {
-        JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox));
-    } else {
-        JS_EvaluateUCScript(subcx, sandbox, src, srclen, name, 1, &rval);
-        JS_SET_RVAL(cx, vp, rval);
-    }
-    
-    ret = JS_TRUE;
-
-done:
-    if(name) JS_free(cx, name);
-    FINISH_REQUEST(subcx);
-    JS_DestroyContext(subcx);
-    return ret;
-}
-
-
-static JSBool
-gc(JSContext* cx, uintN argc, jsval* vp)
-{
-    JS_GC(cx);
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return JS_TRUE;
-}
-
-
-static JSBool
-print(JSContext* cx, uintN argc, jsval* vp)
-{
-    jsval* argv = JS_ARGV(cx, vp);
-    couch_print(cx, argc, argv);
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return JS_TRUE;
-}
-
-
-static JSBool
-quit(JSContext* cx, uintN argc, jsval* vp)
-{
-    jsval* argv = JS_ARGV(cx, vp);
-    int exit_code = 0;
-    JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
-    exit(exit_code);
-}
-
-
-static JSBool
-readline(JSContext* cx, uintN argc, jsval* vp)
-{
-    JSString* line;
-
-    /* GC Occasionally */
-    JS_MaybeGC(cx);
-
-    line = couch_readline(cx, stdin);
-    if(line == NULL) return JS_FALSE;
-
-    JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(line));
-    return JS_TRUE;
-}
-
-
-static JSBool
-seal(JSContext* cx, uintN argc, jsval* vp)
-{
-    jsval* argv = JS_ARGV(cx, vp);
-    JSObject *target;
-    JSBool deep = JS_FALSE;
-
-    if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
-        return JS_FALSE;
-
-    if(!target) {
-        JS_SET_RVAL(cx, vp, JSVAL_VOID);
-        return JS_TRUE;
-    }
-
-    if(JS_SealObject(cx, target, deep) != JS_TRUE)
-        return JS_FALSE;
-
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return JS_TRUE;
-}
-
-
-JSClass CouchHTTPClass = {
-    "CouchHTTP",
-    JSCLASS_HAS_PRIVATE
-        | JSCLASS_CONSTRUCT_PROTOTYPE
-        | JSCLASS_HAS_RESERVED_SLOTS(2),
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    req_dtor,
-    JSCLASS_NO_OPTIONAL_MEMBERS
-};
-
-
-JSPropertySpec CouchHTTPProperties[] = {
-    {"status", 0, JSPROP_READONLY, req_status, NULL},
-    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
-    {0, 0, 0, 0, 0}
-};
-
-
-JSFunctionSpec CouchHTTPFunctions[] = {
-    JS_FS("_open", (JSNative) req_open, 3, JSFUN_FAST_NATIVE, 0),
-    JS_FS("_setRequestHeader", (JSNative) req_set_hdr, 2, JSFUN_FAST_NATIVE, 0),
-    JS_FS("_send", (JSNative) req_send, 1, JSFUN_FAST_NATIVE, 0),
-    JS_FS_END
-};
-
-
-static JSClass global_class = {
-    "GlobalClass",
-    JSCLASS_GLOBAL_FLAGS,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_PropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
-};
-
-
-static JSFunctionSpec global_functions[] = {
-    JS_FS("evalcx", (JSNative) evalcx, 0, JSFUN_FAST_NATIVE, 0),
-    JS_FS("gc", (JSNative) gc, 0, JSFUN_FAST_NATIVE, 0),
-    JS_FS("print", (JSNative) print, 0, JSFUN_FAST_NATIVE, 0),
-    JS_FS("quit", (JSNative) quit, 0, JSFUN_FAST_NATIVE, 0),
-    JS_FS("readline", (JSNative) readline, 0, JSFUN_FAST_NATIVE, 0),
-    JS_FS("seal", (JSNative) seal, 0, JSFUN_FAST_NATIVE, 0),
-    JS_FS_END
-};
-
-
-int
-main(int argc, const char* argv[])
-{
-    JSRuntime* rt = NULL;
-    JSContext* cx = NULL;
-    JSObject* global = NULL;
-    JSObject* klass = NULL;
-    JSScript* script;
-    JSString* scriptsrc;
-    jschar* schars;
-    size_t slen;
-    jsval sroot;
-    jsval result;
-    int i;
-
-    couch_args* args = couch_parse_args(argc, argv);
-    
-    rt = JS_NewRuntime(64L * 1024L * 1024L);
-    if(rt == NULL)
-        return 1;
-
-    cx = JS_NewContext(rt, args->stack_size);
-    if(cx == NULL)
-        return 1;
-
-    JS_SetErrorReporter(cx, couch_error);
-    JS_ToggleOptions(cx, JSOPTION_XML);
-    JS_SetContextPrivate(cx, args);
-    
-    SETUP_REQUEST(cx);
-
-    global = JS_NewObject(cx, &global_class, NULL, NULL);
-    if(global == NULL)
-        return 1;
-
-    JS_SetGlobalObject(cx, global);
-    
-    if(!JS_InitStandardClasses(cx, global))
-        return 1;
-
-    if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
-        return 1;
- 
-    if(args->use_http) {
-        http_check_enabled();
-
-        klass = JS_InitClass(
-            cx, global,
-            NULL,
-            &CouchHTTPClass, req_ctor,
-            0,
-            CouchHTTPProperties, CouchHTTPFunctions,
-            NULL, NULL
-        );
-
-        if(!klass)
-        {
-            fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
-            exit(2);
-        }
-    } 
-
-    for (i = 0 ; args->scripts[i] ; i++) {
-        // Convert script source to jschars.
-        scriptsrc = couch_readfile(cx, args->scripts[i]);
-        if(!scriptsrc)
-            return 1;
-
-        schars = JS_GetStringChars(scriptsrc);
-        slen = JS_GetStringLength(scriptsrc);
-
-        // Root it so GC doesn't collect it.
-        sroot = STRING_TO_JSVAL(scriptsrc);
-        if(JS_AddRoot(cx, &sroot) != JS_TRUE) {
-            fprintf(stderr, "Internal root error.\n");
-            return 1;
-        }
-
-        // Compile and run
-        script = JS_CompileUCScript(cx, global, schars, slen,
-                                    args->scripts[i], 1);
-        if(!script) {
-            fprintf(stderr, "Failed to compile script.\n");
-            return 1;
-        }
-
-        JS_ExecuteScript(cx, global, script, &result);
-
-        // Warning message if we don't remove it.
-        JS_RemoveRoot(cx, &sroot);
-    }
-
-    FINISH_REQUEST(cx);
-    JS_DestroyContext(cx);
-    JS_DestroyRuntime(rt);
-    JS_ShutDown();
-
-    return 0;
-}

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/d05eb316/rebar.config
----------------------------------------------------------------------
diff --git a/rebar.config b/rebar.config
deleted file mode 100644
index def6879..0000000
--- a/rebar.config
+++ /dev/null
@@ -1,11 +0,0 @@
-{port_specs, [{"priv/couch_icu_driver.so", ["priv/icu_driver/couch_icu_driver.c"]}]}.
-
-{port_env, [
-  {"DRV_CFLAGS",  "$DRV_CFLAGS -DPIC -O2 -fno-common"},
-  {"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -lpthread"},
-  {"linux", "DRV_LDFLAGS", "$DRV_LDFLAGS -lcrypt"},
-  {"freebsd", "DRV_CFLAGS", "$DRV_CFLAGS -I/usr/local/include"},
-  {"freebsd", "DRV_LDFLAGS", "$DRV_LDFLAGS -L/usr/local/lib"},
-  {"solaris", "DRV_CFLAGS", "$DRV_CFLAGS -I/opt/local/include"},
-  {"solaris", "DRV_LDFLAGS", "$DRV_LDFLAGS -L/opt/local/lib"}
-]}.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/d05eb316/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
new file mode 100644
index 0000000..a0e1345
--- /dev/null
+++ b/rebar.config.script
@@ -0,0 +1,69 @@
+%% 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.
+
+%% declare values
+CouchJSName = case os:type() of
+    {win32, _} ->
+        "couchjs.exe";
+    _ ->
+        "couchjs"
+end,
+Version = string:strip(os:cmd("git describe"), right, $\n),
+
+%% build config.h
+ConfigH = [
+ {"SM185", ""},
+ {"HAVE_JS_GET_STRING_CHARS_AND_LENGTH", "1"},
+ {"JSSCRIPT_TYPE", "JSObject*"},
+ {"COUCHJS_NAME", "\"" ++ CouchJSName++ "\""},
+ {"PACKAGE", "\"apache-couchdb\""},
+ {"PACKAGE_BUGREPORT", "\"https://issues.apache.org/jira/browse/COUCHDB\""},
+ {"PACKAGE_NAME", "\"Apache CouchDB\""},
+ {"PACKAGE_STRING", "\"Apache CouchDB " ++ Version ++ "\""},
+ {"PACKAGE_VERSION", "\"" ++ Version ++ "\""}],
+ConfigSrc = [["#define ", K, " ", V, $\n] || {K, V} <- ConfigH],
+ok = file:write_file("priv/couch_js/config.h", ConfigSrc),
+
+%% compile-time parameters
+JSLIBS = "-lmozjs185",
+{CFLAGS0, LDFLAGS} = case os:type() of
+    {unix, darwin} ->
+        {"-DXP_UNIX -I/usr/local/include/js", JSLIBS};
+    {unix, linux} ->
+        {"-DXP_UNIX -I/usr/include/js", JSLIBS ++ " -lm"};
+    {unix, _} ->
+        {"-DXP_UNIX -I/usr/local/include/js", JSLIBS ++ " -lm"};
+    _ ->
+        {"-DXP_WIN -I/usr/include/js", JSLIBS}
+end,
+CFLAGS1 = CFLAGS0 ++ " -DWITHOUT_CURL",
+
+PortEnv = [
+    {"CFLAGS", "$CFLAGS -Wall -c -g -O2 " ++ CFLAGS1},
+    {"LDFLAGS", LDFLAGS}],
+
+CouchJSSpec = [{filename:join(["priv", CouchJSName]),
+                ["priv/couch_js/{help,http,main,utf8,util}.c"]}],
+SpawnSpec = [{"priv/couchspawnkillable", ["priv/spawnkillable/*.c"]}],
+
+PortSpecs = case os:type() of
+    {win32, _} ->
+        CouchJSSpec ++ SpawnSpec;
+    _ ->
+        {ok, _} = file:copy("priv/spawnkillable/couchspawnkillable.sh",
+                            "priv/couchspawnkillable"),
+        os:cmd("chmod +x priv/couchspawnkillable"),
+        CouchJSSpec
+end,
+
+[{port_env, PortEnv},
+ {port_specs, PortSpecs}].


[05/50] couch commit: updated refs/heads/import to 09c6556

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

BugzID: 14798


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

Branch: refs/heads/import
Commit: e5e5880b27218a067ba49def549c8b311cb33418
Parents: 5a2ec4f
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Mon Dec 10 14:29:30 2012 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:23 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/e5e5880b/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index e420ce9..4e4f938 100644
--- a/src/couch_query_servers.erl
+++ b/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) ->


[09/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/a7d16632
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/a7d16632
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/a7d16632

Branch: refs/heads/import
Commit: a7d166329b65f208d69f8be252ef3890a9df5ca0
Parents: 54a7b40
Author: Robert Newson <rn...@apache.org>
Authored: Sat Mar 9 18:22:19 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

----------------------------------------------------------------------
 src/couch.app.tpl.in                 |  3 +-
 src/couch.erl                        |  8 ---
 src/couch_auth_cache.erl             | 33 ++++++++----
 src/couch_changes.erl                |  2 +-
 src/couch_compaction_daemon.erl      | 32 ++++++++----
 src/couch_compress.erl               |  2 +-
 src/couch_db.erl                     | 10 ++--
 src/couch_db_update_notifier_sup.erl | 19 ++++---
 src/couch_db_updater.erl             | 12 ++---
 src/couch_drv.erl                    |  2 +-
 src/couch_ejson_compare.erl          |  2 +-
 src/couch_external_manager.erl       | 26 +++++++---
 src/couch_external_server.erl        | 22 ++++++--
 src/couch_httpd.erl                  | 85 +++++++++++--------------------
 src/couch_httpd_auth.erl             | 28 +++++-----
 src/couch_httpd_cors.erl             |  6 +--
 src/couch_httpd_db.erl               |  2 +-
 src/couch_httpd_external.erl         |  2 +-
 src/couch_httpd_misc_handlers.erl    | 18 +++----
 src/couch_httpd_oauth.erl            | 10 ++--
 src/couch_httpd_rewrite.erl          |  4 +-
 src/couch_httpd_vhost.erl            | 38 +++++++++-----
 src/couch_log.erl                    | 51 +++++++++++--------
 src/couch_os_daemons.erl             | 33 ++++++++----
 src/couch_os_process.erl             |  4 +-
 src/couch_passwords.erl              |  4 +-
 src/couch_proc_manager.erl           |  6 +--
 src/couch_secondary_sup.erl          |  2 +-
 src/couch_server.erl                 | 56 +++++++++++++-------
 src/couch_server_sup.erl             | 53 ++++++++-----------
 src/couch_stats_aggregator.erl       | 27 +++++++---
 src/couch_users_db.erl               |  2 +-
 src/couch_uuids.erl                  | 23 +++++++--
 33 files changed, 361 insertions(+), 266 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a7d16632/src/couch.app.tpl.in
----------------------------------------------------------------------
diff --git a/src/couch.app.tpl.in b/src/couch.app.tpl.in
index f83b6f6..1cd0154 100644
--- a/src/couch.app.tpl.in
+++ b/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-couch/blob/a7d16632/src/couch.erl
----------------------------------------------------------------------
diff --git a/src/couch.erl b/src/couch.erl
index c18df0b..7d53d0c 100644
--- a/src/couch.erl
+++ b/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-couch/blob/a7d16632/src/couch_auth_cache.erl
----------------------------------------------------------------------
diff --git a/src/couch_auth_cache.erl b/src/couch_auth_cache.erl
index 5f4c8f9..1650495 100644
--- a/src/couch_auth_cache.erl
+++ b/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-couch/blob/a7d16632/src/couch_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_changes.erl b/src/couch_changes.erl
index cbca9cb..d36b45f 100644
--- a/src/couch_changes.erl
+++ b/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-couch/blob/a7d16632/src/couch_compaction_daemon.erl
----------------------------------------------------------------------
diff --git a/src/couch_compaction_daemon.erl b/src/couch_compaction_daemon.erl
index b9bf969..3251d5f 100644
--- a/src/couch_compaction_daemon.erl
+++ b/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-couch/blob/a7d16632/src/couch_compress.erl
----------------------------------------------------------------------
diff --git a/src/couch_compress.erl b/src/couch_compress.erl
index 0b9334a..6b47a7a 100644
--- a/src/couch_compress.erl
+++ b/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-couch/blob/a7d16632/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 5f91633..56cb0d2 100644
--- a/src/couch_db.erl
+++ b/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-couch/blob/a7d16632/src/couch_db_update_notifier_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_update_notifier_sup.erl b/src/couch_db_update_notifier_sup.erl
index e7cc16c..9eb943a 100644
--- a/src/couch_db_update_notifier_sup.erl
+++ b/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-couch/blob/a7d16632/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index e1dc7c3..c64911e 100644
--- a/src/couch_db_updater.erl
+++ b/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-couch/blob/a7d16632/src/couch_drv.erl
----------------------------------------------------------------------
diff --git a/src/couch_drv.erl b/src/couch_drv.erl
index de4d76e..7fe119a 100644
--- a/src/couch_drv.erl
+++ b/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-couch/blob/a7d16632/src/couch_ejson_compare.erl
----------------------------------------------------------------------
diff --git a/src/couch_ejson_compare.erl b/src/couch_ejson_compare.erl
index 083ff42..7b000fc 100644
--- a/src/couch_ejson_compare.erl
+++ b/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-couch/blob/a7d16632/src/couch_external_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_external_manager.erl b/src/couch_external_manager.erl
index dec2880..a8cad63 100644
--- a/src/couch_external_manager.erl
+++ b/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-couch/blob/a7d16632/src/couch_external_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_external_server.erl b/src/couch_external_server.erl
index a3924d0..56406bb 100644
--- a/src/couch_external_server.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd.erl b/src/couch_httpd.erl
index 53ae47e..db90129 100644
--- a/src/couch_httpd.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd_auth.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_auth.erl b/src/couch_httpd_auth.erl
index 785dd79..a747869 100644
--- a/src/couch_httpd_auth.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd_cors.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_cors.erl b/src/couch_httpd_cors.erl
index 5432fbd..d98357a 100644
--- a/src/couch_httpd_cors.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_db.erl b/src/couch_httpd_db.erl
index 2ac4971..c70245c 100644
--- a/src/couch_httpd_db.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd_external.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_external.erl b/src/couch_httpd_external.erl
index 077136d..8322dcd 100644
--- a/src/couch_httpd_external.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_misc_handlers.erl b/src/couch_httpd_misc_handlers.erl
index ff79f14..e46dee3 100644
--- a/src/couch_httpd_misc_handlers.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd_oauth.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_oauth.erl b/src/couch_httpd_oauth.erl
index 57799e6..8fd4c30 100644
--- a/src/couch_httpd_oauth.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd_rewrite.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_rewrite.erl b/src/couch_httpd_rewrite.erl
index 428d30c..abd6af5 100644
--- a/src/couch_httpd_rewrite.erl
+++ b/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-couch/blob/a7d16632/src/couch_httpd_vhost.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_vhost.erl b/src/couch_httpd_vhost.erl
index 258f4eb..29fddfe 100644
--- a/src/couch_httpd_vhost.erl
+++ b/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-couch/blob/a7d16632/src/couch_log.erl
----------------------------------------------------------------------
diff --git a/src/couch_log.erl b/src/couch_log.erl
index cd4bbbb..d1aa701 100644
--- a/src/couch_log.erl
+++ b/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-couch/blob/a7d16632/src/couch_os_daemons.erl
----------------------------------------------------------------------
diff --git a/src/couch_os_daemons.erl b/src/couch_os_daemons.erl
index 00fd7b3..3560149 100644
--- a/src/couch_os_daemons.erl
+++ b/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-couch/blob/a7d16632/src/couch_os_process.erl
----------------------------------------------------------------------
diff --git a/src/couch_os_process.erl b/src/couch_os_process.erl
index fcf9da5..c6e6520 100644
--- a/src/couch_os_process.erl
+++ b/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-couch/blob/a7d16632/src/couch_passwords.erl
----------------------------------------------------------------------
diff --git a/src/couch_passwords.erl b/src/couch_passwords.erl
index 43f3380..d0f36cc 100644
--- a/src/couch_passwords.erl
+++ b/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-couch/blob/a7d16632/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index 94946a1..6130fc9 100644
--- a/src/couch_proc_manager.erl
+++ b/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-couch/blob/a7d16632/src/couch_secondary_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_secondary_sup.erl b/src/couch_secondary_sup.erl
index 6320fd9..4f2d1c8 100644
--- a/src/couch_secondary_sup.erl
+++ b/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-couch/blob/a7d16632/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index 40c2d7e..c23ec05 100644
--- a/src/couch_server.erl
+++ b/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-couch/blob/a7d16632/src/couch_server_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_server_sup.erl b/src/couch_server_sup.erl
index 528ac7c..c42bcfb 100644
--- a/src/couch_server_sup.erl
+++ b/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-couch/blob/a7d16632/src/couch_stats_aggregator.erl
----------------------------------------------------------------------
diff --git a/src/couch_stats_aggregator.erl b/src/couch_stats_aggregator.erl
index 6090355..416c9a0 100644
--- a/src/couch_stats_aggregator.erl
+++ b/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-couch/blob/a7d16632/src/couch_users_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_users_db.erl b/src/couch_users_db.erl
index 9fe069f..76acfee 100644
--- a/src/couch_users_db.erl
+++ b/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-couch/blob/a7d16632/src/couch_uuids.erl
----------------------------------------------------------------------
diff --git a/src/couch_uuids.erl b/src/couch_uuids.erl
index ac9b463..3065938 100644
--- a/src/couch_uuids.erl
+++ b/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()};


[46/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Switch JSON encoding/decoding to Jiffy


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

Branch: refs/heads/import
Commit: bc9483216b76c4bf61eb7223e0e14289420129e3
Parents: 331d549
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Feb 4 22:20:32 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 22:20:32 2014 -0600

----------------------------------------------------------------------
 include/couch_db.hrl |  4 ++--
 src/couch_util.erl   | 12 ++++++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/bc948321/include/couch_db.hrl
----------------------------------------------------------------------
diff --git a/include/couch_db.hrl b/include/couch_db.hrl
index ffecae0..2c015df 100644
--- a/include/couch_db.hrl
+++ b/include/couch_db.hrl
@@ -18,8 +18,8 @@
 -define(MIN_STR, <<"">>).
 -define(MAX_STR, <<255>>). % illegal utf string
 
--define(JSON_ENCODE(V), ejson:encode(V)).
--define(JSON_DECODE(V), ejson:decode(V)).
+-define(JSON_ENCODE(V), couch_util:json_encode(V)).
+-define(JSON_DECODE(V), couch_util:json_decode(V)).
 
 -define(b2l(V), binary_to_list(V)).
 -define(l2b(V), list_to_binary(V)).

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/bc948321/src/couch_util.erl
----------------------------------------------------------------------
diff --git a/src/couch_util.erl b/src/couch_util.erl
index d09211a..beb9622 100644
--- a/src/couch_util.erl
+++ b/src/couch_util.erl
@@ -21,6 +21,7 @@
 -export([get_nested_json_value/2, json_user_ctx/1]).
 -export([proplist_apply_field/2, json_apply_field/2]).
 -export([to_binary/1, to_integer/1, to_list/1, url_encode/1]).
+-export([json_encode/1, json_decode/1]).
 -export([verify/2,simple_call/2,shutdown_sync/1]).
 -export([get_value/2, get_value/3]).
 -export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
@@ -376,6 +377,17 @@ url_encode([H|T]) ->
 url_encode([]) ->
     [].
 
+json_encode(V) ->
+    jiffy:encode(V, [force_utf8]).
+
+json_decode(V) ->
+    try
+        jiffy:decode(V)
+    catch
+        throw:Error ->
+            throw({invalid_json, Error})
+    end.
+
 verify([X|RestX], [Y|RestY], Result) ->
     verify(RestX, RestY, (X bxor Y) bor Result);
 verify([], [], Result) ->


[03/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: 5718463e74f745a64ae83266a1ddf4051c1f6275
Parents: ee7998d
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Oct 25 00:41:17 2012 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:23 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/5718463e/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 3707108..2253e62 100644
--- a/src/couch_db.erl
+++ b/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),


[30/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/68d60f07
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/68d60f07
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/68d60f07

Branch: refs/heads/import
Commit: 68d60f073270bef6d95b2be6ecfd9ccd472bd78a
Parents: 1a8d72c
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Mar 13 02:36:33 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_db.erl | 6 +++++-
 src/couch_server.erl   | 6 ++++--
 2 files changed, 9 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/68d60f07/src/couch_httpd_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_db.erl b/src/couch_httpd_db.erl
index c70245c..50fba6c 100644
--- a/src/couch_httpd_db.erl
+++ b/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-couch/blob/68d60f07/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index c23ec05..3d4a1a6 100644
--- a/src/couch_server.erl
+++ b/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};


[26/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/e09b8074
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/e09b8074
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/e09b8074

Branch: refs/heads/import
Commit: e09b8074fec59a508905b700c5252df7eb5b5338
Parents: 15b84c0
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Mar 11 13:39:42 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:25 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/e09b8074/src/couch_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_changes.erl b/src/couch_changes.erl
index d36b45f..4346109 100644
--- a/src/couch_changes.erl
+++ b/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


[50/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Make sure and save the default referer


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

Branch: refs/heads/import
Commit: 09c6556049f9e19e3ec7152b59c1911f88e727f5
Parents: f8c2335
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Feb 6 22:52:03 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Thu Feb 6 22:52:03 2014 -0600

----------------------------------------------------------------------
 priv/couch_js/http.c | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/09c65560/priv/couch_js/http.c
----------------------------------------------------------------------
diff --git a/priv/couch_js/http.c b/priv/couch_js/http.c
index 767573f..c5d5e88 100644
--- a/priv/couch_js/http.c
+++ b/priv/couch_js/http.c
@@ -362,6 +362,7 @@ http_uri(JSContext* cx, JSObject* req, couch_args* args, jsval* uri_val)
     if (!args->uri_file) {
         uri_str = JS_InternString(cx, "http://localhost:15986/");
         *uri_val = STRING_TO_JSVAL(uri_str);
+        JS_SetReservedSlot(cx, req, 0, *uri_val);
         return JS_TRUE;
     }
 


[13/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/54a7b406
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/54a7b406
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/54a7b406

Branch: refs/heads/import
Commit: 54a7b406eba0e9b486dcc147561d0dc2858f6d34
Parents: 14d1dd2
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Feb 21 00:14:43 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/54a7b406/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index e8d8c49..40c2d7e 100644
--- a/src/couch_server.erl
+++ b/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}


[11/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: 651e26f6156a55b267d411d5be196ed3f4aa610c
Parents: ab02c8c
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Jan 23 15:10:57 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/651e26f6/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index 40dc3f9..1c74456 100644
--- a/src/couch_server.erl
+++ b/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] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: f8fb11a05182140cadf9cbe1b67def35afb53aaa
Parents: dd16693
Author: Robert Newson <ro...@cloudant.com>
Authored: Sat Jan 5 12:39:07 2013 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:23 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f8fb11a0/src/couch.app.tpl.in
----------------------------------------------------------------------
diff --git a/src/couch.app.tpl.in b/src/couch.app.tpl.in
index dc284e4..f83b6f6 100644
--- a/src/couch.app.tpl.in
+++ b/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]}
 ]}.


[20/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: c3bc1160e7ba64e2a53639442c1561f687e1022a
Parents: 78a4f42
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu Jan 24 01:12:56 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/c3bc1160/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index f5953a1..5f91633 100644
--- a/src/couch_db.erl
+++ b/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))


[08/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/dd166930
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/dd166930
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/dd166930

Branch: refs/heads/import
Commit: dd166930c048cc666407f3216ebcdd1262b2a449
Parents: 4cc61f1
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Nov 13 17:25:35 2012 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:23 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/dd166930/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 67c8a49..f5953a1 100644
--- a/src/couch_db.erl
+++ b/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 ->


[15/50] couch commit: updated refs/heads/import to 09c6556

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


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

Branch: refs/heads/import
Commit: 207708a09adf9162f2fe133a1662a3b90b222df7
Parents: 651e26f
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Jan 23 15:16:29 2013 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/207708a0/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index 1be3e3a..e1dc7c3 100644
--- a/src/couch_db_updater.erl
+++ b/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}.


[40/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Purge view_query_args and point to mrargs (when rebasing, pull in the other bits from ba152cb2153e892c0d8eec7f6fbeecf3dcaff10a)


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

Branch: refs/heads/import
Commit: 295602b8b9347fe6e3cd315311088a15dc1e169d
Parents: 6c8c480
Author: Robert Newson <rn...@apache.org>
Authored: Mon Dec 23 11:44:52 2013 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 include/couch_db.hrl | 26 --------------------------
 src/couch_db.erl     |  2 +-
 2 files changed, 1 insertion(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/295602b8/include/couch_db.hrl
----------------------------------------------------------------------
diff --git a/include/couch_db.hrl b/include/couch_db.hrl
index 61a59f7..ffecae0 100644
--- a/include/couch_db.hrl
+++ b/include/couch_db.hrl
@@ -179,32 +179,6 @@
     after_doc_read = nil     % nil | fun(Doc, Db) -> NewDoc
     }).
 
-
--record(view_query_args, {
-    start_key,
-    end_key,
-    start_docid = ?MIN_STR,
-    end_docid = ?MAX_STR,
-
-    direction = fwd,
-    inclusive_end=true, % aka a closed-interval
-
-    limit = 10000000000, % Huge number to simplify logic
-    skip = 0,
-
-    group_level = 0,
-
-    view_type = nil,
-    include_docs = false,
-    conflicts = false,
-    stale = false,
-    multi_get = false,
-    callback = nil,
-    list = nil,
-    keys = nil,
-    sorted = true
-}).
-
 -record(view_fold_helper_funs, {
     reduce_count,
     passed_end,

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/295602b8/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index e4e8cca..32a0049 100644
--- a/src/couch_db.erl
+++ b/src/couch_db.erl
@@ -291,7 +291,7 @@ get_last_purged(#db{fd=Fd, header=#db_header{purged_docs=PurgedPointer}}) ->
     couch_file:pread_term(Fd, PurgedPointer).
 
 get_doc_count(Db) ->
-    {ok, {Count, _DelCount}} = couch_btree:full_reduce(Db#db.id_tree),
+    {ok, {Count, _, _}} = couch_btree:full_reduce(Db#db.id_tree),
     {ok, Count}.
 
 get_db_info(Db) ->


[12/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@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-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/15b84c05
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/15b84c05
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/15b84c05

Branch: refs/heads/import
Commit: 15b84c051eca732be0644e6af7a3a134bbf329b5
Parents: 22fdbe2
Author: Robert Newson <rn...@apache.org>
Authored: Sun Mar 10 16:12:28 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:24 2014 -0600

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/15b84c05/include/couch_db.hrl
----------------------------------------------------------------------
diff --git a/include/couch_db.hrl b/include/couch_db.hrl
index 77006e4..61a59f7 100644
--- a/include/couch_db.hrl
+++ b/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-couch/blob/15b84c05/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 7734c7c..e4e8cca 100644
--- a/src/couch_db.erl
+++ b/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-couch/blob/15b84c05/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index c64911e..cc48ef8 100644
--- a/src/couch_db_updater.erl
+++ b/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-couch/blob/15b84c05/src/couch_doc.erl
----------------------------------------------------------------------
diff --git a/src/couch_doc.erl b/src/couch_doc.erl
index bcf79d2..6f2ca9b 100644
--- a/src/couch_doc.erl
+++ b/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-couch/blob/15b84c05/src/couch_util.erl
----------------------------------------------------------------------
diff --git a/src/couch_util.erl b/src/couch_util.erl
index 3556d36..d09211a 100644
--- a/src/couch_util.erl
+++ b/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.


[47/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Switch the default URI port to 15986

BigCouch has the single node API on 15986 for node 1. This is just a
temporary convenience change while we hack on the merge.


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

Branch: refs/heads/import
Commit: 91ae53eeea9dee7b8c4d788a28e9ad51072c9381
Parents: bc94832
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Feb 4 22:21:02 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 22:21:02 2014 -0600

----------------------------------------------------------------------
 priv/couch_js/http.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/91ae53ee/priv/couch_js/http.c
----------------------------------------------------------------------
diff --git a/priv/couch_js/http.c b/priv/couch_js/http.c
index c66b5da..767573f 100644
--- a/priv/couch_js/http.c
+++ b/priv/couch_js/http.c
@@ -358,9 +358,9 @@ http_uri(JSContext* cx, JSObject* req, couch_args* args, jsval* uri_val)
     FILE* uri_fp = NULL;
     JSString* uri_str;
 
-    // Default is http://localhost:5984/ when no uri file is specified
+    // Default is http://localhost:15986/ when no uri file is specified
     if (!args->uri_file) {
-        uri_str = JS_InternString(cx, "http://localhost:5984/");
+        uri_str = JS_InternString(cx, "http://localhost:15986/");
         *uri_val = STRING_TO_JSVAL(uri_str);
         return JS_TRUE;
     }


[35/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Fix formatting of rebar.config.script


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

Branch: refs/heads/import
Commit: dd17921d96f46d0bdd555bc2e43edecd4f465929
Parents: b51ea97
Author: Paul J. Davis <pa...@gmail.com>
Authored: Mon Feb 3 15:47:59 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 17:03:53 2014 -0600

----------------------------------------------------------------------
 rebar.config.script | 52 +++++++++++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/dd17921d/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index b92bde1..bbc8400 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -10,30 +10,32 @@
 %% License for the specific language governing permissions and limitations under
 %% the License.
 
-%% declare values
 CouchJSName = case os:type() of
     {win32, _} ->
         "couchjs.exe";
     _ ->
         "couchjs"
 end,
+CouchJSPath = filename:join(["priv", CouchJSName]),
 Version = string:strip(os:cmd("git describe --always"), right, $\n),
 
-%% build config.h
+
 ConfigH = [
- {"SM185", ""},
- {"HAVE_JS_GET_STRING_CHARS_AND_LENGTH", "1"},
- {"JSSCRIPT_TYPE", "JSObject*"},
- {"COUCHJS_NAME", "\"" ++ CouchJSName++ "\""},
- {"PACKAGE", "\"apache-couchdb\""},
- {"PACKAGE_BUGREPORT", "\"https://issues.apache.org/jira/browse/COUCHDB\""},
- {"PACKAGE_NAME", "\"Apache CouchDB\""},
- {"PACKAGE_STRING", "\"Apache CouchDB " ++ Version ++ "\""},
- {"PACKAGE_VERSION", "\"" ++ Version ++ "\""}],
+    {"SM185", ""},
+    {"HAVE_JS_GET_STRING_CHARS_AND_LENGTH", "1"},
+    {"JSSCRIPT_TYPE", "JSObject*"},
+    {"COUCHJS_NAME", "\"" ++ CouchJSName++ "\""},
+    {"PACKAGE", "\"apache-couchdb\""},
+    {"PACKAGE_BUGREPORT", "\"https://issues.apache.org/jira/browse/COUCHDB\""},
+    {"PACKAGE_NAME", "\"Apache CouchDB\""},
+    {"PACKAGE_STRING", "\"Apache CouchDB " ++ Version ++ "\""},
+    {"PACKAGE_VERSION", "\"" ++ Version ++ "\""}
+],
+
 ConfigSrc = [["#define ", K, " ", V, $\n] || {K, V} <- ConfigH],
 ok = file:write_file("priv/couch_js/config.h", ConfigSrc),
 
-%% compile-time parameters
+
 JSLIBS = "-lmozjs185",
 {CFLAGS0, LDFLAGS} = case os:type() of
     {unix, darwin} ->
@@ -47,19 +49,24 @@ JSLIBS = "-lmozjs185",
 end,
 CFLAGS1 = CFLAGS0 ++ " -DWITHOUT_CURL",
 
+
 PortEnv = [
     {"DRV_CFLAGS",  "$DRV_CFLAGS -DPIC -O2 -fno-common"},
     {"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -lpthread"},
     {"CFLAGS", "$CFLAGS -Wall -c -g -O2 " ++ CFLAGS1},
-    {"LDFLAGS", LDFLAGS}],
+    {"LDFLAGS", LDFLAGS}
+],
+
 
-CouchJSSpec = [{filename:join(["priv", CouchJSName]),
-                ["priv/couch_js/{help,http,main,utf8,util}.c"]}],
-SpawnSpec = [{"priv/couchspawnkillable", ["priv/spawnkillable/*.c"]}],
-IcuSpec = [{"priv/couch_icu_driver.so", ["priv/icu_driver/*.c"]}],
-CompareSpec = [{"priv/couch_ejson_compare.so", ["priv/couch_ejson_compare/*.c"]}],
+BaseSpecs = [
+    {CouchJSPath, ["priv/couch_js/*.c"]},
+    {"priv/couch_icu_driver.so", ["priv/icu_driver/*.c"]},
+    {"priv/couch_ejson_compare.so", ["priv/couch_ejson_compare/*.c"]}
+],
 
-BaseSpecs = CouchJSSpec ++ IcuSpec ++ CompareSpec,
+SpawnSpec = [
+    {"priv/couchspawnkillable", ["priv/spawnkillable/*.c"]}
+],
 
 PortSpecs = case os:type() of
     {win32, _} ->
@@ -71,5 +78,8 @@ PortSpecs = case os:type() of
         BaseSpecs
 end,
 
-[{port_env, PortEnv},
- {port_specs, PortSpecs}].
+
+[
+    {port_env, PortEnv},
+    {port_specs, PortSpecs}
+].


[44/50] couch commit: updated refs/heads/import to 09c6556

Posted by da...@apache.org.
Check for configure settings to enable cURL


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

Branch: refs/heads/import
Commit: 783326a985e0e3f59bf67dfb05a1d5d5fd12b5da
Parents: cee3471
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Feb 4 22:08:06 2014 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Tue Feb 4 22:08:06 2014 -0600

----------------------------------------------------------------------
 rebar.config.script | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/783326a9/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
index 8e7c8e6..88483e8 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -19,6 +19,13 @@ end,
 CouchJSPath = filename:join(["priv", CouchJSName]),
 Version = string:strip(os:cmd("git describe --always"), right, $\n),
 
+CouchConfig = case filelib:is_file(os:getenv("COUCHDB_CONFIG")) of
+    true ->
+        {ok, Result} = file:consult(os:getenv("COUCHDB_CONFIG")),
+        Result;
+    false ->
+        []
+end.
 
 ConfigH = [
     {"SM185", ""},
@@ -35,15 +42,21 @@ ConfigH = [
 ConfigSrc = [["#define ", K, " ", V, $\n] || {K, V} <- ConfigH],
 ok = file:write_file("priv/couch_js/config.h", ConfigSrc),
 
-JS_LDFLAGS = "-lmozjs185 -DWITHOUTCURL",
+{JS_CFLAGS, JS_LDFLAGS} = case lists:keyfind(with_curl, 1, CouchConfig) of
+    {with_curl, true} ->
+        {"-DHAVE_CURL ", "-DHAVE_CURL -lmozjs185 -lcurl"};
+    _ ->
+        {"", "-lmozjs185"}
+end,
+
 CouchJSSrc = ["priv/couch_js/{help,http,main,utf8,util}.c"],
 
 BaseSpecs = [
         %% couchjs
-        {"darwin", CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", "-DXP_UNIX -I/usr/local/include/js"}, {"LDFLAGS", JS_LDFLAGS}]}]},
-        {"linux",  CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", "-DXP_UNIX -I/usr/include/js"}, {"LDFLAGS", JS_LDFLAGS ++ " -lm"}]}]},
-        {"unix",   CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", "-DXP_UNIX -I/usr/local/include/js}"}, {"LDFLAGS", JS_LDFLAGS ++ " -lm"}]}]},
-        {"win32",  CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", "-DXP_WIN -I/usr/include/js"}, {"LDFLAGS", JS_LDFLAGS}]}]},
+        {"darwin", CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", JS_CFLAGS ++ "-DXP_UNIX -I/usr/local/include/js"}, {"LDFLAGS", JS_LDFLAGS}]}]},
+        {"linux",  CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", JS_CFLAGS ++ "-DXP_UNIX -I/usr/include/js"}, {"LDFLAGS", JS_LDFLAGS ++ " -lm"}]}]},
+        {"unix",   CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", JS_CFLAGS ++ "-DXP_UNIX -I/usr/local/include/js}"}, {"LDFLAGS", JS_LDFLAGS ++ " -lm"}]}]},
+        {"win32",  CouchJSPath, CouchJSSrc, [{env, [{"CFLAGS", JS_CFLAGS ++ "-DXP_WIN -I/usr/include/js"}, {"LDFLAGS", JS_LDFLAGS}]}]},
         % ICU
         {"", "priv/couch_icu_driver.so", ["priv/icu_driver/*.c"], [{env, [
             {"DRV_CFLAGS",  "$DRV_CFLAGS -DPIC -O2 -fno-common"},