@@ -270,13 +270,15 @@ void OpMSet(const OpArgs& op_args, const ShardArgs& args, atomic_bool* success)
270
270
SetCmd sg (op_args, false );
271
271
272
272
size_t index = 0 ;
273
+ bool partial = false ;
273
274
for (auto it = args.begin (); it != args.end (); ++it) {
274
275
string_view key = *it;
275
276
++it;
276
277
string_view value = *it;
277
278
DVLOG (1 ) << " MSet " << key << " :" << value;
278
279
if (sg.Set (params, key, value) != OpStatus::OK) { // OOM for example.
279
280
success->store (false );
281
+ partial = true ;
280
282
break ;
281
283
}
282
284
index += 2 ;
@@ -285,18 +287,29 @@ void OpMSet(const OpArgs& op_args, const ShardArgs& args, atomic_bool* success)
285
287
if (auto journal = op_args.shard ->journal (); journal) {
286
288
// We write a custom journal because an OOM in the above loop could lead to partial success, so
287
289
// we replicate only what was changed.
288
- string_view cmd;
289
- ArgSlice cmd_args;
290
- if (index == 0 ) {
291
- // All shards must record the tx was executed for the replica to execute it, so we send a PING
292
- // in case nothing was changed
293
- cmd = " PING" ;
290
+ if (partial) {
291
+ string_view cmd;
292
+ ArgSlice cmd_args;
293
+ vector<string_view> store_args (index);
294
+ if (index == 0 ) {
295
+ // All shards must record the tx was executed for the replica to execute it, so we send a
296
+ // PING in case nothing was changed
297
+ cmd = " PING" ;
298
+ } else {
299
+ // journal [0, i)
300
+ cmd = " MSET" ;
301
+ unsigned i = 0 ;
302
+ for (string_view arg : args) {
303
+ store_args[i++] = arg;
304
+ if (i >= store_args.size ())
305
+ break ;
306
+ }
307
+ cmd_args = absl::MakeSpan (store_args);
308
+ }
309
+ RecordJournal (op_args, cmd, cmd_args, op_args.tx ->GetUniqueShardCnt ());
294
310
} else {
295
- // journal [0, i)
296
- cmd = " MSET" ;
297
- cmd_args = ArgSlice (args.begin (), index);
311
+ RecordJournal (op_args, " MSET" , args, op_args.tx ->GetUniqueShardCnt ());
298
312
}
299
- RecordJournal (op_args, cmd, cmd_args, op_args.tx ->GetUniqueShardCnt ());
300
313
}
301
314
}
302
315
@@ -1166,16 +1179,17 @@ void StringFamily::MGet(CmdArgList args, ConnectionContext* cntx) {
1166
1179
src.storage_list ->next = res.storage_list ;
1167
1180
res.storage_list = src.storage_list ;
1168
1181
src.storage_list = nullptr ;
1169
-
1170
- for (size_t j = 0 ; j < src.resp_arr .size (); ++j) {
1171
- if (!src.resp_arr [j])
1182
+ ShardArgs shard_args = transaction->GetShardArgs (sid);
1183
+ unsigned src_indx = 0 ;
1184
+ for (auto it = shard_args.begin (); it != shard_args.end (); ++it, ++src_indx) {
1185
+ if (!src.resp_arr [src_indx])
1172
1186
continue ;
1173
1187
1174
- uint32_t indx = transaction-> ReverseArgIndex (sid, j );
1188
+ uint32_t indx = it. index ( );
1175
1189
1176
- res.resp_arr [indx] = std::move (src.resp_arr [j ]);
1190
+ res.resp_arr [indx] = std::move (src.resp_arr [src_indx ]);
1177
1191
if (cntx->protocol () == Protocol::MEMCACHE) {
1178
- res.resp_arr [indx]->key = ArgS (args, indx) ;
1192
+ res.resp_arr [indx]->key = *it ;
1179
1193
}
1180
1194
}
1181
1195
}
@@ -1491,9 +1505,7 @@ void StringFamily::Register(CommandRegistry* registry) {
1491
1505
<< CI{" GETEX" , CO::WRITE | CO::DENYOOM | CO::FAST | CO::NO_AUTOJOURNAL, -1 , 1 , 1 , acl::kGetEx }
1492
1506
.HFUNC (GetEx)
1493
1507
<< CI{" GETSET" , CO::WRITE | CO::DENYOOM | CO::FAST, 3 , 1 , 1 , acl::kGetSet }.HFUNC (GetSet)
1494
- << CI{" MGET" , CO::READONLY | CO::FAST | CO::REVERSE_MAPPING | CO::IDEMPOTENT, -2 , 1 , -1 ,
1495
- acl::kMGet }
1496
- .HFUNC (MGet)
1508
+ << CI{" MGET" , CO::READONLY | CO::FAST | CO::IDEMPOTENT, -2 , 1 , -1 , acl::kMGet }.HFUNC (MGet)
1497
1509
<< CI{" MSET" , kMSetMask , -3 , 1 , -1 , acl::kMSet }.HFUNC (MSet)
1498
1510
<< CI{" MSETNX" , kMSetMask , -3 , 1 , -1 , acl::kMSetNx }.HFUNC (MSetNx)
1499
1511
<< CI{" STRLEN" , CO::READONLY | CO::FAST, 2 , 1 , 1 , acl::kStrLen }.HFUNC (StrLen)
0 commit comments