@@ -153,8 +153,9 @@ tuple<const CommandId*, absl::InlinedVector<string, 5>> GeneratePopulateCommand(
153
153
}
154
154
155
155
void DoPopulateBatch (string_view type, string_view prefix, size_t val_size, bool random_value,
156
- int32_t elements, const PopulateBatch& batch, ServerFamily* sf,
157
- ConnectionContext* cntx) {
156
+ int32_t elements,
157
+ std::optional<std::pair<uint32_t , uint32_t >> expire_ttl_range,
158
+ const PopulateBatch& batch, ServerFamily* sf, ConnectionContext* cntx) {
158
159
boost::intrusive_ptr<Transaction> local_tx =
159
160
new Transaction{sf->service ().mutable_registry ()->Find (" EXEC" )};
160
161
local_tx->StartMultiNonAtomic ();
@@ -194,6 +195,28 @@ void DoPopulateBatch(string_view type, string_view prefix, size_t val_size, bool
194
195
stub_tx->InitByArgs (cntx->ns , local_cntx.conn_state .db_index , args_span);
195
196
196
197
sf->service ().InvokeCmd (cid, args_span, &crb, &local_cntx);
198
+
199
+ if (expire_ttl_range.has_value ()) {
200
+ uint32_t start = expire_ttl_range->first ;
201
+ uint32_t end = expire_ttl_range->second ;
202
+ uint32_t expire_ttl = rand () % (end - start) + start;
203
+ VLOG (1 ) << " set key " << key << " expire ttl as " << expire_ttl;
204
+ auto cid = sf->service ().mutable_registry ()->Find (" EXPIRE" );
205
+ absl::InlinedVector<string, 5 > args;
206
+ args.push_back (std::move (key));
207
+ args.push_back (to_string (expire_ttl));
208
+ args_view.clear ();
209
+ for (auto & arg : args) {
210
+ args_view.push_back (arg);
211
+ }
212
+ auto args_span = absl::MakeSpan (args_view);
213
+ stub_tx->MultiSwitchCmd (cid);
214
+ local_cntx.cid = cid;
215
+ crb.SetReplyMode (ReplyMode::NONE);
216
+ stub_tx->InitByArgs (cntx->ns , local_cntx.conn_state .db_index , args_span);
217
+
218
+ sf->service ().InvokeCmd (cid, args_span, &crb, &local_cntx);
219
+ }
197
220
}
198
221
}
199
222
@@ -536,7 +559,8 @@ void DebugCmd::Run(CmdArgList args, facade::SinkReplyBuilder* builder) {
536
559
" Return sync id and array of number of journal commands executed for each replica flow" ,
537
560
" WATCHED" ,
538
561
" Shows the watched keys as a result of BLPOP and similar operations." ,
539
- " POPULATE <count> [prefix] [size] [RAND] [SLOTS start end] [TYPE type] [ELEMENTS elements]" ,
562
+ " POPULATE <count> [prefix] [size] [RAND] [SLOTS start end] [TYPE type] [ELEMENTS elements]"
563
+ " [EXPIRE start end]" ,
540
564
" Create <count> string keys named key:<num> with value value:<num>." ,
541
565
" If <prefix> is specified then it is used instead of the 'key' prefix." ,
542
566
" If <size> is specified then X character is concatenated multiple times to value:<num>" ,
@@ -545,6 +569,7 @@ void DebugCmd::Run(CmdArgList args, facade::SinkReplyBuilder* builder) {
545
569
" If SLOTS is specified then create keys only in given slots range." ,
546
570
" TYPE specifies data type (must be STRING/LIST/SET/HASH/ZSET/JSON), default STRING." ,
547
571
" ELEMENTS specifies how many sub elements if relevant (like entries in a list / set)." ,
572
+ " EXPIRE specifies key expire ttl range." ,
548
573
" OBJHIST" ,
549
574
" Prints histogram of object sizes." ,
550
575
" STACKTRACE" ,
@@ -729,6 +754,9 @@ void DebugCmd::Migration(CmdArgList args, facade::SinkReplyBuilder* builder) {
729
754
return builder->SendError (UnknownSubCmd (" MIGRATION" , " DEBUG" ));
730
755
}
731
756
757
+ // Populate arguments format:
758
+ // required: (total count) (key prefix) (val size)
759
+ // optional: [RAND | TYPE typename | ELEMENTS element num | SLOTS (key value)+ | EXPIRE start end]
732
760
optional<DebugCmd::PopulateOptions> DebugCmd::ParsePopulateArgs (CmdArgList args,
733
761
facade::SinkReplyBuilder* builder) {
734
762
if (args.size () < 2 ) {
@@ -802,7 +830,25 @@ optional<DebugCmd::PopulateOptions> DebugCmd::ParsePopulateArgs(CmdArgList args,
802
830
}
803
831
options.slot_range = cluster::SlotRange{.start = static_cast <SlotId>(start.value ()),
804
832
.end = static_cast <SlotId>(end.value ())};
805
-
833
+ } else if (str == " EXPIRE" ) {
834
+ if (args.size () < index + 3 ) {
835
+ builder->SendError (kSyntaxErr );
836
+ return nullopt ;
837
+ }
838
+ uint32_t start, end;
839
+ if (!absl::SimpleAtoi (ArgS (args, ++index), &start)) {
840
+ builder->SendError (kSyntaxErr );
841
+ return nullopt ;
842
+ }
843
+ if (!absl::SimpleAtoi (ArgS (args, ++index), &end)) {
844
+ builder->SendError (kSyntaxErr );
845
+ return nullopt ;
846
+ }
847
+ if (start >= end) {
848
+ builder->SendError (kExpiryOutOfRange );
849
+ return nullopt ;
850
+ }
851
+ options.expire_ttl_range = std::make_pair (start, end);
806
852
} else {
807
853
builder->SendError (kSyntaxErr );
808
854
return nullopt ;
@@ -889,7 +935,8 @@ void DebugCmd::PopulateRangeFiber(uint64_t from, uint64_t num_of_keys,
889
935
if (shard_batch.sz == 32 ) {
890
936
ess.Add (sid, [this , index, options, shard_batch] {
891
937
DoPopulateBatch (options.type , options.prefix , options.val_size ,
892
- options.populate_random_values , options.elements , shard_batch, &sf_, cntx_);
938
+ options.populate_random_values , options.elements , options.expire_ttl_range ,
939
+ shard_batch, &sf_, cntx_);
893
940
if (index % 50 == 0 ) {
894
941
ThisFiber::Yield ();
895
942
}
@@ -902,7 +949,7 @@ void DebugCmd::PopulateRangeFiber(uint64_t from, uint64_t num_of_keys,
902
949
903
950
ess.AwaitRunningOnShardQueue ([&](EngineShard* shard) {
904
951
DoPopulateBatch (options.type , options.prefix , options.val_size , options.populate_random_values ,
905
- options.elements , ps[shard->shard_id ()], &sf_, cntx_);
952
+ options.elements , options. expire_ttl_range , ps[shard->shard_id ()], &sf_, cntx_);
906
953
// Debug populate does not use transaction framework therefore we call OnCbFinish manually
907
954
// after running the callback
908
955
// Note that running debug populate while running flushall/db can cause dcheck fail because the
0 commit comments