Skip to content

Commit 29f855a

Browse files
committed
wip: add POST /db/_max_generation
1 parent 528f5ea commit 29f855a

File tree

9 files changed

+104
-1
lines changed

9 files changed

+104
-1
lines changed

src/chttpd/src/chttpd_db.erl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,19 @@ db_req(#httpd{method = 'GET', path_parts = [_, <<"_revs_limit">>]} = Req, Db) ->
855855
send_json(Req, fabric:get_revs_limit(Db));
856856
db_req(#httpd{path_parts = [_, <<"_revs_limit">>]} = Req, _Db) ->
857857
send_method_not_allowed(Req, "PUT,GET");
858+
db_req(#httpd{method = 'PUT', path_parts = [_, <<"_max_generation">>]} = Req, Db) ->
859+
Options = [{user_ctx, Req#httpd.user_ctx}],
860+
case chttpd:json_body(Req) of
861+
MaxGen when is_integer(MaxGen), MaxGen > 0 ->
862+
case fabric:set_max_generation(Db, MaxGen, Options) of
863+
ok ->
864+
send_json(Req, {[{<<"ok">>, true}]});
865+
Error ->
866+
throw(Error)
867+
end;
868+
_ ->
869+
throw({bad_request, "`max_generation` must be positive integer"})
870+
end;
858871
db_req(#httpd{method = 'PUT', path_parts = [_, <<"_purged_infos_limit">>]} = Req, Db) ->
859872
Options = [{user_ctx, Req#httpd.user_ctx}],
860873
case chttpd:json_body(Req) of

src/couch/src/couch_bt_engine.erl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
get_uuid/1,
5050

5151
set_revs_limit/2,
52+
set_max_generation/2,
5253
set_purge_infos_limit/2,
5354
set_security/2,
5455
set_props/2,
@@ -388,6 +389,17 @@ set_revs_limit(#st{header = Header} = St, RevsLimit) ->
388389
},
389390
{ok, increment_update_seq(NewSt)}.
390391

392+
set_max_generation(#st{filepath = FilePath, gen_fds = GenFds, header = Header} = St, MaxGen) ->
393+
NewSt = St#st{
394+
header = couch_bt_engine_header:set(Header, [
395+
{max_generation, MaxGen}
396+
]),
397+
needs_commit = true
398+
},
399+
GenFds1 = open_missing_generation_files(FilePath, GenFds, MaxGen),
400+
NewSt1 = NewSt#st{gen_fds = GenFds1},
401+
{ok, increment_update_seq(NewSt1)}.
402+
391403
set_purge_infos_limit(#st{header = Header} = St, PurgeInfosLimit) ->
392404
NewSt = St#st{
393405
header = couch_bt_engine_header:set(Header, [
@@ -982,6 +994,18 @@ open_generation_files(FilePath, Generations, Options) ->
982994
lists:seq(1, Generations)
983995
).
984996

997+
open_missing_generation_files(FilePath, GenFds, MaxGen) ->
998+
open_missing_generation_files(FilePath, GenFds, MaxGen, 1).
999+
1000+
open_missing_generation_files(FilePath, GenFds, MaxGen, Gen) when Gen > MaxGen ->
1001+
GenFds;
1002+
open_missing_generation_files(FilePath, [], MaxGen, Gen) ->
1003+
Rest = open_missing_generation_files(FilePath, [], MaxGen, Gen + 1),
1004+
Fd = open_generation_file(FilePath, Gen, []),
1005+
[Fd | Rest];
1006+
open_missing_generation_files(FilePath, [Fd | Rest], MaxGen, Gen) ->
1007+
[Fd | open_missing_generation_files(FilePath, Rest, MaxGen, Gen + 1)].
1008+
9851009
maybe_open_generation_files(FilePath, Generations, Options) ->
9861010
case lists:member(compacting, Options) of
9871011
true -> [];

src/couch/src/couch_db.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
is_partitioned/1,
6464

6565
set_revs_limit/2,
66+
set_max_generation/2,
6667
set_purge_infos_limit/2,
6768
set_security/2,
6869
set_user_ctx/2,
@@ -540,6 +541,12 @@ purge_client_exists(DbName, DocId, Props) ->
540541
true
541542
end.
542543

544+
set_max_generation(#db{main_pid = Pid} = Db, MaxGen) when MaxGen > 0 ->
545+
check_is_admin(Db),
546+
gen_server:call(Pid, {set_max_generation, MaxGen}, infinity);
547+
set_max_generation(_Db, _MaxGen) ->
548+
throw(invalid_purge_infos_limit).
549+
543550
set_purge_infos_limit(#db{main_pid = Pid} = Db, Limit) when Limit > 0 ->
544551
check_is_admin(Db),
545552
gen_server:call(Pid, {set_purge_infos_limit, Limit}, infinity);

src/couch/src/couch_db_engine.erl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@
276276
-callback set_revs_limit(DbHandle :: db_handle(), RevsLimit :: pos_integer()) ->
277277
{ok, NewDbHandle :: db_handle()}.
278278

279+
-callback set_max_generation(DbHandle :: db_handle(), MaxGen :: pos_integer()) ->
280+
{ok, NewDbHandle :: db_handle()}.
281+
279282
-callback set_purge_infos_limit(DbHandle :: db_handle(), Limit :: pos_integer()) ->
280283
{ok, NewDbHandle :: db_handle()}.
281284

@@ -685,6 +688,7 @@
685688

686689
set_revs_limit/2,
687690
set_security/2,
691+
set_max_generation/2,
688692
set_purge_infos_limit/2,
689693
set_props/2,
690694

@@ -851,6 +855,11 @@ set_revs_limit(#db{} = Db, RevsLimit) ->
851855
{ok, NewSt} = Engine:set_revs_limit(EngineState, RevsLimit),
852856
{ok, Db#db{engine = {Engine, NewSt}}}.
853857

858+
set_max_generation(#db{} = Db, MaxGen) ->
859+
#db{engine = {Engine, EngineState}} = Db,
860+
{ok, NewSt} = Engine:set_max_generation(EngineState, MaxGen),
861+
{ok, Db#db{engine = {Engine, NewSt}}}.
862+
854863
set_purge_infos_limit(#db{} = Db, PurgedDocsLimit) ->
855864
#db{engine = {Engine, EngineState}} = Db,
856865
{ok, NewSt} = Engine:set_purge_infos_limit(EngineState, PurgedDocsLimit),

src/couch/src/couch_db_updater.erl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ handle_call({set_revs_limit, Limit}, _From, Db) ->
8989
Db3 = commit_data(Db2),
9090
ok = couch_server:db_updated(Db3),
9191
{reply, ok, Db3};
92+
handle_call({set_max_generation, MaxGen}, _From, Db) ->
93+
{ok, Db2} = couch_db_engine:set_max_generation(Db, MaxGen),
94+
ok = couch_server:db_updated(Db2),
95+
{reply, ok, Db2};
9296
handle_call({set_purge_infos_limit, Limit}, _From, Db) ->
9397
{ok, Db2} = couch_db_engine:set_purge_infos_limit(Db, Limit),
9498
ok = couch_server:db_updated(Db2),

src/fabric/src/fabric.erl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
get_revs_limit/1,
3030
get_security/1, get_security/2,
3131
get_all_security/1, get_all_security/2,
32+
set_max_generation/3,
3233
get_purge_infos_limit/1,
3334
set_purge_infos_limit/3,
3435
get_purged_infos/1,
@@ -185,6 +186,13 @@ set_security(DbName, SecObj) ->
185186
set_security(DbName, SecObj, Options) ->
186187
fabric_db_meta:set_security(dbname(DbName), SecObj, opts(Options)).
187188

189+
%% @doc sets the upper bound for the number of storage generations
190+
-spec set_max_generation(dbname(), pos_integer(), [option()]) -> ok.
191+
set_max_generation(DbName, MaxGen, Options) when
192+
is_integer(MaxGen), MaxGen > 0
193+
->
194+
fabric_db_meta:set_max_generation(dbname(DbName), MaxGen, opts(Options)).
195+
188196
%% @doc sets the upper bound for the number of stored purge requests
189197
-spec set_purge_infos_limit(dbname(), pos_integer(), [option()]) -> ok.
190198
set_purge_infos_limit(DbName, Limit, Options) when

src/fabric/src/fabric_db_meta.erl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
set_revs_limit/3,
1717
set_security/3,
1818
get_all_security/2,
19+
set_max_generation/3,
1920
set_purge_infos_limit/3
2021
]).
2122

@@ -51,6 +52,21 @@ handle_revs_message(ok, Worker, {Workers, Waiting}) ->
5152
handle_revs_message(Error, _, _Acc) ->
5253
{error, Error}.
5354

55+
set_max_generation(DbName, MaxGen, Options) ->
56+
Shards = mem3:shards(DbName),
57+
Workers = fabric_util:submit_jobs(Shards, set_max_generation, [MaxGen, Options]),
58+
Handler = fun handle_purge_message/3,
59+
Acc0 = {Workers, length(Workers) - 1},
60+
case fabric_util:recv(Workers, #shard.ref, Handler, Acc0) of
61+
{ok, ok} ->
62+
ok;
63+
{timeout, {DefunctWorkers, _}} ->
64+
fabric_util:log_timeout(DefunctWorkers, "set_purged_docs_limit"),
65+
{error, timeout};
66+
Error ->
67+
Error
68+
end.
69+
5470
set_purge_infos_limit(DbName, Limit, Options) ->
5571
Shards = mem3:shards(DbName),
5672
Workers = fabric_util:submit_jobs(Shards, set_purge_infos_limit, [Limit, Options]),

src/fabric/src/fabric_rpc.erl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
]).
4040
-export([get_all_security/2, open_shard/2]).
4141
-export([compact/1, compact/2]).
42-
-export([get_purge_seq/2, get_purged_infos/1, purge_docs/3, set_purge_infos_limit/3]).
42+
-export([
43+
get_purge_seq/2, get_purged_infos/1, purge_docs/3, set_max_generation/3, set_purge_infos_limit/3
44+
]).
4345

4446
-export([
4547
get_db_info/2,
@@ -259,6 +261,9 @@ get_all_security(DbName, Options) ->
259261
set_revs_limit(DbName, Limit, Options) ->
260262
with_db(DbName, Options, {couch_db, set_revs_limit, [Limit]}).
261263

264+
set_max_generation(DbName, MaxGen, Options) ->
265+
with_db(DbName, Options, {couch_db, set_max_generation, [MaxGen]}).
266+
262267
set_purge_infos_limit(DbName, Limit, Options) ->
263268
with_db(DbName, Options, {couch_db, set_purge_infos_limit, [Limit]}).
264269

t.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,23 @@ test_doc_with_att_compact () {
2020
check-files 'OBVIOUS ATTACHMENT' 0 1
2121
}
2222

23+
test_max_gen_upgrade () {
24+
create-db 0
25+
26+
create-doc 'the-doc' '{ "basic": "DOC BODY" }'
27+
add-att 'the-doc' 'the-att' 'VERY OBVIOUS ATTACHMENT DATA'
28+
compact 0
29+
30+
check-files 'DOC BODY' 1
31+
check-files 'OBVIOUS ATTACHMENT' 1
32+
33+
cdb '/asd/_max_generation' -X PUT -d '2'
34+
compact 0
35+
36+
check-files 'DOC BODY' 0 1
37+
check-files 'OBVIOUS ATTACHMENT' 0 1
38+
}
39+
2340
test_doc_compact_add_att () {
2441
create-doc 'the-doc' '{ "basic": "DOC BODY" }'
2542
compact 0

0 commit comments

Comments
 (0)