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
1b1f47c9
Commit
1b1f47c9
authored
Nov 03, 2010
by
antirez
Browse files
command lookup process turned into a much more flexible and probably faster hash table
parent
297e77c6
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/db.c
View file @
1b1f47c9
...
...
@@ -435,16 +435,14 @@ time_t getExpire(redisDb *db, robj *key) {
* will be consistent even if we allow write operations against expiring
* keys. */
void
propagateExpire
(
redisDb
*
db
,
robj
*
key
)
{
struct
redisCommand
*
cmd
;
robj
*
argv
[
2
];
cmd
=
lookupCommand
(
"del"
);
argv
[
0
]
=
createStringObject
(
"DEL"
,
3
);
argv
[
1
]
=
key
;
incrRefCount
(
key
);
if
(
server
.
appendonly
)
feedAppendOnlyFile
(
cm
d
,
db
->
id
,
argv
,
2
);
feedAppendOnlyFile
(
server
.
delComman
d
,
db
->
id
,
argv
,
2
);
if
(
listLength
(
server
.
slaves
))
replicationFeedSlaves
(
server
.
slaves
,
db
->
id
,
argv
,
2
);
...
...
src/dict.c
View file @
1b1f47c9
...
...
@@ -42,6 +42,7 @@
#include <assert.h>
#include <limits.h>
#include <sys/time.h>
#include <ctype.h>
#include "dict.h"
#include "zmalloc.h"
...
...
@@ -94,6 +95,15 @@ unsigned int dictGenHashFunction(const unsigned char *buf, int len) {
return
hash
;
}
/* And a case insensitive version */
unsigned
int
dictGenCaseHashFunction
(
const
unsigned
char
*
buf
,
int
len
)
{
unsigned
int
hash
=
5381
;
while
(
len
--
)
hash
=
((
hash
<<
5
)
+
hash
)
+
(
tolower
(
*
buf
++
));
/* hash * 33 + c */
return
hash
;
}
/* ----------------------------- API implementation ------------------------- */
/* Reset an hashtable already initialized with ht_init().
...
...
src/dict.h
View file @
1b1f47c9
...
...
@@ -137,6 +137,7 @@ void dictReleaseIterator(dictIterator *iter);
dictEntry
*
dictGetRandomKey
(
dict
*
d
);
void
dictPrintStats
(
dict
*
d
);
unsigned
int
dictGenHashFunction
(
const
unsigned
char
*
buf
,
int
len
);
unsigned
int
dictGenCaseHashFunction
(
const
unsigned
char
*
buf
,
int
len
);
void
dictEmpty
(
dict
*
d
);
void
dictEnableResize
(
void
);
void
dictDisableResize
(
void
);
...
...
src/multi.c
View file @
1b1f47c9
...
...
@@ -65,12 +65,10 @@ void discardCommand(redisClient *c) {
/* Send a MULTI command to all the slaves and AOF file. Check the execCommand
* implememntation for more information. */
void
execCommandReplicateMulti
(
redisClient
*
c
)
{
struct
redisCommand
*
cmd
;
robj
*
multistring
=
createStringObject
(
"MULTI"
,
5
);
cmd
=
lookupCommand
(
"multi"
);
if
(
server
.
appendonly
)
feedAppendOnlyFile
(
cm
d
,
c
->
db
->
id
,
&
multistring
,
1
);
feedAppendOnlyFile
(
server
.
multiComman
d
,
c
->
db
->
id
,
&
multistring
,
1
);
if
(
listLength
(
server
.
slaves
))
replicationFeedSlaves
(
server
.
slaves
,
c
->
db
->
id
,
&
multistring
,
1
);
decrRefCount
(
multistring
);
...
...
src/redis.c
View file @
1b1f47c9
...
...
@@ -252,6 +252,15 @@ int dictSdsKeyCompare(void *privdata, const void *key1,
return memcmp(key1, key2, l1) == 0;
}
/* A case insensitive version used for the command lookup table. */
int dictSdsKeyCaseCompare(void *privdata, const void *key1,
const void *key2)
{
DICT_NOTUSED(privdata);
return strcasecmp(key1, key2) == 0;
}
void dictRedisObjectDestructor(void *privdata, void *val)
{
DICT_NOTUSED(privdata);
...
...
@@ -283,6 +292,10 @@ unsigned int dictSdsHash(const void *key) {
return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));
}
unsigned int dictSdsCaseHash(const void *key) {
return dictGenCaseHashFunction((unsigned char*)key, sdslen((char*)key));
}
int dictEncObjKeyCompare(void *privdata, const void *key1,
const void *key2)
{
...
...
@@ -364,6 +377,16 @@ dictType keyptrDictType = {
NULL /* val destructor */
};
/* Command table. sds string -> command struct pointer. */
dictType commandTableDictType = {
dictSdsCaseHash, /* hash function */
NULL, /* key dup */
NULL, /* val dup */
dictSdsKeyCaseCompare, /* key compare */
dictSdsDestructor, /* key destructor */
NULL /* val destructor */
};
/* Hash type hash table (note that small hashes are represented with zimpaps) */
dictType hashDictType = {
dictEncObjHash, /* hash function */
...
...
@@ -791,6 +814,12 @@ void initServer() {
redisLog(REDIS_WARNING, "Can't open /dev/null: %s", server.neterr);
exit(1);
}
server.commands = dictCreate(&commandTableDictType,NULL);
populateCommandTable();
server.delCommand = lookupCommandByCString("del");
server.multiCommand = lookupCommandByCString("multi");
server.clients = listCreate();
server.slaves = listCreate();
server.monitors = listCreate();
...
...
@@ -860,31 +889,34 @@ void initServer() {
if (server.vm_enabled) vmInit();
}
int
qsortRedisCommands
(
const
void
*
r1
,
const
void
*
r2
)
{
return
strcasecmp
(
((
struct
redisCommand
*
)
r1
)
->
name
,
((
struct
redisCommand
*
)
r2
)
->
name
);
}
/* Populates the Redis Command Table starting from the hard coded list
* we have on top of redis.c file. */
void populateCommandTable(void) {
int j;
int numcommands = sizeof(readonlyCommandTable)/sizeof(struct redisCommand);
for (j = 0; j < numcommands; j++) {
struct redisCommand *c = readonlyCommandTable+j;
int retval;
void
sortCommandTable
()
{
/* Copy and sort the read-only version of the command table */
commandTable
=
(
struct
redisCommand
*
)
zmalloc
(
sizeof
(
readonlyCommandTable
));
memcpy
(
commandTable
,
readonlyCommandTable
,
sizeof
(
readonlyCommandTable
));
qsort
(
commandTable
,
sizeof
(
readonlyCommandTable
)
/
sizeof
(
struct
redisCommand
),
sizeof
(
struct
redisCommand
),
qsortRedisCommands
);
retval = dictAdd(server.commands, sdsnew(c->name), c);
assert(retval == DICT_OK);
}
}
/* ====================== Commands lookup and execution ===================== */
struct
redisCommand
*
lookupCommand
(
char
*
name
)
{
struct
redisCommand
tmp
=
{
name
,
NULL
,
0
,
0
,
NULL
,
0
,
0
,
0
};
return
bsearch
(
&
tmp
,
commandTable
,
sizeof
(
readonlyCommandTable
)
/
sizeof
(
struct
redisCommand
),
sizeof
(
struct
redisCommand
),
qsortRedisCommands
);
struct redisCommand *lookupCommand(sds name) {
return dictFetchValue(server.commands, name);
}
struct redisCommand *lookupCommandByCString(char *s) {
struct redisCommand *cmd;
sds name = sdsnew(s);
cmd = dictFetchValue(server.commands, name);
sdsfree(name);
return cmd;
}
/* Call() is the core of Redis execution of a command */
...
...
@@ -1443,7 +1475,6 @@ int main(int argc, char **argv) {
time_t start;
initServerConfig();
sortCommandTable
();
if (argc == 2) {
if (strcmp(argv[1], "-v") == 0 ||
strcmp(argv[1], "--version") == 0) version();
...
...
src/redis.h
View file @
1b1f47c9
...
...
@@ -360,6 +360,8 @@ struct redisServer {
long
long
dirty
;
/* changes to DB from the last save */
long
long
dirty_before_bgsave
;
/* used to restore dirty on failed BGSAVE */
list
*
clients
;
dict
*
commands
;
/* Command table hahs table */
struct
redisCommand
*
delCommand
,
*
multiCommand
;
/* often lookedup cmds */
list
*
slaves
,
*
monitors
;
char
neterr
[
ANET_ERR_LEN
];
aeEventLoop
*
el
;
...
...
@@ -746,7 +748,8 @@ zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj);
void
freeMemoryIfNeeded
(
void
);
int
processCommand
(
redisClient
*
c
);
void
setupSigSegvAction
(
void
);
struct
redisCommand
*
lookupCommand
(
char
*
name
);
struct
redisCommand
*
lookupCommand
(
sds
name
);
struct
redisCommand
*
lookupCommandByCString
(
char
*
s
);
void
call
(
redisClient
*
c
,
struct
redisCommand
*
cmd
);
int
prepareForShutdown
();
void
redisLog
(
int
level
,
const
char
*
fmt
,
...);
...
...
@@ -754,6 +757,7 @@ void usage();
void
updateDictResizePolicy
(
void
);
int
htNeedsResize
(
dict
*
dict
);
void
oom
(
const
char
*
msg
);
void
populateCommandTable
(
void
);
/* Virtual Memory */
void
vmInit
(
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