|
32 | 32 | #include "slowlog.h"
|
33 | 33 | #include "bio.h"
|
34 | 34 | #include "latency.h"
|
| 35 | +#include "rifl.h" |
35 | 36 |
|
36 | 37 | #include <time.h>
|
37 | 38 | #include <signal.h>
|
@@ -124,7 +125,7 @@ struct redisServer server; /* server global state */
|
124 | 125 | */
|
125 | 126 | struct redisCommand redisCommandTable[] = {
|
126 | 127 | {"get",getCommand,2,"rF",0,NULL,1,1,1,0,0},
|
127 |
| - {"set",setCommand,-3,"wm",0,NULL,1,1,1,0,0}, |
| 128 | + {"set",setCommand,-5,"wmO",0,NULL,1,1,1,0,0}, |
128 | 129 | {"setnx",setnxCommand,3,"wmF",0,NULL,1,1,1,0,0},
|
129 | 130 | {"setex",setexCommand,4,"wm",0,NULL,1,1,1,0,0},
|
130 | 131 | {"psetex",psetexCommand,4,"wm",0,NULL,1,1,1,0,0},
|
@@ -1446,6 +1447,8 @@ void createSharedObjects(void) {
|
1446 | 1447 | * string in string comparisons for the ZRANGEBYLEX command. */
|
1447 | 1448 | shared.minstring = createStringObject("minstring",9);
|
1448 | 1449 | shared.maxstring = createStringObject("maxstring",9);
|
| 1450 | + shared.riflDuplicate = createObject(OBJ_STRING,sdsnew("+OK (RIFL duplicate)\r\n")); |
| 1451 | + shared.riflClientIdCollision = createObject(OBJ_STRING,sdsnew("-ERR (RIFL clientId collision)\r\n")); |
1449 | 1452 | }
|
1450 | 1453 |
|
1451 | 1454 | void initServerConfig(void) {
|
@@ -2027,6 +2030,7 @@ void populateCommandTable(void) {
|
2027 | 2030 | case 'M': c->flags |= CMD_SKIP_MONITOR; break;
|
2028 | 2031 | case 'k': c->flags |= CMD_ASKING; break;
|
2029 | 2032 | case 'F': c->flags |= CMD_FAST; break;
|
| 2033 | + case 'O': c->flags |= CMD_AT_MOST_ONCE; break; |
2030 | 2034 | default: serverPanic("Unsupported command flag"); break;
|
2031 | 2035 | }
|
2032 | 2036 | f++;
|
@@ -2249,6 +2253,19 @@ void call(client *c, int flags) {
|
2249 | 2253 | /* Call the command. */
|
2250 | 2254 | dirty = server.dirty;
|
2251 | 2255 | start = ustime();
|
| 2256 | + // TODO(seojin): Add RIFL check. |
| 2257 | + if (c->cmd->flags & CMD_AT_MOST_ONCE) { |
| 2258 | + getLongLongFromObject(c->argv[c->argc-2], &c->clientId); |
| 2259 | + getLongLongFromObject(c->argv[c->argc-1], &c->requestId); |
| 2260 | + if (!riflCheckClientIdOk(c)) { |
| 2261 | + addReply(c, shared.riflClientIdCollision); |
| 2262 | + return; |
| 2263 | + } |
| 2264 | + if (riflCheckDuplicate(c->clientId, c->requestId)){ |
| 2265 | + addReply(c, shared.riflDuplicate); |
| 2266 | + return; |
| 2267 | + } |
| 2268 | + } |
2252 | 2269 | c->cmd->proc(c);
|
2253 | 2270 | duration = ustime()-start;
|
2254 | 2271 | dirty = server.dirty-dirty;
|
@@ -2752,6 +2769,7 @@ void addReplyCommand(client *c, struct redisCommand *cmd) {
|
2752 | 2769 | flagcount += addReplyCommandFlag(c,cmd,CMD_SKIP_MONITOR, "skip_monitor");
|
2753 | 2770 | flagcount += addReplyCommandFlag(c,cmd,CMD_ASKING, "asking");
|
2754 | 2771 | flagcount += addReplyCommandFlag(c,cmd,CMD_FAST, "fast");
|
| 2772 | + flagcount += addReplyCommandFlag(c,cmd,CMD_AT_MOST_ONCE, "execute_at_most_once"); |
2755 | 2773 | if (cmd->getkeys_proc) {
|
2756 | 2774 | addReplyStatus(c, "movablekeys");
|
2757 | 2775 | flagcount += 1;
|
|
0 commit comments