You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by wo...@apache.org on 2017/10/10 21:24:07 UTC
[couchdb] branch 749-fix-couch_peruser-app-structure updated
(4336dd4 -> bf2a2c1)
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a change to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git.
omit 4336dd4 80 cols
omit 87b0df9 whitespace and more state fixes
omit 372fb35 fix state
omit cb64096 fix style
omit 94d0ffd fix state call
omit 564b901 unlink changes listeners before exiting them so we survive
omit 3420b87 document ini entries
omit 697ab2d update README
omit 3e32c76 whitespace
omit c9d4ac8 move function declaration around for internal consistency
omit 3a426db s,init/0,init_state/0,
omit 57459a4 s/clusterState/state/ && s/state/changes_state/
omit 2ac9d55 remove leftover code from olde notification system
omit b8334ee add registered modules
omit 5d3b902 simplify couch_persuer.app definition
omit 8b9cc5e fix tests
omit 6203e08 add type specs
omit 736c269 make sure peruser listeners are only initialised once per node
omit 0400ca5 remove reliance on couch_replicator_clustering, handle cluster state internally
omit a35c53b move couch_replication_clustering:owner/3 to mem3.erl
omit b10249b track cluster state in gen_server state and get notfied from mem3 directly
omit a29e164 Ensure a user creation is handlined on one node only
omit 18f558c feat: mango test runner: do not rely on timeout for CouchDB start alone
omit b975e24 Start and stop couch_peruser in the test suite
omit b66e2ef Make couch_peruser a proper Erlang app
add b030a86 Return reduce overflow errors to the client
add a0e0885 Merge pull request #797 from apache/improve-reduce-limit-errors
new 2f49de8 Make couch_peruser a proper Erlang app
new b12683c Start and stop couch_peruser in the test suite
new 7da9d8b feat: mango test runner: do not rely on timeout for CouchDB start alone
new 599dcb3 Ensure a user creation is handlined on one node only
new 1af7ed4 track cluster state in gen_server state and get notfied from mem3 directly
new 93fb6ee move couch_replication_clustering:owner/3 to mem3.erl
new e34d048 remove reliance on couch_replicator_clustering, handle cluster state internally
new f0c2883 make sure peruser listeners are only initialised once per node
new ee9c872 add type specs
new 22656c8 fix tests
new 64ee2b7 simplify couch_persuer.app definition
new 90d4934 add registered modules
new 6487e38 remove leftover code from olde notification system
new 557ab00 s/clusterState/state/ && s/state/changes_state/
new e22f784 s,init/0,init_state/0,
new 3ed4838 move function declaration around for internal consistency
new e10a04b whitespace
new 3771f35 update README
new cc275cd document ini entries
new 4847c02 unlink changes listeners before exiting them so we survive
new 9ae8851 fix state call
new 28b400d fix style
new 96efbff fix state
new 570d6ee whitespace and more state fixes
new bf2a2c1 80 cols
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (4336dd4)
\
N -- N -- N refs/heads/749-fix-couch_peruser-app-structure (bf2a2c1)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 25 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
src/couch/src/couch_query_servers.erl | 29 ++++++++++++++++++++++++-----
src/couch_mrview/src/couch_mrview_http.erl | 6 +++++-
src/fabric/src/fabric_util.erl | 2 --
src/fabric/src/fabric_view.erl | 2 ++
test/javascript/tests/view_errors.js | 4 ++--
5 files changed, 33 insertions(+), 10 deletions(-)
--
To stop receiving notification emails like this one, please contact
['"commits@couchdb.apache.org" <co...@couchdb.apache.org>'].
[couchdb] 03/25: feat: mango test runner: do not rely on timeout
for CouchDB start alone
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 7da9d8bb7e0b54aad9ddc17681f71c4cf7ec66d7
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sun Oct 1 13:14:43 2017 +0200
feat: mango test runner: do not rely on timeout for CouchDB start alone
On slow build nodes, 10 seconds might not be enough of a wait.
---
test/build/test-run-couch-for-mango.sh | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/test/build/test-run-couch-for-mango.sh b/test/build/test-run-couch-for-mango.sh
index 6034a79..0597a8f 100755
--- a/test/build/test-run-couch-for-mango.sh
+++ b/test/build/test-run-couch-for-mango.sh
@@ -13,8 +13,17 @@
./dev/run -n 1 --admin=testuser:testpass &
export SERVER_PID=$!
-sleep 10
-curl http://dev:15984
+
+COUCH_STARTED=-1
+while ( [ $COUCH_STARTED -ne 0 ] ); do
+ curl -s http://127.0.0.1:15984
+ COUCH_STARTED=$?
+ if [ $COUCH_STARTED -ne 0 ]; then
+ # do not wait another 5 seconds if couch started now
+ sleep 5
+ fi
+done
+
cd src/mango/
nosetests
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 17/25: whitespace
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit e10a04bff527dbdf9ea6cf61f7f4bd1f8c554b32
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 08:12:31 2017 +0200
whitespace
---
src/couch_peruser/src/couch_peruser.erl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index 7943a9c..c5110da 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -133,7 +133,7 @@ changes_handler({change, {Doc}, _Prepend}, _ResType, ChangesState=#changes_state
% couch_log:debug("peruser: changes_handler() on DbName/Doc ~p/~p", [DbName, Doc]),
case couch_util:get_value(<<"id">>, Doc) of
- <<"org.couchdb.user:",User/binary>>=DocId ->
+ <<"org.couchdb.user:",User/binary>> = DocId ->
case should_handle_doc(DbName, DocId) of
true ->
case couch_util:get_value(<<"deleted">>, Doc, false) of
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 09/25: add type specs
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit ee9c8725901696034c2603d6509ef626711dc8b7
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sun Oct 8 16:28:38 2017 +0200
add type specs
---
src/couch_peruser/src/couch_peruser.erl | 53 +++++++++++++++++++++------------
1 file changed, 34 insertions(+), 19 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index e722b7e..16305c6 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -33,20 +33,20 @@
]).
-record(state, {
- parent,
- db_name,
- delete_dbs,
- changes_pid,
- changes_ref
+ parent :: pid(),
+ db_name :: binary(),
+ delete_dbs :: boolean(),
+ changes_pid :: pid(),
+ changes_ref :: reference()
}).
-record(clusterState, {
- parent,
- db_name,
- delete_dbs,
- states,
- mem3_cluster_pid,
- cluster_stable
+ parent :: pid(),
+ db_name :: binary(),
+ delete_dbs :: boolean(),
+ states :: list(),
+ mem3_cluster_pid :: pid(),
+ cluster_stable :: boolean()
}).
-define(USERDB_PREFIX, "userdb-").
@@ -57,10 +57,11 @@
%%
%% Please leave in the commented-out couch_log:debug calls, thanks! — Jan
%%
-
+-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+-spec init() -> #clusterState{}.
init() ->
couch_log:debug("peruser: starting on node ~p in pid ~p", [node(), self()]),
case config:get_boolean("couch_peruser", "enable", false) of
@@ -92,11 +93,12 @@ init() ->
end.
% Cluster membership change notification callback
--spec notify_cluster_event(pid(), {cluster, any()}) -> ok.
+-spec notify_cluster_event(Server :: pid(), Event :: {cluster, any()}) -> ok.
notify_cluster_event(Server, {cluster, _} = Event) ->
% couch_log:debug("peruser: received cluster event ~p on node ~p", [Event, node()]),
gen_server:cast(Server, Event).
+-spec start_listening(ClusterState :: #clusterState{}) -> #clusterState{} | ok.
start_listening(#clusterState{states=States}=ClusterState) when length(States) > 0 ->
% couch_log:debug("peruser: start_listening() already run on node ~p in pid ~p", [node(), self()]),
ClusterState;
@@ -119,6 +121,7 @@ start_listening(#clusterState{db_name=DbName, delete_dbs=DeleteDbs} = ClusterSta
config:set("couch_peruser", "enable", "false", lists:concat([binary_to_list(DbName), " is missing"]))
end.
+-spec init_changes_handler(State :: #state{}) -> ok.
init_changes_handler(#state{db_name=DbName} = State) ->
% couch_log:debug("peruser: init_changes_handler() on DbName ~p", [DbName]),
try
@@ -132,7 +135,8 @@ init_changes_handler(#state{db_name=DbName} = State) ->
ok
end.
-
+-type db_change() :: {atom(), tuple(), binary()}.
+-spec changes_handler(Change :: db_change(), ResultType :: any(), State :: #state{}) -> #state{}.
changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName}) ->
% couch_log:debug("peruser: changes_handler() on DbName/Doc ~p/~p", [DbName, Doc]),
@@ -165,7 +169,7 @@ changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName
changes_handler(_Event, _ResType, State) ->
State.
-
+-spec should_handle_doc(ShardName :: binary(), DocId::binary()) -> boolean().
should_handle_doc(ShardName, DocId) ->
case is_stable() of
false ->
@@ -178,6 +182,7 @@ should_handle_doc(ShardName, DocId) ->
should_handle_doc_int(ShardName, DocId)
end.
+-spec should_handle_doc_int(ShardName :: binary(), DocId :: binary()) -> boolean().
should_handle_doc_int(ShardName, DocId) ->
DbName = mem3:dbname(ShardName),
Live = [erlang:node() | erlang:nodes()],
@@ -192,7 +197,7 @@ should_handle_doc_int(ShardName, DocId) ->
false
end.
-
+-spec delete_user_db(User :: binary()) -> binary().
delete_user_db(User) ->
UserDb = user_db_name(User),
try
@@ -205,6 +210,7 @@ delete_user_db(User) ->
end,
UserDb.
+-spec ensure_user_db(User :: binary()) -> binary().
ensure_user_db(User) ->
UserDb = user_db_name(User),
try
@@ -218,6 +224,7 @@ ensure_user_db(User) ->
end,
UserDb.
+-spec add_user(User :: binary(), Properties :: tuple(), Acc :: tuple()) -> tuple().
add_user(User, Prop, {Modified, SecProps}) ->
{PropValue} = couch_util:get_value(Prop, SecProps, {[]}),
Names = couch_util:get_value(<<"names">>, PropValue, []),
@@ -234,6 +241,7 @@ add_user(User, Prop, {Modified, SecProps}) ->
{<<"names">>, [User | Names]})}})}
end.
+-spec remove_user(User :: binary(), Properties :: tuple(), Acc :: tuple()) -> tuple().
remove_user(User, Prop, {Modified, SecProps}) ->
{PropValue} = couch_util:get_value(Prop, SecProps, {[]}),
Names = couch_util:get_value(<<"names">>, PropValue, []),
@@ -250,10 +258,11 @@ remove_user(User, Prop, {Modified, SecProps}) ->
{<<"names">>, lists:delete(User, Names)})}})}
end.
+-spec ensure_security(User :: binary(), UserDb :: binary(), TransformFun :: fun()) -> ok.
ensure_security(User, UserDb, TransformFun) ->
case fabric:get_all_security(UserDb, [?ADMIN_CTX]) of
{error, no_majority} ->
- % single node, ignore
+ % TODO: make sure this is still true: single node, ignore
ok;
{ok, Shards} ->
{_ShardInfo, {SecProps}} = hd(Shards),
@@ -272,11 +281,13 @@ ensure_security(User, UserDb, TransformFun) ->
end
end.
+-spec user_db_name(User :: binary()) -> binary().
user_db_name(User) ->
HexUser = list_to_binary(
[string:to_lower(integer_to_list(X, 16)) || <<X>> <= User]),
<<?USERDB_PREFIX,HexUser/binary>>.
+-spec exit_changes(ClusterState :: #clusterState{}) -> ok.
exit_changes(ClusterState) ->
lists:foreach(fun (State) ->
demonitor(State#state.changes_ref, [flush]),
@@ -289,16 +300,20 @@ is_stable() ->
% Mem3 cluster callbacks
+% TODO: find out what type Server is
+-spec cluster_unstable(Server :: any()) -> any().
cluster_unstable(Server) ->
gen_server:cast(Server, cluster_unstable),
Server.
+% TODO: find out what type Server is
+-spec cluster_stable(Server :: any()) -> any().
cluster_stable(Server) ->
gen_server:cast(Server, cluster_stable),
Server.
%% gen_server callbacks
-
+-spec init(Options :: list()) -> {ok, #clusterState{}}.
init([]) ->
ok = subscribe_for_changes(),
{ok, init()}.
@@ -344,13 +359,13 @@ handle_info(restart_config_listener, State) ->
handle_info(_Msg, State) ->
{noreply, State}.
+-spec subscribe_for_changes() -> ok.
subscribe_for_changes() ->
config:subscribe_for_changes([
{"couch_httpd_auth", "authentication_db"},
"couch_peruser"
]).
-
terminate(_Reason, _State) ->
%% Everything should be linked or monitored, let nature
%% take its course.
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 04/25: Ensure a user creation is handlined on one node
only
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 599dcb32a7609359aa7e170d7ef8e95dd539b10d
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sat Oct 7 17:04:54 2017 +0200
Ensure a user creation is handlined on one node only
This patch makes use of the mechanism that ensures that replications
are only run on one node.
When the cluster has nodes added/removed all changes listeners are
restarted.
---
src/couch_peruser/src/couch_peruser.app.src | 2 +-
src/couch_peruser/src/couch_peruser.erl | 158 +++++++++++++++++++---------
2 files changed, 110 insertions(+), 50 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.app.src b/src/couch_peruser/src/couch_peruser.app.src
index 777446d..42b7b25 100644
--- a/src/couch_peruser/src/couch_peruser.app.src
+++ b/src/couch_peruser/src/couch_peruser.app.src
@@ -14,7 +14,7 @@
{description, "couch_peruser - maintains per-user databases in CouchDB"},
{vsn, git},
{registered, []},
- {applications, [kernel, stdlib, config, couch, fabric]},
+ {applications, [kernel, stdlib, config, couch, fabric, couch_replicator, mem3]},
{mod, {couch_peruser_app, []}},
{env, []},
{modules, [couch_peruser, couch_peruser_app, couch_peruser_sup]}
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index 63ef084..9161f56 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -22,6 +22,9 @@
-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
+% cluster state notification callback
+-export([notify_cluster_event/2]).
+
-export([init_changes_handler/1, changes_handler/3]).
-record(state, {parent, db_name, delete_dbs, changes_pid, changes_ref}).
@@ -34,10 +37,13 @@ start_link() ->
gen_server:start_link(?MODULE, [], []).
init() ->
+ couch_log:debug("peruser: starting on node ~p", [node()]),
case config:get_boolean("couch_peruser", "enable", false) of
false ->
+ couch_log:debug("peruser: disabled on node ~p", [node()]),
#clusterState{};
true ->
+ couch_log:debug("peruser: enabled on node ~p", [node()]),
DbName = ?l2b(config:get(
"couch_httpd_auth", "authentication_db", "_users")),
DeleteDbs = config:get_boolean("couch_peruser", "delete_dbs", false),
@@ -47,21 +53,37 @@ init() ->
db_name = DbName,
delete_dbs = DeleteDbs
},
- try
- States = lists:map(fun (A) ->
- S = #state{parent = ClusterState#clusterState.parent,
- db_name = A#shard.name,
- delete_dbs = DeleteDbs},
- {Pid, Ref} = spawn_opt(
- ?MODULE, init_changes_handler, [S], [link, monitor]),
- S#state{changes_pid=Pid, changes_ref=Ref}
- end, mem3:local_shards(DbName)),
-
- ClusterState#clusterState{states = States}
- catch error:database_does_not_exist ->
- couch_log:warning("couch_peruser can't proceed as underlying database (~s) is missing, disables itself.", [DbName]),
- config:set("couch_peruser", "enable", "false", lists:concat([binary_to_list(DbName), " is missing"]))
- end
+
+ % set up cluster-stable listener
+ couch_replicator_clustering:link_cluster_event_listener(?MODULE,
+ notify_cluster_event, [self()]),
+
+ couch_log:debug("peruser: registered for cluster event on node ~p", [node()]),
+ ClusterState
+ end.
+
+% Cluster membership change notification callback
+-spec notify_cluster_event(pid(), {cluster, any()}) -> ok.
+notify_cluster_event(Server, {cluster, _} = Event) ->
+ couch_log:debug("peruser: received cluster event ~p on node ~p", [Event, node()]),
+ gen_server:cast(Server, Event).
+
+start_listening(#clusterState{db_name=DbName, delete_dbs=DeleteDbs} = ClusterState) ->
+ couch_log:debug("peruser: start_listening() on node ~p", [node()]),
+ try
+ States = lists:map(fun (A) ->
+ S = #state{parent = ClusterState#clusterState.parent,
+ db_name = A#shard.name,
+ delete_dbs = DeleteDbs},
+ {Pid, Ref} = spawn_opt(
+ ?MODULE, init_changes_handler, [S], [link, monitor]),
+ S#state{changes_pid=Pid, changes_ref=Ref}
+ end, mem3:local_shards(DbName)),
+
+ ClusterState#clusterState{states = States}
+ catch error:database_does_not_exist ->
+ couch_log:warning("couch_peruser can't proceed as underlying database (~s) is missing, disables itself.", [DbName]),
+ config:set("couch_peruser", "enable", "false", lists:concat([binary_to_list(DbName), " is missing"]))
end.
init_changes_handler(#state{db_name=DbName} = State) ->
@@ -76,24 +98,30 @@ init_changes_handler(#state{db_name=DbName} = State) ->
ok
end.
-changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{}) ->
+
+changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName}) ->
case couch_util:get_value(<<"id">>, Doc) of
- <<"org.couchdb.user:",User/binary>> ->
- case couch_util:get_value(<<"deleted">>, Doc, false) of
- false ->
- UserDb = ensure_user_db(User),
- ok = ensure_security(User, UserDb, fun add_user/3),
- State;
+ <<"org.couchdb.user:",User/binary>>=DocId ->
+ case should_handle_doc(DbName, DocId) of
true ->
- case State#state.delete_dbs of
- true ->
- _UserDb = delete_user_db(User),
- State;
+ case couch_util:get_value(<<"deleted">>, Doc, false) of
false ->
- UserDb = user_db_name(User),
- ok = ensure_security(User, UserDb, fun remove_user/3),
- State
- end
+ UserDb = ensure_user_db(User),
+ ok = ensure_security(User, UserDb, fun add_user/3),
+ State;
+ true ->
+ case State#state.delete_dbs of
+ true ->
+ _UserDb = delete_user_db(User),
+ State;
+ false ->
+ UserDb = user_db_name(User),
+ ok = ensure_security(User, UserDb, fun remove_user/3),
+ State
+ end
+ end;
+ false ->
+ State
end;
_ ->
State
@@ -101,6 +129,25 @@ changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{}) ->
changes_handler(_Event, _ResType, State) ->
State.
+should_handle_doc(DbName, DocId) ->
+ case couch_replicator_clustering:owner(DbName, DocId) of
+ unstable ->
+ % todo: when we do proper resume[1], we can return false here
+ % and rely on a module restart when the cluster is stable again
+ % in the meantime, we risk conflicts when the cluster gets unstable
+ % and users are being created.
+ % [1] https://github.com/apache/couchdb/issues/872
+ true;
+ ThisNode when ThisNode =:= node() ->
+ couch_log:debug("peruser: handling ~s/~s", [DbName, DocId]),
+ % do the deed
+ true;
+ _OtherNode ->
+ couch_log:debug("peruser: skipping ~s/~s", [DbName, DocId]),
+ false
+ end.
+
+
delete_user_db(User) ->
UserDb = user_db_name(User),
try
@@ -158,20 +205,25 @@ remove_user(User, Prop, {Modified, SecProps}) ->
end.
ensure_security(User, UserDb, TransformFun) ->
- {ok, Shards} = fabric:get_all_security(UserDb, [?ADMIN_CTX]),
- {_ShardInfo, {SecProps}} = hd(Shards),
- % assert that shards have the same security object
- true = lists:all(fun ({_, {SecProps1}}) ->
- SecProps =:= SecProps1
- end, Shards),
- case lists:foldl(
- fun (Prop, SAcc) -> TransformFun(User, Prop, SAcc) end,
- {false, SecProps},
- [<<"admins">>, <<"members">>]) of
- {false, _} ->
- ok;
- {true, SecProps1} ->
- ok = fabric:set_security(UserDb, {SecProps1}, [?ADMIN_CTX])
+ case fabric:get_all_security(UserDb, [?ADMIN_CTX]) of
+ {error, no_majority} ->
+ % single node, ignore
+ ok;
+ {ok, Shards} ->
+ {_ShardInfo, {SecProps}} = hd(Shards),
+ % assert that shards have the same security object
+ true = lists:all(fun ({_, {SecProps1}}) ->
+ SecProps =:= SecProps1
+ end, Shards),
+ case lists:foldl(
+ fun (Prop, SAcc) -> TransformFun(User, Prop, SAcc) end,
+ {false, SecProps},
+ [<<"admins">>, <<"members">>]) of
+ {false, _} ->
+ ok;
+ {true, SecProps1} ->
+ ok = fabric:set_security(UserDb, {SecProps1}, [?ADMIN_CTX])
+ end
end.
user_db_name(User) ->
@@ -179,6 +231,11 @@ user_db_name(User) ->
[string:to_lower(integer_to_list(X, 16)) || <<X>> <= User]),
<<?USERDB_PREFIX,HexUser/binary>>.
+exit_changes(ClusterState) ->
+ lists:foreach(fun (State) ->
+ demonitor(State#state.changes_ref, [flush]),
+ exit(State#state.changes_pid, kill)
+ end, ClusterState#clusterState.states).
%% gen_server callbacks
@@ -191,16 +248,19 @@ handle_call(_Msg, _From, State) ->
handle_cast(update_config, ClusterState) when ClusterState#clusterState.states =/= undefined ->
- lists:foreach(fun (State) ->
- demonitor(State#state.changes_ref, [flush]),
- exit(State#state.changes_pid, kill)
- end, ClusterState#clusterState.states),
-
+ exit_changes(ClusterState),
{noreply, init()};
handle_cast(update_config, _) ->
{noreply, init()};
handle_cast(stop, State) ->
{stop, normal, State};
+handle_cast({cluster, unstable}, ClusterState) when ClusterState#clusterState.states =/= undefined ->
+ exit_changes(ClusterState),
+ {noreply, init()};
+handle_cast({cluster, unstable}, _) ->
+ {noreply, init()};
+handle_cast({cluster, stable}, State) ->
+ {noreply, start_listening(State)};
handle_cast(_Msg, State) ->
{noreply, State}.
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 05/25: track cluster state in gen_server state and get
notfied from mem3 directly
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 1af7ed4b54875263c9fe62da210bba93f6168ad1
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sat Oct 7 23:17:30 2017 +0200
track cluster state in gen_server state and get notfied from mem3 directly
---
src/couch_peruser/src/couch_peruser.erl | 65 ++++++++++++++++++++++++---------
1 file changed, 48 insertions(+), 17 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index 9161f56..a31ff60 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -12,12 +12,11 @@
-module(couch_peruser).
-behaviour(gen_server).
+-behaviour(mem3_cluster).
-include_lib("couch/include/couch_db.hrl").
-include_lib("mem3/include/mem3.hrl").
--define(USERDB_PREFIX, "userdb-").
-
% gen_server callbacks
-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
@@ -27,10 +26,25 @@
-export([init_changes_handler/1, changes_handler/3]).
+% mem3_cluster callbacks
+-export([
+ cluster_stable/1,
+ cluster_unstable/1
+]).
+
-record(state, {parent, db_name, delete_dbs, changes_pid, changes_ref}).
--record(clusterState, {parent, db_name, delete_dbs, states}).
+-record(clusterState, {parent,
+ db_name,
+ delete_dbs,
+ states,
+ mem3_cluster_pid,
+ cluster_stable
+}).
+-define(USERDB_PREFIX, "userdb-").
-define(RELISTEN_DELAY, 5000).
+-define(DEFAULT_QUIET_PERIOD, 60). % seconds
+-define(DEFAULT_START_PERIOD, 5). % seconds
start_link() ->
@@ -48,18 +62,24 @@ init() ->
"couch_httpd_auth", "authentication_db", "_users")),
DeleteDbs = config:get_boolean("couch_peruser", "delete_dbs", false),
- ClusterState = #clusterState{
- parent = self(),
- db_name = DbName,
- delete_dbs = DeleteDbs
- },
-
% set up cluster-stable listener
- couch_replicator_clustering:link_cluster_event_listener(?MODULE,
- notify_cluster_event, [self()]),
+ Period = abs(config:get_integer("couch_peruser", "cluster_quiet_period",
+ ?DEFAULT_QUIET_PERIOD)),
+ StartPeriod = abs(config:get_integer("couch_peruser", "cluster_start_period",
+ ?DEFAULT_START_PERIOD)),
+
+ {ok, Mem3Cluster} = mem3_cluster:start_link(?MODULE, self(), StartPeriod,
+ Period),
couch_log:debug("peruser: registered for cluster event on node ~p", [node()]),
- ClusterState
+
+ #clusterState{
+ parent = self(),
+ db_name = DbName,
+ delete_dbs = DeleteDbs,
+ mem3_cluster_pid = Mem3Cluster,
+ cluster_stable = false
+ }
end.
% Cluster membership change notification callback
@@ -80,7 +100,7 @@ start_listening(#clusterState{db_name=DbName, delete_dbs=DeleteDbs} = ClusterSta
S#state{changes_pid=Pid, changes_ref=Ref}
end, mem3:local_shards(DbName)),
- ClusterState#clusterState{states = States}
+ ClusterState#clusterState{states = States, cluster_stable = true}
catch error:database_does_not_exist ->
couch_log:warning("couch_peruser can't proceed as underlying database (~s) is missing, disables itself.", [DbName]),
config:set("couch_peruser", "enable", "false", lists:concat([binary_to_list(DbName), " is missing"]))
@@ -166,6 +186,7 @@ ensure_user_db(User) ->
{ok, _DbInfo} = fabric:get_db_info(UserDb)
catch error:database_does_not_exist ->
case fabric:create_db(UserDb, [?ADMIN_CTX]) of
+ {error, file_exists} -> ok;
ok -> ok;
accepted -> ok
end
@@ -207,7 +228,7 @@ remove_user(User, Prop, {Modified, SecProps}) ->
ensure_security(User, UserDb, TransformFun) ->
case fabric:get_all_security(UserDb, [?ADMIN_CTX]) of
{error, no_majority} ->
- % single node, ignore
+ % single node, ignore
ok;
{ok, Shards} ->
{_ShardInfo, {SecProps}} = hd(Shards),
@@ -237,6 +258,16 @@ exit_changes(ClusterState) ->
exit(State#state.changes_pid, kill)
end, ClusterState#clusterState.states).
+% Mem3 cluster callbacks
+
+cluster_unstable(Server) ->
+ gen_server:cast(Server, cluster_unstable),
+ Server.
+
+cluster_stable(Server) ->
+ gen_server:cast(Server, cluster_stable),
+ Server.
+
%% gen_server callbacks
init([]) ->
@@ -254,12 +285,12 @@ handle_cast(update_config, _) ->
{noreply, init()};
handle_cast(stop, State) ->
{stop, normal, State};
-handle_cast({cluster, unstable}, ClusterState) when ClusterState#clusterState.states =/= undefined ->
+handle_cast(cluster_unstable, ClusterState) when ClusterState#clusterState.states =/= undefined ->
exit_changes(ClusterState),
{noreply, init()};
-handle_cast({cluster, unstable}, _) ->
+handle_cast(cluster_unstable, _) ->
{noreply, init()};
-handle_cast({cluster, stable}, State) ->
+handle_cast(cluster_stable, State) ->
{noreply, start_listening(State)};
handle_cast(_Msg, State) ->
{noreply, State}.
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 18/25: update README
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 3771f35e1678379406cbd0ee6366b0bf3aa8d190
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 08:45:44 2017 +0200
update README
---
src/couch_peruser/README.md | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/couch_peruser/README.md b/src/couch_peruser/README.md
index 70f8348..64a0518 100644
--- a/src/couch_peruser/README.md
+++ b/src/couch_peruser/README.md
@@ -1,6 +1,6 @@
# couch_peruser [![Build Status](https://travis-ci.org/apache/couchdb-peruser.svg?branch=master)](https://travis-ci.org/apache/couchdb-peruser)
-couch_peruser is a CouchDB daemon that ensures that a private per-user
+couch_peruser is a CouchDB application that ensures that a private per-user
database exists for each document in _users. These databases are
writable only by the corresponding user. Databases are in the form:
@@ -15,3 +15,20 @@ correctly implement in just about any language, especially JavaScript
and Erlang. Other encodings would be possible, but would require
additional client and server-side code to support that encoding. This
is the simplest scheme that is obviously correct.
+
+## Implementation Notes
+
+The module itself is a `gen_server` and it implements the `mem3_cluster`
+behaviour.
+
+In a CouchDB cluster, the module runs on each node in the cluster. On startup,
+it launches a changes listener for each shard of the `authentication_db`
+(`_users`).
+
+In a cluster, when a change notification comes in (after a user doc has been
+created/updated/deleted), each node independently calculates if it should
+handle the notification based on the current list of active nodes in the
+cluster. This ensures that we avoid trying to update the internal `_dbs`
+concurrently and causing conflicts. It also ensures that at least one node
+does handle a notification. The mechanism that handles this does survive
+cluster reconfigurations transparently.
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 07/25: remove reliance on couch_replicator_clustering,
handle cluster state internally
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit e34d0484c561600162f714d251decbea73abd423
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sun Oct 8 11:14:28 2017 +0200
remove reliance on couch_replicator_clustering, handle cluster state internally
---
src/couch_peruser/src/couch_peruser.erl | 56 ++++++++++++++++++++++-----------
1 file changed, 37 insertions(+), 19 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index a31ff60..791431c 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -33,7 +33,8 @@
]).
-record(state, {parent, db_name, delete_dbs, changes_pid, changes_ref}).
--record(clusterState, {parent,
+-record(clusterState, {
+ parent,
db_name,
delete_dbs,
states,
@@ -48,10 +49,10 @@
start_link() ->
- gen_server:start_link(?MODULE, [], []).
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init() ->
- couch_log:debug("peruser: starting on node ~p", [node()]),
+ couch_log:debug("peruser: starting on node ~p in pid ~p", [node(), self()]),
case config:get_boolean("couch_peruser", "enable", false) of
false ->
couch_log:debug("peruser: disabled on node ~p", [node()]),
@@ -107,6 +108,8 @@ start_listening(#clusterState{db_name=DbName, delete_dbs=DeleteDbs} = ClusterSta
end.
init_changes_handler(#state{db_name=DbName} = State) ->
+ % leave for debugging
+ % couch_log:debug("peruser: init_changes_handler() on DbName ~p", [DbName]),
try
{ok, Db} = couch_db:open_int(DbName, [?ADMIN_CTX, sys_db]),
FunAcc = {fun ?MODULE:changes_handler/3, State},
@@ -120,6 +123,9 @@ init_changes_handler(#state{db_name=DbName} = State) ->
changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName}) ->
+ % leave for debugging
+ % couch_log:debug("peruser: changes_handler() on DbName/Doc ~p/~p", [DbName, Doc]),
+
case couch_util:get_value(<<"id">>, Doc) of
<<"org.couchdb.user:",User/binary>>=DocId ->
case should_handle_doc(DbName, DocId) of
@@ -149,22 +155,28 @@ changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName
changes_handler(_Event, _ResType, State) ->
State.
-should_handle_doc(DbName, DocId) ->
- case couch_replicator_clustering:owner(DbName, DocId) of
- unstable ->
- % todo: when we do proper resume[1], we can return false here
- % and rely on a module restart when the cluster is stable again
- % in the meantime, we risk conflicts when the cluster gets unstable
- % and users are being created.
- % [1] https://github.com/apache/couchdb/issues/872
- true;
- ThisNode when ThisNode =:= node() ->
- couch_log:debug("peruser: handling ~s/~s", [DbName, DocId]),
- % do the deed
- true;
- _OtherNode ->
- couch_log:debug("peruser: skipping ~s/~s", [DbName, DocId]),
- false
+should_handle_doc(ShardName, DocId) ->
+ should_handle_doc_int(ShardName, DocId, is_stable()).
+
+should_handle_doc_int(ShardName, DocId, false) ->
+ % when the cluster is unstable, we have already stopped all Listeners
+ % the next stable event will restart all listeners and pick up this
+ % doc change
+ couch_log:debug("peruser: skipping, cluster unstable ~s/~s", [ShardName, DocId]),
+ false;
+should_handle_doc_int(ShardName, DocId, true) ->
+ DbName = mem3:dbname(ShardName),
+ Live = [erlang:node() | erlang:nodes()],
+ Shards = mem3:shards(DbName, DocId),
+ Nodes = [N || #shard{node=N} <- Shards, lists:member(N, Live)],
+ case mem3:owner(DbName, DocId, Nodes) of
+ ThisNode when ThisNode =:= node() ->
+ couch_log:debug("peruser: handling ~s/~s", [DbName, DocId]),
+ % do the deed
+ true;
+ _OtherNode ->
+ couch_log:debug("peruser: skipping ~s/~s", [DbName, DocId]),
+ false
end.
@@ -258,6 +270,10 @@ exit_changes(ClusterState) ->
exit(State#state.changes_pid, kill)
end, ClusterState#clusterState.states).
+-spec is_stable() -> true | false.
+is_stable() ->
+ gen_server:call(?MODULE, is_stable).
+
% Mem3 cluster callbacks
cluster_unstable(Server) ->
@@ -274,6 +290,8 @@ init([]) ->
ok = subscribe_for_changes(),
{ok, init()}.
+handle_call(is_stable, _From, #clusterState{cluster_stable = IsStable} = State) ->
+ {reply, IsStable, State};
handle_call(_Msg, _From, State) ->
{reply, error, State}.
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 21/25: fix state call
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 9ae88514637d59a4e66bf9de906876739542a251
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Tue Oct 10 10:47:39 2017 +0200
fix state call
---
src/couch_peruser/src/couch_peruser.erl | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index 2493387..f130e13 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -279,10 +279,10 @@ user_db_name(User) ->
[string:to_lower(integer_to_list(X, 16)) || <<X>> <= User]),
<<?USERDB_PREFIX,HexUser/binary>>.
--spec exit_changes(State :: #state{}) -> ok.
-exit_changes(State) ->
+-spec exit_changes(ChangesState :: #changes_state{}) -> ok.
+exit_changes(ChangesState) ->
lists:foreach(fun (ChangesState) ->
- demonitor(State#changes_state.changes_ref, [flush]),
+ demonitor(ChangesState#changes_state.changes_ref, [flush]),
unlink(ChangesState#changes_state.changes_pid),
exit(ChangesState#changes_state.changes_pid, kill)
end, State#state.states).
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 19/25: document ini entries
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit cc275cdb494291c09bc1508fdb00340f0c176318
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 08:49:52 2017 +0200
document ini entries
---
rel/overlay/etc/default.ini | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index 56f9147..4e61deb 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -88,6 +88,10 @@ enable = false
; If set to true and a user is deleted, the respective database gets
; deleted as well.
delete_dbs = false
+; Wait this many seconds after startup before attaching changes listeners
+; cluster_start_period = 5
+; Re-check cluster state at least every cluster_quiet_period seconds
+; cluster_quiet_period = 60
[httpd]
port = {{backend_port}}
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 11/25: simplify couch_persuer.app definition
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 64ee2b7b90e4b5da804301a527a5388c98c98877
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 07:54:39 2017 +0200
simplify couch_persuer.app definition
---
src/couch_peruser/src/couch_peruser.app.src | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.app.src b/src/couch_peruser/src/couch_peruser.app.src
index 9859e03..f7c5134 100644
--- a/src/couch_peruser/src/couch_peruser.app.src
+++ b/src/couch_peruser/src/couch_peruser.app.src
@@ -16,6 +16,5 @@
{registered, []},
{applications, [kernel, stdlib, config, couch, fabric, mem3]},
{mod, {couch_peruser_app, []}},
- {env, []},
- {modules, [couch_peruser, couch_peruser_app, couch_peruser_sup]}
+ {env, []}
]}.
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 25/25: 80 cols
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit bf2a2c139efecbba184cdeba6b4d14c19e5e84a0
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Tue Oct 10 20:59:40 2017 +0200
80 cols
---
src/couch_peruser/src/couch_peruser.erl | 37 ++++++++++++++++++++++++++-------
1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index a394659..0c76932 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -131,8 +131,14 @@ init_changes_handler(#changes_state{db_name=DbName} = ChangesState) ->
end.
-type db_change() :: {atom(), tuple(), binary()}.
--spec changes_handler(Change :: db_change(), ResultType :: any(), ChangesState :: #changes_state{}) -> #changes_state{}.
-changes_handler({change, {Doc}, _Prepend}, _ResType, ChangesState=#changes_state{db_name=DbName}) ->
+-spec changes_handler(
+ Change :: db_change(),
+ ResultType :: any(),
+ ChangesState :: #changes_state{}) -> #changes_state{}.
+changes_handler(
+ {change, {Doc}, _Prepend},
+ _ResType,
+ ChangesState=#changes_state{db_name=DbName}) ->
% couch_log:debug("peruser: changes_handler() on DbName/Doc ~p/~p", [DbName, Doc]),
case couch_util:get_value(<<"id">>, Doc) of
@@ -171,13 +177,16 @@ should_handle_doc(ShardName, DocId) ->
% when the cluster is unstable, we have already stopped all Listeners
% the next stable event will restart all listeners and pick up this
% doc change
- couch_log:debug("peruser: skipping, cluster unstable ~s/~s", [ShardName, DocId]),
+ couch_log:debug("peruser: skipping, cluster unstable ~s/~s",
+ [ShardName, DocId]),
false;
true ->
should_handle_doc_int(ShardName, DocId)
end.
--spec should_handle_doc_int(ShardName :: binary(), DocId :: binary()) -> boolean().
+-spec should_handle_doc_int(
+ ShardName :: binary(),
+ DocId :: binary()) -> boolean().
should_handle_doc_int(ShardName, DocId) ->
DbName = mem3:dbname(ShardName),
Live = [erlang:node() | erlang:nodes()],
@@ -219,7 +228,10 @@ ensure_user_db(User) ->
end,
UserDb.
--spec add_user(User :: binary(), Properties :: tuple(), Acc :: tuple()) -> tuple().
+-spec add_user(
+ User :: binary(),
+ Properties :: tuple(),
+ Acc :: tuple()) -> tuple().
add_user(User, Prop, {Modified, SecProps}) ->
{PropValue} = couch_util:get_value(Prop, SecProps, {[]}),
Names = couch_util:get_value(<<"names">>, PropValue, []),
@@ -236,7 +248,10 @@ add_user(User, Prop, {Modified, SecProps}) ->
{<<"names">>, [User | Names]})}})}
end.
--spec remove_user(User :: binary(), Properties :: tuple(), Acc :: tuple()) -> tuple().
+-spec remove_user(
+ User :: binary(),
+ Properties :: tuple(),
+ Acc :: tuple()) -> tuple().
remove_user(User, Prop, {Modified, SecProps}) ->
{PropValue} = couch_util:get_value(Prop, SecProps, {[]}),
Names = couch_util:get_value(<<"names">>, PropValue, []),
@@ -253,7 +268,10 @@ remove_user(User, Prop, {Modified, SecProps}) ->
{<<"names">>, lists:delete(User, Names)})}})}
end.
--spec ensure_security(User :: binary(), UserDb :: binary(), TransformFun :: fun()) -> ok.
+-spec ensure_security(
+ User :: binary(),
+ UserDb :: binary(),
+ TransformFun :: fun()) -> ok.
ensure_security(User, UserDb, TransformFun) ->
case fabric:get_all_security(UserDb, [?ADMIN_CTX]) of
{error, no_majority} ->
@@ -348,7 +366,10 @@ handle_info({'DOWN', _Ref, _, _, _Reason}, State) ->
{stop, normal, State};
handle_info({config_change, "couch_peruser", _, _, _}, State) ->
handle_cast(update_config, State);
-handle_info({config_change, "couch_httpd_auth", "authentication_db", _, _}, State) ->
+handle_info({
+ config_change,
+ "couch_httpd_auth",
+ "authentication_db", _, _}, State) ->
handle_cast(update_config, State);
handle_info({gen_event_EXIT, _Handler, _Reason}, State) ->
erlang:send_after(?RELISTEN_DELAY, self(), restart_config_listener),
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 15/25: s,init/0,init_state/0,
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit e22f7842b503c76a5d773e4589bb3034fa57a583
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 08:10:52 2017 +0200
s,init/0,init_state/0,
---
src/couch_peruser/src/couch_peruser.erl | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index bda74ec..f820fe6 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -58,8 +58,8 @@
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
--spec init() -> #state{}.
-init() ->
+-spec init_state() -> #state{}.
+init_state() ->
couch_log:debug("peruser: starting on node ~p in pid ~p", [node(), self()]),
case config:get_boolean("couch_peruser", "enable", false) of
false ->
@@ -308,7 +308,7 @@ cluster_stable(Server) ->
-spec init(Options :: list()) -> {ok, #state{}}.
init([]) ->
ok = subscribe_for_changes(),
- {ok, init()}.
+ {ok, init_state()}.
handle_call(is_stable, _From, #state{cluster_stable = IsStable} = State) ->
{reply, IsStable, State};
@@ -318,16 +318,16 @@ handle_call(_Msg, _From, State) ->
handle_cast(update_config, State) when State#state.states =/= undefined ->
exit_changes(State),
- {noreply, init()};
+ {noreply, init_state()};
handle_cast(update_config, _) ->
- {noreply, init()};
+ {noreply, init_state()};
handle_cast(stop, State) ->
{stop, normal, State};
handle_cast(cluster_unstable, State) when State#state.states =/= undefined ->
exit_changes(State),
- {noreply, init()};
+ {noreply, init_state()};
handle_cast(cluster_unstable, _) ->
- {noreply, init()};
+ {noreply, init_state()};
handle_cast(cluster_stable, State) ->
{noreply, start_listening(State)};
handle_cast(_Msg, State) ->
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 10/25: fix tests
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 22656c86b3d5f3ad977bb72c4375874403940158
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sun Oct 8 16:54:17 2017 +0200
fix tests
---
src/couch_peruser/src/couch_peruser.app.src | 2 +-
src/couch_peruser/test/couch_peruser_test.erl | 17 +++++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/couch_peruser/src/couch_peruser.app.src b/src/couch_peruser/src/couch_peruser.app.src
index 42b7b25..9859e03 100644
--- a/src/couch_peruser/src/couch_peruser.app.src
+++ b/src/couch_peruser/src/couch_peruser.app.src
@@ -14,7 +14,7 @@
{description, "couch_peruser - maintains per-user databases in CouchDB"},
{vsn, git},
{registered, []},
- {applications, [kernel, stdlib, config, couch, fabric, couch_replicator, mem3]},
+ {applications, [kernel, stdlib, config, couch, fabric, mem3]},
{mod, {couch_peruser_app, []}},
{env, []},
{modules, [couch_peruser, couch_peruser_app, couch_peruser_sup]}
diff --git a/src/couch_peruser/test/couch_peruser_test.erl b/src/couch_peruser/test/couch_peruser_test.erl
index f7ef8cd..726b2db 100644
--- a/src/couch_peruser/test/couch_peruser_test.erl
+++ b/src/couch_peruser/test/couch_peruser_test.erl
@@ -35,13 +35,22 @@ setup() ->
do_request(put, get_base_url() ++ "/" ++ ?b2l(TestAuthDb)),
do_request(put, get_cluster_base_url() ++ "/" ++ ?b2l(TestAuthDb)),
set_config("couch_httpd_auth", "authentication_db", ?b2l(TestAuthDb)),
+ set_config("couch_peruser", "cluster_quiet_period", "1"),
+ set_config("couch_peruser", "cluster_start_period", "1"),
set_config("couch_peruser", "enable", "true"),
+ set_config("cluster", "n", "1"),
+ set_config("log", "level", "debug"),
+ timer:sleep(6000),
TestAuthDb.
teardown(TestAuthDb) ->
set_config("couch_peruser", "enable", "false"),
set_config("couch_peruser", "delete_dbs", "false"),
set_config("couch_httpd_auth", "authentication_db", "_users"),
+ set_config("couch_peruser", "cluster_quiet_period", "60"),
+ set_config("couch_peruser", "cluster_start_period", "5"),
+ set_config("cluster", "n", "3"),
+ set_config("log", "level", "info"),
do_request(delete, get_cluster_base_url() ++ "/" ++ ?b2l(TestAuthDb)),
do_request(delete, get_base_url() ++ "/" ++ ?b2l(TestAuthDb)),
lists:foreach(fun (DbName) ->
@@ -153,8 +162,10 @@ should_delete_user_db(TestAuthDb) ->
UserDbName = <<"userdb-626172">>,
set_config("couch_peruser", "delete_dbs", "true"),
create_user(TestAuthDb, User),
+ timer:sleep(2000),
?assert(lists:member(UserDbName, all_dbs())),
delete_user(TestAuthDb, User),
+ timer:sleep(2000),
?_assert(not lists:member(UserDbName, all_dbs())).
should_reflect_config_changes(TestAuthDb) ->
@@ -162,20 +173,26 @@ should_reflect_config_changes(TestAuthDb) ->
UserDbName = <<"userdb-62617a">>,
set_config("couch_peruser", "delete_dbs", "true"),
create_user(TestAuthDb, User),
+ timer:sleep(2000),
?assert(lists:member(UserDbName, all_dbs())),
delete_user(TestAuthDb, User),
+ timer:sleep(2000),
?assert(not lists:member(UserDbName, all_dbs())),
create_user(TestAuthDb, User),
+ timer:sleep(2000),
?assert(lists:member(UserDbName, all_dbs())),
set_config("couch_peruser", "delete_dbs", "false"),
delete_user(TestAuthDb, User),
+ timer:sleep(2000),
?assert(lists:member(UserDbName, all_dbs())),
create_user(TestAuthDb, User),
set_config("couch_peruser", "delete_dbs", "true"),
delete_user(TestAuthDb, User),
+ timer:sleep(2000),
?assert(not lists:member(UserDbName, all_dbs())),
set_config("couch_peruser", "enable", "false"),
create_user(TestAuthDb, User),
+ timer:sleep(2000),
?_assert(not lists:member(UserDbName, all_dbs())).
should_add_user_to_db_admins(TestAuthDb) ->
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 13/25: remove leftover code from olde notification system
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 6487e38ce9b389aae8ca0e8f99cd945506380778
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 07:56:12 2017 +0200
remove leftover code from olde notification system
---
src/couch_peruser/src/couch_peruser.erl | 8 --------
1 file changed, 8 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index 16305c6..c2ac6ab 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -21,9 +21,6 @@
-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-% cluster state notification callback
--export([notify_cluster_event/2]).
-
-export([init_changes_handler/1, changes_handler/3]).
% mem3_cluster callbacks
@@ -92,11 +89,6 @@ init() ->
}
end.
-% Cluster membership change notification callback
--spec notify_cluster_event(Server :: pid(), Event :: {cluster, any()}) -> ok.
-notify_cluster_event(Server, {cluster, _} = Event) ->
- % couch_log:debug("peruser: received cluster event ~p on node ~p", [Event, node()]),
- gen_server:cast(Server, Event).
-spec start_listening(ClusterState :: #clusterState{}) -> #clusterState{} | ok.
start_listening(#clusterState{states=States}=ClusterState) when length(States) > 0 ->
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 08/25: make sure peruser listeners are only initialised
once per node
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit f0c28835a6a8d4b08de4eaf94b7d07d2d4865e8c
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sun Oct 8 15:36:31 2017 +0200
make sure peruser listeners are only initialised once per node
---
src/couch_peruser/src/couch_peruser.erl | 59 ++++++++++++++++++++-------------
1 file changed, 36 insertions(+), 23 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index 791431c..e722b7e 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -32,7 +32,14 @@
cluster_unstable/1
]).
--record(state, {parent, db_name, delete_dbs, changes_pid, changes_ref}).
+-record(state, {
+ parent,
+ db_name,
+ delete_dbs,
+ changes_pid,
+ changes_ref
+}).
+
-record(clusterState, {
parent,
db_name,
@@ -47,6 +54,9 @@
-define(DEFAULT_QUIET_PERIOD, 60). % seconds
-define(DEFAULT_START_PERIOD, 5). % seconds
+%%
+%% Please leave in the commented-out couch_log:debug calls, thanks! — Jan
+%%
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
@@ -72,8 +82,6 @@ init() ->
{ok, Mem3Cluster} = mem3_cluster:start_link(?MODULE, self(), StartPeriod,
Period),
- couch_log:debug("peruser: registered for cluster event on node ~p", [node()]),
-
#clusterState{
parent = self(),
db_name = DbName,
@@ -86,11 +94,14 @@ init() ->
% Cluster membership change notification callback
-spec notify_cluster_event(pid(), {cluster, any()}) -> ok.
notify_cluster_event(Server, {cluster, _} = Event) ->
- couch_log:debug("peruser: received cluster event ~p on node ~p", [Event, node()]),
+ % couch_log:debug("peruser: received cluster event ~p on node ~p", [Event, node()]),
gen_server:cast(Server, Event).
+start_listening(#clusterState{states=States}=ClusterState) when length(States) > 0 ->
+ % couch_log:debug("peruser: start_listening() already run on node ~p in pid ~p", [node(), self()]),
+ ClusterState;
start_listening(#clusterState{db_name=DbName, delete_dbs=DeleteDbs} = ClusterState) ->
- couch_log:debug("peruser: start_listening() on node ~p", [node()]),
+ % couch_log:debug("peruser: start_listening() on node ~p", [node()]),
try
States = lists:map(fun (A) ->
S = #state{parent = ClusterState#clusterState.parent,
@@ -100,6 +111,7 @@ start_listening(#clusterState{db_name=DbName, delete_dbs=DeleteDbs} = ClusterSta
?MODULE, init_changes_handler, [S], [link, monitor]),
S#state{changes_pid=Pid, changes_ref=Ref}
end, mem3:local_shards(DbName)),
+ % couch_log:debug("peruser: start_listening() States ~p", [States]),
ClusterState#clusterState{states = States, cluster_stable = true}
catch error:database_does_not_exist ->
@@ -108,7 +120,6 @@ start_listening(#clusterState{db_name=DbName, delete_dbs=DeleteDbs} = ClusterSta
end.
init_changes_handler(#state{db_name=DbName} = State) ->
- % leave for debugging
% couch_log:debug("peruser: init_changes_handler() on DbName ~p", [DbName]),
try
{ok, Db} = couch_db:open_int(DbName, [?ADMIN_CTX, sys_db]),
@@ -123,7 +134,6 @@ init_changes_handler(#state{db_name=DbName} = State) ->
changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName}) ->
- % leave for debugging
% couch_log:debug("peruser: changes_handler() on DbName/Doc ~p/~p", [DbName, Doc]),
case couch_util:get_value(<<"id">>, Doc) of
@@ -155,28 +165,31 @@ changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName
changes_handler(_Event, _ResType, State) ->
State.
+
should_handle_doc(ShardName, DocId) ->
- should_handle_doc_int(ShardName, DocId, is_stable()).
-
-should_handle_doc_int(ShardName, DocId, false) ->
- % when the cluster is unstable, we have already stopped all Listeners
- % the next stable event will restart all listeners and pick up this
- % doc change
- couch_log:debug("peruser: skipping, cluster unstable ~s/~s", [ShardName, DocId]),
- false;
-should_handle_doc_int(ShardName, DocId, true) ->
+ case is_stable() of
+ false ->
+ % when the cluster is unstable, we have already stopped all Listeners
+ % the next stable event will restart all listeners and pick up this
+ % doc change
+ couch_log:debug("peruser: skipping, cluster unstable ~s/~s", [ShardName, DocId]),
+ false;
+ true ->
+ should_handle_doc_int(ShardName, DocId)
+ end.
+
+should_handle_doc_int(ShardName, DocId) ->
DbName = mem3:dbname(ShardName),
Live = [erlang:node() | erlang:nodes()],
Shards = mem3:shards(DbName, DocId),
Nodes = [N || #shard{node=N} <- Shards, lists:member(N, Live)],
case mem3:owner(DbName, DocId, Nodes) of
- ThisNode when ThisNode =:= node() ->
- couch_log:debug("peruser: handling ~s/~s", [DbName, DocId]),
- % do the deed
- true;
- _OtherNode ->
- couch_log:debug("peruser: skipping ~s/~s", [DbName, DocId]),
- false
+ ThisNode when ThisNode =:= node() ->
+ couch_log:debug("peruser: handling ~s/~s", [DbName, DocId]),
+ true; % do the database action
+ _OtherNode ->
+ couch_log:debug("peruser: skipping ~s/~s", [DbName, DocId]),
+ false
end.
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 02/25: Start and stop couch_peruser in the test suite
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit b12683ce7a85d28b868128b74eb06f184047c5d2
Author: Russell Branca <ch...@apache.org>
AuthorDate: Thu Aug 17 19:40:38 2017 +0000
Start and stop couch_peruser in the test suite
---
src/couch_peruser/test/couch_peruser_test.erl | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/couch_peruser/test/couch_peruser_test.erl b/src/couch_peruser/test/couch_peruser_test.erl
index c6fde03..f7ef8cd 100644
--- a/src/couch_peruser/test/couch_peruser_test.erl
+++ b/src/couch_peruser/test/couch_peruser_test.erl
@@ -20,12 +20,14 @@
setup_all() ->
TestCtx = test_util:start_couch([chttpd]),
+ ok = application:start(couch_peruser),
Hashed = couch_passwords:hash_admin_password(?ADMIN_PASSWORD),
ok = config:set("admins", ?ADMIN_USERNAME, ?b2l(Hashed), _Persist=false),
TestCtx.
teardown_all(TestCtx) ->
config:delete("admins", ?ADMIN_USERNAME),
+ ok = application:stop(couch_peruser),
test_util:stop_couch(TestCtx).
setup() ->
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 06/25: move couch_replication_clustering:owner/3 to
mem3.erl
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 93fb6ee9da907c53f44ad6887c6c9a1309f118aa
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sat Oct 7 23:24:14 2017 +0200
move couch_replication_clustering:owner/3 to mem3.erl
---
src/couch_replicator/src/couch_replicator.erl | 2 +-
src/couch_replicator/src/couch_replicator_clustering.erl | 10 +---------
src/mem3/src/mem3.erl | 8 +++++++-
3 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/src/couch_replicator/src/couch_replicator.erl b/src/couch_replicator/src/couch_replicator.erl
index c67b37d..8b7cd5c 100644
--- a/src/couch_replicator/src/couch_replicator.erl
+++ b/src/couch_replicator/src/couch_replicator.erl
@@ -184,7 +184,7 @@ active_doc(DbName, DocId) ->
Live = [node() | nodes()],
Nodes = lists:usort([N || #shard{node=N} <- Shards,
lists:member(N, Live)]),
- Owner = couch_replicator_clustering:owner(DbName, DocId, Nodes),
+ Owner = mem3:owner(DbName, DocId, Nodes),
case active_doc_rpc(DbName, DocId, [Owner]) of
{ok, DocInfo} ->
{ok, DocInfo};
diff --git a/src/couch_replicator/src/couch_replicator_clustering.erl b/src/couch_replicator/src/couch_replicator_clustering.erl
index ed01465..3d5229b 100644
--- a/src/couch_replicator/src/couch_replicator_clustering.erl
+++ b/src/couch_replicator/src/couch_replicator_clustering.erl
@@ -45,7 +45,6 @@
-export([
owner/2,
- owner/3,
is_stable/0,
link_cluster_event_listener/3
]).
@@ -96,13 +95,6 @@ owner(_DbName, _DocId) ->
node().
-% Direct calculation of node membership. This is the algorithm part. It
-% doesn't read the shard map, just picks owner based on a hash.
--spec owner(binary(), binary(), [node()]) -> node().
-owner(DbName, DocId, Nodes) ->
- hd(mem3_util:rotate_list({DbName, DocId}, lists:usort(Nodes))).
-
-
-spec is_stable() -> true | false.
is_stable() ->
gen_server:call(?MODULE, is_stable).
@@ -200,4 +192,4 @@ owner_int(ShardName, DocId) ->
Live = [node() | nodes()],
Shards = mem3:shards(DbName, DocId),
Nodes = [N || #shard{node=N} <- Shards, lists:member(N, Live)],
- owner(DbName, DocId, Nodes).
+ mem3:owner(DbName, DocId, Nodes).
diff --git a/src/mem3/src/mem3.erl b/src/mem3/src/mem3.erl
index e2cbb2e..047154a 100644
--- a/src/mem3/src/mem3.erl
+++ b/src/mem3/src/mem3.erl
@@ -19,7 +19,7 @@
-export([compare_nodelists/0, compare_shards/1]).
-export([quorum/1, group_by_proximity/1]).
-export([live_shards/2]).
--export([belongs/2]).
+-export([belongs/2, owner/3]).
-export([get_placement/1]).
%% For mem3 use only.
@@ -311,6 +311,12 @@ name(#shard{name=Name}) ->
name(#ordered_shard{name=Name}) ->
Name.
+% Direct calculation of node membership. This is the algorithm part. It
+% doesn't read the shard map, just picks owner based on a hash.
+-spec owner(binary(), binary(), [node()]) -> node().
+owner(DbName, DocId, Nodes) ->
+ hd(mem3_util:rotate_list({DbName, DocId}, lists:usort(Nodes))).
+
-ifdef(TEST).
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 14/25: s/clusterState/state/ && s/state/changes_state/
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 557ab003149972355c2be019b4557a1694a42cc3
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 08:08:24 2017 +0200
s/clusterState/state/ && s/state/changes_state/
---
src/couch_peruser/src/couch_peruser.erl | 76 ++++++++++++++++-----------------
1 file changed, 38 insertions(+), 38 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index c2ac6ab..bda74ec 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -29,7 +29,7 @@
cluster_unstable/1
]).
--record(state, {
+-record(changes_state, {
parent :: pid(),
db_name :: binary(),
delete_dbs :: boolean(),
@@ -37,7 +37,7 @@
changes_ref :: reference()
}).
--record(clusterState, {
+-record(state, {
parent :: pid(),
db_name :: binary(),
delete_dbs :: boolean(),
@@ -58,13 +58,13 @@
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
--spec init() -> #clusterState{}.
+-spec init() -> #state{}.
init() ->
couch_log:debug("peruser: starting on node ~p in pid ~p", [node(), self()]),
case config:get_boolean("couch_peruser", "enable", false) of
false ->
couch_log:debug("peruser: disabled on node ~p", [node()]),
- #clusterState{};
+ #state{};
true ->
couch_log:debug("peruser: enabled on node ~p", [node()]),
DbName = ?l2b(config:get(
@@ -80,7 +80,7 @@ init() ->
{ok, Mem3Cluster} = mem3_cluster:start_link(?MODULE, self(), StartPeriod,
Period),
- #clusterState{
+ #state{
parent = self(),
db_name = DbName,
delete_dbs = DeleteDbs,
@@ -90,35 +90,35 @@ init() ->
end.
--spec start_listening(ClusterState :: #clusterState{}) -> #clusterState{} | ok.
-start_listening(#clusterState{states=States}=ClusterState) when length(States) > 0 ->
+-spec start_listening(State :: #state{}) -> #state{} | ok.
+start_listening(#state{states=ChangesStates}=State) when length(ChangesStates) > 0 ->
% couch_log:debug("peruser: start_listening() already run on node ~p in pid ~p", [node(), self()]),
- ClusterState;
-start_listening(#clusterState{db_name=DbName, delete_dbs=DeleteDbs} = ClusterState) ->
+ State;
+start_listening(#state{db_name=DbName, delete_dbs=DeleteDbs} = State) ->
% couch_log:debug("peruser: start_listening() on node ~p", [node()]),
try
States = lists:map(fun (A) ->
- S = #state{parent = ClusterState#clusterState.parent,
+ S = #changes_state{parent = State#state.parent,
db_name = A#shard.name,
delete_dbs = DeleteDbs},
{Pid, Ref} = spawn_opt(
?MODULE, init_changes_handler, [S], [link, monitor]),
- S#state{changes_pid=Pid, changes_ref=Ref}
+ S#changes_state{changes_pid=Pid, changes_ref=Ref}
end, mem3:local_shards(DbName)),
% couch_log:debug("peruser: start_listening() States ~p", [States]),
- ClusterState#clusterState{states = States, cluster_stable = true}
+ State#state{states = States, cluster_stable = true}
catch error:database_does_not_exist ->
couch_log:warning("couch_peruser can't proceed as underlying database (~s) is missing, disables itself.", [DbName]),
config:set("couch_peruser", "enable", "false", lists:concat([binary_to_list(DbName), " is missing"]))
end.
--spec init_changes_handler(State :: #state{}) -> ok.
-init_changes_handler(#state{db_name=DbName} = State) ->
+-spec init_changes_handler(ChangesState :: #changes_state{}) -> ok.
+init_changes_handler(#changes_state{db_name=DbName} = ChangesState) ->
% couch_log:debug("peruser: init_changes_handler() on DbName ~p", [DbName]),
try
{ok, Db} = couch_db:open_int(DbName, [?ADMIN_CTX, sys_db]),
- FunAcc = {fun ?MODULE:changes_handler/3, State},
+ FunAcc = {fun ?MODULE:changes_handler/3, ChangesState},
(couch_changes:handle_db_changes(
#changes_args{feed="continuous", timeout=infinity},
{json_req, null},
@@ -128,8 +128,8 @@ init_changes_handler(#state{db_name=DbName} = State) ->
end.
-type db_change() :: {atom(), tuple(), binary()}.
--spec changes_handler(Change :: db_change(), ResultType :: any(), State :: #state{}) -> #state{}.
-changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName}) ->
+-spec changes_handler(Change :: db_change(), ResultType :: any(), ChangesState :: #changes_state{}) -> #changes_state{}.
+changes_handler({change, {Doc}, _Prepend}, _ResType, ChangesState=#changes_state{db_name=DbName}) ->
% couch_log:debug("peruser: changes_handler() on DbName/Doc ~p/~p", [DbName, Doc]),
case couch_util:get_value(<<"id">>, Doc) of
@@ -140,26 +140,26 @@ changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{db_name=DbName
false ->
UserDb = ensure_user_db(User),
ok = ensure_security(User, UserDb, fun add_user/3),
- State;
+ ChangesState;
true ->
- case State#state.delete_dbs of
+ case ChangesState#changes_state.delete_dbs of
true ->
_UserDb = delete_user_db(User),
- State;
+ ChangesState;
false ->
UserDb = user_db_name(User),
ok = ensure_security(User, UserDb, fun remove_user/3),
- State
+ ChangesState
end
end;
false ->
- State
+ ChangesState
end;
_ ->
- State
+ ChangesState
end;
-changes_handler(_Event, _ResType, State) ->
- State.
+changes_handler(_Event, _ResType, ChangesState) ->
+ ChangesState.
-spec should_handle_doc(ShardName :: binary(), DocId::binary()) -> boolean().
should_handle_doc(ShardName, DocId) ->
@@ -279,12 +279,12 @@ user_db_name(User) ->
[string:to_lower(integer_to_list(X, 16)) || <<X>> <= User]),
<<?USERDB_PREFIX,HexUser/binary>>.
--spec exit_changes(ClusterState :: #clusterState{}) -> ok.
-exit_changes(ClusterState) ->
- lists:foreach(fun (State) ->
- demonitor(State#state.changes_ref, [flush]),
- exit(State#state.changes_pid, kill)
- end, ClusterState#clusterState.states).
+-spec exit_changes(State :: #state{}) -> ok.
+exit_changes(State) ->
+ lists:foreach(fun (ChangesState) ->
+ demonitor(State#changes_state.changes_ref, [flush]),
+ exit(ChangesState#changes_state.changes_pid, kill)
+ end, State#state.states).
-spec is_stable() -> true | false.
is_stable() ->
@@ -305,26 +305,26 @@ cluster_stable(Server) ->
Server.
%% gen_server callbacks
--spec init(Options :: list()) -> {ok, #clusterState{}}.
+-spec init(Options :: list()) -> {ok, #state{}}.
init([]) ->
ok = subscribe_for_changes(),
{ok, init()}.
-handle_call(is_stable, _From, #clusterState{cluster_stable = IsStable} = State) ->
+handle_call(is_stable, _From, #state{cluster_stable = IsStable} = State) ->
{reply, IsStable, State};
handle_call(_Msg, _From, State) ->
{reply, error, State}.
-handle_cast(update_config, ClusterState) when ClusterState#clusterState.states =/= undefined ->
- exit_changes(ClusterState),
+handle_cast(update_config, State) when State#state.states =/= undefined ->
+ exit_changes(State),
{noreply, init()};
handle_cast(update_config, _) ->
{noreply, init()};
handle_cast(stop, State) ->
{stop, normal, State};
-handle_cast(cluster_unstable, ClusterState) when ClusterState#clusterState.states =/= undefined ->
- exit_changes(ClusterState),
+handle_cast(cluster_unstable, State) when State#state.states =/= undefined ->
+ exit_changes(State),
{noreply, init()};
handle_cast(cluster_unstable, _) ->
{noreply, init()};
@@ -333,7 +333,7 @@ handle_cast(cluster_stable, State) ->
handle_cast(_Msg, State) ->
{noreply, State}.
-handle_info({'DOWN', Ref, _, _, _Reason}, #state{changes_ref=Ref} = State) ->
+handle_info({'DOWN', Ref, _, _, _Reason}, #changes_state{changes_ref=Ref} = State) ->
{stop, normal, State};
handle_info({config_change, "couch_peruser", _, _, _}, State) ->
handle_cast(update_config, State);
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 20/25: unlink changes listeners before exiting them so we
survive
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 4847c02a743478b39e37f1f6182ab7476860ec31
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 21:26:19 2017 +0200
unlink changes listeners before exiting them so we survive
---
src/couch_peruser/src/couch_peruser.erl | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index c5110da..2493387 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -283,6 +283,7 @@ user_db_name(User) ->
exit_changes(State) ->
lists:foreach(fun (ChangesState) ->
demonitor(State#changes_state.changes_ref, [flush]),
+ unlink(ChangesState#changes_state.changes_pid),
exit(ChangesState#changes_state.changes_pid, kill)
end, State#state.states).
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 23/25: fix state
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 96efbfffd4414fb7776542338daf9c92453aca5f
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Tue Oct 10 10:52:09 2017 +0200
fix state
---
src/couch_peruser/src/couch_peruser.erl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index 23def43..8394db5 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -343,7 +343,7 @@ handle_cast(cluster_stable, State) ->
handle_cast(_Msg, State) ->
{noreply, State}.
-handle_info({'DOWN', Ref, _, _, _Reason}, #changes_state{changes_ref=Ref} = State) ->
+handle_info({'DOWN', _Ref, _, _, _Reason}, State) ->
{stop, normal, State};
handle_info({config_change, "couch_peruser", _, _, _}, State) ->
handle_cast(update_config, State);
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 16/25: move function declaration around for internal
consistency
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 3ed4838f3065164cac73d9b95b561dc32a4ea529
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 08:12:01 2017 +0200
move function declaration around for internal consistency
---
src/couch_peruser/src/couch_peruser.erl | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index f820fe6..7943a9c 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -290,6 +290,13 @@ exit_changes(State) ->
is_stable() ->
gen_server:call(?MODULE, is_stable).
+-spec subscribe_for_changes() -> ok.
+subscribe_for_changes() ->
+ config:subscribe_for_changes([
+ {"couch_httpd_auth", "authentication_db"},
+ "couch_peruser"
+ ]).
+
% Mem3 cluster callbacks
% TODO: find out what type Server is
@@ -351,13 +358,6 @@ handle_info(restart_config_listener, State) ->
handle_info(_Msg, State) ->
{noreply, State}.
--spec subscribe_for_changes() -> ok.
-subscribe_for_changes() ->
- config:subscribe_for_changes([
- {"couch_httpd_auth", "authentication_db"},
- "couch_peruser"
- ]).
-
terminate(_Reason, _State) ->
%% Everything should be linked or monitored, let nature
%% take its course.
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 12/25: add registered modules
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 90d49349c3f794010a1da06751d2db9c0bf25964
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Mon Oct 9 07:55:27 2017 +0200
add registered modules
---
src/couch_peruser/src/couch_peruser.app.src | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/couch_peruser/src/couch_peruser.app.src b/src/couch_peruser/src/couch_peruser.app.src
index f7c5134..6cfaf44 100644
--- a/src/couch_peruser/src/couch_peruser.app.src
+++ b/src/couch_peruser/src/couch_peruser.app.src
@@ -13,7 +13,7 @@
{application, couch_peruser, [
{description, "couch_peruser - maintains per-user databases in CouchDB"},
{vsn, git},
- {registered, []},
+ {registered, [couch_peruser, couch_peruser_sup]},
{applications, [kernel, stdlib, config, couch, fabric, mem3]},
{mod, {couch_peruser_app, []}},
{env, []}
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 22/25: fix style
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 28b400dcfa664b48f090ed455c7e678e562bc1d2
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Tue Oct 10 10:49:24 2017 +0200
fix style
---
src/couch_peruser/src/couch_peruser.erl | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index f130e13..23def43 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -98,9 +98,11 @@ start_listening(#state{db_name=DbName, delete_dbs=DeleteDbs} = State) ->
% couch_log:debug("peruser: start_listening() on node ~p", [node()]),
try
States = lists:map(fun (A) ->
- S = #changes_state{parent = State#state.parent,
- db_name = A#shard.name,
- delete_dbs = DeleteDbs},
+ S = #changes_state{
+ parent = State#state.parent,
+ db_name = A#shard.name,
+ delete_dbs = DeleteDbs
+ },
{Pid, Ref} = spawn_opt(
?MODULE, init_changes_handler, [S], [link, monitor]),
S#changes_state{changes_pid=Pid, changes_ref=Ref}
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 01/25: Make couch_peruser a proper Erlang app
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 2f49de81c8f85d8ab34483c524e71e092de542c5
Author: Russell Branca <ch...@apache.org>
AuthorDate: Thu Aug 17 17:21:35 2017 +0000
Make couch_peruser a proper Erlang app
---
rel/overlay/etc/default.ini | 1 -
src/couch_peruser/src/couch_peruser.app.src | 5 ++++-
...couch_peruser.app.src => couch_peruser_app.erl} | 22 +++++++++++++------
...couch_peruser.app.src => couch_peruser_sup.erl} | 25 ++++++++++++++++------
4 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index 1228535..56f9147 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -254,7 +254,6 @@ uuids={couch_uuids, start, []}
auth_cache={couch_auth_cache, start_link, []}
os_daemons={couch_os_daemons, start_link, []}
compaction_daemon={couch_compaction_daemon, start_link, []}
-couch_peruser={couch_peruser, start_link, []}
[mango]
; Set to true to disable the "index all fields" text index, which can lead
diff --git a/src/couch_peruser/src/couch_peruser.app.src b/src/couch_peruser/src/couch_peruser.app.src
index fb6d45b..777446d 100644
--- a/src/couch_peruser/src/couch_peruser.app.src
+++ b/src/couch_peruser/src/couch_peruser.app.src
@@ -14,5 +14,8 @@
{description, "couch_peruser - maintains per-user databases in CouchDB"},
{vsn, git},
{registered, []},
- {applications, [kernel, stdlib, config, couch, fabric]}
+ {applications, [kernel, stdlib, config, couch, fabric]},
+ {mod, {couch_peruser_app, []}},
+ {env, []},
+ {modules, [couch_peruser, couch_peruser_app, couch_peruser_sup]}
]}.
diff --git a/src/couch_peruser/src/couch_peruser.app.src b/src/couch_peruser/src/couch_peruser_app.erl
similarity index 65%
copy from src/couch_peruser/src/couch_peruser.app.src
copy to src/couch_peruser/src/couch_peruser_app.erl
index fb6d45b..770c082 100644
--- a/src/couch_peruser/src/couch_peruser.app.src
+++ b/src/couch_peruser/src/couch_peruser_app.erl
@@ -2,7 +2,7 @@
% 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
+% 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
@@ -10,9 +10,17 @@
% License for the specific language governing permissions and limitations under
% the License.
-{application, couch_peruser, [
- {description, "couch_peruser - maintains per-user databases in CouchDB"},
- {vsn, git},
- {registered, []},
- {applications, [kernel, stdlib, config, couch, fabric]}
-]}.
+-module(couch_peruser_app).
+
+-behaviour(application).
+
+-export([start/2, stop/1]).
+
+
+start(_Type, _StartArgs) ->
+ couch_peruser_sup:start_link().
+
+
+stop(_State) ->
+ ok.
+
diff --git a/src/couch_peruser/src/couch_peruser.app.src b/src/couch_peruser/src/couch_peruser_sup.erl
similarity index 53%
copy from src/couch_peruser/src/couch_peruser.app.src
copy to src/couch_peruser/src/couch_peruser_sup.erl
index fb6d45b..b89a363 100644
--- a/src/couch_peruser/src/couch_peruser.app.src
+++ b/src/couch_peruser/src/couch_peruser_sup.erl
@@ -2,7 +2,7 @@
% 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
+% 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
@@ -10,9 +10,20 @@
% License for the specific language governing permissions and limitations under
% the License.
-{application, couch_peruser, [
- {description, "couch_peruser - maintains per-user databases in CouchDB"},
- {vsn, git},
- {registered, []},
- {applications, [kernel, stdlib, config, couch, fabric]}
-]}.
+-module(couch_peruser_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/0, init/1]).
+
+%% Helper macro for declaring children of supervisor
+-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
+
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+
+init([]) ->
+ {ok, { {one_for_one, 5, 10}, [?CHILD(couch_peruser, worker)]}}.
+
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.
[couchdb] 24/25: whitespace and more state fixes
Posted by wo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wohali pushed a commit to branch 749-fix-couch_peruser-app-structure
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 570d6eeb0beaac3d5e86b1c70b97fa128eb1dc06
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Tue Oct 10 20:57:01 2017 +0200
whitespace and more state fixes
---
src/couch_peruser/src/couch_peruser.erl | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index 8394db5..a394659 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -74,8 +74,8 @@ init_state() ->
% set up cluster-stable listener
Period = abs(config:get_integer("couch_peruser", "cluster_quiet_period",
?DEFAULT_QUIET_PERIOD)),
- StartPeriod = abs(config:get_integer("couch_peruser", "cluster_start_period",
- ?DEFAULT_START_PERIOD)),
+ StartPeriod = abs(config:get_integer("couch_peruser",
+ "cluster_start_period", ?DEFAULT_START_PERIOD)),
{ok, Mem3Cluster} = mem3_cluster:start_link(?MODULE, self(), StartPeriod,
Period),
@@ -91,7 +91,8 @@ init_state() ->
-spec start_listening(State :: #state{}) -> #state{} | ok.
-start_listening(#state{states=ChangesStates}=State) when length(ChangesStates) > 0 ->
+start_listening(#state{states=ChangesStates}=State)
+ when length(ChangesStates) > 0 ->
% couch_log:debug("peruser: start_listening() already run on node ~p in pid ~p", [node(), self()]),
State;
start_listening(#state{db_name=DbName, delete_dbs=DeleteDbs} = State) ->
@@ -281,8 +282,8 @@ user_db_name(User) ->
[string:to_lower(integer_to_list(X, 16)) || <<X>> <= User]),
<<?USERDB_PREFIX,HexUser/binary>>.
--spec exit_changes(ChangesState :: #changes_state{}) -> ok.
-exit_changes(ChangesState) ->
+-spec exit_changes(State :: #state{}) -> ok.
+exit_changes(State) ->
lists:foreach(fun (ChangesState) ->
demonitor(ChangesState#changes_state.changes_ref, [flush]),
unlink(ChangesState#changes_state.changes_pid),
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.