X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/c2f816b4233355b6b8426572bd6e2c024fa24193..d0cfb2be643e5102cb24c3d22a1cf9cfc9df20d1:/src/redis.c diff --git a/src/redis.c b/src/redis.c index 866ac360..9112adb5 100644 --- a/src/redis.c +++ b/src/redis.c @@ -70,12 +70,12 @@ struct redisServer server; /* server global state */ struct redisCommand *commandTable; struct redisCommand redisCommandTable[] = { {"get",getCommand,2,0,NULL,1,1,1,0,0}, - {"set",setCommand,3,REDIS_CMD_DENYOOM,NULL,0,0,0,0,0}, - {"setnx",setnxCommand,3,REDIS_CMD_DENYOOM,NULL,0,0,0,0,0}, - {"setex",setexCommand,4,REDIS_CMD_DENYOOM,NULL,0,0,0,0,0}, + {"set",setCommand,3,REDIS_CMD_DENYOOM,noPreloadGetKeys,1,1,1,0,0}, + {"setnx",setnxCommand,3,REDIS_CMD_DENYOOM,noPreloadGetKeys,1,1,1,0,0}, + {"setex",setexCommand,4,REDIS_CMD_DENYOOM,noPreloadGetKeys,2,2,1,0,0}, {"append",appendCommand,3,REDIS_CMD_DENYOOM,NULL,1,1,1,0,0}, {"strlen",strlenCommand,2,0,NULL,1,1,1,0,0}, - {"del",delCommand,-2,0,NULL,0,0,0,0,0}, + {"del",delCommand,-2,0,noPreloadGetKeys,1,-1,1,0,0}, {"exists",existsCommand,2,0,NULL,1,1,1,0,0}, {"setbit",setbitCommand,4,REDIS_CMD_DENYOOM,NULL,1,1,1,0,0}, {"getbit",getbitCommand,3,0,NULL,1,1,1,0,0}, @@ -94,7 +94,7 @@ struct redisCommand redisCommandTable[] = { {"lpop",lpopCommand,2,0,NULL,1,1,1,0,0}, {"brpop",brpopCommand,-3,0,NULL,1,1,1,0,0}, {"brpoplpush",brpoplpushCommand,4,REDIS_CMD_DENYOOM,NULL,1,2,1,0,0}, - {"blpop",blpopCommand,-3,0,NULL,1,1,1,0,0}, + {"blpop",blpopCommand,-3,0,NULL,1,-2,1,0,0}, {"llen",llenCommand,2,0,NULL,1,1,1,0,0}, {"lindex",lindexCommand,3,0,NULL,1,1,1,0,0}, {"lset",lsetCommand,4,REDIS_CMD_DENYOOM,NULL,1,1,1,0,0}, @@ -121,8 +121,8 @@ struct redisCommand redisCommandTable[] = { {"zrem",zremCommand,3,0,NULL,1,1,1,0,0}, {"zremrangebyscore",zremrangebyscoreCommand,4,0,NULL,1,1,1,0,0}, {"zremrangebyrank",zremrangebyrankCommand,4,0,NULL,1,1,1,0,0}, - {"zunionstore",zunionstoreCommand,-4,REDIS_CMD_DENYOOM,zunionInterBlockClientOnSwappedKeys,0,0,0,0,0}, - {"zinterstore",zinterstoreCommand,-4,REDIS_CMD_DENYOOM,zunionInterBlockClientOnSwappedKeys,0,0,0,0,0}, + {"zunionstore",zunionstoreCommand,-4,REDIS_CMD_DENYOOM,zunionInterGetKeys,0,0,0,0,0}, + {"zinterstore",zinterstoreCommand,-4,REDIS_CMD_DENYOOM,zunionInterGetKeys,0,0,0,0,0}, {"zrange",zrangeCommand,-4,0,NULL,1,1,1,0,0}, {"zrangebyscore",zrangebyscoreCommand,-4,0,NULL,1,1,1,0,0}, {"zrevrangebyscore",zrevrangebyscoreCommand,-4,0,NULL,1,1,1,0,0}, @@ -152,10 +152,10 @@ struct redisCommand redisCommandTable[] = { {"randomkey",randomkeyCommand,1,0,NULL,0,0,0,0,0}, {"select",selectCommand,2,0,NULL,0,0,0,0,0}, {"move",moveCommand,3,0,NULL,1,1,1,0,0}, - {"rename",renameCommand,3,0,NULL,1,1,1,0,0}, - {"renamenx",renamenxCommand,3,0,NULL,1,1,1,0,0}, - {"expire",expireCommand,3,0,NULL,0,0,0,0,0}, - {"expireat",expireatCommand,3,0,NULL,0,0,0,0,0}, + {"rename",renameCommand,3,0,renameGetKeys,1,2,1,0,0}, + {"renamenx",renamenxCommand,3,0,renameGetKeys,1,2,1,0,0}, + {"expire",expireCommand,3,0,NULL,1,1,1,0,0}, + {"expireat",expireatCommand,3,0,NULL,1,1,1,0,0}, {"keys",keysCommand,2,0,NULL,0,0,0,0,0}, {"dbsize",dbsizeCommand,1,0,NULL,0,0,0,0,0}, {"auth",authCommand,2,0,NULL,0,0,0,0,0}, @@ -168,7 +168,7 @@ struct redisCommand redisCommandTable[] = { {"lastsave",lastsaveCommand,1,0,NULL,0,0,0,0,0}, {"type",typeCommand,2,0,NULL,1,1,1,0,0}, {"multi",multiCommand,1,0,NULL,0,0,0,0,0}, - {"exec",execCommand,1,REDIS_CMD_DENYOOM,execBlockClientOnSwappedKeys,0,0,0,0,0}, + {"exec",execCommand,1,REDIS_CMD_DENYOOM,NULL,0,0,0,0,0}, {"discard",discardCommand,1,0,NULL,0,0,0,0,0}, {"sync",syncCommand,1,0,NULL,0,0,0,0,0}, {"flushdb",flushdbCommand,1,0,NULL,0,0,0,0,0}, @@ -186,8 +186,13 @@ struct redisCommand redisCommandTable[] = { {"psubscribe",psubscribeCommand,-2,0,NULL,0,0,0,0,0}, {"punsubscribe",punsubscribeCommand,-1,0,NULL,0,0,0,0,0}, {"publish",publishCommand,3,REDIS_CMD_FORCE_REPLICATION,NULL,0,0,0,0,0}, - {"watch",watchCommand,-2,0,NULL,0,0,0,0,0}, - {"unwatch",unwatchCommand,1,0,NULL,0,0,0,0,0} + {"watch",watchCommand,-2,0,noPreloadGetKeys,1,-1,1,0,0}, + {"unwatch",unwatchCommand,1,0,NULL,0,0,0,0,0}, + {"cluster",clusterCommand,-2,0,NULL,0,0,0,0,0}, + {"restore",restoreCommand,4,0,NULL,0,0,0,0,0}, + {"migrate",migrateCommand,6,0,NULL,0,0,0,0,0}, + {"dump",dumpCommand,2,0,NULL,0,0,0,0,0}, + {"object",objectCommand,-2,0,NULL,0,0,0,0,0} }; /*============================ Utility functions ============================ */ @@ -200,14 +205,20 @@ void redisLogRaw(int level, const char *msg) { time_t now = time(NULL); FILE *fp; char buf[64]; + int rawmode = (level & REDIS_LOG_RAW); + level &= 0xff; /* clear flags */ if (level < server.verbosity) return; fp = (server.logfile == NULL) ? stdout : fopen(server.logfile,"a"); if (!fp) return; - strftime(buf,sizeof(buf),"%d %b %H:%M:%S",localtime(&now)); - fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg); + if (rawmode) { + fprintf(fp,"%s",msg); + } else { + strftime(buf,sizeof(buf),"%d %b %H:%M:%S",localtime(&now)); + fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg); + } fflush(fp); if (server.logfile) fclose(fp); @@ -222,7 +233,7 @@ void redisLog(int level, const char *fmt, ...) { va_list ap; char msg[REDIS_MAX_LOGMSG_LEN]; - if (level < server.verbosity) return; + if ((level&0xff) < server.verbosity) return; va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); @@ -440,6 +451,17 @@ dictType keylistDictType = { dictListDestructor /* val destructor */ }; +/* Cluster nodes hash table, mapping nodes addresses 1.2.3.4:6379 to + * clusterNode structures. */ +dictType clusterNodesDictType = { + dictSdsHash, /* hash function */ + NULL, /* key dup */ + NULL, /* val dup */ + dictSdsKeyCompare, /* key compare */ + dictSdsDestructor, /* key destructor */ + NULL /* val destructor */ +}; + int htNeedsResize(dict *dict) { long long size, used; @@ -669,6 +691,9 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { * to detect transfer failures. */ if (!(loops % 10)) replicationCron(); + /* Run other sub-systems specific cron jobs */ + if (server.cluster_enabled && !(loops % 10)) clusterCron(); + server.cronloops++; return 100; } @@ -823,6 +848,8 @@ void initServerConfig() { server.set_max_intset_entries = REDIS_SET_MAX_INTSET_ENTRIES; server.shutdown_asap = 0; server.cache_flush_delay = 0; + server.cluster_enabled = 0; + server.cluster.configfile = zstrdup("nodes.conf"); updateLRUClock(); resetServerSaveParams(); @@ -945,6 +972,7 @@ void initServer() { } if (server.ds_enabled) dsInit(); + if (server.cluster_enabled) clusterInit(); srand(time(NULL)^getpid()); } @@ -1051,6 +1079,27 @@ int processCommand(redisClient *c) { return REDIS_OK; } + /* If cluster is enabled, redirect here */ + if (server.cluster_enabled && + !(cmd->getkeys_proc == NULL && cmd->firstkey == 0)) { + int hashslot; + + if (server.cluster.state != REDIS_CLUSTER_OK) { + addReplyError(c,"The cluster is down. Check with CLUSTER INFO for more information"); + return REDIS_OK; + } else { + clusterNode *n = getNodeByQuery(c,cmd,c->argv,c->argc,&hashslot); + if (n == NULL) { + addReplyError(c,"Invalid cross-node request"); + return REDIS_OK; + } else if (n != server.cluster.myself) { + addReplySds(c,sdscatprintf(sdsempty(), + "-MOVED %d %s:%d\r\n",hashslot,n->ip,n->port)); + return REDIS_OK; + } + } + } + /* Handle the maxmemory directive. * * First we try to free some memory if possible (if there are volatile @@ -1455,6 +1504,15 @@ sds genRedisInfoString(char *section) { } } + /* Clusetr */ + if (allsections || defsections || !strcasecmp(section,"cluster")) { + if (sections++) info = sdscat(info,"\r\n"); + info = sdscatprintf(info, + "# Cluster\r\n" + "cluster_enabled:%d\r\n", + server.cluster_enabled); + } + /* Key space */ if (allsections || defsections || !strcasecmp(section,"keyspace")) { if (sections++) info = sdscat(info,"\r\n"); @@ -1663,6 +1721,23 @@ void usage() { exit(1); } +void redisAsciiArt(void) { +#include "asciilogo.h" + char *buf = zmalloc(1024*16); + + snprintf(buf,1024*16,ascii_logo, + REDIS_VERSION, + redisGitSHA1(), + strtol(redisGitDirty(),NULL,10) > 0, + (sizeof(long) == 8) ? "64" : "32", + server.cluster_enabled ? "cluster" : "stand alone", + server.port, + (long) getpid() + ); + redisLogRaw(REDIS_NOTICE|REDIS_LOG_RAW,buf); + zfree(buf); +} + int main(int argc, char **argv) { long long start; @@ -1681,6 +1756,7 @@ int main(int argc, char **argv) { if (server.daemonize) daemonize(); initServer(); if (server.daemonize) createPidFile(); + redisAsciiArt(); redisLog(REDIS_NOTICE,"Server started, Redis version " REDIS_VERSION); #ifdef __linux__ linuxOvercommitMemoryWarning();