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
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