summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjiangphcn <jiangph@cn.ibm.com>2017-11-30 11:58:08 +0800
committerJan Lehnardt <jan@apache.org>2017-12-08 15:46:18 +0100
commitac7a00cd9f654825e4a3bb39b7a07871598ecef6 (patch)
tree414de852d49bffe9386f6102763891628d96ea61
parent6fce0fe102f9b033aa1b1e606b66da71ef51d0f4 (diff)
downloadcouchdb-ac7a00cd9f654825e4a3bb39b7a07871598ecef6.tar.gz
Make q configurable for peruser dbs
issue 875
-rw-r--r--rel/overlay/etc/default.ini3
-rw-r--r--rel/overlay/etc/local.ini3
-rw-r--r--src/couch_peruser/src/couch_peruser.erl26
-rw-r--r--src/couch_peruser/test/couch_peruser_test.erl54
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,