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
86fe8fde
Commit
86fe8fde
authored
Jan 19, 2018
by
antirez
Browse files
CG: consumer lookup + initial streamReplyWithRange() work to supprot CG.
parent
ccdae090
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/blocked.c
View file @
86fe8fde
...
@@ -326,7 +326,9 @@ void handleClientsBlockedOnKeys(void) {
...
@@ -326,7 +326,9 @@ void handleClientsBlockedOnKeys(void) {
addReplyMultiBulkLen
(
receiver
,
2
);
addReplyMultiBulkLen
(
receiver
,
2
);
addReplyBulk
(
receiver
,
rl
->
key
);
addReplyBulk
(
receiver
,
rl
->
key
);
streamReplyWithRange
(
receiver
,
s
,
&
start
,
NULL
,
streamReplyWithRange
(
receiver
,
s
,
&
start
,
NULL
,
receiver
->
bpop
.
xread_count
,
0
);
receiver
->
bpop
.
xread_count
,
0
,
NULL
,
NULL
);
}
}
}
}
}
}
...
...
src/stream.h
View file @
86fe8fde
...
@@ -64,7 +64,7 @@ typedef struct streamCG {
...
@@ -64,7 +64,7 @@ typedef struct streamCG {
/* A specific consumer in a consumer group. */
/* A specific consumer in a consumer group. */
typedef
struct
streamConsumer
{
typedef
struct
streamConsumer
{
mstime_t
seen_time
;
/* Last time this consumer was active. */
mstime_t
seen_time
;
/* Last time this consumer was active. */
sds
*
name
;
/* Consumer name. This is how the consumer
sds
name
;
/* Consumer name. This is how the consumer
will be identified in the consumer group
will be identified in the consumer group
protocol. Case sensitive. */
protocol. Case sensitive. */
rax
*
pel
;
/* Consumer specific pending entries list: all
rax
*
pel
;
/* Consumer specific pending entries list: all
...
@@ -89,7 +89,7 @@ struct client;
...
@@ -89,7 +89,7 @@ struct client;
stream
*
streamNew
(
void
);
stream
*
streamNew
(
void
);
void
freeStream
(
stream
*
s
);
void
freeStream
(
stream
*
s
);
size_t
streamReplyWithRange
(
struct
client
*
c
,
stream
*
s
,
streamID
*
start
,
streamID
*
end
,
size_t
count
,
int
rev
);
size_t
streamReplyWithRange
(
struct
client
*
c
,
stream
*
s
,
streamID
*
start
,
streamID
*
end
,
size_t
count
,
int
rev
,
streamCG
*
group
,
streamConsumer
*
consumer
);
void
streamIteratorStart
(
streamIterator
*
si
,
stream
*
s
,
streamID
*
start
,
streamID
*
end
,
int
rev
);
void
streamIteratorStart
(
streamIterator
*
si
,
stream
*
s
,
streamID
*
start
,
streamID
*
end
,
int
rev
);
int
streamIteratorGetID
(
streamIterator
*
si
,
streamID
*
id
,
int64_t
*
numfields
);
int
streamIteratorGetID
(
streamIterator
*
si
,
streamID
*
id
,
int64_t
*
numfields
);
void
streamIteratorGetField
(
streamIterator
*
si
,
unsigned
char
**
fieldptr
,
unsigned
char
**
valueptr
,
int64_t
*
fieldlen
,
int64_t
*
valuelen
);
void
streamIteratorGetField
(
streamIterator
*
si
,
unsigned
char
**
fieldptr
,
unsigned
char
**
valueptr
,
int64_t
*
fieldlen
,
int64_t
*
valuelen
);
...
...
src/t_stream.c
View file @
86fe8fde
...
@@ -42,6 +42,7 @@
...
@@ -42,6 +42,7 @@
void
streamFreeCG
(
streamCG
*
cg
);
void
streamFreeCG
(
streamCG
*
cg
);
streamCG
*
streamLookupCG
(
stream
*
s
,
sds
groupname
);
streamCG
*
streamLookupCG
(
stream
*
s
,
sds
groupname
);
streamConsumer
*
streamLookupConsumer
(
streamCG
*
cg
,
sds
name
);
/* -----------------------------------------------------------------------
/* -----------------------------------------------------------------------
* Low level stream encoding: a radix tree of listpacks.
* Low level stream encoding: a radix tree of listpacks.
...
@@ -659,8 +660,19 @@ void streamIteratorStop(streamIterator *si) {
...
@@ -659,8 +660,19 @@ void streamIteratorStop(streamIterator *si) {
* receive is between start and end inclusive, if 'count' is non zero, no more
* receive is between start and end inclusive, if 'count' is non zero, no more
* than 'count' elemnets are sent. The 'end' pointer can be NULL to mean that
* than 'count' elemnets are sent. The 'end' pointer can be NULL to mean that
* we want all the elements from 'start' till the end of the stream. If 'rev'
* we want all the elements from 'start' till the end of the stream. If 'rev'
* is non zero, elements are produced in reversed order from end to start. */
* is non zero, elements are produced in reversed order from end to start.
size_t
streamReplyWithRange
(
client
*
c
,
stream
*
s
,
streamID
*
start
,
streamID
*
end
,
size_t
count
,
int
rev
)
{
*
* If group and consumer are not NULL, the function performs additional work:
* 1. It updates the last delivered ID in the group in case we are
* sending IDs greater than the current last ID.
* 2. If the requested IDs are already assigned to some other consumer, the
* function will not return it to the client.
* 3. An entry in the pending list will be created for every entry delivered
* for the first time to this consumer. This is only performed if
* consumer != NULL, so in order to implement the XREADGROUP NOACK option
* no consumer is passed to this function.
*/
size_t
streamReplyWithRange
(
client
*
c
,
stream
*
s
,
streamID
*
start
,
streamID
*
end
,
size_t
count
,
int
rev
,
streamCG
*
group
,
streamConsumer
*
consumer
)
{
void
*
arraylen_ptr
=
addDeferredMultiBulkLength
(
c
);
void
*
arraylen_ptr
=
addDeferredMultiBulkLength
(
c
);
size_t
arraylen
=
0
;
size_t
arraylen
=
0
;
streamIterator
si
;
streamIterator
si
;
...
@@ -903,7 +915,7 @@ void xrangeGenericCommand(client *c, int rev) {
...
@@ -903,7 +915,7 @@ void xrangeGenericCommand(client *c, int rev) {
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
emptymultibulk
))
==
NULL
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
emptymultibulk
))
==
NULL
||
checkType
(
c
,
o
,
OBJ_STREAM
))
return
;
||
checkType
(
c
,
o
,
OBJ_STREAM
))
return
;
s
=
o
->
ptr
;
s
=
o
->
ptr
;
streamReplyWithRange
(
c
,
s
,
&
startid
,
&
endid
,
count
,
rev
);
streamReplyWithRange
(
c
,
s
,
&
startid
,
&
endid
,
count
,
rev
,
NULL
,
NULL
);
}
}
/* XRANGE key start end [COUNT <n>] */
/* XRANGE key start end [COUNT <n>] */
...
@@ -1063,13 +1075,18 @@ void xreadCommand(client *c) {
...
@@ -1063,13 +1075,18 @@ void xreadCommand(client *c) {
* so start from the next ID, since we want only messages with
* so start from the next ID, since we want only messages with
* IDs greater than start. */
* IDs greater than start. */
streamID
start
=
*
gt
;
streamID
start
=
*
gt
;
start
.
seq
++
;
/*
C
an't overflow
,
i
t's an uint64_t
*/
start
.
seq
++
;
/*
uint64_t c
an't overflow i
n this context.
*/
/* Emit the two elements sub-array consisting of the name
/* Emit the two elements sub-array consisting of the name
* of the stream and the data we extracted from it. */
* of the stream and the data we extracted from it. */
addReplyMultiBulkLen
(
c
,
2
);
addReplyMultiBulkLen
(
c
,
2
);
addReplyBulk
(
c
,
c
->
argv
[
i
+
streams_arg
]);
addReplyBulk
(
c
,
c
->
argv
[
i
+
streams_arg
]);
streamReplyWithRange
(
c
,
s
,
&
start
,
NULL
,
count
,
0
);
streamConsumer
*
consumer
=
NULL
;
if
(
groups
)
consumer
=
streamLookupConsumer
(
groups
[
i
],
consumername
->
ptr
);
streamReplyWithRange
(
c
,
s
,
&
start
,
NULL
,
count
,
0
,
groups
?
groups
[
i
]
:
NULL
,
consumer
);
}
}
}
}
...
@@ -1118,6 +1135,7 @@ void streamNotAckedFree(streamNotAcked *na) {
...
@@ -1118,6 +1135,7 @@ void streamNotAckedFree(streamNotAcked *na) {
}
}
void
streamConsumerFree
(
streamConsumer
*
sc
)
{
void
streamConsumerFree
(
streamConsumer
*
sc
)
{
zfree
(
sc
->
name
);
zfree
(
sc
);
zfree
(
sc
);
}
}
...
@@ -1154,6 +1172,22 @@ streamCG *streamLookupCG(stream *s, sds groupname) {
...
@@ -1154,6 +1172,22 @@ streamCG *streamLookupCG(stream *s, sds groupname) {
return
(
cg
==
raxNotFound
)
?
NULL
:
cg
;
return
(
cg
==
raxNotFound
)
?
NULL
:
cg
;
}
}
/* Lookup the consumer with the specified name in the group 'cg': if the
* consumer does not exist it is automatically created as a side effect
* of calling this function, otherwise its last seen time is updated and
* the existing consumer reference returned. */
streamConsumer
*
streamLookupConsumer
(
streamCG
*
cg
,
sds
name
)
{
streamConsumer
*
c
=
raxFind
(
cg
->
consumers
,(
unsigned
char
*
)
name
,
sdslen
(
name
));
if
(
c
==
raxNotFound
)
{
c
=
zmalloc
(
sizeof
(
*
c
));
c
->
name
=
sdsdup
(
name
);
c
->
pel
=
raxNew
();
}
c
->
seen_time
=
mstime
();
return
c
;
}
/* -----------------------------------------------------------------------
/* -----------------------------------------------------------------------
* Consumer groups commands
* Consumer groups commands
* ----------------------------------------------------------------------- */
* ----------------------------------------------------------------------- */
...
...
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