Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
999494ce
Unverified
Commit
999494ce
authored
Jan 08, 2021
by
Madelyn Olson
Committed by
GitHub
Jan 08, 2021
Browse files
Throw error for conflicting bcast tracking prefixes (#8176)
Throw an error if there are conflicting bcast tracking prefixes.
parent
47579bdf
Changes
4
Show whitespace changes
Inline
Side-by-side
src/networking.c
View file @
999494ce
...
...
@@ -2800,6 +2800,13 @@ NULL
return
;
}
if
(
options
&
CLIENT_TRACKING_BCAST
)
{
if
(
!
checkPrefixCollisionsOrReply
(
c
,
prefix
,
numprefix
))
{
zfree
(
prefix
);
return
;
}
}
enableTracking
(
c
,
redir
,
options
,
prefix
,
numprefix
);
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"off"
))
{
disableTracking
(
c
);
...
...
src/server.h
View file @
999494ce
...
...
@@ -1849,6 +1849,7 @@ uint64_t trackingGetTotalItems(void);
uint64_t
trackingGetTotalKeys
(
void
);
uint64_t
trackingGetTotalPrefixes
(
void
);
void
trackingBroadcastInvalidationMessages
(
void
);
int
checkPrefixCollisionsOrReply
(
client
*
c
,
robj
**
prefix
,
size_t
numprefix
);
/* List data type */
void
listTypeTryConversion
(
robj
*
subject
,
robj
*
value
);
...
...
src/tracking.c
View file @
999494ce
...
...
@@ -99,6 +99,57 @@ void disableTracking(client *c) {
}
}
static
int
stringCheckPrefix
(
unsigned
char
*
s1
,
size_t
s1_len
,
unsigned
char
*
s2
,
size_t
s2_len
)
{
size_t
min_length
=
s1_len
<
s2_len
?
s1_len
:
s2_len
;
return
memcmp
(
s1
,
s2
,
min_length
)
==
0
;
}
/* Check if any of the provided prefixes collide with one another or
* with an existing prefix for the client. A collision is defined as two
* prefixes that will emit an invalidation for the same key. If no prefix
* collision is found, 1 is return, otherwise 0 is returned and the client
* has an error emitted describing the error. */
int
checkPrefixCollisionsOrReply
(
client
*
c
,
robj
**
prefixes
,
size_t
numprefix
)
{
for
(
size_t
i
=
0
;
i
<
numprefix
;
i
++
)
{
/* Check input list has no overlap with existing prefixes. */
if
(
c
->
client_tracking_prefixes
)
{
raxIterator
ri
;
raxStart
(
&
ri
,
c
->
client_tracking_prefixes
);
raxSeek
(
&
ri
,
"^"
,
NULL
,
0
);
while
(
raxNext
(
&
ri
))
{
if
(
stringCheckPrefix
(
ri
.
key
,
ri
.
key_len
,
prefixes
[
i
]
->
ptr
,
sdslen
(
prefixes
[
i
]
->
ptr
)))
{
sds
collision
=
sdsnewlen
(
ri
.
key
,
ri
.
key_len
);
addReplyErrorFormat
(
c
,
"Prefix '%s' overlaps with an existing prefix '%s'. "
"Prefixes for a single client must not overlap."
,
(
unsigned
char
*
)
prefixes
[
i
]
->
ptr
,
(
unsigned
char
*
)
collision
);
sdsfree
(
collision
);
raxStop
(
&
ri
);
return
0
;
}
}
raxStop
(
&
ri
);
}
/* Check input has no overlap with itself. */
for
(
size_t
j
=
i
+
1
;
j
<
numprefix
;
j
++
)
{
if
(
stringCheckPrefix
(
prefixes
[
i
]
->
ptr
,
sdslen
(
prefixes
[
i
]
->
ptr
),
prefixes
[
j
]
->
ptr
,
sdslen
(
prefixes
[
j
]
->
ptr
)))
{
addReplyErrorFormat
(
c
,
"Prefix '%s' overlaps with another provided prefix '%s'. "
"Prefixes for a single client must not overlap."
,
(
unsigned
char
*
)
prefixes
[
i
]
->
ptr
,
(
unsigned
char
*
)
prefixes
[
j
]
->
ptr
);
return
i
;
}
}
}
return
-
1
;
}
/* Set the client 'c' to track the prefix 'prefix'. If the client 'c' is
* already registered for the specified prefix, no operation is performed. */
void
enableBcastTrackingForPrefix
(
client
*
c
,
char
*
prefix
,
size_t
plen
)
{
...
...
tests/unit/tracking.tcl
View file @
999494ce
...
...
@@ -325,6 +325,24 @@ start_server {tags {"tracking"}} {
assert
{
$ping
_reply eq
{
PONG
}}
}
test
{
BCAST with prefix collisions throw errors
}
{
set r
[
redis_client
]
catch
{
$r
CLIENT TRACKING ON BCAST PREFIX FOOBAR PREFIX FOO
}
output
assert_match
{
ERR Prefix 'FOOBAR'*'FOO'*
}
$output
catch
{
$r
CLIENT TRACKING ON BCAST PREFIX FOO PREFIX FOOBAR
}
output
assert_match
{
ERR Prefix 'FOO'*'FOOBAR'*
}
$output
$r CLIENT TRACKING ON BCAST PREFIX FOO PREFIX BAR
catch
{
$r
CLIENT TRACKING ON BCAST PREFIX FO
}
output
assert_match
{
ERR Prefix 'FO'*'FOO'*
}
$output
catch
{
$r
CLIENT TRACKING ON BCAST PREFIX BARB
}
output
assert_match
{
ERR Prefix 'BARB'*'BAR'*
}
$output
$r CLIENT TRACKING OFF
}
test
{
Tracking gets notification on tracking table key eviction
}
{
$rd_redirection HELLO 2
r CLIENT TRACKING off
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment