MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / getexCommand

Function getexCommand

src/t_string.cpp:331–405  ·  view source on GitHub ↗

* GETEX [PERSIST][EX seconds][PX milliseconds][EXAT seconds-timestamp][PXAT milliseconds-timestamp] * * The getexCommand() function implements extended options and variants of the GET command. Unlike GET * command this command is not read-only. * * The default behavior when no options are specified is same as GET and does not alter any TTL. * * Only one of the below options can be use

Source from the content-addressed store, hash-verified

329 * Command would either return the bulk string, error or nil.
330 */
331void getexCommand(client *c) {
332 robj *expire = NULL;
333 int unit = UNIT_SECONDS;
334 int flags = OBJ_NO_FLAGS;
335
336 if (parseExtendedStringArgumentsOrReply(c,&flags,&unit,&expire,COMMAND_GET) != C_OK) {
337 return;
338 }
339
340 robj_roptr o;
341
342 if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == nullptr)
343 return;
344
345 if (checkType(c,o,OBJ_STRING)) {
346 return;
347 }
348
349 long long milliseconds = 0, when = 0;
350
351 /* Validate the expiration time value first */
352 if (expire) {
353 if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != C_OK)
354 return;
355 if (milliseconds <= 0 || (unit == UNIT_SECONDS && milliseconds > LLONG_MAX / 1000)) {
356 /* Negative value provided or multiplication is gonna overflow. */
357 addReplyErrorFormat(c, "invalid expire time in %s", c->cmd->name);
358 return;
359 }
360 if (unit == UNIT_SECONDS) milliseconds *= 1000;
361 when = milliseconds;
362 if ((flags & OBJ_PX) || (flags & OBJ_EX))
363 when += mstime();
364 if (when <= 0) {
365 /* Overflow detected. */
366 addReplyErrorFormat(c, "invalid expire time in %s", c->cmd->name);
367 return;
368 }
369 }
370
371 /* We need to do this before we expire the key or delete it */
372 addReplyBulk(c,o);
373
374 /* This command is never propagated as is. It is either propagated as PEXPIRE[AT],DEL,UNLINK or PERSIST.
375 * This why it doesn't need special handling in feedAppendOnlyFile to convert relative expire time to absolute one. */
376 if (((flags & OBJ_PXAT) || (flags & OBJ_EXAT)) && checkAlreadyExpired(milliseconds)) {
377 /* When PXAT/EXAT absolute timestamp is specified, there can be a chance that timestamp
378 * has already elapsed so delete the key in that case. */
379 int deleted = g_pserver->lazyfree_lazy_expire ? dbAsyncDelete(c->db, c->argv[1]) :
380 dbSyncDelete(c->db, c->argv[1]);
381 serverAssert(deleted);
382 robj *aux = g_pserver->lazyfree_lazy_expire ? shared.unlink : shared.del;
383 rewriteClientCommandVector(c,2,aux,c->argv[1]);
384 signalModifiedKey(c, c->db, c->argv[1]);
385 notifyKeyspaceEvent(NOTIFY_GENERIC, "del", c->argv[1], c->db->id);
386 g_pserver->dirty++;
387 } else if (expire) {
388 setExpire(c,c->db,c->argv[1],nullptr,when);

Callers

nothing calls this directly

Calls 15

lookupKeyReadOrReplyFunction · 0.85
checkTypeFunction · 0.85
addReplyErrorFormatFunction · 0.85
addReplyBulkFunction · 0.85
checkAlreadyExpiredFunction · 0.85
dbAsyncDeleteFunction · 0.85
dbSyncDeleteFunction · 0.85
signalModifiedKeyFunction · 0.85
notifyKeyspaceEventFunction · 0.85

Tested by

no test coverage detected