Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Turbo码先生
redis
提交
b1ec3336
R
redis
项目概览
Turbo码先生
/
redis
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b1ec3336
编写于
9月 13, 2017
作者:
A
antirez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Streams: stream iteration refactoring, WIP 1.
上级
1a603e1a
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
114 addition
and
0 deletion
+114
-0
src/t_stream.c
src/t_stream.c
+114
-0
未找到文件。
src/t_stream.c
浏览文件 @
b1ec3336
...
...
@@ -196,6 +196,120 @@ int streamAppendItem(stream *s, robj **argv, int numfields, streamID *added_id,
return
C_OK
;
}
/* We define an iterator to iterate stream items in an abstract way, without
* caring about the radix tree + listpack representation. Technically speaking
* the iterator is only used inside streamReplyWithRange(), so could just
* be implemented inside the function, but practically there is the AOF
* rewriting code that also needs to iterate the stream to emit the XADD
* commands. */
typedef
struct
streamIterator
{
uint64_t
start_key
[
2
];
/* Start key as 128 bit big endian. */
uint64_t
end_key
[
2
];
/* End key as 128 bit big endian. */
raxIterator
ri
;
/* Rax iterator. */
unsigned
char
*
lp
;
/* Current listpack. */
unsigned
char
*
lp_ele
;
/* Current listpack cursor. */
}
streamIterator
;
/* Initialize the stream iterator, so that we can call iterating functions
* to get the next items. This requires a corresponding streamIteratorStop()
* at the end.
*
* Once the iterator is initalized, we iterate like this:
*
* streamIterator myiterator;
* streamIteratorStart(&myiterator,...);
* size_t numfields;
* while(streamIteratorGetID(&myitereator,&ID,&numfields)) {
* while(numfields--) {
* unsigned char *key, *value;
* size_t key_len, value_len;
* streamIteratorGetField(&myiterator,&key,&value,&key_len,&value_len);
*
* ... do what you want with key and value ...
* }
* }
* streamIteratorStop(&myiterator); */
void
streamIteratorStart
(
streamIterator
*
si
,
stream
*
s
,
streamID
*
start
,
streamID
*
end
)
{
/* Intialize the iterator and translates the iteration start/stop
* elements into a 128 big big-endian number. */
streamEncodeID
(
si
->
start_key
,
start
);
if
(
end
)
{
streamEncodeID
(
si
->
end_key
,
end
);
}
else
{
/* We assume that UINT64_MAX is the same in little and big
* endian, that is, all bits set. */
si
->
end_key
[
0
]
=
UINT64_MAX
;
si
->
end_key
[
0
]
=
UINT64_MAX
;
}
raxStart
(
&
si
->
ri
,
s
->
rax
);
/* Seek the correct node in the radix tree. */
if
(
start
->
ms
||
start
->
seq
)
{
raxSeek
(
&
si
->
ri
,
"<="
,(
unsigned
char
*
)
si
->
start_key
,
sizeof
(
si
->
start_key
));
if
(
raxEOF
(
&
si
->
ri
))
raxSeek
(
&
si
->
ri
,
">"
,(
unsigned
char
*
)
si
->
start_key
,
sizeof
(
si
->
start_key
));
}
else
{
raxSeek
(
&
si
->
ri
,
"^"
,
NULL
,
0
);
}
si
->
lp
=
NULL
;
/* There is no current listpack right now. */
si
->
lp_ele
=
NULL
;
/* Current listpack cursor. */
}
/* Return 1 and store the current item ID at 'id' if there are still
* elements within the iteration range, otherwise return 0 in order to
* signal the iteration terminated. */
int
streamIteratorGetID
(
streamIterator
*
si
,
streamID
*
id
,
size_t
*
numfields
)
{
while
(
1
)
{
/* Will stop when element > stop_key or end of radix tree. */
/* If the current listpack is set to NULL, this is the start of the
* iteration or the previous listpack was completely iterated.
* Go to the next node. */
if
(
si
->
lp
==
NULL
||
si
->
lp_ele
==
NULL
)
{
if
(
!
raxNext
(
&
si
->
ri
))
return
0
;
serverAssert
(
si
->
ri
.
key_len
==
sizeof
(
streamID
));
si
->
lp
=
si
->
ri
.
data
;
si
->
lp_ele
=
lpFirst
(
si
->
lp
);
}
/* For every radix tree node, iterate the corresponding listpack,
* returning elements when they are within range. */
while
(
si
->
lp_ele
)
{
int64_t
e_len
;
unsigned
char
buf
[
LP_INTBUF_SIZE
];
unsigned
char
*
e
=
lpGet
(
si
->
lp_ele
,
&
e_len
,
buf
);
serverAssert
(
e_len
==
sizeof
(
streamID
));
/* Go to next field: number of elements. */
si
->
lp_ele
=
lpNext
(
si
->
lp
,
si
->
lp_ele
);
/* If current >= start */
if
(
memcmp
(
e
,
si
->
start_key
,
sizeof
(
streamID
))
>=
0
)
{
if
(
memcmp
(
e
,
si
->
end_key
,
sizeof
(
streamID
))
>
0
)
return
0
;
/* We are already out of range. */
streamDecodeID
(
e
,
id
);
*
numfields
=
lpGetInteger
(
si
->
lp_ele
);
return
1
;
/* Valid item returned. */
}
else
{
/* If we do not emit, we have to discard. */
int64_t
numfields
=
lpGetInteger
(
si
->
lp_ele
);
si
->
lp_ele
=
lpNext
(
si
->
lp
,
si
->
lp_ele
);
for
(
int64_t
i
=
0
;
i
<
numfields
*
2
;
i
++
)
si
->
lp_ele
=
lpNext
(
si
->
lp
,
si
->
lp_ele
);
}
}
/* End of listpack reached. Try the next radix tree node. */
}
}
/* Stop the stream iterator. The only cleanup we need is to free the rax
* itereator, since the stream iterator itself is supposed to be stack
* allocated. */
void
streamIteratorStop
(
streamIterator
*
si
)
{
raxStop
(
&
si
->
ri
);
}
/* Send the specified range to the client 'c'. The range the client will
* 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
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录