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
3305306f
Commit
3305306f
authored
Apr 01, 2009
by
antirez
Browse files
Initial implementation of EXPIRE
parent
300827b6
Changes
5
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
3305306f
...
@@ -6,7 +6,7 @@ DEBUG?= -g
...
@@ -6,7 +6,7 @@ DEBUG?= -g
CFLAGS
?=
-std
=
c99
-pedantic
-O2
-Wall
-W
-DSDS_ABORT_ON_OOM
CFLAGS
?=
-std
=
c99
-pedantic
-O2
-Wall
-W
-DSDS_ABORT_ON_OOM
CCOPT
=
$(CFLAGS)
CCOPT
=
$(CFLAGS)
OBJ
=
adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o
OBJ
=
adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o
fastlz.o
BENCHOBJ
=
ae.o anet.o benchmark.o sds.o adlist.o zmalloc.o
BENCHOBJ
=
ae.o anet.o benchmark.o sds.o adlist.o zmalloc.o
CLIOBJ
=
anet.o sds.o adlist.o redis-cli.o zmalloc.o
CLIOBJ
=
anet.o sds.o adlist.o redis-cli.o zmalloc.o
...
...
TODO
View file @
3305306f
- GETSET
- GETSET
- Fix pure-PHP lib for the new protocol
- keys expire
- keys expire
- sunion ssub
- sunion ssub
- network layer stresser in test in demo
- network layer stresser in test in demo
...
...
dict.h
View file @
3305306f
...
@@ -107,8 +107,8 @@ typedef struct dictIterator {
...
@@ -107,8 +107,8 @@ typedef struct dictIterator {
#define dictGetEntryKey(he) ((he)->key)
#define dictGetEntryKey(he) ((he)->key)
#define dictGetEntryVal(he) ((he)->val)
#define dictGetEntryVal(he) ((he)->val)
#define dict
GetHashTableSize
(ht) ((ht)->size)
#define dict
Slots
(ht) ((ht)->size)
#define dict
GetHashTableUsed
(ht) ((ht)->used)
#define dict
Size
(ht) ((ht)->used)
/* API */
/* API */
dict
*
dictCreate
(
dictType
*
type
,
void
*
privDataPtr
);
dict
*
dictCreate
(
dictType
*
type
,
void
*
privDataPtr
);
...
...
redis-cli.c
View file @
3305306f
...
@@ -102,6 +102,7 @@ static struct redisCommand cmdTable[] = {
...
@@ -102,6 +102,7 @@ static struct redisCommand cmdTable[] = {
{
"sort"
,
-
2
,
REDIS_CMD_INLINE
},
{
"sort"
,
-
2
,
REDIS_CMD_INLINE
},
{
"info"
,
1
,
REDIS_CMD_INLINE
},
{
"info"
,
1
,
REDIS_CMD_INLINE
},
{
"mget"
,
-
2
,
REDIS_CMD_INLINE
},
{
"mget"
,
-
2
,
REDIS_CMD_INLINE
},
{
"expire"
,
3
,
REDIS_CMD_INLINE
},
{
NULL
,
0
,
0
}
{
NULL
,
0
,
0
}
};
};
...
...
redis.c
View file @
3305306f
...
@@ -158,11 +158,17 @@ typedef struct redisObject {
...
@@ -158,11 +158,17 @@ typedef struct redisObject {
int
refcount
;
int
refcount
;
}
robj
;
}
robj
;
typedef
struct
redisDb
{
dict
*
dict
;
dict
*
expires
;
int
id
;
}
redisDb
;
/* With multiplexing we need to take per-clinet state.
/* With multiplexing we need to take per-clinet state.
* Clients are taken in a liked list. */
* Clients are taken in a liked list. */
typedef
struct
redisClient
{
typedef
struct
redisClient
{
int
fd
;
int
fd
;
dict
*
dict
;
redisDb
*
db
;
int
dictid
;
int
dictid
;
sds
querybuf
;
sds
querybuf
;
robj
*
argv
[
REDIS_MAX_ARGS
];
robj
*
argv
[
REDIS_MAX_ARGS
];
...
@@ -185,7 +191,7 @@ struct saveparam {
...
@@ -185,7 +191,7 @@ struct saveparam {
struct
redisServer
{
struct
redisServer
{
int
port
;
int
port
;
int
fd
;
int
fd
;
dict
**
dict
;
redisDb
*
db
;
dict
*
sharingpool
;
dict
*
sharingpool
;
unsigned
int
sharingpoolsize
;
unsigned
int
sharingpoolsize
;
long
long
dirty
;
/* changes to DB from the last save */
long
long
dirty
;
/* changes to DB from the last save */
...
@@ -276,6 +282,9 @@ static robj *createStringObject(char *ptr, size_t len);
...
@@ -276,6 +282,9 @@ static robj *createStringObject(char *ptr, size_t len);
static
void
replicationFeedSlaves
(
list
*
slaves
,
struct
redisCommand
*
cmd
,
int
dictid
,
robj
**
argv
,
int
argc
);
static
void
replicationFeedSlaves
(
list
*
slaves
,
struct
redisCommand
*
cmd
,
int
dictid
,
robj
**
argv
,
int
argc
);
static
int
syncWithMaster
(
void
);
static
int
syncWithMaster
(
void
);
static
robj
*
tryObjectSharing
(
robj
*
o
);
static
robj
*
tryObjectSharing
(
robj
*
o
);
static
int
removeExpire
(
redisDb
*
db
,
robj
*
key
);
static
int
expireIfNeeded
(
redisDb
*
db
,
robj
*
key
);
static
int
deleteIfVolatile
(
redisDb
*
db
,
robj
*
key
);
static
void
authCommand
(
redisClient
*
c
);
static
void
authCommand
(
redisClient
*
c
);
static
void
pingCommand
(
redisClient
*
c
);
static
void
pingCommand
(
redisClient
*
c
);
...
@@ -324,6 +333,7 @@ static void lremCommand(redisClient *c);
...
@@ -324,6 +333,7 @@ static void lremCommand(redisClient *c);
static
void
infoCommand
(
redisClient
*
c
);
static
void
infoCommand
(
redisClient
*
c
);
static
void
mgetCommand
(
redisClient
*
c
);
static
void
mgetCommand
(
redisClient
*
c
);
static
void
monitorCommand
(
redisClient
*
c
);
static
void
monitorCommand
(
redisClient
*
c
);
static
void
expireCommand
(
redisClient
*
c
);
/*================================= Globals ================================= */
/*================================= Globals ================================= */
...
@@ -378,6 +388,7 @@ static struct redisCommand cmdTable[] = {
...
@@ -378,6 +388,7 @@ static struct redisCommand cmdTable[] = {
{
"sort"
,
sortCommand
,
-
2
,
REDIS_CMD_INLINE
},
{
"sort"
,
sortCommand
,
-
2
,
REDIS_CMD_INLINE
},
{
"info"
,
infoCommand
,
1
,
REDIS_CMD_INLINE
},
{
"info"
,
infoCommand
,
1
,
REDIS_CMD_INLINE
},
{
"monitor"
,
monitorCommand
,
1
,
REDIS_CMD_INLINE
},
{
"monitor"
,
monitorCommand
,
1
,
REDIS_CMD_INLINE
},
{
"expire"
,
expireCommand
,
3
,
REDIS_CMD_INLINE
},
{
NULL
,
NULL
,
0
,
0
}
{
NULL
,
NULL
,
0
,
0
}
};
};
...
@@ -628,8 +639,8 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
...
@@ -628,8 +639,8 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
/* If the percentage of used slots in the HT reaches REDIS_HT_MINFILL
/* If the percentage of used slots in the HT reaches REDIS_HT_MINFILL
* we resize the hash table to save memory */
* we resize the hash table to save memory */
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
size
=
dict
GetHashTableSize
(
server
.
dict
[
j
]
);
size
=
dict
Slots
(
server
.
db
[
j
].
dict
);
used
=
dict
GetHashTableUsed
(
server
.
dict
[
j
]
);
used
=
dict
Size
(
server
.
db
[
j
].
dict
);
if
(
!
(
loops
%
5
)
&&
used
>
0
)
{
if
(
!
(
loops
%
5
)
&&
used
>
0
)
{
redisLog
(
REDIS_DEBUG
,
"DB %d: %d keys in %d slots HT."
,
j
,
used
,
size
);
redisLog
(
REDIS_DEBUG
,
"DB %d: %d keys in %d slots HT."
,
j
,
used
,
size
);
/* dictPrintStats(server.dict); */
/* dictPrintStats(server.dict); */
...
@@ -637,7 +648,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
...
@@ -637,7 +648,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
if
(
size
&&
used
&&
size
>
REDIS_HT_MINSLOTS
&&
if
(
size
&&
used
&&
size
>
REDIS_HT_MINSLOTS
&&
(
used
*
100
/
size
<
REDIS_HT_MINFILL
))
{
(
used
*
100
/
size
<
REDIS_HT_MINFILL
))
{
redisLog
(
REDIS_NOTICE
,
"The hash table %d is too sparse, resize it..."
,
j
);
redisLog
(
REDIS_NOTICE
,
"The hash table %d is too sparse, resize it..."
,
j
);
dictResize
(
server
.
dict
[
j
]
);
dictResize
(
server
.
d
b
[
j
].
d
ict
);
redisLog
(
REDIS_NOTICE
,
"Hash table %d resized."
,
j
);
redisLog
(
REDIS_NOTICE
,
"Hash table %d resized."
,
j
);
}
}
}
}
...
@@ -648,7 +659,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
...
@@ -648,7 +659,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
listLength
(
server
.
clients
)
-
listLength
(
server
.
slaves
),
listLength
(
server
.
clients
)
-
listLength
(
server
.
slaves
),
listLength
(
server
.
slaves
),
listLength
(
server
.
slaves
),
server
.
usedmemory
,
server
.
usedmemory
,
dict
GetHashTableUsed
(
server
.
sharingpool
));
dict
Size
(
server
.
sharingpool
));
}
}
/* Close connections of timedout clients */
/* Close connections of timedout clients */
...
@@ -787,18 +798,21 @@ static void initServer() {
...
@@ -787,18 +798,21 @@ static void initServer() {
server
.
objfreelist
=
listCreate
();
server
.
objfreelist
=
listCreate
();
createSharedObjects
();
createSharedObjects
();
server
.
el
=
aeCreateEventLoop
();
server
.
el
=
aeCreateEventLoop
();
server
.
d
ict
=
zmalloc
(
sizeof
(
dict
*
)
*
server
.
dbnum
);
server
.
d
b
=
zmalloc
(
sizeof
(
redisDb
)
*
server
.
dbnum
);
server
.
sharingpool
=
dictCreate
(
&
setDictType
,
NULL
);
server
.
sharingpool
=
dictCreate
(
&
setDictType
,
NULL
);
server
.
sharingpoolsize
=
1024
;
server
.
sharingpoolsize
=
1024
;
if
(
!
server
.
d
ict
||
!
server
.
clients
||
!
server
.
slaves
||
!
server
.
monitors
||
!
server
.
el
||
!
server
.
objfreelist
)
if
(
!
server
.
d
b
||
!
server
.
clients
||
!
server
.
slaves
||
!
server
.
monitors
||
!
server
.
el
||
!
server
.
objfreelist
)
oom
(
"server initialization"
);
/* Fatal OOM */
oom
(
"server initialization"
);
/* Fatal OOM */
server
.
fd
=
anetTcpServer
(
server
.
neterr
,
server
.
port
,
server
.
bindaddr
);
server
.
fd
=
anetTcpServer
(
server
.
neterr
,
server
.
port
,
server
.
bindaddr
);
if
(
server
.
fd
==
-
1
)
{
if
(
server
.
fd
==
-
1
)
{
redisLog
(
REDIS_WARNING
,
"Opening TCP port: %s"
,
server
.
neterr
);
redisLog
(
REDIS_WARNING
,
"Opening TCP port: %s"
,
server
.
neterr
);
exit
(
1
);
exit
(
1
);
}
}
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
server
.
dict
[
j
]
=
dictCreate
(
&
hashDictType
,
NULL
);
server
.
db
[
j
].
dict
=
dictCreate
(
&
hashDictType
,
NULL
);
server
.
db
[
j
].
expires
=
dictCreate
(
&
setDictType
,
NULL
);
server
.
db
[
j
].
id
=
j
;
}
server
.
cronloops
=
0
;
server
.
cronloops
=
0
;
server
.
bgsaveinprogress
=
0
;
server
.
bgsaveinprogress
=
0
;
server
.
lastsave
=
time
(
NULL
);
server
.
lastsave
=
time
(
NULL
);
...
@@ -814,8 +828,10 @@ static void initServer() {
...
@@ -814,8 +828,10 @@ static void initServer() {
static
void
emptyDb
()
{
static
void
emptyDb
()
{
int
j
;
int
j
;
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
dictEmpty
(
server
.
dict
[
j
]);
dictEmpty
(
server
.
db
[
j
].
dict
);
dictEmpty
(
server
.
db
[
j
].
expires
);
}
}
}
/* I agree, this is a very rudimental way to load a configuration...
/* I agree, this is a very rudimental way to load a configuration...
...
@@ -1150,9 +1166,9 @@ static int processCommand(redisClient *c) {
...
@@ -1150,9 +1166,9 @@ static int processCommand(redisClient *c) {
dirty
=
server
.
dirty
;
dirty
=
server
.
dirty
;
cmd
->
proc
(
c
);
cmd
->
proc
(
c
);
if
(
server
.
dirty
-
dirty
!=
0
&&
listLength
(
server
.
slaves
))
if
(
server
.
dirty
-
dirty
!=
0
&&
listLength
(
server
.
slaves
))
replicationFeedSlaves
(
server
.
slaves
,
cmd
,
c
->
d
ict
id
,
c
->
argv
,
c
->
argc
);
replicationFeedSlaves
(
server
.
slaves
,
cmd
,
c
->
d
b
->
id
,
c
->
argv
,
c
->
argc
);
if
(
listLength
(
server
.
monitors
))
if
(
listLength
(
server
.
monitors
))
replicationFeedSlaves
(
server
.
monitors
,
cmd
,
c
->
d
ict
id
,
c
->
argv
,
c
->
argc
);
replicationFeedSlaves
(
server
.
monitors
,
cmd
,
c
->
d
b
->
id
,
c
->
argv
,
c
->
argc
);
server
.
stat_numcommands
++
;
server
.
stat_numcommands
++
;
/* Prepare the client for the next command */
/* Prepare the client for the next command */
...
@@ -1310,8 +1326,7 @@ again:
...
@@ -1310,8 +1326,7 @@ again:
static
int
selectDb
(
redisClient
*
c
,
int
id
)
{
static
int
selectDb
(
redisClient
*
c
,
int
id
)
{
if
(
id
<
0
||
id
>=
server
.
dbnum
)
if
(
id
<
0
||
id
>=
server
.
dbnum
)
return
REDIS_ERR
;
return
REDIS_ERR
;
c
->
dict
=
server
.
dict
[
id
];
c
->
db
=
&
server
.
db
[
id
];
c
->
dictid
=
id
;
return
REDIS_OK
;
return
REDIS_OK
;
}
}
...
@@ -1413,14 +1428,6 @@ static robj *createSetObject(void) {
...
@@ -1413,14 +1428,6 @@ static robj *createSetObject(void) {
return
createObject
(
REDIS_SET
,
d
);
return
createObject
(
REDIS_SET
,
d
);
}
}
#if 0
static robj *createHashObject(void) {
dict *d = dictCreate(&hashDictType,NULL);
if (!d) oom("dictCreate");
return createObject(REDIS_SET,d);
}
#endif
static
void
freeStringObject
(
robj
*
o
)
{
static
void
freeStringObject
(
robj
*
o
)
{
sdsfree
(
o
->
ptr
);
sdsfree
(
o
->
ptr
);
}
}
...
@@ -1462,7 +1469,7 @@ static robj *tryObjectSharing(robj *o) {
...
@@ -1462,7 +1469,7 @@ static robj *tryObjectSharing(robj *o) {
struct
dictEntry
*
de
;
struct
dictEntry
*
de
;
unsigned
long
c
;
unsigned
long
c
;
if
(
server
.
shareobjects
==
0
)
return
o
;
if
(
o
==
NULL
||
server
.
shareobjects
==
0
)
return
o
;
assert
(
o
->
type
==
REDIS_STRING
);
assert
(
o
->
type
==
REDIS_STRING
);
de
=
dictFind
(
server
.
sharingpool
,
o
);
de
=
dictFind
(
server
.
sharingpool
,
o
);
...
@@ -1479,7 +1486,7 @@ static robj *tryObjectSharing(robj *o) {
...
@@ -1479,7 +1486,7 @@ static robj *tryObjectSharing(robj *o) {
* shared we increment its count, everytime there is a miss we
* shared we increment its count, everytime there is a miss we
* recrement the counter of a random object. If this object reaches
* recrement the counter of a random object. If this object reaches
* zero we remove the object and put the current object instead. */
* zero we remove the object and put the current object instead. */
if
(
dict
GetHashTableUsed
(
server
.
sharingpool
)
>=
if
(
dict
Size
(
server
.
sharingpool
)
>=
server
.
sharingpoolsize
)
{
server
.
sharingpoolsize
)
{
de
=
dictGetRandomKey
(
server
.
sharingpool
);
de
=
dictGetRandomKey
(
server
.
sharingpool
);
assert
(
de
!=
NULL
);
assert
(
de
!=
NULL
);
...
@@ -1502,6 +1509,26 @@ static robj *tryObjectSharing(robj *o) {
...
@@ -1502,6 +1509,26 @@ static robj *tryObjectSharing(robj *o) {
}
}
}
}
static
robj
*
lookupKey
(
redisDb
*
db
,
robj
*
key
)
{
dictEntry
*
de
=
dictFind
(
db
->
dict
,
key
);
return
de
?
dictGetEntryVal
(
de
)
:
NULL
;
}
static
robj
*
lookupKeyRead
(
redisDb
*
db
,
robj
*
key
)
{
expireIfNeeded
(
db
,
key
);
return
lookupKey
(
db
,
key
);
}
static
robj
*
lookupKeyWrite
(
redisDb
*
db
,
robj
*
key
)
{
deleteIfVolatile
(
db
,
key
);
return
lookupKey
(
db
,
key
);
}
static
int
deleteKey
(
redisDb
*
db
,
robj
*
key
)
{
if
(
dictSize
(
db
->
expires
))
dictDelete
(
db
->
expires
,
key
);
return
dictDelete
(
db
->
dict
,
key
)
==
DICT_OK
;
}
/*============================ DB saving/loading ============================ */
/*============================ DB saving/loading ============================ */
static
int
rdbSaveType
(
FILE
*
fp
,
unsigned
char
type
)
{
static
int
rdbSaveType
(
FILE
*
fp
,
unsigned
char
type
)
{
...
@@ -1604,8 +1631,8 @@ static int rdbSave(char *filename) {
...
@@ -1604,8 +1631,8 @@ static int rdbSave(char *filename) {
}
}
if
(
fwrite
(
"REDIS0001"
,
9
,
1
,
fp
)
==
0
)
goto
werr
;
if
(
fwrite
(
"REDIS0001"
,
9
,
1
,
fp
)
==
0
)
goto
werr
;
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
dict
*
d
=
server
.
dict
[
j
]
;
dict
*
d
=
server
.
d
b
[
j
].
d
ict
;
if
(
dict
GetHashTableUsed
(
d
)
==
0
)
continue
;
if
(
dict
Size
(
d
)
==
0
)
continue
;
di
=
dictGetIterator
(
d
);
di
=
dictGetIterator
(
d
);
if
(
!
di
)
{
if
(
!
di
)
{
fclose
(
fp
);
fclose
(
fp
);
...
@@ -1645,7 +1672,7 @@ static int rdbSave(char *filename) {
...
@@ -1645,7 +1672,7 @@ static int rdbSave(char *filename) {
dictEntry
*
de
;
dictEntry
*
de
;
if
(
!
set
)
oom
(
"dictGetIteraotr"
);
if
(
!
set
)
oom
(
"dictGetIteraotr"
);
if
(
rdbSaveLen
(
fp
,
dict
GetHashTableUsed
(
set
))
==
-
1
)
goto
werr
;
if
(
rdbSaveLen
(
fp
,
dict
Size
(
set
))
==
-
1
)
goto
werr
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
eleobj
=
dictGetEntryKey
(
de
);
robj
*
eleobj
=
dictGetEntryKey
(
de
);
...
@@ -1785,7 +1812,7 @@ static robj *rdbLoadStringObject(FILE*fp, int rdbver) {
...
@@ -1785,7 +1812,7 @@ static robj *rdbLoadStringObject(FILE*fp, int rdbver) {
case
REDIS_RDB_ENC_INT8
:
case
REDIS_RDB_ENC_INT8
:
case
REDIS_RDB_ENC_INT16
:
case
REDIS_RDB_ENC_INT16
:
case
REDIS_RDB_ENC_INT32
:
case
REDIS_RDB_ENC_INT32
:
return
rdbLoadIntegerObject
(
fp
,
len
);
return
tryObjectSharing
(
rdbLoadIntegerObject
(
fp
,
len
)
)
;
default:
default:
assert
(
0
!=
0
);
assert
(
0
!=
0
);
}
}
...
@@ -1806,7 +1833,7 @@ static int rdbLoad(char *filename) {
...
@@ -1806,7 +1833,7 @@ static int rdbLoad(char *filename) {
uint32_t
dbid
;
uint32_t
dbid
;
int
type
;
int
type
;
int
retval
;
int
retval
;
dict
*
d
=
server
.
dict
[
0
]
;
dict
*
d
=
server
.
d
b
[
0
].
d
ict
;
char
buf
[
1024
];
char
buf
[
1024
];
int
rdbver
;
int
rdbver
;
fp
=
fopen
(
filename
,
"r"
);
fp
=
fopen
(
filename
,
"r"
);
...
@@ -1838,7 +1865,7 @@ static int rdbLoad(char *filename) {
...
@@ -1838,7 +1865,7 @@ static int rdbLoad(char *filename) {
redisLog
(
REDIS_WARNING
,
"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting
\n
"
,
server
.
dbnum
);
redisLog
(
REDIS_WARNING
,
"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting
\n
"
,
server
.
dbnum
);
exit
(
1
);
exit
(
1
);
}
}
d
=
server
.
d
ict
[
dbid
];
d
=
server
.
d
b
[
dbid
]
.
dict
;
continue
;
continue
;
}
}
/* Read key */
/* Read key */
...
@@ -1916,10 +1943,10 @@ static void echoCommand(redisClient *c) {
...
@@ -1916,10 +1943,10 @@ static void echoCommand(redisClient *c) {
static
void
setGenericCommand
(
redisClient
*
c
,
int
nx
)
{
static
void
setGenericCommand
(
redisClient
*
c
,
int
nx
)
{
int
retval
;
int
retval
;
retval
=
dictAdd
(
c
->
dict
,
c
->
argv
[
1
],
c
->
argv
[
2
]);
retval
=
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
1
],
c
->
argv
[
2
]);
if
(
retval
==
DICT_ERR
)
{
if
(
retval
==
DICT_ERR
)
{
if
(
!
nx
)
{
if
(
!
nx
)
{
dictReplace
(
c
->
dict
,
c
->
argv
[
1
],
c
->
argv
[
2
]);
dictReplace
(
c
->
db
->
dict
,
c
->
argv
[
1
],
c
->
argv
[
2
]);
incrRefCount
(
c
->
argv
[
2
]);
incrRefCount
(
c
->
argv
[
2
]);
}
else
{
}
else
{
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
...
@@ -1930,6 +1957,7 @@ static void setGenericCommand(redisClient *c, int nx) {
...
@@ -1930,6 +1957,7 @@ static void setGenericCommand(redisClient *c, int nx) {
incrRefCount
(
c
->
argv
[
2
]);
incrRefCount
(
c
->
argv
[
2
]);
}
}
server
.
dirty
++
;
server
.
dirty
++
;
removeExpire
(
c
->
db
,
c
->
argv
[
1
]);
addReply
(
c
,
nx
?
shared
.
cone
:
shared
.
ok
);
addReply
(
c
,
nx
?
shared
.
cone
:
shared
.
ok
);
}
}
...
@@ -1942,14 +1970,11 @@ static void setnxCommand(redisClient *c) {
...
@@ -1942,14 +1970,11 @@ static void setnxCommand(redisClient *c) {
}
}
static
void
getCommand
(
redisClient
*
c
)
{
static
void
getCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
=
lookupKeyRead
(
c
->
db
,
c
->
argv
[
1
]);
de
=
dictFind
(
c
->
dict
,
c
->
argv
[
1
]);
if
(
o
==
NULL
)
{
if
(
de
==
NULL
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
(
c
,
shared
.
nullbulk
);
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_STRING
)
{
if
(
o
->
type
!=
REDIS_STRING
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
...
@@ -1961,17 +1986,14 @@ static void getCommand(redisClient *c) {
...
@@ -1961,17 +1986,14 @@ static void getCommand(redisClient *c) {
}
}
static
void
mgetCommand
(
redisClient
*
c
)
{
static
void
mgetCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
int
j
;
int
j
;
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"*%d
\r\n
"
,
c
->
argc
-
1
));
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"*%d
\r\n
"
,
c
->
argc
-
1
));
for
(
j
=
1
;
j
<
c
->
argc
;
j
++
)
{
for
(
j
=
1
;
j
<
c
->
argc
;
j
++
)
{
de
=
dictFin
d
(
c
->
d
ict
,
c
->
argv
[
j
]);
robj
*
o
=
lookupKeyRea
d
(
c
->
d
b
,
c
->
argv
[
j
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
(
c
,
shared
.
nullbulk
);
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_STRING
)
{
if
(
o
->
type
!=
REDIS_STRING
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
(
c
,
shared
.
nullbulk
);
}
else
{
}
else
{
...
@@ -1984,17 +2006,14 @@ static void mgetCommand(redisClient *c) {
...
@@ -1984,17 +2006,14 @@ static void mgetCommand(redisClient *c) {
}
}
static
void
incrDecrCommand
(
redisClient
*
c
,
int
incr
)
{
static
void
incrDecrCommand
(
redisClient
*
c
,
int
incr
)
{
dictEntry
*
de
;
long
long
value
;
long
long
value
;
int
retval
;
int
retval
;
robj
*
o
;
robj
*
o
;
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
value
=
0
;
value
=
0
;
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_STRING
)
{
if
(
o
->
type
!=
REDIS_STRING
)
{
value
=
0
;
value
=
0
;
}
else
{
}
else
{
...
@@ -2006,9 +2025,10 @@ static void incrDecrCommand(redisClient *c, int incr) {
...
@@ -2006,9 +2025,10 @@ static void incrDecrCommand(redisClient *c, int incr) {
value
+=
incr
;
value
+=
incr
;
o
=
createObject
(
REDIS_STRING
,
sdscatprintf
(
sdsempty
(),
"%lld"
,
value
));
o
=
createObject
(
REDIS_STRING
,
sdscatprintf
(
sdsempty
(),
"%lld"
,
value
));
retval
=
dictAdd
(
c
->
dict
,
c
->
argv
[
1
],
o
);
retval
=
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
1
],
o
);
if
(
retval
==
DICT_ERR
)
{
if
(
retval
==
DICT_ERR
)
{
dictReplace
(
c
->
dict
,
c
->
argv
[
1
],
o
);
dictReplace
(
c
->
db
->
dict
,
c
->
argv
[
1
],
o
);
removeExpire
(
c
->
db
,
c
->
argv
[
1
]);
}
else
{
}
else
{
incrRefCount
(
c
->
argv
[
1
]);
incrRefCount
(
c
->
argv
[
1
]);
}
}
...
@@ -2039,7 +2059,7 @@ static void decrbyCommand(redisClient *c) {
...
@@ -2039,7 +2059,7 @@ static void decrbyCommand(redisClient *c) {
/* ========================= Type agnostic commands ========================= */
/* ========================= Type agnostic commands ========================= */
static
void
delCommand
(
redisClient
*
c
)
{
static
void
delCommand
(
redisClient
*
c
)
{
if
(
d
ictD
elete
(
c
->
d
ict
,
c
->
argv
[
1
])
==
DICT_OK
)
{
if
(
delete
Key
(
c
->
d
b
,
c
->
argv
[
1
]))
{
server
.
dirty
++
;
server
.
dirty
++
;
addReply
(
c
,
shared
.
cone
);
addReply
(
c
,
shared
.
cone
);
}
else
{
}
else
{
...
@@ -2048,13 +2068,7 @@ static void delCommand(redisClient *c) {
...
@@ -2048,13 +2068,7 @@ static void delCommand(redisClient *c) {
}
}
static
void
existsCommand
(
redisClient
*
c
)
{
static
void
existsCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
addReply
(
c
,
lookupKeyRead
(
c
->
db
,
c
->
argv
[
1
])
?
shared
.
cone
:
shared
.
czero
);
de
=
dictFind
(
c
->
dict
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
addReply
(
c
,
shared
.
czero
);
else
addReply
(
c
,
shared
.
cone
);
}
}
static
void
selectCommand
(
redisClient
*
c
)
{
static
void
selectCommand
(
redisClient
*
c
)
{
...
@@ -2069,8 +2083,11 @@ static void selectCommand(redisClient *c) {
...
@@ -2069,8 +2083,11 @@ static void selectCommand(redisClient *c) {
static
void
randomkeyCommand
(
redisClient
*
c
)
{
static
void
randomkeyCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
dictEntry
*
de
;
de
=
dictGetRandomKey
(
c
->
dict
);
while
(
1
)
{
de
=
dictGetRandomKey
(
c
->
db
->
dict
);
if
(
expireIfNeeded
(
c
->
db
,
dictGetEntryKey
(
de
))
==
0
)
break
;
}
if
(
de
==
NULL
)
{
if
(
de
==
NULL
)
{
addReply
(
c
,
shared
.
crlf
);
addReply
(
c
,
shared
.
crlf
);
}
else
{
}
else
{
...
@@ -2088,20 +2105,23 @@ static void keysCommand(redisClient *c) {
...
@@ -2088,20 +2105,23 @@ static void keysCommand(redisClient *c) {
int
numkeys
=
0
,
keyslen
=
0
;
int
numkeys
=
0
,
keyslen
=
0
;
robj
*
lenobj
=
createObject
(
REDIS_STRING
,
NULL
);
robj
*
lenobj
=
createObject
(
REDIS_STRING
,
NULL
);
di
=
dictGetIterator
(
c
->
dict
);
di
=
dictGetIterator
(
c
->
db
->
dict
);
if
(
!
di
)
oom
(
"dictGetIterator"
);
if
(
!
di
)
oom
(
"dictGetIterator"
);
addReply
(
c
,
lenobj
);
addReply
(
c
,
lenobj
);
decrRefCount
(
lenobj
);
decrRefCount
(
lenobj
);
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
keyobj
=
dictGetEntryKey
(
de
);
robj
*
keyobj
=
dictGetEntryKey
(
de
);
sds
key
=
keyobj
->
ptr
;
sds
key
=
keyobj
->
ptr
;
if
((
pattern
[
0
]
==
'*'
&&
pattern
[
1
]
==
'\0'
)
||
if
((
pattern
[
0
]
==
'*'
&&
pattern
[
1
]
==
'\0'
)
||
stringmatchlen
(
pattern
,
plen
,
key
,
sdslen
(
key
),
0
))
{
stringmatchlen
(
pattern
,
plen
,
key
,
sdslen
(
key
),
0
))
{
if
(
numkeys
!=
0
)
if
(
expireIfNeeded
(
c
->
db
,
keyobj
)
==
0
)
{
addReply
(
c
,
shared
.
space
);
if
(
numkeys
!=
0
)
addReply
(
c
,
keyobj
);
addReply
(
c
,
shared
.
space
);
numkeys
++
;
addReply
(
c
,
keyobj
);
keyslen
+=
sdslen
(
key
);
numkeys
++
;
keyslen
+=
sdslen
(
key
);
}
}
}
}
}
dictReleaseIterator
(
di
);
dictReleaseIterator
(
di
);
...
@@ -2111,7 +2131,7 @@ static void keysCommand(redisClient *c) {
...
@@ -2111,7 +2131,7 @@ static void keysCommand(redisClient *c) {
static
void
dbsizeCommand
(
redisClient
*
c
)
{
static
void
dbsizeCommand
(
redisClient
*
c
)
{
addReplySds
(
c
,
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
":%lu
\r\n
"
,
dict
GetHashTableUsed
(
c
->
dict
)));
sdscatprintf
(
sdsempty
(),
":%lu
\r\n
"
,
dict
Size
(
c
->
db
->
dict
)));
}
}
static
void
lastsaveCommand
(
redisClient
*
c
)
{
static
void
lastsaveCommand
(
redisClient
*
c
)
{
...
@@ -2120,15 +2140,13 @@ static void lastsaveCommand(redisClient *c) {
...
@@ -2120,15 +2140,13 @@ static void lastsaveCommand(redisClient *c) {
}
}
static
void
typeCommand
(
redisClient
*
c
)
{
static
void
typeCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
char
*
type
;
char
*
type
;
de
=
dictFin
d
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyRea
d
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
type
=
"+none"
;
type
=
"+none"
;
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
switch
(
o
->
type
)
{
switch
(
o
->
type
)
{
case
REDIS_STRING
:
type
=
"+string"
;
break
;
case
REDIS_STRING
:
type
=
"+string"
;
break
;
case
REDIS_LIST
:
type
=
"+list"
;
break
;
case
REDIS_LIST
:
type
=
"+list"
;
break
;
...
@@ -2175,7 +2193,6 @@ static void shutdownCommand(redisClient *c) {
...
@@ -2175,7 +2193,6 @@ static void shutdownCommand(redisClient *c) {
}
}
static
void
renameGenericCommand
(
redisClient
*
c
,
int
nx
)
{
static
void
renameGenericCommand
(
redisClient
*
c
,
int
nx
)
{
dictEntry
*
de
;
robj
*
o
;
robj
*
o
;
/* To use the same key as src and dst is probably an error */
/* To use the same key as src and dst is probably an error */
...
@@ -2184,24 +2201,24 @@ static void renameGenericCommand(redisClient *c, int nx) {
...
@@ -2184,24 +2201,24 @@ static void renameGenericCommand(redisClient *c, int nx) {
return
;
return
;
}
}
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nokeyerr
);
addReply
(
c
,
shared
.
nokeyerr
);
return
;
return
;
}
}
o
=
dictGetEntryVal
(
de
);
incrRefCount
(
o
);
incrRefCount
(
o
);
if
(
dictAdd
(
c
->
dict
,
c
->
argv
[
2
],
o
)
==
DICT_ERR
)
{
deleteIfVolatile
(
c
->
db
,
c
->
argv
[
2
]);
if
(
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
2
],
o
)
==
DICT_ERR
)
{
if
(
nx
)
{
if
(
nx
)
{
decrRefCount
(
o
);
decrRefCount
(
o
);
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
return
;
return
;
}
}
dictReplace
(
c
->
dict
,
c
->
argv
[
2
],
o
);
dictReplace
(
c
->
db
->
dict
,
c
->
argv
[
2
],
o
);
}
else
{
}
else
{
incrRefCount
(
c
->
argv
[
2
]);
incrRefCount
(
c
->
argv
[
2
]);
}
}
d
ictD
elete
(
c
->
d
ict
,
c
->
argv
[
1
]);
delete
Key
(
c
->
d
b
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
addReply
(
c
,
nx
?
shared
.
cone
:
shared
.
ok
);
addReply
(
c
,
nx
?
shared
.
cone
:
shared
.
ok
);
}
}
...
@@ -2215,21 +2232,19 @@ static void renamenxCommand(redisClient *c) {
...
@@ -2215,21 +2232,19 @@ static void renamenxCommand(redisClient *c) {
}
}
static
void
moveCommand
(
redisClient
*
c
)
{
static
void
moveCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
robj
*
o
,
*
key
;
redisDb
*
src
,
*
dst
;
dict
*
src
,
*
dst
;
int
srcid
;
int
srcid
;
/* Obtain source and target DB pointers */
/* Obtain source and target DB pointers */
src
=
c
->
d
ict
;
src
=
c
->
d
b
;
srcid
=
c
->
d
ict
id
;
srcid
=
c
->
d
b
->
id
;
if
(
selectDb
(
c
,
atoi
(
c
->
argv
[
2
]
->
ptr
))
==
REDIS_ERR
)
{
if
(
selectDb
(
c
,
atoi
(
c
->
argv
[
2
]
->
ptr
))
==
REDIS_ERR
)
{
addReply
(
c
,
shared
.
outofrangeerr
);
addReply
(
c
,
shared
.
outofrangeerr
);
return
;
return
;
}
}
dst
=
c
->
dict
;
dst
=
c
->
db
;
c
->
dict
=
src
;
selectDb
(
c
,
srcid
);
/* Back to the source DB */
c
->
dictid
=
srcid
;
/* If the user is moving using as target the same
/* If the user is moving using as target the same
* DB as the source DB it is probably an error. */
* DB as the source DB it is probably an error. */
...
@@ -2239,24 +2254,23 @@ static void moveCommand(redisClient *c) {
...
@@ -2239,24 +2254,23 @@ static void moveCommand(redisClient *c) {
}
}
/* Check if the element exists and get a reference */
/* Check if the element exists and get a reference */
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
!
de
)
{
if
(
!
o
)
{
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
return
;
return
;
}
}
/* Try to add the element to the target DB */
/* Try to add the element to the target DB */
key
=
dictGetEntryKey
(
de
);
deleteIfVolatile
(
dst
,
c
->
argv
[
1
]);
o
=
dictGetEntryVal
(
de
);
if
(
dictAdd
(
dst
->
dict
,
c
->
argv
[
1
],
o
)
==
DICT_ERR
)
{
if
(
dictAdd
(
dst
,
key
,
o
)
==
DICT_ERR
)
{
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
return
;
return
;
}
}
incrRefCount
(
key
);
incrRefCount
(
c
->
argv
[
1
]
);
incrRefCount
(
o
);
incrRefCount
(
o
);
/* OK! key moved, free the entry in the source DB */
/* OK! key moved, free the entry in the source DB */
d
ictD
elete
(
src
,
c
->
argv
[
1
]);
delete
Key
(
src
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
addReply
(
c
,
shared
.
cone
);
addReply
(
c
,
shared
.
cone
);
}
}
...
@@ -2264,11 +2278,10 @@ static void moveCommand(redisClient *c) {
...
@@ -2264,11 +2278,10 @@ static void moveCommand(redisClient *c) {
/* =================================== Lists ================================ */
/* =================================== Lists ================================ */
static
void
pushGenericCommand
(
redisClient
*
c
,
int
where
)
{
static
void
pushGenericCommand
(
redisClient
*
c
,
int
where
)
{
robj
*
lobj
;
robj
*
lobj
;
dictEntry
*
de
;
list
*
list
;
list
*
list
;
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
lobj
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
lobj
==
NULL
)
{
lobj
=
createListObject
();
lobj
=
createListObject
();
list
=
lobj
->
ptr
;
list
=
lobj
->
ptr
;
if
(
where
==
REDIS_HEAD
)
{
if
(
where
==
REDIS_HEAD
)
{
...
@@ -2276,11 +2289,10 @@ static void pushGenericCommand(redisClient *c, int where) {
...
@@ -2276,11 +2289,10 @@ static void pushGenericCommand(redisClient *c, int where) {
}
else
{
}
else
{
if
(
!
listAddNodeTail
(
list
,
c
->
argv
[
2
]))
oom
(
"listAddNodeTail"
);
if
(
!
listAddNodeTail
(
list
,
c
->
argv
[
2
]))
oom
(
"listAddNodeTail"
);
}
}
dictAdd
(
c
->
dict
,
c
->
argv
[
1
],
lobj
);
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
1
],
lobj
);
incrRefCount
(
c
->
argv
[
1
]);
incrRefCount
(
c
->
argv
[
1
]);
incrRefCount
(
c
->
argv
[
2
]);
incrRefCount
(
c
->
argv
[
2
]);
}
else
{
}
else
{
lobj
=
dictGetEntryVal
(
de
);
if
(
lobj
->
type
!=
REDIS_LIST
)
{
if
(
lobj
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
return
;
return
;
...
@@ -2306,15 +2318,14 @@ static void rpushCommand(redisClient *c) {
...
@@ -2306,15 +2318,14 @@ static void rpushCommand(redisClient *c) {
}
}
static
void
llenCommand
(
redisClient
*
c
)
{
static
void
llenCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
list
*
l
;
list
*
l
;
de
=
dictFin
d
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyRea
d
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
return
;
return
;
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_LIST
)
{
if
(
o
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
...
@@ -2325,15 +2336,13 @@ static void llenCommand(redisClient *c) {
...
@@ -2325,15 +2336,13 @@ static void llenCommand(redisClient *c) {
}
}
static
void
lindexCommand
(
redisClient
*
c
)
{
static
void
lindexCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
int
index
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
int
index
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
de
=
dictFin
d
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyRea
d
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
(
c
,
shared
.
nullbulk
);
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_LIST
)
{
if
(
o
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
...
@@ -2354,15 +2363,13 @@ static void lindexCommand(redisClient *c) {
...
@@ -2354,15 +2363,13 @@ static void lindexCommand(redisClient *c) {
}
}
static
void
lsetCommand
(
redisClient
*
c
)
{
static
void
lsetCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
int
index
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
int
index
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nokeyerr
);
addReply
(
c
,
shared
.
nokeyerr
);
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_LIST
)
{
if
(
o
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
...
@@ -2386,14 +2393,12 @@ static void lsetCommand(redisClient *c) {
...
@@ -2386,14 +2393,12 @@ static void lsetCommand(redisClient *c) {
}
}
static
void
popGenericCommand
(
redisClient
*
c
,
int
where
)
{
static
void
popGenericCommand
(
redisClient
*
c
,
int
where
)
{
dictEntry
*
de
;
robj
*
o
;
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
(
c
,
shared
.
nullbulk
);
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_LIST
)
{
if
(
o
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
...
@@ -2428,16 +2433,14 @@ static void rpopCommand(redisClient *c) {
...
@@ -2428,16 +2433,14 @@ static void rpopCommand(redisClient *c) {
}
}
static
void
lrangeCommand
(
redisClient
*
c
)
{
static
void
lrangeCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
int
start
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
int
start
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
int
end
=
atoi
(
c
->
argv
[
3
]
->
ptr
);
int
end
=
atoi
(
c
->
argv
[
3
]
->
ptr
);
de
=
dictFin
d
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyRea
d
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nullmultibulk
);
addReply
(
c
,
shared
.
nullmultibulk
);
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_LIST
)
{
if
(
o
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
...
@@ -2477,16 +2480,14 @@ static void lrangeCommand(redisClient *c) {
...
@@ -2477,16 +2480,14 @@ static void lrangeCommand(redisClient *c) {
}
}
static
void
ltrimCommand
(
redisClient
*
c
)
{
static
void
ltrimCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
int
start
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
int
start
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
int
end
=
atoi
(
c
->
argv
[
3
]
->
ptr
);
int
end
=
atoi
(
c
->
argv
[
3
]
->
ptr
);
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nokeyerr
);
addReply
(
c
,
shared
.
nokeyerr
);
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_LIST
)
{
if
(
o
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
...
@@ -2528,14 +2529,12 @@ static void ltrimCommand(redisClient *c) {
...
@@ -2528,14 +2529,12 @@ static void ltrimCommand(redisClient *c) {
}
}
static
void
lremCommand
(
redisClient
*
c
)
{
static
void
lremCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nokeyerr
);
addReply
(
c
,
shared
.
nokeyerr
);
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_LIST
)
{
if
(
o
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
...
@@ -2570,16 +2569,14 @@ static void lremCommand(redisClient *c) {
...
@@ -2570,16 +2569,14 @@ static void lremCommand(redisClient *c) {
/* ==================================== Sets ================================ */
/* ==================================== Sets ================================ */
static
void
saddCommand
(
redisClient
*
c
)
{
static
void
saddCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
set
;
robj
*
set
;
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
set
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
set
==
NULL
)
{
set
=
createSetObject
();
set
=
createSetObject
();
dictAdd
(
c
->
dict
,
c
->
argv
[
1
],
set
);
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
1
],
set
);
incrRefCount
(
c
->
argv
[
1
]);
incrRefCount
(
c
->
argv
[
1
]);
}
else
{
}
else
{
set
=
dictGetEntryVal
(
de
);
if
(
set
->
type
!=
REDIS_SET
)
{
if
(
set
->
type
!=
REDIS_SET
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
return
;
return
;
...
@@ -2595,15 +2592,12 @@ static void saddCommand(redisClient *c) {
...
@@ -2595,15 +2592,12 @@ static void saddCommand(redisClient *c) {
}
}
static
void
sremCommand
(
redisClient
*
c
)
{
static
void
sremCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
set
;
de
=
dictFind
(
c
->
d
ict
,
c
->
argv
[
1
]);
set
=
lookupKeyWrite
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
set
==
NULL
)
{
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
}
else
{
}
else
{
robj
*
set
;
set
=
dictGetEntryVal
(
de
);
if
(
set
->
type
!=
REDIS_SET
)
{
if
(
set
->
type
!=
REDIS_SET
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
return
;
return
;
...
@@ -2618,15 +2612,12 @@ static void sremCommand(redisClient *c) {
...
@@ -2618,15 +2612,12 @@ static void sremCommand(redisClient *c) {
}
}
static
void
sismemberCommand
(
redisClient
*
c
)
{
static
void
sismemberCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
set
;
de
=
dictFin
d
(
c
->
d
ict
,
c
->
argv
[
1
]);
set
=
lookupKeyRea
d
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
set
==
NULL
)
{
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
}
else
{
}
else
{
robj
*
set
;
set
=
dictGetEntryVal
(
de
);
if
(
set
->
type
!=
REDIS_SET
)
{
if
(
set
->
type
!=
REDIS_SET
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
return
;
return
;
...
@@ -2639,21 +2630,20 @@ static void sismemberCommand(redisClient *c) {
...
@@ -2639,21 +2630,20 @@ static void sismemberCommand(redisClient *c) {
}
}
static
void
scardCommand
(
redisClient
*
c
)
{
static
void
scardCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
robj
*
o
;
dict
*
s
;
dict
*
s
;
de
=
dictFin
d
(
c
->
d
ict
,
c
->
argv
[
1
]);
o
=
lookupKeyRea
d
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
return
;
return
;
}
else
{
}
else
{
robj
*
o
=
dictGetEntryVal
(
de
);
if
(
o
->
type
!=
REDIS_SET
)
{
if
(
o
->
type
!=
REDIS_SET
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
}
else
{
}
else
{
s
=
o
->
ptr
;
s
=
o
->
ptr
;
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
":%d
\r\n
"
,
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
":%d
\r\n
"
,
dict
GetHashTableUsed
(
s
)));
dict
Size
(
s
)));
}
}
}
}
}
}
...
@@ -2661,7 +2651,7 @@ static void scardCommand(redisClient *c) {
...
@@ -2661,7 +2651,7 @@ static void scardCommand(redisClient *c) {
static
int
qsortCompareSetsByCardinality
(
const
void
*
s1
,
const
void
*
s2
)
{
static
int
qsortCompareSetsByCardinality
(
const
void
*
s1
,
const
void
*
s2
)
{
dict
**
d1
=
(
void
*
)
s1
,
**
d2
=
(
void
*
)
s2
;
dict
**
d1
=
(
void
*
)
s1
,
**
d2
=
(
void
*
)
s2
;
return
dict
GetHashTableUsed
(
*
d1
)
-
dictGetHashTableUsed
(
*
d2
);
return
dict
Size
(
*
d1
)
-
dictSize
(
*
d2
);
}
}
static
void
sinterGenericCommand
(
redisClient
*
c
,
robj
**
setskeys
,
int
setsnum
,
robj
*
dstkey
)
{
static
void
sinterGenericCommand
(
redisClient
*
c
,
robj
**
setskeys
,
int
setsnum
,
robj
*
dstkey
)
{
...
@@ -2674,15 +2664,15 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
...
@@ -2674,15 +2664,15 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
if
(
!
dv
)
oom
(
"sinterCommand"
);
if
(
!
dv
)
oom
(
"sinterCommand"
);
for
(
j
=
0
;
j
<
setsnum
;
j
++
)
{
for
(
j
=
0
;
j
<
setsnum
;
j
++
)
{
robj
*
setobj
;
robj
*
setobj
;
dictEntry
*
de
;
setobj
=
dstkey
?
de
=
dictFind
(
c
->
dict
,
setskeys
[
j
]);
lookupKeyWrite
(
c
->
db
,
setskeys
[
j
])
:
if
(
!
de
)
{
lookupKeyRead
(
c
->
db
,
setskeys
[
j
]);
if
(
!
setobj
)
{
zfree
(
dv
);
zfree
(
dv
);
addReply
(
c
,
shared
.
nokeyerr
);
addReply
(
c
,
shared
.
nokeyerr
);
return
;
return
;
}
}
setobj
=
dictGetEntryVal
(
de
);
if
(
setobj
->
type
!=
REDIS_SET
)
{
if
(
setobj
->
type
!=
REDIS_SET
)
{
zfree
(
dv
);
zfree
(
dv
);
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
...
@@ -2707,8 +2697,8 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
...
@@ -2707,8 +2697,8 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
/* If we have a target key where to store the resulting set
/* If we have a target key where to store the resulting set
* create this key with an empty set inside */
* create this key with an empty set inside */
dstset
=
createSetObject
();
dstset
=
createSetObject
();
d
ictD
elete
(
c
->
d
ict
,
dstkey
);
delete
Key
(
c
->
d
b
,
dstkey
);
dictAdd
(
c
->
dict
,
dstkey
,
dstset
);
dictAdd
(
c
->
db
->
dict
,
dstkey
,
dstset
);
incrRefCount
(
dstkey
);
incrRefCount
(
dstkey
);
}
}
...
@@ -2754,7 +2744,8 @@ static void sinterstoreCommand(redisClient *c) {
...
@@ -2754,7 +2744,8 @@ static void sinterstoreCommand(redisClient *c) {
}
}
static
void
flushdbCommand
(
redisClient
*
c
)
{
static
void
flushdbCommand
(
redisClient
*
c
)
{
dictEmpty
(
c
->
dict
);
dictEmpty
(
c
->
db
->
dict
);
dictEmpty
(
c
->
db
->
expires
);
addReply
(
c
,
shared
.
ok
);
addReply
(
c
,
shared
.
ok
);
rdbSave
(
server
.
dbfilename
);
rdbSave
(
server
.
dbfilename
);
}
}
...
@@ -2775,12 +2766,11 @@ redisSortOperation *createSortOperation(int type, robj *pattern) {
...
@@ -2775,12 +2766,11 @@ redisSortOperation *createSortOperation(int type, robj *pattern) {
/* Return the value associated to the key with a name obtained
/* Return the value associated to the key with a name obtained
* substituting the first occurence of '*' in 'pattern' with 'subst' */
* substituting the first occurence of '*' in 'pattern' with 'subst' */
robj
*
lookupKeyByPattern
(
dict
*
dict
,
robj
*
pattern
,
robj
*
subst
)
{
robj
*
lookupKeyByPattern
(
redisDb
*
db
,
robj
*
pattern
,
robj
*
subst
)
{
char
*
p
;
char
*
p
;
sds
spat
,
ssub
;
sds
spat
,
ssub
;
robj
keyobj
;
robj
keyobj
;
int
prefixlen
,
sublen
,
postfixlen
;
int
prefixlen
,
sublen
,
postfixlen
;
dictEntry
*
de
;
/* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */
/* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */
struct
{
struct
{
long
len
;
long
len
;
...
@@ -2788,7 +2778,6 @@ robj *lookupKeyByPattern(dict *dict, robj *pattern, robj *subst) {
...
@@ -2788,7 +2778,6 @@ robj *lookupKeyByPattern(dict *dict, robj *pattern, robj *subst) {
char
buf
[
REDIS_SORTKEY_MAX
+
1
];
char
buf
[
REDIS_SORTKEY_MAX
+
1
];
}
keyname
;
}
keyname
;
spat
=
pattern
->
ptr
;
spat
=
pattern
->
ptr
;
ssub
=
subst
->
ptr
;
ssub
=
subst
->
ptr
;
if
(
sdslen
(
spat
)
+
sdslen
(
ssub
)
-
1
>
REDIS_SORTKEY_MAX
)
return
NULL
;
if
(
sdslen
(
spat
)
+
sdslen
(
ssub
)
-
1
>
REDIS_SORTKEY_MAX
)
return
NULL
;
...
@@ -2808,10 +2797,8 @@ robj *lookupKeyByPattern(dict *dict, robj *pattern, robj *subst) {
...
@@ -2808,10 +2797,8 @@ robj *lookupKeyByPattern(dict *dict, robj *pattern, robj *subst) {
keyobj
.
type
=
REDIS_STRING
;
keyobj
.
type
=
REDIS_STRING
;
keyobj
.
ptr
=
((
char
*
)
&
keyname
)
+
(
sizeof
(
long
)
*
2
);
keyobj
.
ptr
=
((
char
*
)
&
keyname
)
+
(
sizeof
(
long
)
*
2
);
de
=
dictFind
(
dict
,
&
keyobj
);
/* printf("lookup '%s' => %p\n", keyname.buf,de); */
/* printf("lookup '%s' => %p\n", keyname.buf,de); */
if
(
!
de
)
return
NULL
;
return
lookupKeyRead
(
db
,
&
keyobj
);
return
dictGetEntryVal
(
de
);
}
}
/* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with
/* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with
...
@@ -2856,7 +2843,6 @@ static int sortCompare(const void *s1, const void *s2) {
...
@@ -2856,7 +2843,6 @@ static int sortCompare(const void *s1, const void *s2) {
/* The SORT command is the most complex command in Redis. Warning: this code
/* The SORT command is the most complex command in Redis. Warning: this code
* is optimized for speed and a bit less for readability */
* is optimized for speed and a bit less for readability */
static
void
sortCommand
(
redisClient
*
c
)
{
static
void
sortCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
list
*
operations
;
list
*
operations
;
int
outputlen
=
0
;
int
outputlen
=
0
;
int
desc
=
0
,
alpha
=
0
;
int
desc
=
0
,
alpha
=
0
;
...
@@ -2867,12 +2853,11 @@ static void sortCommand(redisClient *c) {
...
@@ -2867,12 +2853,11 @@ static void sortCommand(redisClient *c) {
redisSortObject
*
vector
;
/* Resulting vector to sort */
redisSortObject
*
vector
;
/* Resulting vector to sort */
/* Lookup the key to sort. It must be of the right types */
/* Lookup the key to sort. It must be of the right types */
de
=
dictFin
d
(
c
->
d
ict
,
c
->
argv
[
1
]);
sortval
=
lookupKeyRea
d
(
c
->
d
b
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
if
(
sortval
==
NULL
)
{
addReply
(
c
,
shared
.
nokeyerr
);
addReply
(
c
,
shared
.
nokeyerr
);
return
;
return
;
}
}
sortval
=
dictGetEntryVal
(
de
);
if
(
sortval
->
type
!=
REDIS_SET
&&
sortval
->
type
!=
REDIS_LIST
)
{
if
(
sortval
->
type
!=
REDIS_SET
&&
sortval
->
type
!=
REDIS_LIST
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
return
;
return
;
...
@@ -2937,7 +2922,7 @@ static void sortCommand(redisClient *c) {
...
@@ -2937,7 +2922,7 @@ static void sortCommand(redisClient *c) {
/* Load the sorting vector with all the objects to sort */
/* Load the sorting vector with all the objects to sort */
vectorlen
=
(
sortval
->
type
==
REDIS_LIST
)
?
vectorlen
=
(
sortval
->
type
==
REDIS_LIST
)
?
listLength
((
list
*
)
sortval
->
ptr
)
:
listLength
((
list
*
)
sortval
->
ptr
)
:
dict
GetHashTableUsed
((
dict
*
)
sortval
->
ptr
);
dict
Size
((
dict
*
)
sortval
->
ptr
);
vector
=
zmalloc
(
sizeof
(
redisSortObject
)
*
vectorlen
);
vector
=
zmalloc
(
sizeof
(
redisSortObject
)
*
vectorlen
);
if
(
!
vector
)
oom
(
"allocating objects vector for SORT"
);
if
(
!
vector
)
oom
(
"allocating objects vector for SORT"
);
j
=
0
;
j
=
0
;
...
@@ -2975,7 +2960,7 @@ static void sortCommand(redisClient *c) {
...
@@ -2975,7 +2960,7 @@ static void sortCommand(redisClient *c) {
if
(
sortby
)
{
if
(
sortby
)
{
robj
*
byval
;
robj
*
byval
;
byval
=
lookupKeyByPattern
(
c
->
d
ict
,
sortby
,
vector
[
j
].
obj
);
byval
=
lookupKeyByPattern
(
c
->
d
b
,
sortby
,
vector
[
j
].
obj
);
if
(
!
byval
||
byval
->
type
!=
REDIS_STRING
)
continue
;
if
(
!
byval
||
byval
->
type
!=
REDIS_STRING
)
continue
;
if
(
alpha
)
{
if
(
alpha
)
{
vector
[
j
].
u
.
cmpobj
=
byval
;
vector
[
j
].
u
.
cmpobj
=
byval
;
...
@@ -3020,7 +3005,7 @@ static void sortCommand(redisClient *c) {
...
@@ -3020,7 +3005,7 @@ static void sortCommand(redisClient *c) {
}
}
while
(
ln
)
{
while
(
ln
)
{
redisSortOperation
*
sop
=
ln
->
value
;
redisSortOperation
*
sop
=
ln
->
value
;
robj
*
val
=
lookupKeyByPattern
(
c
->
d
ict
,
sop
->
pattern
,
robj
*
val
=
lookupKeyByPattern
(
c
->
d
b
,
sop
->
pattern
,
vector
[
j
].
obj
);
vector
[
j
].
obj
);
if
(
sop
->
type
==
REDIS_SORT_GET
)
{
if
(
sop
->
type
==
REDIS_SORT_GET
)
{
...
@@ -3080,6 +3065,85 @@ static void infoCommand(redisClient *c) {
...
@@ -3080,6 +3065,85 @@ static void infoCommand(redisClient *c) {
addReply
(
c
,
shared
.
crlf
);
addReply
(
c
,
shared
.
crlf
);
}
}
static
void
monitorCommand
(
redisClient
*
c
)
{
/* ignore MONITOR if aleady slave or in monitor mode */
if
(
c
->
flags
&
REDIS_SLAVE
)
return
;
c
->
flags
|=
(
REDIS_SLAVE
|
REDIS_MONITOR
);
c
->
slaveseldb
=
0
;
if
(
!
listAddNodeTail
(
server
.
monitors
,
c
))
oom
(
"listAddNodeTail"
);
addReply
(
c
,
shared
.
ok
);
}
/* ================================= Expire ================================= */
static
int
removeExpire
(
redisDb
*
db
,
robj
*
key
)
{
if
(
dictDelete
(
db
->
expires
,
key
)
==
DICT_OK
)
{
return
1
;
}
else
{
return
0
;
}
}
static
int
setExpire
(
redisDb
*
db
,
robj
*
key
,
time_t
when
)
{
if
(
dictAdd
(
db
->
expires
,
key
,(
void
*
)
when
)
==
DICT_ERR
)
{
return
0
;
}
else
{
incrRefCount
(
key
);
return
1
;
}
}
static
int
expireIfNeeded
(
redisDb
*
db
,
robj
*
key
)
{
time_t
when
;
dictEntry
*
de
;
/* No expire? return ASAP */
if
(
dictSize
(
db
->
expires
)
==
0
||
(
de
=
dictFind
(
db
->
expires
,
key
))
==
NULL
)
return
0
;
/* Lookup the expire */
when
=
(
time_t
)
dictGetEntryVal
(
de
);
if
(
time
(
NULL
)
<=
when
)
return
0
;
/* Delete the key */
dictDelete
(
db
->
expires
,
key
);
return
dictDelete
(
db
->
dict
,
key
)
==
DICT_OK
;
}
static
int
deleteIfVolatile
(
redisDb
*
db
,
robj
*
key
)
{
dictEntry
*
de
;
/* No expire? return ASAP */
if
(
dictSize
(
db
->
expires
)
==
0
||
(
de
=
dictFind
(
db
->
expires
,
key
))
==
NULL
)
return
0
;
/* Delete the key */
dictDelete
(
db
->
expires
,
key
);
return
dictDelete
(
db
->
dict
,
key
)
==
DICT_OK
;
}
static
void
expireCommand
(
redisClient
*
c
)
{
dictEntry
*
de
;
int
seconds
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
de
=
dictFind
(
c
->
db
->
dict
,
c
->
argv
[
1
]);
if
(
de
==
NULL
)
{
addReply
(
c
,
shared
.
czero
);
return
;
}
if
(
seconds
<=
0
)
{
addReply
(
c
,
shared
.
czero
);
return
;
}
else
{
time_t
when
=
time
(
NULL
)
+
seconds
;
if
(
setExpire
(
c
->
db
,
c
->
argv
[
1
],
when
))
addReply
(
c
,
shared
.
cone
);
else
addReply
(
c
,
shared
.
czero
);
return
;
}
}
/* =============================== Replication ============================= */
/* =============================== Replication ============================= */
/* Send the whole output buffer syncronously to the slave. This a general operation in theory, but it is actually useful only for replication. */
/* Send the whole output buffer syncronously to the slave. This a general operation in theory, but it is actually useful only for replication. */
...
@@ -3280,16 +3344,6 @@ static int syncWithMaster(void) {
...
@@ -3280,16 +3344,6 @@ static int syncWithMaster(void) {
return
REDIS_OK
;
return
REDIS_OK
;
}
}
static
void
monitorCommand
(
redisClient
*
c
)
{
/* ignore MONITOR if aleady slave or in monitor mode */
if
(
c
->
flags
&
REDIS_SLAVE
)
return
;
c
->
flags
|=
(
REDIS_SLAVE
|
REDIS_MONITOR
);
c
->
slaveseldb
=
0
;
if
(
!
listAddNodeTail
(
server
.
monitors
,
c
))
oom
(
"listAddNodeTail"
);
addReply
(
c
,
shared
.
ok
);
}
/* =================================== Main! ================================ */
/* =================================== Main! ================================ */
static
void
daemonize
(
void
)
{
static
void
daemonize
(
void
)
{
...
...
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