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
3305306f
Commit
3305306f
authored
Apr 01, 2009
by
antirez
Browse files
Initial implementation of EXPIRE
parent
300827b6
Changes
5
Show 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
)
{
...
@@ -2070,7 +2084,10 @@ static void selectCommand(redisClient *c) {
...
@@ -2070,7 +2084,10 @@ 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,15 +2105,17 @@ static void keysCommand(redisClient *c) {
...
@@ -2088,15 +2105,17 @@ 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
(
expireIfNeeded
(
c
->
db
,
keyobj
)
==
0
)
{
if
(
numkeys
!=
0
)
if
(
numkeys
!=
0
)
addReply
(
c
,
shared
.
space
);
addReply
(
c
,
shared
.
space
);
addReply
(
c
,
keyobj
);
addReply
(
c
,
keyobj
);
...
@@ -2104,6 +2123,7 @@ static void keysCommand(redisClient *c) {
...
@@ -2104,6 +2123,7 @@ static void keysCommand(redisClient *c) {
keyslen
+=
sdslen
(
key
);
keyslen
+=
sdslen
(
key
);
}
}
}
}
}
dictReleaseIterator
(
di
);
dictReleaseIterator
(
di
);
lenobj
->
ptr
=
sdscatprintf
(
sdsempty
(),
"$%lu
\r\n
"
,
keyslen
+
(
numkeys
?
(
numkeys
-
1
)
:
0
));
lenobj
->
ptr
=
sdscatprintf
(
sdsempty
(),
"$%lu
\r\n
"
,
keyslen
+
(
numkeys
?
(
numkeys
-
1
)
:
0
));
addReply
(
c
,
shared
.
crlf
);
addReply
(
c
,
shared
.
crlf
);
...
@@ -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
;
de
=
dictFind
(
c
->
dict
,
setskeys
[
j
]);
setobj
=
dstkey
?
if
(
!
de
)
{
lookupKeyWrite
(
c
->
db
,
setskeys
[
j
])
:
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