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
24044f33
Commit
24044f33
authored
Dec 18, 2019
by
zhaozhao.zz
Browse files
add a new SET option KEEPTTL that doesn't remove expire time
parent
b7c78b76
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/bitops.c
View file @
24044f33
...
@@ -754,7 +754,7 @@ void bitopCommand(client *c) {
...
@@ -754,7 +754,7 @@ void bitopCommand(client *c) {
/* Store the computed value into the target key */
/* Store the computed value into the target key */
if
(
maxlen
)
{
if
(
maxlen
)
{
o
=
createObject
(
OBJ_STRING
,
res
);
o
=
createObject
(
OBJ_STRING
,
res
);
setKey
(
c
->
db
,
targetkey
,
o
);
setKey
(
c
->
db
,
targetkey
,
o
,
0
);
notifyKeyspaceEvent
(
NOTIFY_STRING
,
"set"
,
targetkey
,
c
->
db
->
id
);
notifyKeyspaceEvent
(
NOTIFY_STRING
,
"set"
,
targetkey
,
c
->
db
->
id
);
decrRefCount
(
o
);
decrRefCount
(
o
);
}
else
if
(
dbDelete
(
c
->
db
,
targetkey
))
{
}
else
if
(
dbDelete
(
c
->
db
,
targetkey
))
{
...
...
src/db.c
View file @
24044f33
...
@@ -219,14 +219,14 @@ void dbOverwrite(redisDb *db, robj *key, robj *val) {
...
@@ -219,14 +219,14 @@ void dbOverwrite(redisDb *db, robj *key, robj *val) {
* 3) The expire time of the key is reset (the key is made persistent).
* 3) The expire time of the key is reset (the key is made persistent).
*
*
* All the new keys in the database should be created via this interface. */
* All the new keys in the database should be created via this interface. */
void
setKey
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
)
{
void
setKey
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
,
int
keepttl
)
{
if
(
lookupKeyWrite
(
db
,
key
)
==
NULL
)
{
if
(
lookupKeyWrite
(
db
,
key
)
==
NULL
)
{
dbAdd
(
db
,
key
,
val
);
dbAdd
(
db
,
key
,
val
);
}
else
{
}
else
{
dbOverwrite
(
db
,
key
,
val
);
dbOverwrite
(
db
,
key
,
val
);
}
}
incrRefCount
(
val
);
incrRefCount
(
val
);
removeExpire
(
db
,
key
);
if
(
!
keepttl
)
removeExpire
(
db
,
key
);
signalModifiedKey
(
db
,
key
);
signalModifiedKey
(
db
,
key
);
}
}
...
...
src/geo.c
View file @
24044f33
...
@@ -657,7 +657,7 @@ void georadiusGeneric(client *c, int flags) {
...
@@ -657,7 +657,7 @@ void georadiusGeneric(client *c, int flags) {
if
(
returned_items
)
{
if
(
returned_items
)
{
zsetConvertToZiplistIfNeeded
(
zobj
,
maxelelen
);
zsetConvertToZiplistIfNeeded
(
zobj
,
maxelelen
);
setKey
(
c
->
db
,
storekey
,
zobj
);
setKey
(
c
->
db
,
storekey
,
zobj
,
0
);
decrRefCount
(
zobj
);
decrRefCount
(
zobj
);
notifyKeyspaceEvent
(
NOTIFY_ZSET
,
"georadiusstore"
,
storekey
,
notifyKeyspaceEvent
(
NOTIFY_ZSET
,
"georadiusstore"
,
storekey
,
c
->
db
->
id
);
c
->
db
->
id
);
...
...
src/module.c
View file @
24044f33
...
@@ -2107,7 +2107,7 @@ RedisModuleString *RM_RandomKey(RedisModuleCtx *ctx) {
...
@@ -2107,7 +2107,7 @@ RedisModuleString *RM_RandomKey(RedisModuleCtx *ctx) {
int
RM_StringSet
(
RedisModuleKey
*
key
,
RedisModuleString
*
str
)
{
int
RM_StringSet
(
RedisModuleKey
*
key
,
RedisModuleString
*
str
)
{
if
(
!
(
key
->
mode
&
REDISMODULE_WRITE
)
||
key
->
iter
)
return
REDISMODULE_ERR
;
if
(
!
(
key
->
mode
&
REDISMODULE_WRITE
)
||
key
->
iter
)
return
REDISMODULE_ERR
;
RM_DeleteKey
(
key
);
RM_DeleteKey
(
key
);
setKey
(
key
->
db
,
key
->
key
,
str
);
setKey
(
key
->
db
,
key
->
key
,
str
,
0
);
key
->
value
=
str
;
key
->
value
=
str
;
return
REDISMODULE_OK
;
return
REDISMODULE_OK
;
}
}
...
@@ -2187,7 +2187,7 @@ int RM_StringTruncate(RedisModuleKey *key, size_t newlen) {
...
@@ -2187,7 +2187,7 @@ int RM_StringTruncate(RedisModuleKey *key, size_t newlen) {
if
(
key
->
value
==
NULL
)
{
if
(
key
->
value
==
NULL
)
{
/* Empty key: create it with the new size. */
/* Empty key: create it with the new size. */
robj
*
o
=
createObject
(
OBJ_STRING
,
sdsnewlen
(
NULL
,
newlen
));
robj
*
o
=
createObject
(
OBJ_STRING
,
sdsnewlen
(
NULL
,
newlen
));
setKey
(
key
->
db
,
key
->
key
,
o
);
setKey
(
key
->
db
,
key
->
key
,
o
,
0
);
key
->
value
=
o
;
key
->
value
=
o
;
decrRefCount
(
o
);
decrRefCount
(
o
);
}
else
{
}
else
{
...
@@ -3571,7 +3571,7 @@ int RM_ModuleTypeSetValue(RedisModuleKey *key, moduleType *mt, void *value) {
...
@@ -3571,7 +3571,7 @@ int RM_ModuleTypeSetValue(RedisModuleKey *key, moduleType *mt, void *value) {
if
(
!
(
key
->
mode
&
REDISMODULE_WRITE
)
||
key
->
iter
)
return
REDISMODULE_ERR
;
if
(
!
(
key
->
mode
&
REDISMODULE_WRITE
)
||
key
->
iter
)
return
REDISMODULE_ERR
;
RM_DeleteKey
(
key
);
RM_DeleteKey
(
key
);
robj
*
o
=
createModuleObject
(
mt
,
value
);
robj
*
o
=
createModuleObject
(
mt
,
value
);
setKey
(
key
->
db
,
key
->
key
,
o
);
setKey
(
key
->
db
,
key
->
key
,
o
,
0
);
decrRefCount
(
o
);
decrRefCount
(
o
);
key
->
value
=
o
;
key
->
value
=
o
;
return
REDISMODULE_OK
;
return
REDISMODULE_OK
;
...
...
src/server.h
View file @
24044f33
...
@@ -2025,7 +2025,7 @@ int objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
...
@@ -2025,7 +2025,7 @@ int objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
#define LOOKUP_NOTOUCH (1<<0)
#define LOOKUP_NOTOUCH (1<<0)
void
dbAdd
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
);
void
dbAdd
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
);
void
dbOverwrite
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
);
void
dbOverwrite
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
);
void
setKey
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
);
void
setKey
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
,
int
keepttl
);
int
dbExists
(
redisDb
*
db
,
robj
*
key
);
int
dbExists
(
redisDb
*
db
,
robj
*
key
);
robj
*
dbRandomKey
(
redisDb
*
db
);
robj
*
dbRandomKey
(
redisDb
*
db
);
int
dbSyncDelete
(
redisDb
*
db
,
robj
*
key
);
int
dbSyncDelete
(
redisDb
*
db
,
robj
*
key
);
...
...
src/sort.c
View file @
24044f33
...
@@ -570,7 +570,7 @@ void sortCommand(client *c) {
...
@@ -570,7 +570,7 @@ void sortCommand(client *c) {
}
}
}
}
if
(
outputlen
)
{
if
(
outputlen
)
{
setKey
(
c
->
db
,
storekey
,
sobj
);
setKey
(
c
->
db
,
storekey
,
sobj
,
0
);
notifyKeyspaceEvent
(
NOTIFY_LIST
,
"sortstore"
,
storekey
,
notifyKeyspaceEvent
(
NOTIFY_LIST
,
"sortstore"
,
storekey
,
c
->
db
->
id
);
c
->
db
->
id
);
server
.
dirty
+=
outputlen
;
server
.
dirty
+=
outputlen
;
...
...
src/t_string.c
View file @
24044f33
...
@@ -46,7 +46,7 @@ static int checkStringLength(client *c, long long size) {
...
@@ -46,7 +46,7 @@ static int checkStringLength(client *c, long long size) {
* options and variants. This function is called in order to implement the
* options and variants. This function is called in order to implement the
* following commands: SET, SETEX, PSETEX, SETNX.
* following commands: SET, SETEX, PSETEX, SETNX.
*
*
* 'flags' changes the behavior of the command (NX or XX, see belo
ve
).
* 'flags' changes the behavior of the command (NX or XX, see belo
w
).
*
*
* 'expire' represents an expire to set in form of a Redis object as passed
* 'expire' represents an expire to set in form of a Redis object as passed
* by the user. It is interpreted according to the specified 'unit'.
* by the user. It is interpreted according to the specified 'unit'.
...
@@ -59,10 +59,11 @@ static int checkStringLength(client *c, long long size) {
...
@@ -59,10 +59,11 @@ static int checkStringLength(client *c, long long size) {
* If abort_reply is NULL, "$-1" is used. */
* If abort_reply is NULL, "$-1" is used. */
#define OBJ_SET_NO_FLAGS 0
#define OBJ_SET_NO_FLAGS 0
#define OBJ_SET_NX (1<<0)
/* Set if key not exists. */
#define OBJ_SET_NX (1<<0)
/* Set if key not exists. */
#define OBJ_SET_XX (1<<1)
/* Set if key exists. */
#define OBJ_SET_XX (1<<1)
/* Set if key exists. */
#define OBJ_SET_EX (1<<2)
/* Set if time in seconds is given */
#define OBJ_SET_EX (1<<2)
/* Set if time in seconds is given */
#define OBJ_SET_PX (1<<3)
/* Set if time in ms in given */
#define OBJ_SET_PX (1<<3)
/* Set if time in ms in given */
#define OBJ_SET_KEEPTTL (1<<4)
/* Set and keep the ttl */
void
setGenericCommand
(
client
*
c
,
int
flags
,
robj
*
key
,
robj
*
val
,
robj
*
expire
,
int
unit
,
robj
*
ok_reply
,
robj
*
abort_reply
)
{
void
setGenericCommand
(
client
*
c
,
int
flags
,
robj
*
key
,
robj
*
val
,
robj
*
expire
,
int
unit
,
robj
*
ok_reply
,
robj
*
abort_reply
)
{
long
long
milliseconds
=
0
;
/* initialized to avoid any harmness warning */
long
long
milliseconds
=
0
;
/* initialized to avoid any harmness warning */
...
@@ -83,7 +84,7 @@ void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire,
...
@@ -83,7 +84,7 @@ void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire,
addReply
(
c
,
abort_reply
?
abort_reply
:
shared
.
null
[
c
->
resp
]);
addReply
(
c
,
abort_reply
?
abort_reply
:
shared
.
null
[
c
->
resp
]);
return
;
return
;
}
}
setKey
(
c
->
db
,
key
,
val
);
setKey
(
c
->
db
,
key
,
val
,
flags
&
OBJ_SET_KEEPTTL
);
server
.
dirty
++
;
server
.
dirty
++
;
if
(
expire
)
setExpire
(
c
,
c
->
db
,
key
,
mstime
()
+
milliseconds
);
if
(
expire
)
setExpire
(
c
,
c
->
db
,
key
,
mstime
()
+
milliseconds
);
notifyKeyspaceEvent
(
NOTIFY_STRING
,
"set"
,
key
,
c
->
db
->
id
);
notifyKeyspaceEvent
(
NOTIFY_STRING
,
"set"
,
key
,
c
->
db
->
id
);
...
@@ -92,7 +93,7 @@ void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire,
...
@@ -92,7 +93,7 @@ void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire,
addReply
(
c
,
ok_reply
?
ok_reply
:
shared
.
ok
);
addReply
(
c
,
ok_reply
?
ok_reply
:
shared
.
ok
);
}
}
/* SET key value [NX] [XX] [EX <seconds>] [PX <milliseconds>] */
/* SET key value [NX] [XX]
[KEEPTTL]
[EX <seconds>] [PX <milliseconds>] */
void
setCommand
(
client
*
c
)
{
void
setCommand
(
client
*
c
)
{
int
j
;
int
j
;
robj
*
expire
=
NULL
;
robj
*
expire
=
NULL
;
...
@@ -113,8 +114,13 @@ void setCommand(client *c) {
...
@@ -113,8 +114,13 @@ void setCommand(client *c) {
!
(
flags
&
OBJ_SET_NX
))
!
(
flags
&
OBJ_SET_NX
))
{
{
flags
|=
OBJ_SET_XX
;
flags
|=
OBJ_SET_XX
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"KEEPTTL"
)
&&
!
(
flags
&
OBJ_SET_EX
)
&&
!
(
flags
&
OBJ_SET_PX
))
{
flags
|=
OBJ_SET_KEEPTTL
;
}
else
if
((
a
[
0
]
==
'e'
||
a
[
0
]
==
'E'
)
&&
}
else
if
((
a
[
0
]
==
'e'
||
a
[
0
]
==
'E'
)
&&
(
a
[
1
]
==
'x'
||
a
[
1
]
==
'X'
)
&&
a
[
2
]
==
'\0'
&&
(
a
[
1
]
==
'x'
||
a
[
1
]
==
'X'
)
&&
a
[
2
]
==
'\0'
&&
!
(
flags
&
OBJ_SET_KEEPTTL
)
&&
!
(
flags
&
OBJ_SET_PX
)
&&
next
)
!
(
flags
&
OBJ_SET_PX
)
&&
next
)
{
{
flags
|=
OBJ_SET_EX
;
flags
|=
OBJ_SET_EX
;
...
@@ -123,6 +129,7 @@ void setCommand(client *c) {
...
@@ -123,6 +129,7 @@ void setCommand(client *c) {
j
++
;
j
++
;
}
else
if
((
a
[
0
]
==
'p'
||
a
[
0
]
==
'P'
)
&&
}
else
if
((
a
[
0
]
==
'p'
||
a
[
0
]
==
'P'
)
&&
(
a
[
1
]
==
'x'
||
a
[
1
]
==
'X'
)
&&
a
[
2
]
==
'\0'
&&
(
a
[
1
]
==
'x'
||
a
[
1
]
==
'X'
)
&&
a
[
2
]
==
'\0'
&&
!
(
flags
&
OBJ_SET_KEEPTTL
)
&&
!
(
flags
&
OBJ_SET_EX
)
&&
next
)
!
(
flags
&
OBJ_SET_EX
)
&&
next
)
{
{
flags
|=
OBJ_SET_PX
;
flags
|=
OBJ_SET_PX
;
...
@@ -176,7 +183,7 @@ void getCommand(client *c) {
...
@@ -176,7 +183,7 @@ void getCommand(client *c) {
void
getsetCommand
(
client
*
c
)
{
void
getsetCommand
(
client
*
c
)
{
if
(
getGenericCommand
(
c
)
==
C_ERR
)
return
;
if
(
getGenericCommand
(
c
)
==
C_ERR
)
return
;
c
->
argv
[
2
]
=
tryObjectEncoding
(
c
->
argv
[
2
]);
c
->
argv
[
2
]
=
tryObjectEncoding
(
c
->
argv
[
2
]);
setKey
(
c
->
db
,
c
->
argv
[
1
],
c
->
argv
[
2
]);
setKey
(
c
->
db
,
c
->
argv
[
1
],
c
->
argv
[
2
]
,
0
);
notifyKeyspaceEvent
(
NOTIFY_STRING
,
"set"
,
c
->
argv
[
1
],
c
->
db
->
id
);
notifyKeyspaceEvent
(
NOTIFY_STRING
,
"set"
,
c
->
argv
[
1
],
c
->
db
->
id
);
server
.
dirty
++
;
server
.
dirty
++
;
}
}
...
@@ -321,7 +328,7 @@ void msetGenericCommand(client *c, int nx) {
...
@@ -321,7 +328,7 @@ void msetGenericCommand(client *c, int nx) {
for
(
j
=
1
;
j
<
c
->
argc
;
j
+=
2
)
{
for
(
j
=
1
;
j
<
c
->
argc
;
j
+=
2
)
{
c
->
argv
[
j
+
1
]
=
tryObjectEncoding
(
c
->
argv
[
j
+
1
]);
c
->
argv
[
j
+
1
]
=
tryObjectEncoding
(
c
->
argv
[
j
+
1
]);
setKey
(
c
->
db
,
c
->
argv
[
j
],
c
->
argv
[
j
+
1
]);
setKey
(
c
->
db
,
c
->
argv
[
j
],
c
->
argv
[
j
+
1
]
,
0
);
notifyKeyspaceEvent
(
NOTIFY_STRING
,
"set"
,
c
->
argv
[
j
],
c
->
db
->
id
);
notifyKeyspaceEvent
(
NOTIFY_STRING
,
"set"
,
c
->
argv
[
j
],
c
->
db
->
id
);
}
}
server
.
dirty
+=
(
c
->
argc
-
1
)
/
2
;
server
.
dirty
+=
(
c
->
argc
-
1
)
/
2
;
...
...
tests/unit/expire.tcl
View file @
24044f33
...
@@ -219,4 +219,17 @@ start_server {tags {"expire"}} {
...
@@ -219,4 +219,17 @@ start_server {tags {"expire"}} {
set ttl
[
r ttl foo
]
set ttl
[
r ttl foo
]
assert
{
$ttl
<= 98 && $ttl > 90
}
assert
{
$ttl
<= 98 && $ttl > 90
}
}
}
test
{
SET command will remove expire
}
{
r set foo bar EX 100
r set foo bar
r ttl foo
}
{
-1
}
test
{
SET - use KEEPTTL option, TTL should not be removed
}
{
r set foo bar EX 100
r set foo bar KEEPTTL
set ttl
[
r ttl foo
]
assert
{
$ttl
<= 100 && $ttl > 90
}
}
}
}
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