| 611 | } |
| 612 | |
| 613 | void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc) { |
| 614 | sds buf = sdsempty(); |
| 615 | /* The DB this command was targeting is not the same as the last command |
| 616 | * we appended. To issue a SELECT command is needed. */ |
| 617 | if (dictid != server.aof_selected_db) { |
| 618 | char seldb[64]; |
| 619 | |
| 620 | snprintf(seldb,sizeof(seldb),"%d",dictid); |
| 621 | buf = sdscatprintf(buf,"*2\r\n$6\r\nSELECT\r\n$%lu\r\n%s\r\n", |
| 622 | (unsigned long)strlen(seldb),seldb); |
| 623 | server.aof_selected_db = dictid; |
| 624 | } |
| 625 | |
| 626 | if (cmd->proc == expireCommand || cmd->proc == pexpireCommand || |
| 627 | cmd->proc == expireatCommand) { |
| 628 | /* Translate EXPIRE/PEXPIRE/EXPIREAT into PEXPIREAT */ |
| 629 | buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]); |
| 630 | } else if (cmd->proc == setCommand && argc > 3) { |
| 631 | robj *pxarg = NULL; |
| 632 | /* When SET is used with EX/PX argument setGenericCommand propagates them with PX millisecond argument. |
| 633 | * So since the command arguments are re-written there, we can rely here on the index of PX being 3. */ |
| 634 | if (!strcasecmp(argv[3]->ptr, "px")) { |
| 635 | pxarg = argv[4]; |
| 636 | } |
| 637 | /* For AOF we convert SET key value relative time in milliseconds to SET key value absolute time in |
| 638 | * millisecond. Whenever the condition is true it implies that original SET has been transformed |
| 639 | * to SET PX with millisecond time argument so we do not need to worry about unit here.*/ |
| 640 | if (pxarg) { |
| 641 | robj *millisecond = getDecodedObject(pxarg); |
| 642 | long long when = strtoll(millisecond->ptr,NULL,10); |
| 643 | when += mstime(); |
| 644 | |
| 645 | decrRefCount(millisecond); |
| 646 | |
| 647 | robj *newargs[5]; |
| 648 | newargs[0] = argv[0]; |
| 649 | newargs[1] = argv[1]; |
| 650 | newargs[2] = argv[2]; |
| 651 | newargs[3] = shared.pxat; |
| 652 | newargs[4] = createStringObjectFromLongLong(when); |
| 653 | buf = catAppendOnlyGenericCommand(buf,5,newargs); |
| 654 | decrRefCount(newargs[4]); |
| 655 | } else { |
| 656 | buf = catAppendOnlyGenericCommand(buf,argc,argv); |
| 657 | } |
| 658 | } else { |
| 659 | /* All the other commands don't need translation or need the |
| 660 | * same translation already operated in the command vector |
| 661 | * for the replication itself. */ |
| 662 | buf = catAppendOnlyGenericCommand(buf,argc,argv); |
| 663 | } |
| 664 | |
| 665 | /* Append to the AOF buffer. This will be flushed on disk just before |
| 666 | * of re-entering the event loop, so before the client will get a |
| 667 | * positive reply about the operation performed. */ |
| 668 | if (server.aof_state == AOF_ON) |
| 669 | server.aof_buf = sdscatlen(server.aof_buf,buf,sdslen(buf)); |
| 670 |
no test coverage detected