diff options
-rw-r--r-- | rel/overlay/etc/default.ini | 3 | ||||
-rw-r--r-- | rel/overlay/etc/local.ini | 3 | ||||
-rw-r--r-- | src/couch_peruser/src/couch_peruser.erl | 26 | ||||
-rw-r--r-- | src/couch_peruser/test/couch_peruser_test.erl | 54 |
4 files changed, 70 insertions, 16 deletions
diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini index 0b0ab75ae..c473495fe 100644 --- a/rel/overlay/etc/default.ini +++ b/rel/overlay/etc/default.ini @@ -88,6 +88,9 @@ enable = false ; If set to true and a user is deleted, the respective database gets ; deleted as well. delete_dbs = false +; Set a default q value for peruser-created databases that is different from +; cluster / q +;q = 1 [httpd] port = {{backend_port}} diff --git a/rel/overlay/etc/local.ini b/rel/overlay/etc/local.ini index cd3080ecf..6b46f0fa1 100644 --- a/rel/overlay/etc/local.ini +++ b/rel/overlay/etc/local.ini @@ -17,6 +17,9 @@ ; If set to true and a user is deleted, the respective database gets ; deleted as well. ;delete_dbs = true +; Set a default q value for peruser-created databases that is different from +; cluster / q +;q = 1 [chttpd] ;port = 5984 diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl index 0c769324a..bbf40126c 100644 --- a/src/couch_peruser/src/couch_peruser.erl +++ b/src/couch_peruser/src/couch_peruser.erl @@ -34,7 +34,8 @@ db_name :: binary(), delete_dbs :: boolean(), changes_pid :: pid(), - changes_ref :: reference() + changes_ref :: reference(), + q_for_peruser_db :: integer() }). -record(state, { @@ -43,7 +44,8 @@ delete_dbs :: boolean(), states :: list(), mem3_cluster_pid :: pid(), - cluster_stable :: boolean() + cluster_stable :: boolean(), + q_for_peruser_db :: integer() }). -define(USERDB_PREFIX, "userdb-"). @@ -70,6 +72,8 @@ init_state() -> DbName = ?l2b(config:get( "couch_httpd_auth", "authentication_db", "_users")), DeleteDbs = config:get_boolean("couch_peruser", "delete_dbs", false), + Q = config:get_integer("couch_peruser", "q", 1), + % set up cluster-stable listener Period = abs(config:get_integer("couch_peruser", "cluster_quiet_period", @@ -85,7 +89,8 @@ init_state() -> db_name = DbName, delete_dbs = DeleteDbs, mem3_cluster_pid = Mem3Cluster, - cluster_stable = false + cluster_stable = false, + q_for_peruser_db = Q } end. @@ -95,14 +100,15 @@ 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) -> +start_listening(#state{db_name=DbName, delete_dbs=DeleteDbs, q_for_peruser_db = Q} = 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 + delete_dbs = DeleteDbs, + q_for_peruser_db = Q }, {Pid, Ref} = spawn_opt( ?MODULE, init_changes_handler, [S], [link, monitor]), @@ -138,7 +144,7 @@ init_changes_handler(#changes_state{db_name=DbName} = ChangesState) -> changes_handler( {change, {Doc}, _Prepend}, _ResType, - ChangesState=#changes_state{db_name=DbName}) -> + ChangesState=#changes_state{db_name=DbName, q_for_peruser_db = Q}) -> % couch_log:debug("peruser: changes_handler() on DbName/Doc ~p/~p", [DbName, Doc]), case couch_util:get_value(<<"id">>, Doc) of @@ -147,7 +153,7 @@ changes_handler( true -> case couch_util:get_value(<<"deleted">>, Doc, false) of false -> - UserDb = ensure_user_db(User), + UserDb = ensure_user_db(User, Q), ok = ensure_security(User, UserDb, fun add_user/3), ChangesState; true -> @@ -214,13 +220,13 @@ delete_user_db(User) -> end, UserDb. --spec ensure_user_db(User :: binary()) -> binary(). -ensure_user_db(User) -> +-spec ensure_user_db(User :: binary(), Q :: integer()) -> binary(). +ensure_user_db(User, Q) -> UserDb = user_db_name(User), try {ok, _DbInfo} = fabric:get_db_info(UserDb) catch error:database_does_not_exist -> - case fabric:create_db(UserDb, [?ADMIN_CTX]) of + case fabric:create_db(UserDb, [?ADMIN_CTX, {q, integer_to_list(Q)}]) of {error, file_exists} -> ok; ok -> ok; accepted -> ok diff --git a/src/couch_peruser/test/couch_peruser_test.erl b/src/couch_peruser/test/couch_peruser_test.erl index 2bc98af66..04ef2ea90 100644 --- a/src/couch_peruser/test/couch_peruser_test.erl +++ b/src/couch_peruser/test/couch_peruser_test.erl @@ -66,6 +66,11 @@ set_config(Section, Key, Value) -> get_base_url(), "/_config/", Section, "/", Key]), do_request(put, Url, "\"" ++ Value ++ "\""). +delete_config(Section, Key, Value) -> + Url = lists:concat([ + get_base_url(), "/_config/", Section, "/", Key]), + do_request(delete, Url, "\"" ++ Value ++ "\""). + do_request(Method, Url) -> Headers = [{basic_auth, {?ADMIN_USERNAME, ?ADMIN_PASSWORD}}], {ok, _, _, _} = test_request:request(Method, Url, Headers). @@ -141,15 +146,50 @@ get_cluster_base_url() -> "http://" ++ Addr ++ ":" ++ Port. -should_create_user_db(TestAuthDb) -> +should_create_user_db_with_default(TestAuthDb) -> + create_user(TestAuthDb, "foo"), + wait_for_db_create(<<"userdb-666f6f">>), + {ok, DbInfo} = fabric:get_db_info(<<"userdb-666f6f">>), + {ClusterInfo} = couch_util:get_value(cluster, DbInfo), + [ + ?_assert(lists:member(<<"userdb-666f6f">>, all_dbs())), + ?_assertEqual(1, couch_util:get_value(q, ClusterInfo)) + ]. + +should_create_anon_user_db_with_default(TestAuthDb) -> + create_anon_user(TestAuthDb, "fooo"), + wait_for_db_create(<<"userdb-666f6f6f">>), + {ok, DbInfo} = fabric:get_db_info(<<"userdb-666f6f6f">>), + {ClusterInfo} = couch_util:get_value(cluster, DbInfo), + [ + ?_assert(lists:member(<<"userdb-666f6f6f">>, all_dbs())), + ?_assertEqual(1, couch_util:get_value(q, ClusterInfo)) + ]. + +should_create_user_db_with_q4(TestAuthDb) -> + set_config("couch_peruser", "q", "4"), create_user(TestAuthDb, "foo"), wait_for_db_create(<<"userdb-666f6f">>), - ?_assert(lists:member(<<"userdb-666f6f">>, all_dbs())). + {ok, DbInfo} = fabric:get_db_info(<<"userdb-666f6f">>), + {ClusterInfo} = couch_util:get_value(cluster, DbInfo), + delete_config("couch_peruser", "q", "4"), -should_create_anon_user_db(TestAuthDb) -> + [ + ?_assert(lists:member(<<"userdb-666f6f">>, all_dbs())), + ?_assertEqual(4, couch_util:get_value(q, ClusterInfo)) + ]. + +should_create_anon_user_db_with_q4(TestAuthDb) -> + set_config("couch_peruser", "q", "4"), create_anon_user(TestAuthDb, "fooo"), wait_for_db_create(<<"userdb-666f6f6f">>), - ?_assert(lists:member(<<"userdb-666f6f6f">>, all_dbs())). + {ok, TargetInfo} = fabric:get_db_info(<<"userdb-666f6f6f">>), + {ClusterInfo} = couch_util:get_value(cluster, TargetInfo), + delete_config("couch_peruser", "q", "4"), + [ + ?_assert(lists:member(<<"userdb-666f6f6f">>, all_dbs())), + ?_assertEqual(4, couch_util:get_value(q, ClusterInfo)) + ]. should_not_delete_user_db(TestAuthDb) -> User = "foo", @@ -381,8 +421,10 @@ couch_peruser_test_() -> foreach, fun setup/0, fun teardown/1, [ - fun should_create_anon_user_db/1, - fun should_create_user_db/1, + fun should_create_anon_user_db_with_default/1, + fun should_create_user_db_with_default/1, + fun should_create_user_db_with_q4/1, + fun should_create_anon_user_db_with_q4/1, fun should_not_delete_user_db/1, fun should_delete_user_db/1, fun should_reflect_config_changes/1, |