summaryrefslogtreecommitdiff
path: root/src/networking.c
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2020-02-21 16:39:42 +0100
committerantirez <antirez@gmail.com>2020-02-24 19:09:45 +0100
commitb6378edcd684fb8194861fbc7506614f987afc78 (patch)
tree31deeba5c9b66cb925db4247c01464087e1da519 /src/networking.c
parent8a14fff545eec4f00000be32ea2cc9d49aedfec1 (diff)
downloadredis-b6378edcd684fb8194861fbc7506614f987afc78.tar.gz
Tracking: optin/out implemented.
Diffstat (limited to 'src/networking.c')
-rw-r--r--src/networking.c65
1 files changed, 58 insertions, 7 deletions
diff --git a/src/networking.c b/src/networking.c
index 5b1229fde..4c394af70 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -1365,6 +1365,12 @@ void resetClient(client *c) {
if (!(c->flags & CLIENT_MULTI) && prevcmd != askingCommand)
c->flags &= ~CLIENT_ASKING;
+ /* We do the same for the CACHING command as well. It also affects
+ * the next command or transaction executed, in a way very similar
+ * to ASKING. */
+ if (!(c->flags & CLIENT_MULTI) && prevcmd != clientCommand)
+ c->flags &= ~CLIENT_TRACKING_CACHING;
+
/* Remove the CLIENT_REPLY_SKIP flag if any so that the reply
* to the next command will be sent, but set the flag if the command
* we just processed was "CLIENT REPLY SKIP". */
@@ -2044,7 +2050,7 @@ void clientCommand(client *c) {
"REPLY (on|off|skip) -- Control the replies sent to the current connection.",
"SETNAME <name> -- Assign the name <name> to the current connection.",
"UNBLOCK <clientid> [TIMEOUT|ERROR] -- Unblock the specified blocked client.",
-"TRACKING (on|off) [REDIRECT <id>] [BCAST] [PREFIX first] [PREFIX second] ... -- Enable client keys tracking for client side caching.",
+"TRACKING (on|off) [REDIRECT <id>] [BCAST] [PREFIX first] [PREFIX second] [OPTIN] [OPTOUT]... -- Enable client keys tracking for client side caching.",
"GETREDIR -- Return the client ID we are redirecting to when tracking is enabled.",
NULL
};
@@ -2221,9 +2227,9 @@ NULL
addReply(c,shared.ok);
} else if (!strcasecmp(c->argv[1]->ptr,"tracking") && c->argc >= 3) {
/* CLIENT TRACKING (on|off) [REDIRECT <id>] [BCAST] [PREFIX first]
- * [PREFIX second] ... */
+ * [PREFIX second] [OPTIN] [OPTOUT] ... */
long long redir = 0;
- int bcast = 0;
+ uint64_t options = 0;
robj **prefix = NULL;
size_t numprefix = 0;
@@ -2256,7 +2262,11 @@ NULL
return;
}
} else if (!strcasecmp(c->argv[j]->ptr,"bcast")) {
- bcast = 1;
+ options |= CLIENT_TRACKING_BCAST;
+ } else if (!strcasecmp(c->argv[j]->ptr,"optin")) {
+ options |= CLIENT_TRACKING_OPTIN;
+ } else if (!strcasecmp(c->argv[j]->ptr,"optout")) {
+ options |= CLIENT_TRACKING_OPTOUT;
} else if (!strcasecmp(c->argv[j]->ptr,"prefix") && moreargs) {
j++;
prefix = zrealloc(prefix,sizeof(robj*)*(numprefix+1));
@@ -2272,7 +2282,7 @@ NULL
if (!strcasecmp(c->argv[2]->ptr,"on")) {
/* Before enabling tracking, make sure options are compatible
* among each other and with the current state of the client. */
- if (!bcast && numprefix) {
+ if (!(options & CLIENT_TRACKING_BCAST) && numprefix) {
addReplyError(c,
"PREFIX option requires BCAST mode to be enabled");
zfree(prefix);
@@ -2281,7 +2291,8 @@ NULL
if (c->flags & CLIENT_TRACKING) {
int oldbcast = !!(c->flags & CLIENT_TRACKING_BCAST);
- if (oldbcast != bcast) {
+ int newbcast = !!(options & CLIENT_TRACKING_BCAST);
+ if (oldbcast != newbcast) {
addReplyError(c,
"You can't switch BCAST mode on/off before disabling "
"tracking for this client, and then re-enabling it with "
@@ -2290,7 +2301,17 @@ NULL
return;
}
}
- enableTracking(c,redir,bcast,prefix,numprefix);
+
+ if (options & CLIENT_TRACKING_BCAST &&
+ options & (CLIENT_TRACKING_OPTIN|CLIENT_TRACKING_OPTOUT))
+ {
+ addReplyError(c,
+ "OPTIN and OPTOUT are not compatible with BCAST");
+ zfree(prefix);
+ return;
+ }
+
+ enableTracking(c,redir,options,prefix,numprefix);
} else if (!strcasecmp(c->argv[2]->ptr,"off")) {
disableTracking(c);
} else {
@@ -2300,6 +2321,36 @@ NULL
}
zfree(prefix);
addReply(c,shared.ok);
+ } else if (!strcasecmp(c->argv[1]->ptr,"caching") && c->argc >= 3) {
+ if (!(c->flags & CLIENT_TRACKING)) {
+ addReplyError(c,"CLIENT CACHING can be called only when the "
+ "client is in tracking mode with OPTIN or "
+ "OPTOUT mode enabled");
+ return;
+ }
+
+ char *opt = c->argv[2]->ptr;
+ if (!strcasecmp(opt,"yes")) {
+ if (c->flags & CLIENT_TRACKING_OPTIN) {
+ c->flags |= CLIENT_TRACKING_CACHING;
+ } else {
+ addReplyError(c,"CLIENT CACHING YES is only valid when tracking is enabled in OPTIN mode.");
+ return;
+ }
+ } else if (!strcasecmp(opt,"no")) {
+ if (c->flags & CLIENT_TRACKING_OPTOUT) {
+ c->flags |= CLIENT_TRACKING_CACHING;
+ } else {
+ addReplyError(c,"CLIENT CACHING NO is only valid when tracking is enabled in OPTOUT mode.");
+ return;
+ }
+ } else {
+ addReply(c,shared.syntaxerr);
+ return;
+ }
+
+ /* Common reply for when we succeeded. */
+ addReply(c,shared.ok);
} else if (!strcasecmp(c->argv[1]->ptr,"getredir") && c->argc == 2) {
/* CLIENT GETREDIR */
if (c->flags & CLIENT_TRACKING) {