Tcl script, make target, and redis.c changes to build the static symbol table automagically

This commit is contained in:
antirez 2009-11-10 19:20:32 +01:00
parent f232429386
commit bcfc686db7
5 changed files with 323 additions and 216 deletions

View File

@ -60,6 +60,9 @@ clean:
dep:
$(CC) -MM *.c
staticsymbols:
tclsh utils/build-static-symbols.tcl > staticsymbols.h
test:
tclsh test-redis.tcl

1
TODO
View File

@ -10,7 +10,6 @@ VERSION 1.1 TODO
* Write docs for the "STORE" operaiton of SORT, and GET "#" option.
* Append only mode: testing and a command to rebuild the log from scratch.
* Profiling and optimizations. For instance the commands lookup is probably starting to eat too CPU being a simple list. To implement binary search or an hash table lookup can be a win probably.
* Expiring algorithm should be adaptive. Use the following algorithm. Start testing REDIS_EXPIRELOOKUPS_PER_CRON in the first iteration, and continue with the same amount of keys until the percentage of expired keys > 25%.
VERSION 1.2 TODO

324
redis.c
View File

@ -544,6 +544,7 @@ static struct redisCommand cmdTable[] = {
{"debug",debugCommand,-2,REDIS_CMD_INLINE},
{NULL,NULL,0,0}
};
/*============================ Utility functions ============================ */
/* Glob-style pattern matching. */
@ -1025,7 +1026,7 @@ static void appendServerSaveParams(time_t seconds, int changes) {
server.saveparamslen++;
}
static void ResetServerSaveParams() {
static void resetServerSaveParams() {
zfree(server.saveparams);
server.saveparams = NULL;
server.saveparamslen = 0;
@ -1054,7 +1055,7 @@ static void initServerConfig() {
server.sharingpoolsize = 1024;
server.maxclients = 0;
server.maxmemory = 0;
ResetServerSaveParams();
resetServerSaveParams();
appendServerSaveParams(60*60,1); /* save after 1 hour and 1 change */
appendServerSaveParams(300,100); /* save after 5 minutes and 100 changes */
@ -5534,150 +5535,91 @@ static void debugCommand(redisClient *c) {
}
}
#ifdef HAVE_BACKTRACE
static struct redisFunctionSym symsTable[] = {
{"compareStringObjects", (unsigned long)compareStringObjects},
{"isStringRepresentableAsLong", (unsigned long)isStringRepresentableAsLong},
{"dictEncObjKeyCompare", (unsigned long)dictEncObjKeyCompare},
{"dictEncObjHash", (unsigned long)dictEncObjHash},
{"incrDecrCommand", (unsigned long)incrDecrCommand},
{"freeStringObject", (unsigned long)freeStringObject},
{"freeListObject", (unsigned long)freeListObject},
{"freeSetObject", (unsigned long)freeSetObject},
{"decrRefCount", (unsigned long)decrRefCount},
{"createObject", (unsigned long)createObject},
{"freeClient", (unsigned long)freeClient},
{"rdbLoad", (unsigned long)rdbLoad},
{"rdbSaveStringObject", (unsigned long)rdbSaveStringObject},
{"rdbSaveStringObjectRaw", (unsigned long)rdbSaveStringObjectRaw},
{"addReply", (unsigned long)addReply},
{"addReplySds", (unsigned long)addReplySds},
{"incrRefCount", (unsigned long)incrRefCount},
{"rdbSaveBackground", (unsigned long)rdbSaveBackground},
{"createStringObject", (unsigned long)createStringObject},
{"replicationFeedSlaves", (unsigned long)replicationFeedSlaves},
{"syncWithMaster", (unsigned long)syncWithMaster},
{"tryObjectSharing", (unsigned long)tryObjectSharing},
{"tryObjectEncoding", (unsigned long)tryObjectEncoding},
{"getDecodedObject", (unsigned long)getDecodedObject},
{"removeExpire", (unsigned long)removeExpire},
{"expireIfNeeded", (unsigned long)expireIfNeeded},
{"deleteIfVolatile", (unsigned long)deleteIfVolatile},
{"deleteKey", (unsigned long)deleteKey},
{"getExpire", (unsigned long)getExpire},
{"setExpire", (unsigned long)setExpire},
{"updateSlavesWaitingBgsave", (unsigned long)updateSlavesWaitingBgsave},
{"freeMemoryIfNeeded", (unsigned long)freeMemoryIfNeeded},
{"authCommand", (unsigned long)authCommand},
{"pingCommand", (unsigned long)pingCommand},
{"echoCommand", (unsigned long)echoCommand},
{"setCommand", (unsigned long)setCommand},
{"setnxCommand", (unsigned long)setnxCommand},
{"getCommand", (unsigned long)getCommand},
{"delCommand", (unsigned long)delCommand},
{"existsCommand", (unsigned long)existsCommand},
{"incrCommand", (unsigned long)incrCommand},
{"decrCommand", (unsigned long)decrCommand},
{"incrbyCommand", (unsigned long)incrbyCommand},
{"decrbyCommand", (unsigned long)decrbyCommand},
{"selectCommand", (unsigned long)selectCommand},
{"randomkeyCommand", (unsigned long)randomkeyCommand},
{"keysCommand", (unsigned long)keysCommand},
{"dbsizeCommand", (unsigned long)dbsizeCommand},
{"lastsaveCommand", (unsigned long)lastsaveCommand},
{"saveCommand", (unsigned long)saveCommand},
{"bgsaveCommand", (unsigned long)bgsaveCommand},
{"shutdownCommand", (unsigned long)shutdownCommand},
{"moveCommand", (unsigned long)moveCommand},
{"renameCommand", (unsigned long)renameCommand},
{"renamenxCommand", (unsigned long)renamenxCommand},
{"lpushCommand", (unsigned long)lpushCommand},
{"rpushCommand", (unsigned long)rpushCommand},
{"lpopCommand", (unsigned long)lpopCommand},
{"rpopCommand", (unsigned long)rpopCommand},
{"llenCommand", (unsigned long)llenCommand},
{"lindexCommand", (unsigned long)lindexCommand},
{"lrangeCommand", (unsigned long)lrangeCommand},
{"ltrimCommand", (unsigned long)ltrimCommand},
{"typeCommand", (unsigned long)typeCommand},
{"lsetCommand", (unsigned long)lsetCommand},
{"saddCommand", (unsigned long)saddCommand},
{"sremCommand", (unsigned long)sremCommand},
{"smoveCommand", (unsigned long)smoveCommand},
{"sismemberCommand", (unsigned long)sismemberCommand},
{"scardCommand", (unsigned long)scardCommand},
{"spopCommand", (unsigned long)spopCommand},
{"srandmemberCommand", (unsigned long)srandmemberCommand},
{"sinterCommand", (unsigned long)sinterCommand},
{"sinterstoreCommand", (unsigned long)sinterstoreCommand},
{"sunionCommand", (unsigned long)sunionCommand},
{"sunionstoreCommand", (unsigned long)sunionstoreCommand},
{"sdiffCommand", (unsigned long)sdiffCommand},
{"sdiffstoreCommand", (unsigned long)sdiffstoreCommand},
{"syncCommand", (unsigned long)syncCommand},
{"flushdbCommand", (unsigned long)flushdbCommand},
{"flushallCommand", (unsigned long)flushallCommand},
{"sortCommand", (unsigned long)sortCommand},
{"lremCommand", (unsigned long)lremCommand},
{"infoCommand", (unsigned long)infoCommand},
{"mgetCommand", (unsigned long)mgetCommand},
{"monitorCommand", (unsigned long)monitorCommand},
{"expireCommand", (unsigned long)expireCommand},
{"expireatCommand", (unsigned long)expireatCommand},
{"getsetCommand", (unsigned long)getsetCommand},
{"ttlCommand", (unsigned long)ttlCommand},
{"slaveofCommand", (unsigned long)slaveofCommand},
{"debugCommand", (unsigned long)debugCommand},
{"processCommand", (unsigned long)processCommand},
{"setupSigSegvAction", (unsigned long)setupSigSegvAction},
{"readQueryFromClient", (unsigned long)readQueryFromClient},
{"rdbRemoveTempFile", (unsigned long)rdbRemoveTempFile},
{"msetGenericCommand", (unsigned long)msetGenericCommand},
{"msetCommand", (unsigned long)msetCommand},
{"msetnxCommand", (unsigned long)msetnxCommand},
{"zslCreateNode", (unsigned long)zslCreateNode},
{"zslCreate", (unsigned long)zslCreate},
{"zslFreeNode",(unsigned long)zslFreeNode},
{"zslFree",(unsigned long)zslFree},
{"zslRandomLevel",(unsigned long)zslRandomLevel},
{"zslInsert",(unsigned long)zslInsert},
{"zslDelete",(unsigned long)zslDelete},
{"createZsetObject",(unsigned long)createZsetObject},
{"zaddCommand",(unsigned long)zaddCommand},
{"zrangeGenericCommand",(unsigned long)zrangeGenericCommand},
{"zrangeCommand",(unsigned long)zrangeCommand},
{"zrevrangeCommand",(unsigned long)zrevrangeCommand},
{"zremCommand",(unsigned long)zremCommand},
{"rdbSaveDoubleValue",(unsigned long)rdbSaveDoubleValue},
{"rdbLoadDoubleValue",(unsigned long)rdbLoadDoubleValue},
{"feedAppendOnlyFile",(unsigned long)feedAppendOnlyFile},
{NULL,0}
};
/* =================================== Main! ================================ */
/* This function try to convert a pointer into a function name. It's used in
* oreder to provide a backtrace under segmentation fault that's able to
* display functions declared as static (otherwise the backtrace is useless). */
static char *findFuncName(void *pointer, unsigned long *offset){
int i, ret = -1;
unsigned long off, minoff = 0;
#ifdef __linux__
int linuxOvercommitMemoryValue(void) {
FILE *fp = fopen("/proc/sys/vm/overcommit_memory","r");
char buf[64];
/* Try to match against the Symbol with the smallest offset */
for (i=0; symsTable[i].pointer; i++) {
unsigned long lp = (unsigned long) pointer;
if (lp != (unsigned long)-1 && lp >= symsTable[i].pointer) {
off=lp-symsTable[i].pointer;
if (ret < 0 || off < minoff) {
minoff=off;
ret=i;
}
}
if (!fp) return -1;
if (fgets(buf,64,fp) == NULL) {
fclose(fp);
return -1;
}
if (ret == -1) return NULL;
*offset = minoff;
return symsTable[ret].name;
fclose(fp);
return atoi(buf);
}
void linuxOvercommitMemoryWarning(void) {
if (linuxOvercommitMemoryValue() == 0) {
redisLog(REDIS_WARNING,"WARNING overcommit_memory is set to 0! Background save may fail under low condition memory. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.");
}
}
#endif /* __linux__ */
static void daemonize(void) {
int fd;
FILE *fp;
if (fork() != 0) exit(0); /* parent exits */
setsid(); /* create a new session */
/* Every output goes to /dev/null. If Redis is daemonized but
* the 'logfile' is set to 'stdout' in the configuration file
* it will not log at all. */
if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > STDERR_FILENO) close(fd);
}
/* Try to write the pid file */
fp = fopen(server.pidfile,"w");
if (fp) {
fprintf(fp,"%d\n",getpid());
fclose(fp);
}
}
int main(int argc, char **argv) {
initServerConfig();
if (argc == 2) {
resetServerSaveParams();
loadServerConfig(argv[1]);
} else if (argc > 2) {
fprintf(stderr,"Usage: ./redis-server [/path/to/redis.conf]\n");
exit(1);
} else {
redisLog(REDIS_WARNING,"Warning: no config file specified, using the default config. In order to specify a config file use 'redis-server /path/to/redis.conf'");
}
initServer();
if (server.daemonize) daemonize();
redisLog(REDIS_NOTICE,"Server started, Redis version " REDIS_VERSION);
#ifdef __linux__
linuxOvercommitMemoryWarning();
#endif
if (server.appendonly) {
if (loadAppendOnlyFile(server.appendfilename) == REDIS_OK)
redisLog(REDIS_NOTICE,"DB loaded from append only file");
} else {
if (rdbLoad(server.dbfilename) == REDIS_OK)
redisLog(REDIS_NOTICE,"DB loaded from disk");
}
if (aeCreateFileEvent(server.el, server.fd, AE_READABLE,
acceptHandler, NULL, NULL) == AE_ERR) oom("creating file event");
redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
aeMain(server.el);
aeDeleteEventLoop(server.el);
return 0;
}
/* ============================= Backtrace support ========================= */
#ifdef HAVE_BACKTRACE
static char *findFuncName(void *pointer, unsigned long *offset);
static void *getMcontextEip(ucontext_t *uc) {
#if defined(__FreeBSD__)
return (void*) uc->uc_mcontext.mc_eip;
@ -5772,87 +5714,39 @@ static void setupSigSegvAction(void) {
sigaction (SIGBUS, &act, NULL);
return;
}
#include "staticsymbols.h"
/* This function try to convert a pointer into a function name. It's used in
* oreder to provide a backtrace under segmentation fault that's able to
* display functions declared as static (otherwise the backtrace is useless). */
static char *findFuncName(void *pointer, unsigned long *offset){
int i, ret = -1;
unsigned long off, minoff = 0;
/* Try to match against the Symbol with the smallest offset */
for (i=0; symsTable[i].pointer; i++) {
unsigned long lp = (unsigned long) pointer;
if (lp != (unsigned long)-1 && lp >= symsTable[i].pointer) {
off=lp-symsTable[i].pointer;
if (ret < 0 || off < minoff) {
minoff=off;
ret=i;
}
}
}
if (ret == -1) return NULL;
*offset = minoff;
return symsTable[ret].name;
}
#else /* HAVE_BACKTRACE */
static void setupSigSegvAction(void) {
}
#endif /* HAVE_BACKTRACE */
/* =================================== Main! ================================ */
#ifdef __linux__
int linuxOvercommitMemoryValue(void) {
FILE *fp = fopen("/proc/sys/vm/overcommit_memory","r");
char buf[64];
if (!fp) return -1;
if (fgets(buf,64,fp) == NULL) {
fclose(fp);
return -1;
}
fclose(fp);
/* The End */
return atoi(buf);
}
void linuxOvercommitMemoryWarning(void) {
if (linuxOvercommitMemoryValue() == 0) {
redisLog(REDIS_WARNING,"WARNING overcommit_memory is set to 0! Background save may fail under low condition memory. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.");
}
}
#endif /* __linux__ */
static void daemonize(void) {
int fd;
FILE *fp;
if (fork() != 0) exit(0); /* parent exits */
setsid(); /* create a new session */
/* Every output goes to /dev/null. If Redis is daemonized but
* the 'logfile' is set to 'stdout' in the configuration file
* it will not log at all. */
if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > STDERR_FILENO) close(fd);
}
/* Try to write the pid file */
fp = fopen(server.pidfile,"w");
if (fp) {
fprintf(fp,"%d\n",getpid());
fclose(fp);
}
}
int main(int argc, char **argv) {
initServerConfig();
if (argc == 2) {
ResetServerSaveParams();
loadServerConfig(argv[1]);
} else if (argc > 2) {
fprintf(stderr,"Usage: ./redis-server [/path/to/redis.conf]\n");
exit(1);
} else {
redisLog(REDIS_WARNING,"Warning: no config file specified, using the default config. In order to specify a config file use 'redis-server /path/to/redis.conf'");
}
initServer();
if (server.daemonize) daemonize();
redisLog(REDIS_NOTICE,"Server started, Redis version " REDIS_VERSION);
#ifdef __linux__
linuxOvercommitMemoryWarning();
#endif
if (server.appendonly) {
if (loadAppendOnlyFile(server.appendfilename) == REDIS_OK)
redisLog(REDIS_NOTICE,"DB loaded from append only file");
} else {
if (rdbLoad(server.dbfilename) == REDIS_OK)
redisLog(REDIS_NOTICE,"DB loaded from disk");
}
if (aeCreateFileEvent(server.el, server.fd, AE_READABLE,
acceptHandler, NULL, NULL) == AE_ERR) oom("creating file event");
redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
aeMain(server.el);
aeDeleteEventLoop(server.el);
return 0;
}

189
staticsymbols.h Normal file
View File

@ -0,0 +1,189 @@
static struct redisFunctionSym symsTable[] = {
{"acceptHandler",(unsigned long)acceptHandler},
{"addReply",(unsigned long)addReply},
{"addReplyBulkLen",(unsigned long)addReplyBulkLen},
{"addReplySds",(unsigned long)addReplySds},
{"appendServerSaveParams",(unsigned long)appendServerSaveParams},
{"authCommand",(unsigned long)authCommand},
{"bgsaveCommand",(unsigned long)bgsaveCommand},
{"closeTimedoutClients",(unsigned long)closeTimedoutClients},
{"compareStringObjects",(unsigned long)compareStringObjects},
{"createClient",(unsigned long)createClient},
{"createListObject",(unsigned long)createListObject},
{"createObject",(unsigned long)createObject},
{"createSetObject",(unsigned long)createSetObject},
{"createSharedObjects",(unsigned long)createSharedObjects},
{"createSortOperation",(unsigned long)createSortOperation},
{"createStringObject",(unsigned long)createStringObject},
{"createZsetObject",(unsigned long)createZsetObject},
{"daemonize",(unsigned long)daemonize},
{"dbsizeCommand",(unsigned long)dbsizeCommand},
{"debugCommand",(unsigned long)debugCommand},
{"decrCommand",(unsigned long)decrCommand},
{"decrRefCount",(unsigned long)decrRefCount},
{"decrbyCommand",(unsigned long)decrbyCommand},
{"delCommand",(unsigned long)delCommand},
{"deleteIfVolatile",(unsigned long)deleteIfVolatile},
{"deleteKey",(unsigned long)deleteKey},
{"dictEncObjKeyCompare",(unsigned long)dictEncObjKeyCompare},
{"dictObjKeyCompare",(unsigned long)dictObjKeyCompare},
{"dictRedisObjectDestructor",(unsigned long)dictRedisObjectDestructor},
{"dictVanillaFree",(unsigned long)dictVanillaFree},
{"dupClientReplyValue",(unsigned long)dupClientReplyValue},
{"echoCommand",(unsigned long)echoCommand},
{"existsCommand",(unsigned long)existsCommand},
{"expireCommand",(unsigned long)expireCommand},
{"expireGenericCommand",(unsigned long)expireGenericCommand},
{"expireIfNeeded",(unsigned long)expireIfNeeded},
{"expireatCommand",(unsigned long)expireatCommand},
{"feedAppendOnlyFile",(unsigned long)feedAppendOnlyFile},
{"findFuncName",(unsigned long)findFuncName},
{"flushallCommand",(unsigned long)flushallCommand},
{"flushdbCommand",(unsigned long)flushdbCommand},
{"freeClient",(unsigned long)freeClient},
{"freeClientArgv",(unsigned long)freeClientArgv},
{"freeFakeClient",(unsigned long)freeFakeClient},
{"freeHashObject",(unsigned long)freeHashObject},
{"freeListObject",(unsigned long)freeListObject},
{"freeMemoryIfNeeded",(unsigned long)freeMemoryIfNeeded},
{"freeSetObject",(unsigned long)freeSetObject},
{"freeStringObject",(unsigned long)freeStringObject},
{"freeZsetObject",(unsigned long)freeZsetObject},
{"getCommand",(unsigned long)getCommand},
{"getDecodedObject",(unsigned long)getDecodedObject},
{"getExpire",(unsigned long)getExpire},
{"getMcontextEip",(unsigned long)getMcontextEip},
{"getsetCommand",(unsigned long)getsetCommand},
{"glueReplyBuffersIfNeeded",(unsigned long)glueReplyBuffersIfNeeded},
{"htNeedsResize",(unsigned long)htNeedsResize},
{"incrCommand",(unsigned long)incrCommand},
{"incrDecrCommand",(unsigned long)incrDecrCommand},
{"incrRefCount",(unsigned long)incrRefCount},
{"incrbyCommand",(unsigned long)incrbyCommand},
{"infoCommand",(unsigned long)infoCommand},
{"initServer",(unsigned long)initServer},
{"initServerConfig",(unsigned long)initServerConfig},
{"isStringRepresentableAsLong",(unsigned long)isStringRepresentableAsLong},
{"keysCommand",(unsigned long)keysCommand},
{"lastsaveCommand",(unsigned long)lastsaveCommand},
{"lindexCommand",(unsigned long)lindexCommand},
{"llenCommand",(unsigned long)llenCommand},
{"loadServerConfig",(unsigned long)loadServerConfig},
{"lookupKey",(unsigned long)lookupKey},
{"lookupKeyByPattern",(unsigned long)lookupKeyByPattern},
{"lookupKeyRead",(unsigned long)lookupKeyRead},
{"lookupKeyWrite",(unsigned long)lookupKeyWrite},
{"lpopCommand",(unsigned long)lpopCommand},
{"lpushCommand",(unsigned long)lpushCommand},
{"lrangeCommand",(unsigned long)lrangeCommand},
{"lremCommand",(unsigned long)lremCommand},
{"lsetCommand",(unsigned long)lsetCommand},
{"ltrimCommand",(unsigned long)ltrimCommand},
{"mgetCommand",(unsigned long)mgetCommand},
{"monitorCommand",(unsigned long)monitorCommand},
{"moveCommand",(unsigned long)moveCommand},
{"msetCommand",(unsigned long)msetCommand},
{"msetGenericCommand",(unsigned long)msetGenericCommand},
{"msetnxCommand",(unsigned long)msetnxCommand},
{"oom",(unsigned long)oom},
{"pingCommand",(unsigned long)pingCommand},
{"popGenericCommand",(unsigned long)popGenericCommand},
{"processCommand",(unsigned long)processCommand},
{"processInputBuffer",(unsigned long)processInputBuffer},
{"pushGenericCommand",(unsigned long)pushGenericCommand},
{"qsortCompareSetsByCardinality",(unsigned long)qsortCompareSetsByCardinality},
{"randomkeyCommand",(unsigned long)randomkeyCommand},
{"rdbLoad",(unsigned long)rdbLoad},
{"rdbLoadDoubleValue",(unsigned long)rdbLoadDoubleValue},
{"rdbLoadIntegerObject",(unsigned long)rdbLoadIntegerObject},
{"rdbLoadLen",(unsigned long)rdbLoadLen},
{"rdbLoadLzfStringObject",(unsigned long)rdbLoadLzfStringObject},
{"rdbLoadStringObject",(unsigned long)rdbLoadStringObject},
{"rdbLoadTime",(unsigned long)rdbLoadTime},
{"rdbLoadType",(unsigned long)rdbLoadType},
{"rdbRemoveTempFile",(unsigned long)rdbRemoveTempFile},
{"rdbSave",(unsigned long)rdbSave},
{"rdbSaveBackground",(unsigned long)rdbSaveBackground},
{"rdbSaveDoubleValue",(unsigned long)rdbSaveDoubleValue},
{"rdbSaveLen",(unsigned long)rdbSaveLen},
{"rdbSaveLzfStringObject",(unsigned long)rdbSaveLzfStringObject},
{"rdbSaveStringObject",(unsigned long)rdbSaveStringObject},
{"rdbSaveStringObjectRaw",(unsigned long)rdbSaveStringObjectRaw},
{"rdbSaveTime",(unsigned long)rdbSaveTime},
{"rdbSaveType",(unsigned long)rdbSaveType},
{"rdbTryIntegerEncoding",(unsigned long)rdbTryIntegerEncoding},
{"readQueryFromClient",(unsigned long)readQueryFromClient},
{"redisLog",(unsigned long)redisLog},
{"removeExpire",(unsigned long)removeExpire},
{"renameCommand",(unsigned long)renameCommand},
{"renameGenericCommand",(unsigned long)renameGenericCommand},
{"renamenxCommand",(unsigned long)renamenxCommand},
{"replicationFeedSlaves",(unsigned long)replicationFeedSlaves},
{"resetClient",(unsigned long)resetClient},
{"resetServerSaveParams",(unsigned long)resetServerSaveParams},
{"rpopCommand",(unsigned long)rpopCommand},
{"rpushCommand",(unsigned long)rpushCommand},
{"saddCommand",(unsigned long)saddCommand},
{"saveCommand",(unsigned long)saveCommand},
{"scardCommand",(unsigned long)scardCommand},
{"sdiffCommand",(unsigned long)sdiffCommand},
{"sdiffstoreCommand",(unsigned long)sdiffstoreCommand},
{"sdsDictKeyCompare",(unsigned long)sdsDictKeyCompare},
{"segvHandler",(unsigned long)segvHandler},
{"selectCommand",(unsigned long)selectCommand},
{"selectDb",(unsigned long)selectDb},
{"sendBulkToSlave",(unsigned long)sendBulkToSlave},
{"sendReplyToClient",(unsigned long)sendReplyToClient},
{"serverCron",(unsigned long)serverCron},
{"setCommand",(unsigned long)setCommand},
{"setExpire",(unsigned long)setExpire},
{"setGenericCommand",(unsigned long)setGenericCommand},
{"setnxCommand",(unsigned long)setnxCommand},
{"setupSigSegvAction",(unsigned long)setupSigSegvAction},
{"shutdownCommand",(unsigned long)shutdownCommand},
{"sinterCommand",(unsigned long)sinterCommand},
{"sinterGenericCommand",(unsigned long)sinterGenericCommand},
{"sinterstoreCommand",(unsigned long)sinterstoreCommand},
{"sismemberCommand",(unsigned long)sismemberCommand},
{"slaveofCommand",(unsigned long)slaveofCommand},
{"smoveCommand",(unsigned long)smoveCommand},
{"sortCommand",(unsigned long)sortCommand},
{"sortCompare",(unsigned long)sortCompare},
{"spopCommand",(unsigned long)spopCommand},
{"srandmemberCommand",(unsigned long)srandmemberCommand},
{"sremCommand",(unsigned long)sremCommand},
{"stringObjectLen",(unsigned long)stringObjectLen},
{"sunionCommand",(unsigned long)sunionCommand},
{"sunionDiffGenericCommand",(unsigned long)sunionDiffGenericCommand},
{"sunionstoreCommand",(unsigned long)sunionstoreCommand},
{"syncCommand",(unsigned long)syncCommand},
{"syncRead",(unsigned long)syncRead},
{"syncReadLine",(unsigned long)syncReadLine},
{"syncWithMaster",(unsigned long)syncWithMaster},
{"syncWrite",(unsigned long)syncWrite},
{"tryObjectEncoding",(unsigned long)tryObjectEncoding},
{"tryObjectSharing",(unsigned long)tryObjectSharing},
{"tryResizeHashTables",(unsigned long)tryResizeHashTables},
{"ttlCommand",(unsigned long)ttlCommand},
{"typeCommand",(unsigned long)typeCommand},
{"updateSlavesWaitingBgsave",(unsigned long)updateSlavesWaitingBgsave},
{"yesnotoi",(unsigned long)yesnotoi},
{"zaddCommand",(unsigned long)zaddCommand},
{"zcardCommand",(unsigned long)zcardCommand},
{"zrangeCommand",(unsigned long)zrangeCommand},
{"zrangeGenericCommand",(unsigned long)zrangeGenericCommand},
{"zrangebyscoreCommand",(unsigned long)zrangebyscoreCommand},
{"zremCommand",(unsigned long)zremCommand},
{"zremrangebyscoreCommand",(unsigned long)zremrangebyscoreCommand},
{"zrevrangeCommand",(unsigned long)zrevrangeCommand},
{"zscoreCommand",(unsigned long)zscoreCommand},
{"zslCreate",(unsigned long)zslCreate},
{"zslCreateNode",(unsigned long)zslCreateNode},
{"zslDelete",(unsigned long)zslDelete},
{"zslFirstWithScore",(unsigned long)zslFirstWithScore},
{"zslFree",(unsigned long)zslFree},
{"zslFreeNode",(unsigned long)zslFreeNode},
{"zslInsert",(unsigned long)zslInsert},
{"zslRandomLevel",(unsigned long)zslRandomLevel},
{NULL,0}
};

View File

@ -0,0 +1,22 @@
# Build a symbol table for static symbols of redis.c
# Useful to get stack traces on segfault without a debugger. See redis.c
# for more information.
#
# Copyright(C) 2009 Salvatore Sanfilippo, under the BSD license.
set fd [open redis.c]
set symlist {}
while {[gets $fd line] != -1} {
if {[regexp {^static +[A-z0-9]+[ *]+([A-z0-9]*)\(} $line - sym]} {
lappend symlist $sym
}
}
set symlist [lsort -unique $symlist]
puts "static struct redisFunctionSym symsTable\[\] = {"
foreach sym $symlist {
puts "{\"$sym\",(unsigned long)$sym},"
}
puts "{NULL,0}"
puts "};"
close $fd