Given a key name, this function sends an invalidation message in the * proper channel (depending on RESP version: PubSub or Push message) and * to the proper client (in case fo redirection), in the context of the * client 'c' with tracking enabled. * * In case the 'proto' argument is non zero, the function will assume that * 'keyname' points to a buffer of 'keylen' bytes already expressed in
| 260 | * - Following a flush command, to send a single RESP NULL to indicate |
| 261 | * that all keys are now invalid. */ |
| 262 | void sendTrackingMessage(client *c, char *keyname, size_t keylen, int proto) { |
| 263 | std::unique_lock<fastlock> ul(c->lock); |
| 264 | |
| 265 | int using_redirection = 0; |
| 266 | if (c->client_tracking_redirection) { |
| 267 | client *redir = lookupClientByID(c->client_tracking_redirection); |
| 268 | if (!redir) { |
| 269 | c->flags |= CLIENT_TRACKING_BROKEN_REDIR; |
| 270 | /* We need to signal to the original connection that we |
| 271 | * are unable to send invalidation messages to the redirected |
| 272 | * connection, because the client no longer exist. */ |
| 273 | if (c->resp > 2) { |
| 274 | addReplyPushLen(c,2); |
| 275 | addReplyBulkCBuffer(c,"tracking-redir-broken",21); |
| 276 | addReplyLongLong(c,c->client_tracking_redirection); |
| 277 | } |
| 278 | return; |
| 279 | } |
| 280 | ul.unlock(); |
| 281 | ul = std::unique_lock<fastlock>(redir->lock); |
| 282 | c = redir; |
| 283 | using_redirection = 1; |
| 284 | } |
| 285 | |
| 286 | /* Only send such info for clients in RESP version 3 or more. However |
| 287 | * if redirection is active, and the connection we redirect to is |
| 288 | * in Pub/Sub mode, we can support the feature with RESP 2 as well, |
| 289 | * by sending Pub/Sub messages in the __redis__:invalidate channel. */ |
| 290 | if (c->resp > 2) { |
| 291 | addReplyPushLen(c,2); |
| 292 | addReplyBulkCBuffer(c,"invalidate",10); |
| 293 | } else if (using_redirection && c->flags & CLIENT_PUBSUB) { |
| 294 | /* We use a static object to speedup things, however we assume |
| 295 | * that addReplyPubsubMessage() will not take a reference. */ |
| 296 | addReplyPubsubMessage(c,TrackingChannelName,NULL); |
| 297 | } else { |
| 298 | /* If are here, the client is not using RESP3, nor is |
| 299 | * redirecting to another client. We can't send anything to |
| 300 | * it since RESP2 does not support push messages in the same |
| 301 | * connection. */ |
| 302 | return; |
| 303 | } |
| 304 | |
| 305 | /* Send the "value" part, which is the array of keys. */ |
| 306 | if (proto) { |
| 307 | addReplyProto(c,keyname,keylen); |
| 308 | } else { |
| 309 | addReplyArrayLen(c,1); |
| 310 | addReplyBulkCBuffer(c,keyname,keylen); |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | /* This function is called when a key is modified in Redis and in the case |
| 315 | * we have at least one client with the BCAST mode enabled. |
no test coverage detected