Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xindoo
redis
提交
ee5cfe38
R
redis
项目概览
xindoo
/
redis
通知
2
Star
2
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,体验更适合开发者的 AI 搜索 >>
提交
ee5cfe38
编写于
3月 09, 2010
作者:
A
antirez
浏览文件
操作
浏览文件
下载
差异文件
Merged ZREMBYRANK from Pietern
上级
e3f46030
84105336
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
116 addition
and
48 deletion
+116
-48
redis.c
redis.c
+104
-46
test-redis.tcl
test-redis.tcl
+12
-2
未找到文件。
redis.c
浏览文件 @
ee5cfe38
...
...
@@ -677,6 +677,7 @@ static void zrankCommand(redisClient *c);
static
void
zrevrankCommand
(
redisClient
*
c
);
static
void
hsetCommand
(
redisClient
*
c
);
static
void
hgetCommand
(
redisClient
*
c
);
static
void
zremrangebyrankCommand
(
redisClient
*
c
);
/*================================= Globals ================================= */
...
...
@@ -724,6 +725,7 @@ static struct redisCommand cmdTable[] = {
{
"zincrby"
,
zincrbyCommand
,
4
,
REDIS_CMD_BULK
|
REDIS_CMD_DENYOOM
,
1
,
1
,
1
},
{
"zrem"
,
zremCommand
,
3
,
REDIS_CMD_BULK
,
1
,
1
,
1
},
{
"zremrangebyscore"
,
zremrangebyscoreCommand
,
4
,
REDIS_CMD_INLINE
,
1
,
1
,
1
},
{
"zremrangebyrank"
,
zremrangebyrankCommand
,
4
,
REDIS_CMD_INLINE
,
1
,
1
,
1
},
{
"zrange"
,
zrangeCommand
,
-
4
,
REDIS_CMD_INLINE
,
1
,
1
,
1
},
{
"zrangebyscore"
,
zrangebyscoreCommand
,
-
4
,
REDIS_CMD_INLINE
,
1
,
1
,
1
},
{
"zcount"
,
zcountCommand
,
4
,
REDIS_CMD_INLINE
,
1
,
1
,
1
},
...
...
@@ -5078,6 +5080,31 @@ static void zslInsert(zskiplist *zsl, double score, robj *obj) {
zsl
->
length
++
;
}
/* Internal function used by zslDelete, zslDeleteByScore and zslDeleteByRank */
void
zslDeleteNode
(
zskiplist
*
zsl
,
zskiplistNode
*
x
,
zskiplistNode
**
update
)
{
int
i
;
for
(
i
=
0
;
i
<
zsl
->
level
;
i
++
)
{
if
(
update
[
i
]
->
forward
[
i
]
==
x
)
{
if
(
i
>
0
)
{
update
[
i
]
->
span
[
i
-
1
]
+=
x
->
span
[
i
-
1
]
-
1
;
}
update
[
i
]
->
forward
[
i
]
=
x
->
forward
[
i
];
}
else
{
/* invariant: i > 0, because update[0]->forward[0]
* is always equal to x */
update
[
i
]
->
span
[
i
-
1
]
-=
1
;
}
}
if
(
x
->
forward
[
0
])
{
x
->
forward
[
0
]
->
backward
=
x
->
backward
;
}
else
{
zsl
->
tail
=
x
->
backward
;
}
while
(
zsl
->
level
>
1
&&
zsl
->
header
->
forward
[
zsl
->
level
-
1
]
==
NULL
)
zsl
->
level
--
;
zsl
->
length
--
;
}
/* Delete an element with matching score/object from the skiplist. */
static
int
zslDelete
(
zskiplist
*
zsl
,
double
score
,
robj
*
obj
)
{
zskiplistNode
*
update
[
ZSKIPLIST_MAXLEVEL
],
*
x
;
...
...
@@ -5096,27 +5123,8 @@ static int zslDelete(zskiplist *zsl, double score, robj *obj) {
* is to find the element with both the right score and object. */
x
=
x
->
forward
[
0
];
if
(
x
&&
score
==
x
->
score
&&
compareStringObjects
(
x
->
obj
,
obj
)
==
0
)
{
for
(
i
=
0
;
i
<
zsl
->
level
;
i
++
)
{
if
(
update
[
i
]
->
forward
[
i
]
==
x
)
{
if
(
i
>
0
)
{
update
[
i
]
->
span
[
i
-
1
]
+=
x
->
span
[
i
-
1
]
-
1
;
}
update
[
i
]
->
forward
[
i
]
=
x
->
forward
[
i
];
}
else
{
/* invariant: i > 0, because update[0]->forward[0]
* is always equal to x */
update
[
i
]
->
span
[
i
-
1
]
-=
1
;
}
}
if
(
x
->
forward
[
0
])
{
x
->
forward
[
0
]
->
backward
=
x
->
backward
;
}
else
{
zsl
->
tail
=
x
->
backward
;
}
zslDeleteNode
(
zsl
,
x
,
update
);
zslFreeNode
(
x
);
while
(
zsl
->
level
>
1
&&
zsl
->
header
->
forward
[
zsl
->
level
-
1
]
==
NULL
)
zsl
->
level
--
;
zsl
->
length
--
;
return
1
;
}
else
{
return
0
;
/* not found */
...
...
@@ -5128,7 +5136,7 @@ static int zslDelete(zskiplist *zsl, double score, robj *obj) {
* Min and mx are inclusive, so a score >= min || score <= max is deleted.
* Note that this function takes the reference to the hash table view of the
* sorted set, in order to remove the elements from the hash table too. */
static
unsigned
long
zslDeleteRange
(
zskiplist
*
zsl
,
double
min
,
double
max
,
dict
*
dict
)
{
static
unsigned
long
zslDeleteRange
ByScore
(
zskiplist
*
zsl
,
double
min
,
double
max
,
dict
*
dict
)
{
zskiplistNode
*
update
[
ZSKIPLIST_MAXLEVEL
],
*
x
;
unsigned
long
removed
=
0
;
int
i
;
...
...
@@ -5143,35 +5151,44 @@ static unsigned long zslDeleteRange(zskiplist *zsl, double min, double max, dict
* is to find the element with both the right score and object. */
x
=
x
->
forward
[
0
];
while
(
x
&&
x
->
score
<=
max
)
{
zskiplistNode
*
next
;
zskiplistNode
*
next
=
x
->
forward
[
0
];
zslDeleteNode
(
zsl
,
x
,
update
);
dictDelete
(
dict
,
x
->
obj
);
zslFreeNode
(
x
);
removed
++
;
x
=
next
;
}
return
removed
;
/* not found */
}
for
(
i
=
0
;
i
<
zsl
->
level
;
i
++
)
{
if
(
update
[
i
]
->
forward
[
i
]
==
x
)
{
if
(
i
>
0
)
{
update
[
i
]
->
span
[
i
-
1
]
+=
x
->
span
[
i
-
1
]
-
1
;
}
update
[
i
]
->
forward
[
i
]
=
x
->
forward
[
i
];
}
else
{
/* invariant: i > 0, because update[0]->forward[0]
* is always equal to x */
update
[
i
]
->
span
[
i
-
1
]
-=
1
;
}
}
if
(
x
->
forward
[
0
])
{
x
->
forward
[
0
]
->
backward
=
x
->
backward
;
}
else
{
zsl
->
tail
=
x
->
backward
;
/* Delete all the elements with rank between start and end from the skiplist.
* Start and end are inclusive. Note that start and end need to be 1-based */
static
unsigned
long
zslDeleteRangeByRank
(
zskiplist
*
zsl
,
unsigned
int
start
,
unsigned
int
end
,
dict
*
dict
)
{
zskiplistNode
*
update
[
ZSKIPLIST_MAXLEVEL
],
*
x
;
unsigned
long
traversed
=
0
,
removed
=
0
;
int
i
;
x
=
zsl
->
header
;
for
(
i
=
zsl
->
level
-
1
;
i
>=
0
;
i
--
)
{
while
(
x
->
forward
[
i
]
&&
(
traversed
+
(
i
>
0
?
x
->
span
[
i
-
1
]
:
1
))
<
start
)
{
traversed
+=
i
>
0
?
x
->
span
[
i
-
1
]
:
1
;
x
=
x
->
forward
[
i
];
}
next
=
x
->
forward
[
0
];
update
[
i
]
=
x
;
}
traversed
++
;
x
=
x
->
forward
[
0
];
while
(
x
&&
traversed
<=
end
)
{
zskiplistNode
*
next
=
x
->
forward
[
0
];
zslDeleteNode
(
zsl
,
x
,
update
);
dictDelete
(
dict
,
x
->
obj
);
zslFreeNode
(
x
);
while
(
zsl
->
level
>
1
&&
zsl
->
header
->
forward
[
zsl
->
level
-
1
]
==
NULL
)
zsl
->
level
--
;
zsl
->
length
--
;
removed
++
;
traversed
++
;
x
=
next
;
}
return
removed
;
/* not found */
return
removed
;
}
/* Find the first node having a score equal or greater than the specified one.
...
...
@@ -5386,13 +5403,54 @@ static void zremrangebyscoreCommand(redisClient *c) {
return
;
}
zs
=
zsetobj
->
ptr
;
deleted
=
zslDeleteRange
(
zs
->
zsl
,
min
,
max
,
zs
->
dict
);
deleted
=
zslDeleteRange
ByScore
(
zs
->
zsl
,
min
,
max
,
zs
->
dict
);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
server
.
dirty
+=
deleted
;
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
":%lu
\r\n
"
,
deleted
));
}
}
static
void
zremrangebyrankCommand
(
redisClient
*
c
)
{
int
start
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
int
end
=
atoi
(
c
->
argv
[
3
]
->
ptr
);
robj
*
zsetobj
;
zset
*
zs
;
zsetobj
=
lookupKeyWrite
(
c
->
db
,
c
->
argv
[
1
]);
if
(
zsetobj
==
NULL
)
{
addReply
(
c
,
shared
.
czero
);
}
else
{
if
(
zsetobj
->
type
!=
REDIS_ZSET
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
return
;
}
zs
=
zsetobj
->
ptr
;
int
llen
=
zs
->
zsl
->
length
;
long
deleted
;
/* convert negative indexes */
if
(
start
<
0
)
start
=
llen
+
start
;
if
(
end
<
0
)
end
=
llen
+
end
;
if
(
start
<
0
)
start
=
0
;
if
(
end
<
0
)
end
=
0
;
/* indexes sanity checks */
if
(
start
>
end
||
start
>=
llen
)
{
addReply
(
c
,
shared
.
czero
);
return
;
}
if
(
end
>=
llen
)
end
=
llen
-
1
;
/* increment start and end because zsl*Rank functions
* use 1-based rank */
deleted
=
zslDeleteRangeByRank
(
zs
->
zsl
,
start
+
1
,
end
+
1
,
zs
->
dict
);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
server
.
dirty
+=
deleted
;
addReplyLong
(
c
,
deleted
);
}
}
static
void
zrangeGenericCommand
(
redisClient
*
c
,
int
reverse
)
{
robj
*
o
;
int
start
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
...
...
@@ -5439,9 +5497,9 @@ static void zrangeGenericCommand(redisClient *c, int reverse) {
/* check if starting point is trivial, before searching
* the element in log(N) time */
if
(
reverse
)
{
ln
=
start
==
0
?
zsl
->
tail
:
zslGetElementByRank
(
zsl
,
llen
-
start
);
ln
=
start
==
0
?
zsl
->
tail
:
zslGetElementByRank
(
zsl
,
llen
-
start
);
}
else
{
ln
=
start
==
0
?
zsl
->
header
->
forward
[
0
]
:
zslGetElementByRank
(
zsl
,
start
+
1
);
ln
=
start
==
0
?
zsl
->
header
->
forward
[
0
]
:
zslGetElementByRank
(
zsl
,
start
+
1
);
}
/* Return the result in form of a multi-bulk reply */
...
...
test-redis.tcl
浏览文件 @
ee5cfe38
...
...
@@ -1446,7 +1446,7 @@ proc main {server port} {
$r zrangebyscore zset 20 50 LIMIT 2 3 withscores
}
{
d 40 e 50
}
test
{
ZREMRANGE basics
}
{
test
{
ZREMRANGE
BYSCORE
basics
}
{
$r del zset
$r zadd zset 1 a
$r zadd zset 2 b
...
...
@@ -1456,7 +1456,7 @@ proc main {server port} {
list
[
$r
zremrangebyscore zset 2 4
]
[
$r
zrange zset 0 -1
]
}
{
3
{
a e
}}
test
{
ZREMRANGE from -inf to +inf
}
{
test
{
ZREMRANGE
BYSCORE
from -inf to +inf
}
{
$r del zset
$r zadd zset 1 a
$r zadd zset 2 b
...
...
@@ -1466,6 +1466,16 @@ proc main {server port} {
list
[
$r
zremrangebyscore zset -inf +inf
]
[
$r
zrange zset 0 -1
]
}
{
5
{}}
test
{
ZREMRANGEBYRANK basics
}
{
$r del zset
$r zadd zset 1 a
$r zadd zset 2 b
$r zadd zset 3 c
$r zadd zset 4 d
$r zadd zset 5 e
list
[
$r
zremrangebyrank zset 1 3
]
[
$r
zrange zset 0 -1
]
}
{
3
{
a e
}}
test
{
SORT against sorted sets
}
{
$r del zset
$r zadd zset 1 a
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录