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