diff options
author | Joan Touzet <wohali@users.noreply.github.com> | 2019-01-18 15:16:19 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-18 15:16:19 -0500 |
commit | 6cb050610abde7a822d340b2652cba36b4f2b287 (patch) | |
tree | b54b2694f74ed5d47879687270c40f9714c8597e | |
parent | 8d2af71f2896d5f75ceb0f780993493fcecdf49d (diff) | |
download | couchdb-6cb050610abde7a822d340b2652cba36b4f2b287.tar.gz |
Add new /{db}/_sync_shards endpoint (admin-only) (#1811)
This server admin-only endpoint forces an n-way sync of all shards
across all nodes on which they are hosted.
This can be useful for an administrator adding a new node to the
cluster, after updating _dbs so that the new node hosts an existing db
with content, to force the new node to sync all of that db's shards.
Users may want to bump their `[mem3] sync_concurrency` value to a
larger figure for the duration of the shards sync.
Closes #1807
-rw-r--r-- | src/chttpd/src/chttpd_auth_request.erl | 2 | ||||
-rw-r--r-- | src/mem3/src/mem3_httpd.erl | 20 | ||||
-rw-r--r-- | src/mem3/src/mem3_httpd_handlers.erl | 1 |
3 files changed, 22 insertions, 1 deletions
diff --git a/src/chttpd/src/chttpd_auth_request.erl b/src/chttpd/src/chttpd_auth_request.erl index 9110ed6bc..f85eb9722 100644 --- a/src/chttpd/src/chttpd_auth_request.erl +++ b/src/chttpd/src/chttpd_auth_request.erl @@ -70,6 +70,8 @@ authorize_request_int(#httpd{path_parts=[_DbName, <<"_compact">>|_]}=Req) -> require_db_admin(Req); authorize_request_int(#httpd{path_parts=[_DbName, <<"_view_cleanup">>]}=Req) -> require_db_admin(Req); +authorize_request_int(#httpd{path_parts=[_DbName, <<"_sync_shards">>]}=Req) -> + require_admin(Req); authorize_request_int(#httpd{path_parts=[_DbName|_]}=Req) -> db_authorization_check(Req). diff --git a/src/mem3/src/mem3_httpd.erl b/src/mem3/src/mem3_httpd.erl index 571f06370..c922141b1 100644 --- a/src/mem3/src/mem3_httpd.erl +++ b/src/mem3/src/mem3_httpd.erl @@ -12,7 +12,8 @@ -module(mem3_httpd). --export([handle_membership_req/1, handle_shards_req/2]). +-export([handle_membership_req/1, handle_shards_req/2, + handle_sync_req/2]). %% includes -include_lib("mem3/include/mem3.hrl"). @@ -52,6 +53,16 @@ handle_shards_req(#httpd{path_parts=[_DbName, <<"_shards">>]}=Req, _Db) -> handle_shards_req(#httpd{path_parts=[_DbName, <<"_shards">>, _DocId]}=Req, _Db) -> chttpd:send_method_not_allowed(Req, "GET"). +handle_sync_req(#httpd{method='POST', + path_parts=[_DbName, <<"_sync_shards">>]} = Req, Db) -> + DbName = mem3:dbname(couch_db:name(Db)), + ShardList = [S#shard.name || S <- mem3:ushards(DbName)], + [ sync_shard(S) || S <- ShardList ], + chttpd:send_json(Req, 202, {[{ok, true}]}); +handle_sync_req(Req, _) -> + chttpd:send_method_not_allowed(Req, "POST"). + + %% %% internal %% @@ -64,3 +75,10 @@ json_shards([#shard{node=Node, range=[B,E]} | Rest], AccIn) -> HexEnd = couch_util:to_hex(<<E:32/integer>>), Range = list_to_binary(HexBeg ++ "-" ++ HexEnd), json_shards(Rest, dict:append(Range, Node, AccIn)). + +sync_shard(ShardName) -> + Shards = mem3_shards:for_shard_name(ShardName), + [rpc:call(S1#shard.node, mem3_sync, push, [S1, S2#shard.node]) || + S1 <- Shards, S2 <- Shards, S1 =/= S2], + ok. + diff --git a/src/mem3/src/mem3_httpd_handlers.erl b/src/mem3/src/mem3_httpd_handlers.erl index d8e138c15..7cbd9fe5f 100644 --- a/src/mem3/src/mem3_httpd_handlers.erl +++ b/src/mem3/src/mem3_httpd_handlers.erl @@ -18,6 +18,7 @@ url_handler(<<"_membership">>) -> fun mem3_httpd:handle_membership_req/1; url_handler(_) -> no_match. db_handler(<<"_shards">>) -> fun mem3_httpd:handle_shards_req/2; +db_handler(<<"_sync_shards">>) -> fun mem3_httpd:handle_sync_req/2; db_handler(_) -> no_match. design_handler(_) -> no_match. |