Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
e2665397
Commit
e2665397
authored
Nov 19, 2009
by
antirez
Browse files
ZINCRSCOREBY implemented
parent
37f68e61
Changes
2
Show whitespace changes
Inline
Side-by-side
redis-cli.c
View file @
e2665397
...
@@ -93,6 +93,7 @@ static struct redisCommand cmdTable[] = {
...
@@ -93,6 +93,7 @@ static struct redisCommand cmdTable[] = {
{
"sdiffstore"
,
-
3
,
REDIS_CMD_INLINE
},
{
"sdiffstore"
,
-
3
,
REDIS_CMD_INLINE
},
{
"smembers"
,
2
,
REDIS_CMD_INLINE
},
{
"smembers"
,
2
,
REDIS_CMD_INLINE
},
{
"zadd"
,
4
,
REDIS_CMD_BULK
},
{
"zadd"
,
4
,
REDIS_CMD_BULK
},
{
"zincrscoreby"
,
4
,
REDIS_CMD_BULK
},
{
"zrem"
,
3
,
REDIS_CMD_BULK
},
{
"zrem"
,
3
,
REDIS_CMD_BULK
},
{
"zremrangebyscore"
,
4
,
REDIS_CMD_INLINE
},
{
"zremrangebyscore"
,
4
,
REDIS_CMD_INLINE
},
{
"zrange"
,
4
,
REDIS_CMD_INLINE
},
{
"zrange"
,
4
,
REDIS_CMD_INLINE
},
...
...
redis.c
View file @
e2665397
...
@@ -466,6 +466,7 @@ static void debugCommand(redisClient *c);
...
@@ -466,6 +466,7 @@ static void debugCommand(redisClient *c);
static
void
msetCommand
(
redisClient
*
c
);
static
void
msetCommand
(
redisClient
*
c
);
static
void
msetnxCommand
(
redisClient
*
c
);
static
void
msetnxCommand
(
redisClient
*
c
);
static
void
zaddCommand
(
redisClient
*
c
);
static
void
zaddCommand
(
redisClient
*
c
);
static
void
zincrscorebyCommand
(
redisClient
*
c
);
static
void
zrangeCommand
(
redisClient
*
c
);
static
void
zrangeCommand
(
redisClient
*
c
);
static
void
zrangebyscoreCommand
(
redisClient
*
c
);
static
void
zrangebyscoreCommand
(
redisClient
*
c
);
static
void
zrevrangeCommand
(
redisClient
*
c
);
static
void
zrevrangeCommand
(
redisClient
*
c
);
...
@@ -513,6 +514,7 @@ static struct redisCommand cmdTable[] = {
...
@@ -513,6 +514,7 @@ static struct redisCommand cmdTable[] = {
{
"sdiffstore"
,
sdiffstoreCommand
,
-
3
,
REDIS_CMD_INLINE
|
REDIS_CMD_DENYOOM
},
{
"sdiffstore"
,
sdiffstoreCommand
,
-
3
,
REDIS_CMD_INLINE
|
REDIS_CMD_DENYOOM
},
{
"smembers"
,
sinterCommand
,
2
,
REDIS_CMD_INLINE
},
{
"smembers"
,
sinterCommand
,
2
,
REDIS_CMD_INLINE
},
{
"zadd"
,
zaddCommand
,
4
,
REDIS_CMD_BULK
|
REDIS_CMD_DENYOOM
},
{
"zadd"
,
zaddCommand
,
4
,
REDIS_CMD_BULK
|
REDIS_CMD_DENYOOM
},
{
"zincrscoreby"
,
zincrscorebyCommand
,
4
,
REDIS_CMD_BULK
|
REDIS_CMD_DENYOOM
},
{
"zrem"
,
zremCommand
,
3
,
REDIS_CMD_BULK
},
{
"zrem"
,
zremCommand
,
3
,
REDIS_CMD_BULK
},
{
"zremrangebyscore"
,
zremrangebyscoreCommand
,
4
,
REDIS_CMD_INLINE
},
{
"zremrangebyscore"
,
zremrangebyscoreCommand
,
4
,
REDIS_CMD_INLINE
},
{
"zrange"
,
zrangeCommand
,
4
,
REDIS_CMD_INLINE
},
{
"zrange"
,
zrangeCommand
,
4
,
REDIS_CMD_INLINE
},
...
@@ -1383,7 +1385,6 @@ static void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask)
...
@@ -1383,7 +1385,6 @@ static void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask)
REDIS_NOTUSED
(
el
);
REDIS_NOTUSED
(
el
);
REDIS_NOTUSED
(
mask
);
REDIS_NOTUSED
(
mask
);
/* Use writev() if we have enough buffers to send */
/* Use writev() if we have enough buffers to send */
if
(
!
server
.
glueoutputbuf
&&
if
(
!
server
.
glueoutputbuf
&&
listLength
(
c
->
reply
)
>
REDIS_WRITEV_THRESHOLD
&&
listLength
(
c
->
reply
)
>
REDIS_WRITEV_THRESHOLD
&&
...
@@ -1939,6 +1940,14 @@ static void addReplySds(redisClient *c, sds s) {
...
@@ -1939,6 +1940,14 @@ static void addReplySds(redisClient *c, sds s) {
decrRefCount
(
o
);
decrRefCount
(
o
);
}
}
static
void
addReplyDouble
(
redisClient
*
c
,
double
d
)
{
char
buf
[
128
];
snprintf
(
buf
,
sizeof
(
buf
),
"%.17g"
,
d
);
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"$%d
\r\n
%s
\r\n
"
,
strlen
(
buf
),
buf
));
}
static
void
addReplyBulkLen
(
redisClient
*
c
,
robj
*
obj
)
{
static
void
addReplyBulkLen
(
redisClient
*
c
,
robj
*
obj
)
{
size_t
len
;
size_t
len
;
...
@@ -4220,56 +4229,101 @@ static zskiplistNode *zslFirstWithScore(zskiplist *zsl, double score) {
...
@@ -4220,56 +4229,101 @@ static zskiplistNode *zslFirstWithScore(zskiplist *zsl, double score) {
/* The actual Z-commands implementations */
/* The actual Z-commands implementations */
static
void
zaddCommand
(
redisClient
*
c
)
{
/* This generic command implements both ZADD and ZINCRSCOREBY.
* scoreval is the score if the operation is a ZADD (doincrement == 0) or
* the increment if the operation is a ZINCRSCOREBY (doincrement == 1). */
static
void
zaddGenericCommand
(
redisClient
*
c
,
robj
*
key
,
robj
*
ele
,
double
scoreval
,
int
doincrement
)
{
robj
*
zsetobj
;
robj
*
zsetobj
;
zset
*
zs
;
zset
*
zs
;
double
*
score
;
double
*
score
;
zsetobj
=
lookupKeyWrite
(
c
->
db
,
c
->
argv
[
1
]
);
zsetobj
=
lookupKeyWrite
(
c
->
db
,
key
);
if
(
zsetobj
==
NULL
)
{
if
(
zsetobj
==
NULL
)
{
zsetobj
=
createZsetObject
();
zsetobj
=
createZsetObject
();
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
1
]
,
zsetobj
);
dictAdd
(
c
->
db
->
dict
,
key
,
zsetobj
);
incrRefCount
(
c
->
argv
[
1
]
);
incrRefCount
(
key
);
}
else
{
}
else
{
if
(
zsetobj
->
type
!=
REDIS_ZSET
)
{
if
(
zsetobj
->
type
!=
REDIS_ZSET
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
return
;
return
;
}
}
}
}
score
=
zmalloc
(
sizeof
(
double
));
*
score
=
strtod
(
c
->
argv
[
2
]
->
ptr
,
NULL
);
zs
=
zsetobj
->
ptr
;
zs
=
zsetobj
->
ptr
;
if
(
dictAdd
(
zs
->
dict
,
c
->
argv
[
3
],
score
)
==
DICT_OK
)
{
/* Ok now since we implement both ZADD and ZINCRSCOREBY here the code
* needs to handle the two different conditions. It's all about setting
* '*score', that is, the new score to set, to the right value. */
score
=
zmalloc
(
sizeof
(
double
));
if
(
doincrement
)
{
dictEntry
*
de
;
/* Read the old score. If the element was not present starts from 0 */
de
=
dictFind
(
zs
->
dict
,
ele
);
if
(
de
)
{
double
*
oldscore
=
dictGetEntryVal
(
de
);
*
score
=
*
oldscore
+
scoreval
;
}
else
{
*
score
=
scoreval
;
}
}
else
{
*
score
=
scoreval
;
}
/* What follows is a simple remove and re-insert operation that is common
* to both ZADD and ZINCRSCOREBY... */
if
(
dictAdd
(
zs
->
dict
,
ele
,
score
)
==
DICT_OK
)
{
/* case 1: New element */
/* case 1: New element */
incrRefCount
(
c
->
argv
[
3
]
);
/* added to hash */
incrRefCount
(
ele
);
/* added to hash */
zslInsert
(
zs
->
zsl
,
*
score
,
c
->
argv
[
3
]
);
zslInsert
(
zs
->
zsl
,
*
score
,
ele
);
incrRefCount
(
c
->
argv
[
3
]
);
/* added to skiplist */
incrRefCount
(
ele
);
/* added to skiplist */
server
.
dirty
++
;
server
.
dirty
++
;
if
(
doincrement
)
addReply
(
c
,
shared
.
cone
);
addReply
(
c
,
shared
.
cone
);
else
addReplyDouble
(
c
,
*
score
);
}
else
{
}
else
{
dictEntry
*
de
;
dictEntry
*
de
;
double
*
oldscore
;
double
*
oldscore
;
/* case 2: Score update operation */
/* case 2: Score update operation */
de
=
dictFind
(
zs
->
dict
,
c
->
argv
[
3
]
);
de
=
dictFind
(
zs
->
dict
,
ele
);
assert
(
de
!=
NULL
);
assert
(
de
!=
NULL
);
oldscore
=
dictGetEntryVal
(
de
);
oldscore
=
dictGetEntryVal
(
de
);
if
(
*
score
!=
*
oldscore
)
{
if
(
*
score
!=
*
oldscore
)
{
int
deleted
;
int
deleted
;
deleted
=
zslDelete
(
zs
->
zsl
,
*
oldscore
,
c
->
argv
[
3
]);
/* Remove and insert the element in the skip list with new score */
deleted
=
zslDelete
(
zs
->
zsl
,
*
oldscore
,
ele
);
assert
(
deleted
!=
0
);
assert
(
deleted
!=
0
);
zslInsert
(
zs
->
zsl
,
*
score
,
c
->
argv
[
3
]);
zslInsert
(
zs
->
zsl
,
*
score
,
ele
);
incrRefCount
(
c
->
argv
[
3
]);
incrRefCount
(
ele
);
dictReplace
(
zs
->
dict
,
c
->
argv
[
3
],
score
);
/* Update the score in the hash table */
dictReplace
(
zs
->
dict
,
ele
,
score
);
server
.
dirty
++
;
server
.
dirty
++
;
}
else
{
}
else
{
zfree
(
score
);
zfree
(
score
);
}
}
if
(
doincrement
)
addReplyDouble
(
c
,
*
score
);
else
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
}
}
}
}
static
void
zaddCommand
(
redisClient
*
c
)
{
double
scoreval
;
scoreval
=
strtod
(
c
->
argv
[
2
]
->
ptr
,
NULL
);
zaddGenericCommand
(
c
,
c
->
argv
[
1
],
c
->
argv
[
3
],
scoreval
,
0
);
}
static
void
zincrscorebyCommand
(
redisClient
*
c
)
{
double
scoreval
;
scoreval
=
strtod
(
c
->
argv
[
2
]
->
ptr
,
NULL
);
zaddGenericCommand
(
c
,
c
->
argv
[
1
],
c
->
argv
[
3
],
scoreval
,
1
);
}
static
void
zremCommand
(
redisClient
*
c
)
{
static
void
zremCommand
(
redisClient
*
c
)
{
robj
*
zsetobj
;
robj
*
zsetobj
;
zset
*
zs
;
zset
*
zs
;
...
@@ -4478,12 +4532,9 @@ static void zscoreCommand(redisClient *c) {
...
@@ -4478,12 +4532,9 @@ static void zscoreCommand(redisClient *c) {
if
(
!
de
)
{
if
(
!
de
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
(
c
,
shared
.
nullbulk
);
}
else
{
}
else
{
char
buf
[
128
];
double
*
score
=
dictGetEntryVal
(
de
);
double
*
score
=
dictGetEntryVal
(
de
);
snprintf
(
buf
,
sizeof
(
buf
),
"%.17g"
,
*
score
);
addReplyDouble
(
c
,
*
score
);
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"$%d
\r\n
%s
\r\n
"
,
strlen
(
buf
),
buf
));
}
}
}
}
}
}
...
...
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