/* 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(cmd,c->db->id,&multistring,1);
+ feedAppendOnlyFile(server.multiCommand,c->db->id,&multistring,1);
if (listLength(server.slaves))
replicationFeedSlaves(server.slaves,c->db->id,&multistring,1);
decrRefCount(multistring);
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);
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)
{
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 */
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();
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 */
time_t start;
initServerConfig();
- sortCommandTable();
if (argc == 2) {
if (strcmp(argv[1], "-v") == 0 ||
strcmp(argv[1], "--version") == 0) version();
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;
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, ...);
void updateDictResizePolicy(void);
int htNeedsResize(dict *dict);
void oom(const char *msg);
+void populateCommandTable(void);
/* Virtual Memory */
void vmInit(void);