2  * Copyright (c) 2006-2009, Salvatore Sanfilippo <antirez at gmail dot com> 
   5  * Redistribution and use in source and binary forms, with or without 
   6  * modification, are permitted provided that the following conditions are met: 
   8  *   * Redistributions of source code must retain the above copyright notice, 
   9  *     this list of conditions and the following disclaimer. 
  10  *   * Redistributions in binary form must reproduce the above copyright 
  11  *     notice, this list of conditions and the following disclaimer in the 
  12  *     documentation and/or other materials provided with the distribution. 
  13  *   * Neither the name of Redis nor the names of its contributors may be used 
  14  *     to endorse or promote products derived from this software without 
  15  *     specific prior written permission. 
  17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
  18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
  21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  27  * POSSIBILITY OF SUCH DAMAGE. 
  30 #define REDIS_VERSION "1.050" 
  40 #define __USE_POSIX199309 
  46 #endif /* HAVE_BACKTRACE */ 
  54 #include <arpa/inet.h> 
  58 #include <sys/resource.h> 
  63 #include "solarisfixes.h" 
  67 #include "ae.h"     /* Event driven programming library */ 
  68 #include "sds.h"    /* Dynamic safe strings */ 
  69 #include "anet.h"   /* Networking the easy way */ 
  70 #include "dict.h"   /* Hash tables */ 
  71 #include "adlist.h" /* Linked lists */ 
  72 #include "zmalloc.h" /* total memory usage aware version of malloc/free */ 
  73 #include "lzf.h"    /* LZF compression library */ 
  74 #include "pqsort.h" /* Partial qsort for SORT+LIMIT */ 
  80 /* Static server configuration */ 
  81 #define REDIS_SERVERPORT        6379    /* TCP port */ 
  82 #define REDIS_MAXIDLETIME       (60*5)  /* default client timeout */ 
  83 #define REDIS_IOBUF_LEN         1024 
  84 #define REDIS_LOADBUF_LEN       1024 
  85 #define REDIS_STATIC_ARGS       4 
  86 #define REDIS_DEFAULT_DBNUM     16 
  87 #define REDIS_CONFIGLINE_MAX    1024 
  88 #define REDIS_OBJFREELIST_MAX   1000000 /* Max number of objects to cache */ 
  89 #define REDIS_MAX_SYNC_TIME     60      /* Slave can't take more to sync */ 
  90 #define REDIS_EXPIRELOOKUPS_PER_CRON    100 /* try to expire 100 keys/second */ 
  91 #define REDIS_MAX_WRITE_PER_EVENT (1024*64) 
  92 #define REDIS_REQUEST_MAX_SIZE  (1024*1024*256) /* max bytes in inline command */ 
  94 /* Hash table parameters */ 
  95 #define REDIS_HT_MINFILL        10      /* Minimal hash table fill 10% */ 
  98 #define REDIS_CMD_BULK          1       /* Bulk write command */ 
  99 #define REDIS_CMD_INLINE        2       /* Inline command */ 
 100 /* REDIS_CMD_DENYOOM reserves a longer comment: all the commands marked with 
 101    this flags will return an error when the 'maxmemory' option is set in the 
 102    config file and the server is using more than maxmemory bytes of memory. 
 103    In short this commands are denied on low memory conditions. */ 
 104 #define REDIS_CMD_DENYOOM       4 
 107 #define REDIS_STRING 0 
 113 /* Objects encoding */ 
 114 #define REDIS_ENCODING_RAW 0    /* Raw representation */ 
 115 #define REDIS_ENCODING_INT 1    /* Encoded as integer */ 
 117 /* Object types only used for dumping to disk */ 
 118 #define REDIS_EXPIRETIME 253 
 119 #define REDIS_SELECTDB 254 
 120 #define REDIS_EOF 255 
 122 /* Defines related to the dump file format. To store 32 bits lengths for short 
 123  * keys requires a lot of space, so we check the most significant 2 bits of 
 124  * the first byte to interpreter the length: 
 126  * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte 
 127  * 01|000000 00000000 =>  01, the len is 14 byes, 6 bits + 8 bits of next byte 
 128  * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow 
 129  * 11|000000 this means: specially encoded object will follow. The six bits 
 130  *           number specify the kind of object that follows. 
 131  *           See the REDIS_RDB_ENC_* defines. 
 133  * Lenghts up to 63 are stored using a single byte, most DB keys, and may 
 134  * values, will fit inside. */ 
 135 #define REDIS_RDB_6BITLEN 0 
 136 #define REDIS_RDB_14BITLEN 1 
 137 #define REDIS_RDB_32BITLEN 2 
 138 #define REDIS_RDB_ENCVAL 3 
 139 #define REDIS_RDB_LENERR UINT_MAX 
 141 /* When a length of a string object stored on disk has the first two bits 
 142  * set, the remaining two bits specify a special encoding for the object 
 143  * accordingly to the following defines: */ 
 144 #define REDIS_RDB_ENC_INT8 0        /* 8 bit signed integer */ 
 145 #define REDIS_RDB_ENC_INT16 1       /* 16 bit signed integer */ 
 146 #define REDIS_RDB_ENC_INT32 2       /* 32 bit signed integer */ 
 147 #define REDIS_RDB_ENC_LZF 3         /* string compressed with FASTLZ */ 
 150 #define REDIS_CLOSE 1       /* This client connection should be closed ASAP */ 
 151 #define REDIS_SLAVE 2       /* This client is a slave server */ 
 152 #define REDIS_MASTER 4      /* This client is a master server */ 
 153 #define REDIS_MONITOR 8      /* This client is a slave monitor, see MONITOR */ 
 155 /* Slave replication state - slave side */ 
 156 #define REDIS_REPL_NONE 0   /* No active replication */ 
 157 #define REDIS_REPL_CONNECT 1    /* Must connect to master */ 
 158 #define REDIS_REPL_CONNECTED 2  /* Connected to master */ 
 160 /* Slave replication state - from the point of view of master 
 161  * Note that in SEND_BULK and ONLINE state the slave receives new updates 
 162  * in its output queue. In the WAIT_BGSAVE state instead the server is waiting 
 163  * to start the next background saving in order to send updates to it. */ 
 164 #define REDIS_REPL_WAIT_BGSAVE_START 3 /* master waits bgsave to start feeding it */ 
 165 #define REDIS_REPL_WAIT_BGSAVE_END 4 /* master waits bgsave to start bulk DB transmission */ 
 166 #define REDIS_REPL_SEND_BULK 5 /* master is sending the bulk DB */ 
 167 #define REDIS_REPL_ONLINE 6 /* bulk DB already transmitted, receive updates */ 
 169 /* List related stuff */ 
 173 /* Sort operations */ 
 174 #define REDIS_SORT_GET 0 
 175 #define REDIS_SORT_ASC 1 
 176 #define REDIS_SORT_DESC 2 
 177 #define REDIS_SORTKEY_MAX 1024 
 180 #define REDIS_DEBUG 0 
 181 #define REDIS_NOTICE 1 
 182 #define REDIS_WARNING 2 
 184 /* Anti-warning macro... */ 
 185 #define REDIS_NOTUSED(V) ((void) V) 
 187 #define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^32 elements */ 
 188 #define ZSKIPLIST_P 0.25      /* Skiplist P = 1/4 */ 
 190 /* Append only defines */ 
 191 #define APPENDFSYNC_NO 0 
 192 #define APPENDFSYNC_ALWAYS 1 
 193 #define APPENDFSYNC_EVERYSEC 2 
 195 /*================================= Data types ============================== */ 
 197 /* A redis object, that is a type able to hold a string / list / set */ 
 198 typedef struct redisObject 
{ 
 201     unsigned char encoding
; 
 202     unsigned char notused
[2]; 
 206 typedef struct redisDb 
{ 
 212 /* With multiplexing we need to take per-clinet state. 
 213  * Clients are taken in a liked list. */ 
 214 typedef struct redisClient 
{ 
 219     robj 
**argv
, **mbargv
; 
 221     int bulklen
;            /* bulk read len. -1 if not in bulk read mode */ 
 222     int multibulk
;          /* multi bulk command format active */ 
 225     time_t lastinteraction
; /* time of the last interaction, used for timeout */ 
 226     int flags
;              /* REDIS_CLOSE | REDIS_SLAVE | REDIS_MONITOR */ 
 227     int slaveseldb
;         /* slave selected db, if this client is a slave */ 
 228     int authenticated
;      /* when requirepass is non-NULL */ 
 229     int replstate
;          /* replication state if this is a slave */ 
 230     int repldbfd
;           /* replication DB file descriptor */ 
 231     long repldboff
;          /* replication DB file offset */ 
 232     off_t repldbsize
;       /* replication DB file size */ 
 240 /* Global server state structure */ 
 246     unsigned int sharingpoolsize
; 
 247     long long dirty
;            /* changes to DB from the last save */ 
 249     list 
*slaves
, *monitors
; 
 250     char neterr
[ANET_ERR_LEN
]; 
 252     int cronloops
;              /* number of times the cron function run */ 
 253     list 
*objfreelist
;          /* A list of freed objects to avoid malloc() */ 
 254     time_t lastsave
;            /* Unix time of last save succeeede */ 
 255     size_t usedmemory
;             /* Used memory in megabytes */ 
 256     /* Fields used only for stats */ 
 257     time_t stat_starttime
;         /* server start time */ 
 258     long long stat_numcommands
;    /* number of processed commands */ 
 259     long long stat_numconnections
; /* number of connections received */ 
 272     int bgsaveinprogress
; 
 273     pid_t bgsavechildpid
; 
 274     struct saveparam 
*saveparams
; 
 279     char *appendfilename
; 
 282     /* Replication related */ 
 287     redisClient 
*master
;    /* client that is master for this slave */ 
 289     unsigned int maxclients
; 
 290     unsigned long maxmemory
; 
 291     /* Sort parameters - qsort_r() is only available under BSD so we 
 292      * have to take this state global, in order to pass it to sortCompare() */ 
 298 typedef void redisCommandProc(redisClient 
*c
); 
 299 struct redisCommand 
{ 
 301     redisCommandProc 
*proc
; 
 306 struct redisFunctionSym 
{ 
 308     unsigned long pointer
; 
 311 typedef struct _redisSortObject 
{ 
 319 typedef struct _redisSortOperation 
{ 
 322 } redisSortOperation
; 
 324 /* ZSETs use a specialized version of Skiplists */ 
 326 typedef struct zskiplistNode 
{ 
 327     struct zskiplistNode 
**forward
; 
 328     struct zskiplistNode 
*backward
; 
 333 typedef struct zskiplist 
{ 
 334     struct zskiplistNode 
*header
, *tail
; 
 335     unsigned long length
; 
 339 typedef struct zset 
{ 
 344 /* Our shared "common" objects */ 
 346 struct sharedObjectsStruct 
{ 
 347     robj 
*crlf
, *ok
, *err
, *emptybulk
, *czero
, *cone
, *pong
, *space
, 
 348     *colon
, *nullbulk
, *nullmultibulk
, 
 349     *emptymultibulk
, *wrongtypeerr
, *nokeyerr
, *syntaxerr
, *sameobjecterr
, 
 350     *outofrangeerr
, *plus
, 
 351     *select0
, *select1
, *select2
, *select3
, *select4
, 
 352     *select5
, *select6
, *select7
, *select8
, *select9
; 
 355 /* Global vars that are actally used as constants. The following double 
 356  * values are used for double on-disk serialization, and are initialized 
 357  * at runtime to avoid strange compiler optimizations. */ 
 359 static double R_Zero
, R_PosInf
, R_NegInf
, R_Nan
; 
 361 /*================================ Prototypes =============================== */ 
 363 static void freeStringObject(robj 
*o
); 
 364 static void freeListObject(robj 
*o
); 
 365 static void freeSetObject(robj 
*o
); 
 366 static void decrRefCount(void *o
); 
 367 static robj 
*createObject(int type
, void *ptr
); 
 368 static void freeClient(redisClient 
*c
); 
 369 static int rdbLoad(char *filename
); 
 370 static void addReply(redisClient 
*c
, robj 
*obj
); 
 371 static void addReplySds(redisClient 
*c
, sds s
); 
 372 static void incrRefCount(robj 
*o
); 
 373 static int rdbSaveBackground(char *filename
); 
 374 static robj 
*createStringObject(char *ptr
, size_t len
); 
 375 static void replicationFeedSlaves(list 
*slaves
, struct redisCommand 
*cmd
, int dictid
, robj 
**argv
, int argc
); 
 376 static void feedAppendOnlyFile(struct redisCommand 
*cmd
, int dictid
, robj 
**argv
, int argc
); 
 377 static int syncWithMaster(void); 
 378 static robj 
*tryObjectSharing(robj 
*o
); 
 379 static int tryObjectEncoding(robj 
*o
); 
 380 static robj 
*getDecodedObject(const robj 
*o
); 
 381 static int removeExpire(redisDb 
*db
, robj 
*key
); 
 382 static int expireIfNeeded(redisDb 
*db
, robj 
*key
); 
 383 static int deleteIfVolatile(redisDb 
*db
, robj 
*key
); 
 384 static int deleteKey(redisDb 
*db
, robj 
*key
); 
 385 static time_t getExpire(redisDb 
*db
, robj 
*key
); 
 386 static int setExpire(redisDb 
*db
, robj 
*key
, time_t when
); 
 387 static void updateSlavesWaitingBgsave(int bgsaveerr
); 
 388 static void freeMemoryIfNeeded(void); 
 389 static int processCommand(redisClient 
*c
); 
 390 static void setupSigSegvAction(void); 
 391 static void rdbRemoveTempFile(pid_t childpid
); 
 392 static size_t stringObjectLen(robj 
*o
); 
 393 static void processInputBuffer(redisClient 
*c
); 
 394 static zskiplist 
*zslCreate(void); 
 395 static void zslFree(zskiplist 
*zsl
); 
 396 static void zslInsert(zskiplist 
*zsl
, double score
, robj 
*obj
); 
 398 static void authCommand(redisClient 
*c
); 
 399 static void pingCommand(redisClient 
*c
); 
 400 static void echoCommand(redisClient 
*c
); 
 401 static void setCommand(redisClient 
*c
); 
 402 static void setnxCommand(redisClient 
*c
); 
 403 static void getCommand(redisClient 
*c
); 
 404 static void delCommand(redisClient 
*c
); 
 405 static void existsCommand(redisClient 
*c
); 
 406 static void incrCommand(redisClient 
*c
); 
 407 static void decrCommand(redisClient 
*c
); 
 408 static void incrbyCommand(redisClient 
*c
); 
 409 static void decrbyCommand(redisClient 
*c
); 
 410 static void selectCommand(redisClient 
*c
); 
 411 static void randomkeyCommand(redisClient 
*c
); 
 412 static void keysCommand(redisClient 
*c
); 
 413 static void dbsizeCommand(redisClient 
*c
); 
 414 static void lastsaveCommand(redisClient 
*c
); 
 415 static void saveCommand(redisClient 
*c
); 
 416 static void bgsaveCommand(redisClient 
*c
); 
 417 static void shutdownCommand(redisClient 
*c
); 
 418 static void moveCommand(redisClient 
*c
); 
 419 static void renameCommand(redisClient 
*c
); 
 420 static void renamenxCommand(redisClient 
*c
); 
 421 static void lpushCommand(redisClient 
*c
); 
 422 static void rpushCommand(redisClient 
*c
); 
 423 static void lpopCommand(redisClient 
*c
); 
 424 static void rpopCommand(redisClient 
*c
); 
 425 static void llenCommand(redisClient 
*c
); 
 426 static void lindexCommand(redisClient 
*c
); 
 427 static void lrangeCommand(redisClient 
*c
); 
 428 static void ltrimCommand(redisClient 
*c
); 
 429 static void typeCommand(redisClient 
*c
); 
 430 static void lsetCommand(redisClient 
*c
); 
 431 static void saddCommand(redisClient 
*c
); 
 432 static void sremCommand(redisClient 
*c
); 
 433 static void smoveCommand(redisClient 
*c
); 
 434 static void sismemberCommand(redisClient 
*c
); 
 435 static void scardCommand(redisClient 
*c
); 
 436 static void spopCommand(redisClient 
*c
); 
 437 static void srandmemberCommand(redisClient 
*c
); 
 438 static void sinterCommand(redisClient 
*c
); 
 439 static void sinterstoreCommand(redisClient 
*c
); 
 440 static void sunionCommand(redisClient 
*c
); 
 441 static void sunionstoreCommand(redisClient 
*c
); 
 442 static void sdiffCommand(redisClient 
*c
); 
 443 static void sdiffstoreCommand(redisClient 
*c
); 
 444 static void syncCommand(redisClient 
*c
); 
 445 static void flushdbCommand(redisClient 
*c
); 
 446 static void flushallCommand(redisClient 
*c
); 
 447 static void sortCommand(redisClient 
*c
); 
 448 static void lremCommand(redisClient 
*c
); 
 449 static void infoCommand(redisClient 
*c
); 
 450 static void mgetCommand(redisClient 
*c
); 
 451 static void monitorCommand(redisClient 
*c
); 
 452 static void expireCommand(redisClient 
*c
); 
 453 static void expireatCommand(redisClient 
*c
); 
 454 static void getsetCommand(redisClient 
*c
); 
 455 static void ttlCommand(redisClient 
*c
); 
 456 static void slaveofCommand(redisClient 
*c
); 
 457 static void debugCommand(redisClient 
*c
); 
 458 static void msetCommand(redisClient 
*c
); 
 459 static void msetnxCommand(redisClient 
*c
); 
 460 static void zaddCommand(redisClient 
*c
); 
 461 static void zrangeCommand(redisClient 
*c
); 
 462 static void zrangebyscoreCommand(redisClient 
*c
); 
 463 static void zrevrangeCommand(redisClient 
*c
); 
 464 static void zcardCommand(redisClient 
*c
); 
 465 static void zremCommand(redisClient 
*c
); 
 466 static void zscoreCommand(redisClient 
*c
); 
 467 static void zremrangebyscoreCommand(redisClient 
*c
); 
 469 /*================================= Globals ================================= */ 
 472 static struct redisServer server
; /* server global state */ 
 473 static struct redisCommand cmdTable
[] = { 
 474     {"get",getCommand
,2,REDIS_CMD_INLINE
}, 
 475     {"set",setCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 476     {"setnx",setnxCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 477     {"del",delCommand
,-2,REDIS_CMD_INLINE
}, 
 478     {"exists",existsCommand
,2,REDIS_CMD_INLINE
}, 
 479     {"incr",incrCommand
,2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 480     {"decr",decrCommand
,2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 481     {"mget",mgetCommand
,-2,REDIS_CMD_INLINE
}, 
 482     {"rpush",rpushCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 483     {"lpush",lpushCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 484     {"rpop",rpopCommand
,2,REDIS_CMD_INLINE
}, 
 485     {"lpop",lpopCommand
,2,REDIS_CMD_INLINE
}, 
 486     {"llen",llenCommand
,2,REDIS_CMD_INLINE
}, 
 487     {"lindex",lindexCommand
,3,REDIS_CMD_INLINE
}, 
 488     {"lset",lsetCommand
,4,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 489     {"lrange",lrangeCommand
,4,REDIS_CMD_INLINE
}, 
 490     {"ltrim",ltrimCommand
,4,REDIS_CMD_INLINE
}, 
 491     {"lrem",lremCommand
,4,REDIS_CMD_BULK
}, 
 492     {"sadd",saddCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 493     {"srem",sremCommand
,3,REDIS_CMD_BULK
}, 
 494     {"smove",smoveCommand
,4,REDIS_CMD_BULK
}, 
 495     {"sismember",sismemberCommand
,3,REDIS_CMD_BULK
}, 
 496     {"scard",scardCommand
,2,REDIS_CMD_INLINE
}, 
 497     {"spop",spopCommand
,2,REDIS_CMD_INLINE
}, 
 498     {"srandmember",srandmemberCommand
,2,REDIS_CMD_INLINE
}, 
 499     {"sinter",sinterCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 500     {"sinterstore",sinterstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 501     {"sunion",sunionCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 502     {"sunionstore",sunionstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 503     {"sdiff",sdiffCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 504     {"sdiffstore",sdiffstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 505     {"smembers",sinterCommand
,2,REDIS_CMD_INLINE
}, 
 506     {"zadd",zaddCommand
,4,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 507     {"zrem",zremCommand
,3,REDIS_CMD_BULK
}, 
 508     {"zremrangebyscore",zremrangebyscoreCommand
,4,REDIS_CMD_INLINE
}, 
 509     {"zrange",zrangeCommand
,4,REDIS_CMD_INLINE
}, 
 510     {"zrangebyscore",zrangebyscoreCommand
,4,REDIS_CMD_INLINE
}, 
 511     {"zrevrange",zrevrangeCommand
,4,REDIS_CMD_INLINE
}, 
 512     {"zcard",zcardCommand
,2,REDIS_CMD_INLINE
}, 
 513     {"zscore",zscoreCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 514     {"incrby",incrbyCommand
,3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 515     {"decrby",decrbyCommand
,3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 516     {"getset",getsetCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 517     {"mset",msetCommand
,-3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 518     {"msetnx",msetnxCommand
,-3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 519     {"randomkey",randomkeyCommand
,1,REDIS_CMD_INLINE
}, 
 520     {"select",selectCommand
,2,REDIS_CMD_INLINE
}, 
 521     {"move",moveCommand
,3,REDIS_CMD_INLINE
}, 
 522     {"rename",renameCommand
,3,REDIS_CMD_INLINE
}, 
 523     {"renamenx",renamenxCommand
,3,REDIS_CMD_INLINE
}, 
 524     {"expire",expireCommand
,3,REDIS_CMD_INLINE
}, 
 525     {"expireat",expireatCommand
,3,REDIS_CMD_INLINE
}, 
 526     {"keys",keysCommand
,2,REDIS_CMD_INLINE
}, 
 527     {"dbsize",dbsizeCommand
,1,REDIS_CMD_INLINE
}, 
 528     {"auth",authCommand
,2,REDIS_CMD_INLINE
}, 
 529     {"ping",pingCommand
,1,REDIS_CMD_INLINE
}, 
 530     {"echo",echoCommand
,2,REDIS_CMD_BULK
}, 
 531     {"save",saveCommand
,1,REDIS_CMD_INLINE
}, 
 532     {"bgsave",bgsaveCommand
,1,REDIS_CMD_INLINE
}, 
 533     {"shutdown",shutdownCommand
,1,REDIS_CMD_INLINE
}, 
 534     {"lastsave",lastsaveCommand
,1,REDIS_CMD_INLINE
}, 
 535     {"type",typeCommand
,2,REDIS_CMD_INLINE
}, 
 536     {"sync",syncCommand
,1,REDIS_CMD_INLINE
}, 
 537     {"flushdb",flushdbCommand
,1,REDIS_CMD_INLINE
}, 
 538     {"flushall",flushallCommand
,1,REDIS_CMD_INLINE
}, 
 539     {"sort",sortCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 540     {"info",infoCommand
,1,REDIS_CMD_INLINE
}, 
 541     {"monitor",monitorCommand
,1,REDIS_CMD_INLINE
}, 
 542     {"ttl",ttlCommand
,2,REDIS_CMD_INLINE
}, 
 543     {"slaveof",slaveofCommand
,3,REDIS_CMD_INLINE
}, 
 544     {"debug",debugCommand
,-2,REDIS_CMD_INLINE
}, 
 547 /*============================ Utility functions ============================ */ 
 549 /* Glob-style pattern matching. */ 
 550 int stringmatchlen(const char *pattern
, int patternLen
, 
 551         const char *string
, int stringLen
, int nocase
) 
 556             while (pattern
[1] == '*') { 
 561                 return 1; /* match */ 
 563                 if (stringmatchlen(pattern
+1, patternLen
-1, 
 564                             string
, stringLen
, nocase
)) 
 565                     return 1; /* match */ 
 569             return 0; /* no match */ 
 573                 return 0; /* no match */ 
 583             not = pattern
[0] == '^'; 
 590                 if (pattern
[0] == '\\') { 
 593                     if (pattern
[0] == string
[0]) 
 595                 } else if (pattern
[0] == ']') { 
 597                 } else if (patternLen 
== 0) { 
 601                 } else if (pattern
[1] == '-' && patternLen 
>= 3) { 
 602                     int start 
= pattern
[0]; 
 603                     int end 
= pattern
[2]; 
 611                         start 
= tolower(start
); 
 617                     if (c 
>= start 
&& c 
<= end
) 
 621                         if (pattern
[0] == string
[0]) 
 624                         if (tolower((int)pattern
[0]) == tolower((int)string
[0])) 
 634                 return 0; /* no match */ 
 640             if (patternLen 
>= 2) { 
 647                 if (pattern
[0] != string
[0]) 
 648                     return 0; /* no match */ 
 650                 if (tolower((int)pattern
[0]) != tolower((int)string
[0])) 
 651                     return 0; /* no match */ 
 659         if (stringLen 
== 0) { 
 660             while(*pattern 
== '*') { 
 667     if (patternLen 
== 0 && stringLen 
== 0) 
 672 static void redisLog(int level
, const char *fmt
, ...) { 
 676     fp 
= (server
.logfile 
== NULL
) ? stdout 
: fopen(server
.logfile
,"a"); 
 680     if (level 
>= server
.verbosity
) { 
 686         strftime(buf
,64,"%d %b %H:%M:%S",localtime(&now
)); 
 687         fprintf(fp
,"%s %c ",buf
,c
[level
]); 
 688         vfprintf(fp
, fmt
, ap
); 
 694     if (server
.logfile
) fclose(fp
); 
 697 /*====================== Hash table type implementation  ==================== */ 
 699 /* This is an hash table type that uses the SDS dynamic strings libary as 
 700  * keys and radis objects as values (objects can hold SDS strings, 
 703 static void dictVanillaFree(void *privdata
, void *val
) 
 705     DICT_NOTUSED(privdata
); 
 709 static int sdsDictKeyCompare(void *privdata
, const void *key1
, 
 713     DICT_NOTUSED(privdata
); 
 715     l1 
= sdslen((sds
)key1
); 
 716     l2 
= sdslen((sds
)key2
); 
 717     if (l1 
!= l2
) return 0; 
 718     return memcmp(key1
, key2
, l1
) == 0; 
 721 static void dictRedisObjectDestructor(void *privdata
, void *val
) 
 723     DICT_NOTUSED(privdata
); 
 728 static int dictObjKeyCompare(void *privdata
, const void *key1
, 
 731     const robj 
*o1 
= key1
, *o2 
= key2
; 
 732     return sdsDictKeyCompare(privdata
,o1
->ptr
,o2
->ptr
); 
 735 static unsigned int dictObjHash(const void *key
) { 
 737     return dictGenHashFunction(o
->ptr
, sdslen((sds
)o
->ptr
)); 
 740 static int dictEncObjKeyCompare(void *privdata
, const void *key1
, 
 743     const robj 
*o1 
= key1
, *o2 
= key2
; 
 745     if (o1
->encoding 
== REDIS_ENCODING_RAW 
&& 
 746         o2
->encoding 
== REDIS_ENCODING_RAW
) 
 747         return sdsDictKeyCompare(privdata
,o1
->ptr
,o2
->ptr
); 
 752         dec1 
= o1
->encoding 
!= REDIS_ENCODING_RAW 
? 
 753             getDecodedObject(o1
) : (robj
*)o1
; 
 754         dec2 
= o2
->encoding 
!= REDIS_ENCODING_RAW 
? 
 755             getDecodedObject(o2
) : (robj
*)o2
; 
 756         cmp 
= sdsDictKeyCompare(privdata
,dec1
->ptr
,dec2
->ptr
); 
 757         if (dec1 
!= o1
) decrRefCount(dec1
); 
 758         if (dec2 
!= o2
) decrRefCount(dec2
); 
 763 static unsigned int dictEncObjHash(const void *key
) { 
 766     if (o
->encoding 
== REDIS_ENCODING_RAW
) 
 767         return dictGenHashFunction(o
->ptr
, sdslen((sds
)o
->ptr
)); 
 769         robj 
*dec 
= getDecodedObject(o
); 
 770         unsigned int hash 
= dictGenHashFunction(dec
->ptr
, sdslen((sds
)dec
->ptr
)); 
 776 static dictType setDictType 
= { 
 777     dictEncObjHash
,            /* hash function */ 
 780     dictEncObjKeyCompare
,      /* key compare */ 
 781     dictRedisObjectDestructor
, /* key destructor */ 
 782     NULL                       
/* val destructor */ 
 785 static dictType zsetDictType 
= { 
 786     dictEncObjHash
,            /* hash function */ 
 789     dictEncObjKeyCompare
,      /* key compare */ 
 790     dictRedisObjectDestructor
, /* key destructor */ 
 791     dictVanillaFree            
/* val destructor */ 
 794 static dictType hashDictType 
= { 
 795     dictObjHash
,                /* hash function */ 
 798     dictObjKeyCompare
,          /* key compare */ 
 799     dictRedisObjectDestructor
,  /* key destructor */ 
 800     dictRedisObjectDestructor   
/* val destructor */ 
 803 /* ========================= Random utility functions ======================= */ 
 805 /* Redis generally does not try to recover from out of memory conditions 
 806  * when allocating objects or strings, it is not clear if it will be possible 
 807  * to report this condition to the client since the networking layer itself 
 808  * is based on heap allocation for send buffers, so we simply abort. 
 809  * At least the code will be simpler to read... */ 
 810 static void oom(const char *msg
) { 
 811     fprintf(stderr
, "%s: Out of memory\n",msg
); 
 817 /* ====================== Redis server networking stuff ===================== */ 
 818 static void closeTimedoutClients(void) { 
 821     time_t now 
= time(NULL
); 
 823     listRewind(server
.clients
); 
 824     while ((ln 
= listYield(server
.clients
)) != NULL
) { 
 825         c 
= listNodeValue(ln
); 
 826         if (!(c
->flags 
& REDIS_SLAVE
) &&    /* no timeout for slaves */ 
 827             !(c
->flags 
& REDIS_MASTER
) &&   /* no timeout for masters */ 
 828              (now 
- c
->lastinteraction 
> server
.maxidletime
)) { 
 829             redisLog(REDIS_DEBUG
,"Closing idle client"); 
 835 static int htNeedsResize(dict 
*dict
) { 
 836     long long size
, used
; 
 838     size 
= dictSlots(dict
); 
 839     used 
= dictSize(dict
); 
 840     return (size 
&& used 
&& size 
> DICT_HT_INITIAL_SIZE 
&& 
 841             (used
*100/size 
< REDIS_HT_MINFILL
)); 
 844 /* If the percentage of used slots in the HT reaches REDIS_HT_MINFILL 
 845  * we resize the hash table to save memory */ 
 846 static void tryResizeHashTables(void) { 
 849     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 850         if (htNeedsResize(server
.db
[j
].dict
)) { 
 851             redisLog(REDIS_DEBUG
,"The hash table %d is too sparse, resize it...",j
); 
 852             dictResize(server
.db
[j
].dict
); 
 853             redisLog(REDIS_DEBUG
,"Hash table %d resized.",j
); 
 855         if (htNeedsResize(server
.db
[j
].expires
)) 
 856             dictResize(server
.db
[j
].expires
); 
 860 static int serverCron(struct aeEventLoop 
*eventLoop
, long long id
, void *clientData
) { 
 861     int j
, loops 
= server
.cronloops
++; 
 862     REDIS_NOTUSED(eventLoop
); 
 864     REDIS_NOTUSED(clientData
); 
 866     /* Update the global state with the amount of used memory */ 
 867     server
.usedmemory 
= zmalloc_used_memory(); 
 869     /* Show some info about non-empty databases */ 
 870     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 871         long long size
, used
, vkeys
; 
 873         size 
= dictSlots(server
.db
[j
].dict
); 
 874         used 
= dictSize(server
.db
[j
].dict
); 
 875         vkeys 
= dictSize(server
.db
[j
].expires
); 
 876         if (!(loops 
% 5) && (used 
|| vkeys
)) { 
 877             redisLog(REDIS_DEBUG
,"DB %d: %lld keys (%lld volatile) in %lld slots HT.",j
,used
,vkeys
,size
); 
 878             /* dictPrintStats(server.dict); */ 
 882     /* We don't want to resize the hash tables while a bacground saving 
 883      * is in progress: the saving child is created using fork() that is 
 884      * implemented with a copy-on-write semantic in most modern systems, so 
 885      * if we resize the HT while there is the saving child at work actually 
 886      * a lot of memory movements in the parent will cause a lot of pages 
 888     if (!server
.bgsaveinprogress
) tryResizeHashTables(); 
 890     /* Show information about connected clients */ 
 892         redisLog(REDIS_DEBUG
,"%d clients connected (%d slaves), %zu bytes in use, %d shared objects", 
 893             listLength(server
.clients
)-listLength(server
.slaves
), 
 894             listLength(server
.slaves
), 
 896             dictSize(server
.sharingpool
)); 
 899     /* Close connections of timedout clients */ 
 900     if (server
.maxidletime 
&& !(loops 
% 10)) 
 901         closeTimedoutClients(); 
 903     /* Check if a background saving in progress terminated */ 
 904     if (server
.bgsaveinprogress
) { 
 906         if (wait4(-1,&statloc
,WNOHANG
,NULL
)) { 
 907             int exitcode 
= WEXITSTATUS(statloc
); 
 908             int bysignal 
= WIFSIGNALED(statloc
); 
 910             if (!bysignal 
&& exitcode 
== 0) { 
 911                 redisLog(REDIS_NOTICE
, 
 912                     "Background saving terminated with success"); 
 914                 server
.lastsave 
= time(NULL
); 
 915             } else if (!bysignal 
&& exitcode 
!= 0) { 
 916                 redisLog(REDIS_WARNING
, "Background saving error"); 
 918                 redisLog(REDIS_WARNING
, 
 919                     "Background saving terminated by signal"); 
 920                 rdbRemoveTempFile(server
.bgsavechildpid
); 
 922             server
.bgsaveinprogress 
= 0; 
 923             server
.bgsavechildpid 
= -1; 
 924             updateSlavesWaitingBgsave(exitcode 
== 0 ? REDIS_OK 
: REDIS_ERR
); 
 927         /* If there is not a background saving in progress check if 
 928          * we have to save now */ 
 929          time_t now 
= time(NULL
); 
 930          for (j 
= 0; j 
< server
.saveparamslen
; j
++) { 
 931             struct saveparam 
*sp 
= server
.saveparams
+j
; 
 933             if (server
.dirty 
>= sp
->changes 
&& 
 934                 now
-server
.lastsave 
> sp
->seconds
) { 
 935                 redisLog(REDIS_NOTICE
,"%d changes in %d seconds. Saving...", 
 936                     sp
->changes
, sp
->seconds
); 
 937                 rdbSaveBackground(server
.dbfilename
); 
 943     /* Try to expire a few timed out keys. The algorithm used is adaptive and 
 944      * will use few CPU cycles if there are few expiring keys, otherwise 
 945      * it will get more aggressive to avoid that too much memory is used by 
 946      * keys that can be removed from the keyspace. */ 
 947     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 949         redisDb 
*db 
= server
.db
+j
; 
 951         /* Continue to expire if at the end of the cycle more than 25% 
 952          * of the keys were expired. */ 
 954             int num 
= dictSize(db
->expires
); 
 955             time_t now 
= time(NULL
); 
 958             if (num 
> REDIS_EXPIRELOOKUPS_PER_CRON
) 
 959                 num 
= REDIS_EXPIRELOOKUPS_PER_CRON
; 
 964                 if ((de 
= dictGetRandomKey(db
->expires
)) == NULL
) break; 
 965                 t 
= (time_t) dictGetEntryVal(de
); 
 967                     deleteKey(db
,dictGetEntryKey(de
)); 
 971         } while (expired 
> REDIS_EXPIRELOOKUPS_PER_CRON
/4); 
 974     /* Check if we should connect to a MASTER */ 
 975     if (server
.replstate 
== REDIS_REPL_CONNECT
) { 
 976         redisLog(REDIS_NOTICE
,"Connecting to MASTER..."); 
 977         if (syncWithMaster() == REDIS_OK
) { 
 978             redisLog(REDIS_NOTICE
,"MASTER <-> SLAVE sync succeeded"); 
 984 static void createSharedObjects(void) { 
 985     shared
.crlf 
= createObject(REDIS_STRING
,sdsnew("\r\n")); 
 986     shared
.ok 
= createObject(REDIS_STRING
,sdsnew("+OK\r\n")); 
 987     shared
.err 
= createObject(REDIS_STRING
,sdsnew("-ERR\r\n")); 
 988     shared
.emptybulk 
= createObject(REDIS_STRING
,sdsnew("$0\r\n\r\n")); 
 989     shared
.czero 
= createObject(REDIS_STRING
,sdsnew(":0\r\n")); 
 990     shared
.cone 
= createObject(REDIS_STRING
,sdsnew(":1\r\n")); 
 991     shared
.nullbulk 
= createObject(REDIS_STRING
,sdsnew("$-1\r\n")); 
 992     shared
.nullmultibulk 
= createObject(REDIS_STRING
,sdsnew("*-1\r\n")); 
 993     shared
.emptymultibulk 
= createObject(REDIS_STRING
,sdsnew("*0\r\n")); 
 995     shared
.pong 
= createObject(REDIS_STRING
,sdsnew("+PONG\r\n")); 
 996     shared
.wrongtypeerr 
= createObject(REDIS_STRING
,sdsnew( 
 997         "-ERR Operation against a key holding the wrong kind of value\r\n")); 
 998     shared
.nokeyerr 
= createObject(REDIS_STRING
,sdsnew( 
 999         "-ERR no such key\r\n")); 
1000     shared
.syntaxerr 
= createObject(REDIS_STRING
,sdsnew( 
1001         "-ERR syntax error\r\n")); 
1002     shared
.sameobjecterr 
= createObject(REDIS_STRING
,sdsnew( 
1003         "-ERR source and destination objects are the same\r\n")); 
1004     shared
.outofrangeerr 
= createObject(REDIS_STRING
,sdsnew( 
1005         "-ERR index out of range\r\n")); 
1006     shared
.space 
= createObject(REDIS_STRING
,sdsnew(" ")); 
1007     shared
.colon 
= createObject(REDIS_STRING
,sdsnew(":")); 
1008     shared
.plus 
= createObject(REDIS_STRING
,sdsnew("+")); 
1009     shared
.select0 
= createStringObject("select 0\r\n",10); 
1010     shared
.select1 
= createStringObject("select 1\r\n",10); 
1011     shared
.select2 
= createStringObject("select 2\r\n",10); 
1012     shared
.select3 
= createStringObject("select 3\r\n",10); 
1013     shared
.select4 
= createStringObject("select 4\r\n",10); 
1014     shared
.select5 
= createStringObject("select 5\r\n",10); 
1015     shared
.select6 
= createStringObject("select 6\r\n",10); 
1016     shared
.select7 
= createStringObject("select 7\r\n",10); 
1017     shared
.select8 
= createStringObject("select 8\r\n",10); 
1018     shared
.select9 
= createStringObject("select 9\r\n",10); 
1021 static void appendServerSaveParams(time_t seconds
, int changes
) { 
1022     server
.saveparams 
= zrealloc(server
.saveparams
,sizeof(struct saveparam
)*(server
.saveparamslen
+1)); 
1023     server
.saveparams
[server
.saveparamslen
].seconds 
= seconds
; 
1024     server
.saveparams
[server
.saveparamslen
].changes 
= changes
; 
1025     server
.saveparamslen
++; 
1028 static void ResetServerSaveParams() { 
1029     zfree(server
.saveparams
); 
1030     server
.saveparams 
= NULL
; 
1031     server
.saveparamslen 
= 0; 
1034 static void initServerConfig() { 
1035     server
.dbnum 
= REDIS_DEFAULT_DBNUM
; 
1036     server
.port 
= REDIS_SERVERPORT
; 
1037     server
.verbosity 
= REDIS_DEBUG
; 
1038     server
.maxidletime 
= REDIS_MAXIDLETIME
; 
1039     server
.saveparams 
= NULL
; 
1040     server
.logfile 
= NULL
; /* NULL = log on standard output */ 
1041     server
.bindaddr 
= NULL
; 
1042     server
.glueoutputbuf 
= 1; 
1043     server
.daemonize 
= 0; 
1044     server
.appendonly 
= 0; 
1045     server
.appendfsync 
= APPENDFSYNC_ALWAYS
; 
1046     server
.lastfsync 
= time(NULL
); 
1047     server
.appendfd 
= -1; 
1048     server
.appendseldb 
= -1; /* Make sure the first time will not match */ 
1049     server
.pidfile 
= "/var/run/redis.pid"; 
1050     server
.dbfilename 
= "dump.rdb"; 
1051     server
.appendfilename 
= "appendonly.log"; 
1052     server
.requirepass 
= NULL
; 
1053     server
.shareobjects 
= 0; 
1054     server
.sharingpoolsize 
= 1024; 
1055     server
.maxclients 
= 0; 
1056     server
.maxmemory 
= 0; 
1057     ResetServerSaveParams(); 
1059     appendServerSaveParams(60*60,1);  /* save after 1 hour and 1 change */ 
1060     appendServerSaveParams(300,100);  /* save after 5 minutes and 100 changes */ 
1061     appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */ 
1062     /* Replication related */ 
1064     server
.masterauth 
= NULL
; 
1065     server
.masterhost 
= NULL
; 
1066     server
.masterport 
= 6379; 
1067     server
.master 
= NULL
; 
1068     server
.replstate 
= REDIS_REPL_NONE
; 
1070     /* Double constants initialization */ 
1072     R_PosInf 
= 1.0/R_Zero
; 
1073     R_NegInf 
= -1.0/R_Zero
; 
1074     R_Nan 
= R_Zero
/R_Zero
; 
1077 static void initServer() { 
1080     signal(SIGHUP
, SIG_IGN
); 
1081     signal(SIGPIPE
, SIG_IGN
); 
1082     setupSigSegvAction(); 
1084     server
.clients 
= listCreate(); 
1085     server
.slaves 
= listCreate(); 
1086     server
.monitors 
= listCreate(); 
1087     server
.objfreelist 
= listCreate(); 
1088     createSharedObjects(); 
1089     server
.el 
= aeCreateEventLoop(); 
1090     server
.db 
= zmalloc(sizeof(redisDb
)*server
.dbnum
); 
1091     server
.sharingpool 
= dictCreate(&setDictType
,NULL
); 
1092     server
.fd 
= anetTcpServer(server
.neterr
, server
.port
, server
.bindaddr
); 
1093     if (server
.fd 
== -1) { 
1094         redisLog(REDIS_WARNING
, "Opening TCP port: %s", server
.neterr
); 
1097     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
1098         server
.db
[j
].dict 
= dictCreate(&hashDictType
,NULL
); 
1099         server
.db
[j
].expires 
= dictCreate(&setDictType
,NULL
); 
1100         server
.db
[j
].id 
= j
; 
1102     server
.cronloops 
= 0; 
1103     server
.bgsaveinprogress 
= 0; 
1104     server
.bgsavechildpid 
= -1; 
1105     server
.lastsave 
= time(NULL
); 
1107     server
.usedmemory 
= 0; 
1108     server
.stat_numcommands 
= 0; 
1109     server
.stat_numconnections 
= 0; 
1110     server
.stat_starttime 
= time(NULL
); 
1111     aeCreateTimeEvent(server
.el
, 1, serverCron
, NULL
, NULL
); 
1113     if (server
.appendonly
) { 
1114         server
.appendfd 
= open(server
.appendfilename
,O_WRONLY
|O_APPEND
|O_CREAT
,0644); 
1115         if (server
.appendfd 
== -1) { 
1116             redisLog(REDIS_WARNING
, "Can't open the append-only file: %s", 
1123 /* Empty the whole database */ 
1124 static long long emptyDb() { 
1126     long long removed 
= 0; 
1128     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
1129         removed 
+= dictSize(server
.db
[j
].dict
); 
1130         dictEmpty(server
.db
[j
].dict
); 
1131         dictEmpty(server
.db
[j
].expires
); 
1136 static int yesnotoi(char *s
) { 
1137     if (!strcasecmp(s
,"yes")) return 1; 
1138     else if (!strcasecmp(s
,"no")) return 0; 
1142 /* I agree, this is a very rudimental way to load a configuration... 
1143    will improve later if the config gets more complex */ 
1144 static void loadServerConfig(char *filename
) { 
1146     char buf
[REDIS_CONFIGLINE_MAX
+1], *err 
= NULL
; 
1150     if (filename
[0] == '-' && filename
[1] == '\0') 
1153         if ((fp 
= fopen(filename
,"r")) == NULL
) { 
1154             redisLog(REDIS_WARNING
,"Fatal error, can't open config file"); 
1159     while(fgets(buf
,REDIS_CONFIGLINE_MAX
+1,fp
) != NULL
) { 
1165         line 
= sdstrim(line
," \t\r\n"); 
1167         /* Skip comments and blank lines*/ 
1168         if (line
[0] == '#' || line
[0] == '\0') { 
1173         /* Split into arguments */ 
1174         argv 
= sdssplitlen(line
,sdslen(line
)," ",1,&argc
); 
1175         sdstolower(argv
[0]); 
1177         /* Execute config directives */ 
1178         if (!strcasecmp(argv
[0],"timeout") && argc 
== 2) { 
1179             server
.maxidletime 
= atoi(argv
[1]); 
1180             if (server
.maxidletime 
< 0) { 
1181                 err 
= "Invalid timeout value"; goto loaderr
; 
1183         } else if (!strcasecmp(argv
[0],"port") && argc 
== 2) { 
1184             server
.port 
= atoi(argv
[1]); 
1185             if (server
.port 
< 1 || server
.port 
> 65535) { 
1186                 err 
= "Invalid port"; goto loaderr
; 
1188         } else if (!strcasecmp(argv
[0],"bind") && argc 
== 2) { 
1189             server
.bindaddr 
= zstrdup(argv
[1]); 
1190         } else if (!strcasecmp(argv
[0],"save") && argc 
== 3) { 
1191             int seconds 
= atoi(argv
[1]); 
1192             int changes 
= atoi(argv
[2]); 
1193             if (seconds 
< 1 || changes 
< 0) { 
1194                 err 
= "Invalid save parameters"; goto loaderr
; 
1196             appendServerSaveParams(seconds
,changes
); 
1197         } else if (!strcasecmp(argv
[0],"dir") && argc 
== 2) { 
1198             if (chdir(argv
[1]) == -1) { 
1199                 redisLog(REDIS_WARNING
,"Can't chdir to '%s': %s", 
1200                     argv
[1], strerror(errno
)); 
1203         } else if (!strcasecmp(argv
[0],"loglevel") && argc 
== 2) { 
1204             if (!strcasecmp(argv
[1],"debug")) server
.verbosity 
= REDIS_DEBUG
; 
1205             else if (!strcasecmp(argv
[1],"notice")) server
.verbosity 
= REDIS_NOTICE
; 
1206             else if (!strcasecmp(argv
[1],"warning")) server
.verbosity 
= REDIS_WARNING
; 
1208                 err 
= "Invalid log level. Must be one of debug, notice, warning"; 
1211         } else if (!strcasecmp(argv
[0],"logfile") && argc 
== 2) { 
1214             server
.logfile 
= zstrdup(argv
[1]); 
1215             if (!strcasecmp(server
.logfile
,"stdout")) { 
1216                 zfree(server
.logfile
); 
1217                 server
.logfile 
= NULL
; 
1219             if (server
.logfile
) { 
1220                 /* Test if we are able to open the file. The server will not 
1221                  * be able to abort just for this problem later... */ 
1222                 logfp 
= fopen(server
.logfile
,"a"); 
1223                 if (logfp 
== NULL
) { 
1224                     err 
= sdscatprintf(sdsempty(), 
1225                         "Can't open the log file: %s", strerror(errno
)); 
1230         } else if (!strcasecmp(argv
[0],"databases") && argc 
== 2) { 
1231             server
.dbnum 
= atoi(argv
[1]); 
1232             if (server
.dbnum 
< 1) { 
1233                 err 
= "Invalid number of databases"; goto loaderr
; 
1235         } else if (!strcasecmp(argv
[0],"maxclients") && argc 
== 2) { 
1236             server
.maxclients 
= atoi(argv
[1]); 
1237         } else if (!strcasecmp(argv
[0],"maxmemory") && argc 
== 2) { 
1238             server
.maxmemory 
= strtoll(argv
[1], NULL
, 10); 
1239         } else if (!strcasecmp(argv
[0],"slaveof") && argc 
== 3) { 
1240             server
.masterhost 
= sdsnew(argv
[1]); 
1241             server
.masterport 
= atoi(argv
[2]); 
1242             server
.replstate 
= REDIS_REPL_CONNECT
; 
1243         } else if (!strcasecmp(argv
[0],"masterauth") && argc 
== 2) { 
1244                 server
.masterauth 
= zstrdup(argv
[1]); 
1245         } else if (!strcasecmp(argv
[0],"glueoutputbuf") && argc 
== 2) { 
1246             if ((server
.glueoutputbuf 
= yesnotoi(argv
[1])) == -1) { 
1247                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1249         } else if (!strcasecmp(argv
[0],"shareobjects") && argc 
== 2) { 
1250             if ((server
.shareobjects 
= yesnotoi(argv
[1])) == -1) { 
1251                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1253         } else if (!strcasecmp(argv
[0],"shareobjectspoolsize") && argc 
== 2) { 
1254             server
.sharingpoolsize 
= atoi(argv
[1]); 
1255             if (server
.sharingpoolsize 
< 1) { 
1256                 err 
= "invalid object sharing pool size"; goto loaderr
; 
1258         } else if (!strcasecmp(argv
[0],"daemonize") && argc 
== 2) { 
1259             if ((server
.daemonize 
= yesnotoi(argv
[1])) == -1) { 
1260                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1262         } else if (!strcasecmp(argv
[0],"appendonly") && argc 
== 2) { 
1263             if ((server
.appendonly 
= yesnotoi(argv
[1])) == -1) { 
1264                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1266         } else if (!strcasecmp(argv
[0],"appendfsync") && argc 
== 2) { 
1267             if (!strcasecmp(argv
[1],"no")) { 
1268                 server
.appendfsync 
= APPENDFSYNC_NO
; 
1269             } else if (!strcasecmp(argv
[1],"always")) { 
1270                 server
.appendfsync 
= APPENDFSYNC_ALWAYS
; 
1271             } else if (!strcasecmp(argv
[1],"everysec")) { 
1272                 server
.appendfsync 
= APPENDFSYNC_EVERYSEC
; 
1274                 err 
= "argument must be 'no', 'always' or 'everysec'"; 
1277         } else if (!strcasecmp(argv
[0],"requirepass") && argc 
== 2) { 
1278           server
.requirepass 
= zstrdup(argv
[1]); 
1279         } else if (!strcasecmp(argv
[0],"pidfile") && argc 
== 2) { 
1280           server
.pidfile 
= zstrdup(argv
[1]); 
1281         } else if (!strcasecmp(argv
[0],"dbfilename") && argc 
== 2) { 
1282           server
.dbfilename 
= zstrdup(argv
[1]); 
1284             err 
= "Bad directive or wrong number of arguments"; goto loaderr
; 
1286         for (j 
= 0; j 
< argc
; j
++) 
1291     if (fp 
!= stdin
) fclose(fp
); 
1295     fprintf(stderr
, "\n*** FATAL CONFIG FILE ERROR ***\n"); 
1296     fprintf(stderr
, "Reading the configuration file, at line %d\n", linenum
); 
1297     fprintf(stderr
, ">>> '%s'\n", line
); 
1298     fprintf(stderr
, "%s\n", err
); 
1302 static void freeClientArgv(redisClient 
*c
) { 
1305     for (j 
= 0; j 
< c
->argc
; j
++) 
1306         decrRefCount(c
->argv
[j
]); 
1307     for (j 
= 0; j 
< c
->mbargc
; j
++) 
1308         decrRefCount(c
->mbargv
[j
]); 
1313 static void freeClient(redisClient 
*c
) { 
1316     aeDeleteFileEvent(server
.el
,c
->fd
,AE_READABLE
); 
1317     aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
1318     sdsfree(c
->querybuf
); 
1319     listRelease(c
->reply
); 
1322     ln 
= listSearchKey(server
.clients
,c
); 
1324     listDelNode(server
.clients
,ln
); 
1325     if (c
->flags 
& REDIS_SLAVE
) { 
1326         if (c
->replstate 
== REDIS_REPL_SEND_BULK 
&& c
->repldbfd 
!= -1) 
1328         list 
*l 
= (c
->flags 
& REDIS_MONITOR
) ? server
.monitors 
: server
.slaves
; 
1329         ln 
= listSearchKey(l
,c
); 
1333     if (c
->flags 
& REDIS_MASTER
) { 
1334         server
.master 
= NULL
; 
1335         server
.replstate 
= REDIS_REPL_CONNECT
; 
1342 static void glueReplyBuffersIfNeeded(redisClient 
*c
) { 
1347     listRewind(c
->reply
); 
1348     while((ln 
= listYield(c
->reply
))) { 
1350         totlen 
+= sdslen(o
->ptr
); 
1351         /* This optimization makes more sense if we don't have to copy 
1353         if (totlen 
> 1024) return; 
1359         listRewind(c
->reply
); 
1360         while((ln 
= listYield(c
->reply
))) { 
1362             memcpy(buf
+copylen
,o
->ptr
,sdslen(o
->ptr
)); 
1363             copylen 
+= sdslen(o
->ptr
); 
1364             listDelNode(c
->reply
,ln
); 
1366         /* Now the output buffer is empty, add the new single element */ 
1367         o 
= createObject(REDIS_STRING
,sdsnewlen(buf
,totlen
)); 
1368         listAddNodeTail(c
->reply
,o
); 
1372 static void sendReplyToClient(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1373     redisClient 
*c 
= privdata
; 
1374     int nwritten 
= 0, totwritten 
= 0, objlen
; 
1377     REDIS_NOTUSED(mask
); 
1379     if (server
.glueoutputbuf 
&& listLength(c
->reply
) > 1) 
1380         glueReplyBuffersIfNeeded(c
); 
1381     while(listLength(c
->reply
)) { 
1382         o 
= listNodeValue(listFirst(c
->reply
)); 
1383         objlen 
= sdslen(o
->ptr
); 
1386             listDelNode(c
->reply
,listFirst(c
->reply
)); 
1390         if (c
->flags 
& REDIS_MASTER
) { 
1391             /* Don't reply to a master */ 
1392             nwritten 
= objlen 
- c
->sentlen
; 
1394             nwritten 
= write(fd
, ((char*)o
->ptr
)+c
->sentlen
, objlen 
- c
->sentlen
); 
1395             if (nwritten 
<= 0) break; 
1397         c
->sentlen 
+= nwritten
; 
1398         totwritten 
+= nwritten
; 
1399         /* If we fully sent the object on head go to the next one */ 
1400         if (c
->sentlen 
== objlen
) { 
1401             listDelNode(c
->reply
,listFirst(c
->reply
)); 
1404         /* Note that we avoid to send more thank REDIS_MAX_WRITE_PER_EVENT 
1405          * bytes, in a single threaded server it's a good idea to server 
1406          * other clients as well, even if a very large request comes from 
1407          * super fast link that is always able to accept data (in real world 
1408          * terms think to 'KEYS *' against the loopback interfae) */ 
1409         if (totwritten 
> REDIS_MAX_WRITE_PER_EVENT
) break; 
1411     if (nwritten 
== -1) { 
1412         if (errno 
== EAGAIN
) { 
1415             redisLog(REDIS_DEBUG
, 
1416                 "Error writing to client: %s", strerror(errno
)); 
1421     if (totwritten 
> 0) c
->lastinteraction 
= time(NULL
); 
1422     if (listLength(c
->reply
) == 0) { 
1424         aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
1428 static struct redisCommand 
*lookupCommand(char *name
) { 
1430     while(cmdTable
[j
].name 
!= NULL
) { 
1431         if (!strcasecmp(name
,cmdTable
[j
].name
)) return &cmdTable
[j
]; 
1437 /* resetClient prepare the client to process the next command */ 
1438 static void resetClient(redisClient 
*c
) { 
1444 /* If this function gets called we already read a whole 
1445  * command, argments are in the client argv/argc fields. 
1446  * processCommand() execute the command or prepare the 
1447  * server for a bulk read from the client. 
1449  * If 1 is returned the client is still alive and valid and 
1450  * and other operations can be performed by the caller. Otherwise 
1451  * if 0 is returned the client was destroied (i.e. after QUIT). */ 
1452 static int processCommand(redisClient 
*c
) { 
1453     struct redisCommand 
*cmd
; 
1456     /* Free some memory if needed (maxmemory setting) */ 
1457     if (server
.maxmemory
) freeMemoryIfNeeded(); 
1459     /* Handle the multi bulk command type. This is an alternative protocol 
1460      * supported by Redis in order to receive commands that are composed of 
1461      * multiple binary-safe "bulk" arguments. The latency of processing is 
1462      * a bit higher but this allows things like multi-sets, so if this 
1463      * protocol is used only for MSET and similar commands this is a big win. */ 
1464     if (c
->multibulk 
== 0 && c
->argc 
== 1 && ((char*)(c
->argv
[0]->ptr
))[0] == '*') { 
1465         c
->multibulk 
= atoi(((char*)c
->argv
[0]->ptr
)+1); 
1466         if (c
->multibulk 
<= 0) { 
1470             decrRefCount(c
->argv
[c
->argc
-1]); 
1474     } else if (c
->multibulk
) { 
1475         if (c
->bulklen 
== -1) { 
1476             if (((char*)c
->argv
[0]->ptr
)[0] != '$') { 
1477                 addReplySds(c
,sdsnew("-ERR multi bulk protocol error\r\n")); 
1481                 int bulklen 
= atoi(((char*)c
->argv
[0]->ptr
)+1); 
1482                 decrRefCount(c
->argv
[0]); 
1483                 if (bulklen 
< 0 || bulklen 
> 1024*1024*1024) { 
1485                     addReplySds(c
,sdsnew("-ERR invalid bulk write count\r\n")); 
1490                 c
->bulklen 
= bulklen
+2; /* add two bytes for CR+LF */ 
1494             c
->mbargv 
= zrealloc(c
->mbargv
,(sizeof(robj
*))*(c
->mbargc
+1)); 
1495             c
->mbargv
[c
->mbargc
] = c
->argv
[0]; 
1499             if (c
->multibulk 
== 0) { 
1503                 /* Here we need to swap the multi-bulk argc/argv with the 
1504                  * normal argc/argv of the client structure. */ 
1506                 c
->argv 
= c
->mbargv
; 
1507                 c
->mbargv 
= auxargv
; 
1510                 c
->argc 
= c
->mbargc
; 
1511                 c
->mbargc 
= auxargc
; 
1513                 /* We need to set bulklen to something different than -1 
1514                  * in order for the code below to process the command without 
1515                  * to try to read the last argument of a bulk command as 
1516                  * a special argument. */ 
1518                 /* continue below and process the command */ 
1525     /* -- end of multi bulk commands processing -- */ 
1527     /* The QUIT command is handled as a special case. Normal command 
1528      * procs are unable to close the client connection safely */ 
1529     if (!strcasecmp(c
->argv
[0]->ptr
,"quit")) { 
1533     cmd 
= lookupCommand(c
->argv
[0]->ptr
); 
1535         addReplySds(c
,sdsnew("-ERR unknown command\r\n")); 
1538     } else if ((cmd
->arity 
> 0 && cmd
->arity 
!= c
->argc
) || 
1539                (c
->argc 
< -cmd
->arity
)) { 
1540         addReplySds(c
,sdsnew("-ERR wrong number of arguments\r\n")); 
1543     } else if (server
.maxmemory 
&& cmd
->flags 
& REDIS_CMD_DENYOOM 
&& zmalloc_used_memory() > server
.maxmemory
) { 
1544         addReplySds(c
,sdsnew("-ERR command not allowed when used memory > 'maxmemory'\r\n")); 
1547     } else if (cmd
->flags 
& REDIS_CMD_BULK 
&& c
->bulklen 
== -1) { 
1548         int bulklen 
= atoi(c
->argv
[c
->argc
-1]->ptr
); 
1550         decrRefCount(c
->argv
[c
->argc
-1]); 
1551         if (bulklen 
< 0 || bulklen 
> 1024*1024*1024) { 
1553             addReplySds(c
,sdsnew("-ERR invalid bulk write count\r\n")); 
1558         c
->bulklen 
= bulklen
+2; /* add two bytes for CR+LF */ 
1559         /* It is possible that the bulk read is already in the 
1560          * buffer. Check this condition and handle it accordingly. 
1561          * This is just a fast path, alternative to call processInputBuffer(). 
1562          * It's a good idea since the code is small and this condition 
1563          * happens most of the times. */ 
1564         if ((signed)sdslen(c
->querybuf
) >= c
->bulklen
) { 
1565             c
->argv
[c
->argc
] = createStringObject(c
->querybuf
,c
->bulklen
-2); 
1567             c
->querybuf 
= sdsrange(c
->querybuf
,c
->bulklen
,-1); 
1572     /* Let's try to share objects on the command arguments vector */ 
1573     if (server
.shareobjects
) { 
1575         for(j 
= 1; j 
< c
->argc
; j
++) 
1576             c
->argv
[j
] = tryObjectSharing(c
->argv
[j
]); 
1578     /* Let's try to encode the bulk object to save space. */ 
1579     if (cmd
->flags 
& REDIS_CMD_BULK
) 
1580         tryObjectEncoding(c
->argv
[c
->argc
-1]); 
1582     /* Check if the user is authenticated */ 
1583     if (server
.requirepass 
&& !c
->authenticated 
&& cmd
->proc 
!= authCommand
) { 
1584         addReplySds(c
,sdsnew("-ERR operation not permitted\r\n")); 
1589     /* Exec the command */ 
1590     dirty 
= server
.dirty
; 
1592     if (server
.appendonly 
&& server
.dirty
-dirty
) 
1593         feedAppendOnlyFile(cmd
,c
->db
->id
,c
->argv
,c
->argc
); 
1594     if (server
.dirty
-dirty 
&& listLength(server
.slaves
)) 
1595         replicationFeedSlaves(server
.slaves
,cmd
,c
->db
->id
,c
->argv
,c
->argc
); 
1596     if (listLength(server
.monitors
)) 
1597         replicationFeedSlaves(server
.monitors
,cmd
,c
->db
->id
,c
->argv
,c
->argc
); 
1598     server
.stat_numcommands
++; 
1600     /* Prepare the client for the next command */ 
1601     if (c
->flags 
& REDIS_CLOSE
) { 
1609 static void replicationFeedSlaves(list 
*slaves
, struct redisCommand 
*cmd
, int dictid
, robj 
**argv
, int argc
) { 
1613     /* (args*2)+1 is enough room for args, spaces, newlines */ 
1614     robj 
*static_outv
[REDIS_STATIC_ARGS
*2+1]; 
1616     if (argc 
<= REDIS_STATIC_ARGS
) { 
1619         outv 
= zmalloc(sizeof(robj
*)*(argc
*2+1)); 
1622     for (j 
= 0; j 
< argc
; j
++) { 
1623         if (j 
!= 0) outv
[outc
++] = shared
.space
; 
1624         if ((cmd
->flags 
& REDIS_CMD_BULK
) && j 
== argc
-1) { 
1627             lenobj 
= createObject(REDIS_STRING
, 
1628                 sdscatprintf(sdsempty(),"%d\r\n", 
1629                     stringObjectLen(argv
[j
]))); 
1630             lenobj
->refcount 
= 0; 
1631             outv
[outc
++] = lenobj
; 
1633         outv
[outc
++] = argv
[j
]; 
1635     outv
[outc
++] = shared
.crlf
; 
1637     /* Increment all the refcounts at start and decrement at end in order to 
1638      * be sure to free objects if there is no slave in a replication state 
1639      * able to be feed with commands */ 
1640     for (j 
= 0; j 
< outc
; j
++) incrRefCount(outv
[j
]); 
1642     while((ln 
= listYield(slaves
))) { 
1643         redisClient 
*slave 
= ln
->value
; 
1645         /* Don't feed slaves that are still waiting for BGSAVE to start */ 
1646         if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) continue; 
1648         /* Feed all the other slaves, MONITORs and so on */ 
1649         if (slave
->slaveseldb 
!= dictid
) { 
1653             case 0: selectcmd 
= shared
.select0
; break; 
1654             case 1: selectcmd 
= shared
.select1
; break; 
1655             case 2: selectcmd 
= shared
.select2
; break; 
1656             case 3: selectcmd 
= shared
.select3
; break; 
1657             case 4: selectcmd 
= shared
.select4
; break; 
1658             case 5: selectcmd 
= shared
.select5
; break; 
1659             case 6: selectcmd 
= shared
.select6
; break; 
1660             case 7: selectcmd 
= shared
.select7
; break; 
1661             case 8: selectcmd 
= shared
.select8
; break; 
1662             case 9: selectcmd 
= shared
.select9
; break; 
1664                 selectcmd 
= createObject(REDIS_STRING
, 
1665                     sdscatprintf(sdsempty(),"select %d\r\n",dictid
)); 
1666                 selectcmd
->refcount 
= 0; 
1669             addReply(slave
,selectcmd
); 
1670             slave
->slaveseldb 
= dictid
; 
1672         for (j 
= 0; j 
< outc
; j
++) addReply(slave
,outv
[j
]); 
1674     for (j 
= 0; j 
< outc
; j
++) decrRefCount(outv
[j
]); 
1675     if (outv 
!= static_outv
) zfree(outv
); 
1678 static void processInputBuffer(redisClient 
*c
) { 
1680     if (c
->bulklen 
== -1) { 
1681         /* Read the first line of the query */ 
1682         char *p 
= strchr(c
->querybuf
,'\n'); 
1689             query 
= c
->querybuf
; 
1690             c
->querybuf 
= sdsempty(); 
1691             querylen 
= 1+(p
-(query
)); 
1692             if (sdslen(query
) > querylen
) { 
1693                 /* leave data after the first line of the query in the buffer */ 
1694                 c
->querybuf 
= sdscatlen(c
->querybuf
,query
+querylen
,sdslen(query
)-querylen
); 
1696             *p 
= '\0'; /* remove "\n" */ 
1697             if (*(p
-1) == '\r') *(p
-1) = '\0'; /* and "\r" if any */ 
1698             sdsupdatelen(query
); 
1700             /* Now we can split the query in arguments */ 
1701             if (sdslen(query
) == 0) { 
1702                 /* Ignore empty query */ 
1706             argv 
= sdssplitlen(query
,sdslen(query
)," ",1,&argc
); 
1709             if (c
->argv
) zfree(c
->argv
); 
1710             c
->argv 
= zmalloc(sizeof(robj
*)*argc
); 
1712             for (j 
= 0; j 
< argc
; j
++) { 
1713                 if (sdslen(argv
[j
])) { 
1714                     c
->argv
[c
->argc
] = createObject(REDIS_STRING
,argv
[j
]); 
1721             /* Execute the command. If the client is still valid 
1722              * after processCommand() return and there is something 
1723              * on the query buffer try to process the next command. */ 
1724             if (c
->argc 
&& processCommand(c
) && sdslen(c
->querybuf
)) goto again
; 
1726         } else if (sdslen(c
->querybuf
) >= REDIS_REQUEST_MAX_SIZE
) { 
1727             redisLog(REDIS_DEBUG
, "Client protocol error"); 
1732         /* Bulk read handling. Note that if we are at this point 
1733            the client already sent a command terminated with a newline, 
1734            we are reading the bulk data that is actually the last 
1735            argument of the command. */ 
1736         int qbl 
= sdslen(c
->querybuf
); 
1738         if (c
->bulklen 
<= qbl
) { 
1739             /* Copy everything but the final CRLF as final argument */ 
1740             c
->argv
[c
->argc
] = createStringObject(c
->querybuf
,c
->bulklen
-2); 
1742             c
->querybuf 
= sdsrange(c
->querybuf
,c
->bulklen
,-1); 
1743             /* Process the command. If the client is still valid after 
1744              * the processing and there is more data in the buffer 
1745              * try to parse it. */ 
1746             if (processCommand(c
) && sdslen(c
->querybuf
)) goto again
; 
1752 static void readQueryFromClient(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1753     redisClient 
*c 
= (redisClient
*) privdata
; 
1754     char buf
[REDIS_IOBUF_LEN
]; 
1757     REDIS_NOTUSED(mask
); 
1759     nread 
= read(fd
, buf
, REDIS_IOBUF_LEN
); 
1761         if (errno 
== EAGAIN
) { 
1764             redisLog(REDIS_DEBUG
, "Reading from client: %s",strerror(errno
)); 
1768     } else if (nread 
== 0) { 
1769         redisLog(REDIS_DEBUG
, "Client closed connection"); 
1774         c
->querybuf 
= sdscatlen(c
->querybuf
, buf
, nread
); 
1775         c
->lastinteraction 
= time(NULL
); 
1779     processInputBuffer(c
); 
1782 static int selectDb(redisClient 
*c
, int id
) { 
1783     if (id 
< 0 || id 
>= server
.dbnum
) 
1785     c
->db 
= &server
.db
[id
]; 
1789 static void *dupClientReplyValue(void *o
) { 
1790     incrRefCount((robj
*)o
); 
1794 static redisClient 
*createClient(int fd
) { 
1795     redisClient 
*c 
= zmalloc(sizeof(*c
)); 
1797     anetNonBlock(NULL
,fd
); 
1798     anetTcpNoDelay(NULL
,fd
); 
1799     if (!c
) return NULL
; 
1802     c
->querybuf 
= sdsempty(); 
1811     c
->lastinteraction 
= time(NULL
); 
1812     c
->authenticated 
= 0; 
1813     c
->replstate 
= REDIS_REPL_NONE
; 
1814     c
->reply 
= listCreate(); 
1815     listSetFreeMethod(c
->reply
,decrRefCount
); 
1816     listSetDupMethod(c
->reply
,dupClientReplyValue
); 
1817     if (aeCreateFileEvent(server
.el
, c
->fd
, AE_READABLE
, 
1818         readQueryFromClient
, c
, NULL
) == AE_ERR
) { 
1822     listAddNodeTail(server
.clients
,c
); 
1826 static void addReply(redisClient 
*c
, robj 
*obj
) { 
1827     if (listLength(c
->reply
) == 0 && 
1828         (c
->replstate 
== REDIS_REPL_NONE 
|| 
1829          c
->replstate 
== REDIS_REPL_ONLINE
) && 
1830         aeCreateFileEvent(server
.el
, c
->fd
, AE_WRITABLE
, 
1831         sendReplyToClient
, c
, NULL
) == AE_ERR
) return; 
1832     if (obj
->encoding 
!= REDIS_ENCODING_RAW
) { 
1833         obj 
= getDecodedObject(obj
); 
1837     listAddNodeTail(c
->reply
,obj
); 
1840 static void addReplySds(redisClient 
*c
, sds s
) { 
1841     robj 
*o 
= createObject(REDIS_STRING
,s
); 
1846 static void addReplyBulkLen(redisClient 
*c
, robj 
*obj
) { 
1849     if (obj
->encoding 
== REDIS_ENCODING_RAW
) { 
1850         len 
= sdslen(obj
->ptr
); 
1852         long n 
= (long)obj
->ptr
; 
1859         while((n 
= n
/10) != 0) { 
1863     addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",len
)); 
1866 static void acceptHandler(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1871     REDIS_NOTUSED(mask
); 
1872     REDIS_NOTUSED(privdata
); 
1874     cfd 
= anetAccept(server
.neterr
, fd
, cip
, &cport
); 
1875     if (cfd 
== AE_ERR
) { 
1876         redisLog(REDIS_DEBUG
,"Accepting client connection: %s", server
.neterr
); 
1879     redisLog(REDIS_DEBUG
,"Accepted %s:%d", cip
, cport
); 
1880     if ((c 
= createClient(cfd
)) == NULL
) { 
1881         redisLog(REDIS_WARNING
,"Error allocating resoures for the client"); 
1882         close(cfd
); /* May be already closed, just ingore errors */ 
1885     /* If maxclient directive is set and this is one client more... close the 
1886      * connection. Note that we create the client instead to check before 
1887      * for this condition, since now the socket is already set in nonblocking 
1888      * mode and we can send an error for free using the Kernel I/O */ 
1889     if (server
.maxclients 
&& listLength(server
.clients
) > server
.maxclients
) { 
1890         char *err 
= "-ERR max number of clients reached\r\n"; 
1892         /* That's a best effort error message, don't check write errors */ 
1893         (void) write(c
->fd
,err
,strlen(err
)); 
1897     server
.stat_numconnections
++; 
1900 /* ======================= Redis objects implementation ===================== */ 
1902 static robj 
*createObject(int type
, void *ptr
) { 
1905     if (listLength(server
.objfreelist
)) { 
1906         listNode 
*head 
= listFirst(server
.objfreelist
); 
1907         o 
= listNodeValue(head
); 
1908         listDelNode(server
.objfreelist
,head
); 
1910         o 
= zmalloc(sizeof(*o
)); 
1913     o
->encoding 
= REDIS_ENCODING_RAW
; 
1919 static robj 
*createStringObject(char *ptr
, size_t len
) { 
1920     return createObject(REDIS_STRING
,sdsnewlen(ptr
,len
)); 
1923 static robj 
*createListObject(void) { 
1924     list 
*l 
= listCreate(); 
1926     listSetFreeMethod(l
,decrRefCount
); 
1927     return createObject(REDIS_LIST
,l
); 
1930 static robj 
*createSetObject(void) { 
1931     dict 
*d 
= dictCreate(&setDictType
,NULL
); 
1932     return createObject(REDIS_SET
,d
); 
1935 static robj 
*createZsetObject(void) { 
1936     zset 
*zs 
= zmalloc(sizeof(*zs
)); 
1938     zs
->dict 
= dictCreate(&zsetDictType
,NULL
); 
1939     zs
->zsl 
= zslCreate(); 
1940     return createObject(REDIS_ZSET
,zs
); 
1943 static void freeStringObject(robj 
*o
) { 
1944     if (o
->encoding 
== REDIS_ENCODING_RAW
) { 
1949 static void freeListObject(robj 
*o
) { 
1950     listRelease((list
*) o
->ptr
); 
1953 static void freeSetObject(robj 
*o
) { 
1954     dictRelease((dict
*) o
->ptr
); 
1957 static void freeZsetObject(robj 
*o
) { 
1960     dictRelease(zs
->dict
); 
1965 static void freeHashObject(robj 
*o
) { 
1966     dictRelease((dict
*) o
->ptr
); 
1969 static void incrRefCount(robj 
*o
) { 
1971 #ifdef DEBUG_REFCOUNT 
1972     if (o
->type 
== REDIS_STRING
) 
1973         printf("Increment '%s'(%p), now is: %d\n",o
->ptr
,o
,o
->refcount
); 
1977 static void decrRefCount(void *obj
) { 
1980 #ifdef DEBUG_REFCOUNT 
1981     if (o
->type 
== REDIS_STRING
) 
1982         printf("Decrement '%s'(%p), now is: %d\n",o
->ptr
,o
,o
->refcount
-1); 
1984     if (--(o
->refcount
) == 0) { 
1986         case REDIS_STRING
: freeStringObject(o
); break; 
1987         case REDIS_LIST
: freeListObject(o
); break; 
1988         case REDIS_SET
: freeSetObject(o
); break; 
1989         case REDIS_ZSET
: freeZsetObject(o
); break; 
1990         case REDIS_HASH
: freeHashObject(o
); break; 
1991         default: assert(0 != 0); break; 
1993         if (listLength(server
.objfreelist
) > REDIS_OBJFREELIST_MAX 
|| 
1994             !listAddNodeHead(server
.objfreelist
,o
)) 
1999 static robj 
*lookupKey(redisDb 
*db
, robj 
*key
) { 
2000     dictEntry 
*de 
= dictFind(db
->dict
,key
); 
2001     return de 
? dictGetEntryVal(de
) : NULL
; 
2004 static robj 
*lookupKeyRead(redisDb 
*db
, robj 
*key
) { 
2005     expireIfNeeded(db
,key
); 
2006     return lookupKey(db
,key
); 
2009 static robj 
*lookupKeyWrite(redisDb 
*db
, robj 
*key
) { 
2010     deleteIfVolatile(db
,key
); 
2011     return lookupKey(db
,key
); 
2014 static int deleteKey(redisDb 
*db
, robj 
*key
) { 
2017     /* We need to protect key from destruction: after the first dictDelete() 
2018      * it may happen that 'key' is no longer valid if we don't increment 
2019      * it's count. This may happen when we get the object reference directly 
2020      * from the hash table with dictRandomKey() or dict iterators */ 
2022     if (dictSize(db
->expires
)) dictDelete(db
->expires
,key
); 
2023     retval 
= dictDelete(db
->dict
,key
); 
2026     return retval 
== DICT_OK
; 
2029 /* Try to share an object against the shared objects pool */ 
2030 static robj 
*tryObjectSharing(robj 
*o
) { 
2031     struct dictEntry 
*de
; 
2034     if (o 
== NULL 
|| server
.shareobjects 
== 0) return o
; 
2036     assert(o
->type 
== REDIS_STRING
); 
2037     de 
= dictFind(server
.sharingpool
,o
); 
2039         robj 
*shared 
= dictGetEntryKey(de
); 
2041         c 
= ((unsigned long) dictGetEntryVal(de
))+1; 
2042         dictGetEntryVal(de
) = (void*) c
; 
2043         incrRefCount(shared
); 
2047         /* Here we are using a stream algorihtm: Every time an object is 
2048          * shared we increment its count, everytime there is a miss we 
2049          * recrement the counter of a random object. If this object reaches 
2050          * zero we remove the object and put the current object instead. */ 
2051         if (dictSize(server
.sharingpool
) >= 
2052                 server
.sharingpoolsize
) { 
2053             de 
= dictGetRandomKey(server
.sharingpool
); 
2055             c 
= ((unsigned long) dictGetEntryVal(de
))-1; 
2056             dictGetEntryVal(de
) = (void*) c
; 
2058                 dictDelete(server
.sharingpool
,de
->key
); 
2061             c 
= 0; /* If the pool is empty we want to add this object */ 
2066             retval 
= dictAdd(server
.sharingpool
,o
,(void*)1); 
2067             assert(retval 
== DICT_OK
); 
2074 /* Check if the nul-terminated string 's' can be represented by a long 
2075  * (that is, is a number that fits into long without any other space or 
2076  * character before or after the digits). 
2078  * If so, the function returns REDIS_OK and *longval is set to the value 
2079  * of the number. Otherwise REDIS_ERR is returned */ 
2080 static int isStringRepresentableAsLong(sds s
, long *longval
) { 
2081     char buf
[32], *endptr
; 
2085     value 
= strtol(s
, &endptr
, 10); 
2086     if (endptr
[0] != '\0') return REDIS_ERR
; 
2087     slen 
= snprintf(buf
,32,"%ld",value
); 
2089     /* If the number converted back into a string is not identical 
2090      * then it's not possible to encode the string as integer */ 
2091     if (sdslen(s
) != (unsigned)slen 
|| memcmp(buf
,s
,slen
)) return REDIS_ERR
; 
2092     if (longval
) *longval 
= value
; 
2096 /* Try to encode a string object in order to save space */ 
2097 static int tryObjectEncoding(robj 
*o
) { 
2101     if (o
->encoding 
!= REDIS_ENCODING_RAW
) 
2102         return REDIS_ERR
; /* Already encoded */ 
2104     /* It's not save to encode shared objects: shared objects can be shared 
2105      * everywhere in the "object space" of Redis. Encoded objects can only 
2106      * appear as "values" (and not, for instance, as keys) */ 
2107      if (o
->refcount 
> 1) return REDIS_ERR
; 
2109     /* Currently we try to encode only strings */ 
2110     assert(o
->type 
== REDIS_STRING
); 
2112     /* Check if we can represent this string as a long integer */ 
2113     if (isStringRepresentableAsLong(s
,&value
) == REDIS_ERR
) return REDIS_ERR
; 
2115     /* Ok, this object can be encoded */ 
2116     o
->encoding 
= REDIS_ENCODING_INT
; 
2118     o
->ptr 
= (void*) value
; 
2122 /* Get a decoded version of an encoded object (returned as a new object) */ 
2123 static robj 
*getDecodedObject(const robj 
*o
) { 
2126     assert(o
->encoding 
!= REDIS_ENCODING_RAW
); 
2127     if (o
->type 
== REDIS_STRING 
&& o
->encoding 
== REDIS_ENCODING_INT
) { 
2130         snprintf(buf
,32,"%ld",(long)o
->ptr
); 
2131         dec 
= createStringObject(buf
,strlen(buf
)); 
2138 /* Compare two string objects via strcmp() or alike. 
2139  * Note that the objects may be integer-encoded. In such a case we 
2140  * use snprintf() to get a string representation of the numbers on the stack 
2141  * and compare the strings, it's much faster than calling getDecodedObject(). */ 
2142 static int compareStringObjects(robj 
*a
, robj 
*b
) { 
2143     assert(a
->type 
== REDIS_STRING 
&& b
->type 
== REDIS_STRING
); 
2144     char bufa
[128], bufb
[128], *astr
, *bstr
; 
2147     if (a 
== b
) return 0; 
2148     if (a
->encoding 
!= REDIS_ENCODING_RAW
) { 
2149         snprintf(bufa
,sizeof(bufa
),"%ld",(long) a
->ptr
); 
2155     if (b
->encoding 
!= REDIS_ENCODING_RAW
) { 
2156         snprintf(bufb
,sizeof(bufb
),"%ld",(long) b
->ptr
); 
2162     return bothsds 
? sdscmp(astr
,bstr
) : strcmp(astr
,bstr
); 
2165 static size_t stringObjectLen(robj 
*o
) { 
2166     assert(o
->type 
== REDIS_STRING
); 
2167     if (o
->encoding 
== REDIS_ENCODING_RAW
) { 
2168         return sdslen(o
->ptr
); 
2172         return snprintf(buf
,32,"%ld",(long)o
->ptr
); 
2176 /*============================ DB saving/loading ============================ */ 
2178 static int rdbSaveType(FILE *fp
, unsigned char type
) { 
2179     if (fwrite(&type
,1,1,fp
) == 0) return -1; 
2183 static int rdbSaveTime(FILE *fp
, time_t t
) { 
2184     int32_t t32 
= (int32_t) t
; 
2185     if (fwrite(&t32
,4,1,fp
) == 0) return -1; 
2189 /* check rdbLoadLen() comments for more info */ 
2190 static int rdbSaveLen(FILE *fp
, uint32_t len
) { 
2191     unsigned char buf
[2]; 
2194         /* Save a 6 bit len */ 
2195         buf
[0] = (len
&0xFF)|(REDIS_RDB_6BITLEN
<<6); 
2196         if (fwrite(buf
,1,1,fp
) == 0) return -1; 
2197     } else if (len 
< (1<<14)) { 
2198         /* Save a 14 bit len */ 
2199         buf
[0] = ((len
>>8)&0xFF)|(REDIS_RDB_14BITLEN
<<6); 
2201         if (fwrite(buf
,2,1,fp
) == 0) return -1; 
2203         /* Save a 32 bit len */ 
2204         buf
[0] = (REDIS_RDB_32BITLEN
<<6); 
2205         if (fwrite(buf
,1,1,fp
) == 0) return -1; 
2207         if (fwrite(&len
,4,1,fp
) == 0) return -1; 
2212 /* String objects in the form "2391" "-100" without any space and with a 
2213  * range of values that can fit in an 8, 16 or 32 bit signed value can be 
2214  * encoded as integers to save space */ 
2215 static int rdbTryIntegerEncoding(sds s
, unsigned char *enc
) { 
2217     char *endptr
, buf
[32]; 
2219     /* Check if it's possible to encode this value as a number */ 
2220     value 
= strtoll(s
, &endptr
, 10); 
2221     if (endptr
[0] != '\0') return 0; 
2222     snprintf(buf
,32,"%lld",value
); 
2224     /* If the number converted back into a string is not identical 
2225      * then it's not possible to encode the string as integer */ 
2226     if (strlen(buf
) != sdslen(s
) || memcmp(buf
,s
,sdslen(s
))) return 0; 
2228     /* Finally check if it fits in our ranges */ 
2229     if (value 
>= -(1<<7) && value 
<= (1<<7)-1) { 
2230         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT8
; 
2231         enc
[1] = value
&0xFF; 
2233     } else if (value 
>= -(1<<15) && value 
<= (1<<15)-1) { 
2234         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT16
; 
2235         enc
[1] = value
&0xFF; 
2236         enc
[2] = (value
>>8)&0xFF; 
2238     } else if (value 
>= -((long long)1<<31) && value 
<= ((long long)1<<31)-1) { 
2239         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT32
; 
2240         enc
[1] = value
&0xFF; 
2241         enc
[2] = (value
>>8)&0xFF; 
2242         enc
[3] = (value
>>16)&0xFF; 
2243         enc
[4] = (value
>>24)&0xFF; 
2250 static int rdbSaveLzfStringObject(FILE *fp
, robj 
*obj
) { 
2251     unsigned int comprlen
, outlen
; 
2255     /* We require at least four bytes compression for this to be worth it */ 
2256     outlen 
= sdslen(obj
->ptr
)-4; 
2257     if (outlen 
<= 0) return 0; 
2258     if ((out 
= zmalloc(outlen
+1)) == NULL
) return 0; 
2259     comprlen 
= lzf_compress(obj
->ptr
, sdslen(obj
->ptr
), out
, outlen
); 
2260     if (comprlen 
== 0) { 
2264     /* Data compressed! Let's save it on disk */ 
2265     byte 
= (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_LZF
; 
2266     if (fwrite(&byte
,1,1,fp
) == 0) goto writeerr
; 
2267     if (rdbSaveLen(fp
,comprlen
) == -1) goto writeerr
; 
2268     if (rdbSaveLen(fp
,sdslen(obj
->ptr
)) == -1) goto writeerr
; 
2269     if (fwrite(out
,comprlen
,1,fp
) == 0) goto writeerr
; 
2278 /* Save a string objet as [len][data] on disk. If the object is a string 
2279  * representation of an integer value we try to safe it in a special form */ 
2280 static int rdbSaveStringObjectRaw(FILE *fp
, robj 
*obj
) { 
2284     len 
= sdslen(obj
->ptr
); 
2286     /* Try integer encoding */ 
2288         unsigned char buf
[5]; 
2289         if ((enclen 
= rdbTryIntegerEncoding(obj
->ptr
,buf
)) > 0) { 
2290             if (fwrite(buf
,enclen
,1,fp
) == 0) return -1; 
2295     /* Try LZF compression - under 20 bytes it's unable to compress even 
2296      * aaaaaaaaaaaaaaaaaa so skip it */ 
2300         retval 
= rdbSaveLzfStringObject(fp
,obj
); 
2301         if (retval 
== -1) return -1; 
2302         if (retval 
> 0) return 0; 
2303         /* retval == 0 means data can't be compressed, save the old way */ 
2306     /* Store verbatim */ 
2307     if (rdbSaveLen(fp
,len
) == -1) return -1; 
2308     if (len 
&& fwrite(obj
->ptr
,len
,1,fp
) == 0) return -1; 
2312 /* Like rdbSaveStringObjectRaw() but handle encoded objects */ 
2313 static int rdbSaveStringObject(FILE *fp
, robj 
*obj
) { 
2317     if (obj
->encoding 
!= REDIS_ENCODING_RAW
) { 
2318         dec 
= getDecodedObject(obj
); 
2319         retval 
= rdbSaveStringObjectRaw(fp
,dec
); 
2323         return rdbSaveStringObjectRaw(fp
,obj
); 
2327 /* Save a double value. Doubles are saved as strings prefixed by an unsigned 
2328  * 8 bit integer specifing the length of the representation. 
2329  * This 8 bit integer has special values in order to specify the following 
2335 static int rdbSaveDoubleValue(FILE *fp
, double val
) { 
2336     unsigned char buf
[128]; 
2342     } else if (!isfinite(val
)) { 
2344         buf
[0] = (val 
< 0) ? 255 : 254; 
2346         snprintf((char*)buf
+1,sizeof(buf
)-1,"%.17g",val
); 
2347         buf
[0] = strlen((char*)buf
); 
2350     if (fwrite(buf
,len
,1,fp
) == 0) return -1; 
2354 /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */ 
2355 static int rdbSave(char *filename
) { 
2356     dictIterator 
*di 
= NULL
; 
2361     time_t now 
= time(NULL
); 
2363     snprintf(tmpfile
,256,"temp-%d.rdb", (int) getpid()); 
2364     fp 
= fopen(tmpfile
,"w"); 
2366         redisLog(REDIS_WARNING
, "Failed saving the DB: %s", strerror(errno
)); 
2369     if (fwrite("REDIS0001",9,1,fp
) == 0) goto werr
; 
2370     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
2371         redisDb 
*db 
= server
.db
+j
; 
2373         if (dictSize(d
) == 0) continue; 
2374         di 
= dictGetIterator(d
); 
2380         /* Write the SELECT DB opcode */ 
2381         if (rdbSaveType(fp
,REDIS_SELECTDB
) == -1) goto werr
; 
2382         if (rdbSaveLen(fp
,j
) == -1) goto werr
; 
2384         /* Iterate this DB writing every entry */ 
2385         while((de 
= dictNext(di
)) != NULL
) { 
2386             robj 
*key 
= dictGetEntryKey(de
); 
2387             robj 
*o 
= dictGetEntryVal(de
); 
2388             time_t expiretime 
= getExpire(db
,key
); 
2390             /* Save the expire time */ 
2391             if (expiretime 
!= -1) { 
2392                 /* If this key is already expired skip it */ 
2393                 if (expiretime 
< now
) continue; 
2394                 if (rdbSaveType(fp
,REDIS_EXPIRETIME
) == -1) goto werr
; 
2395                 if (rdbSaveTime(fp
,expiretime
) == -1) goto werr
; 
2397             /* Save the key and associated value */ 
2398             if (rdbSaveType(fp
,o
->type
) == -1) goto werr
; 
2399             if (rdbSaveStringObject(fp
,key
) == -1) goto werr
; 
2400             if (o
->type 
== REDIS_STRING
) { 
2401                 /* Save a string value */ 
2402                 if (rdbSaveStringObject(fp
,o
) == -1) goto werr
; 
2403             } else if (o
->type 
== REDIS_LIST
) { 
2404                 /* Save a list value */ 
2405                 list 
*list 
= o
->ptr
; 
2409                 if (rdbSaveLen(fp
,listLength(list
)) == -1) goto werr
; 
2410                 while((ln 
= listYield(list
))) { 
2411                     robj 
*eleobj 
= listNodeValue(ln
); 
2413                     if (rdbSaveStringObject(fp
,eleobj
) == -1) goto werr
; 
2415             } else if (o
->type 
== REDIS_SET
) { 
2416                 /* Save a set value */ 
2418                 dictIterator 
*di 
= dictGetIterator(set
); 
2421                 if (rdbSaveLen(fp
,dictSize(set
)) == -1) goto werr
; 
2422                 while((de 
= dictNext(di
)) != NULL
) { 
2423                     robj 
*eleobj 
= dictGetEntryKey(de
); 
2425                     if (rdbSaveStringObject(fp
,eleobj
) == -1) goto werr
; 
2427                 dictReleaseIterator(di
); 
2428             } else if (o
->type 
== REDIS_ZSET
) { 
2429                 /* Save a set value */ 
2431                 dictIterator 
*di 
= dictGetIterator(zs
->dict
); 
2434                 if (rdbSaveLen(fp
,dictSize(zs
->dict
)) == -1) goto werr
; 
2435                 while((de 
= dictNext(di
)) != NULL
) { 
2436                     robj 
*eleobj 
= dictGetEntryKey(de
); 
2437                     double *score 
= dictGetEntryVal(de
); 
2439                     if (rdbSaveStringObject(fp
,eleobj
) == -1) goto werr
; 
2440                     if (rdbSaveDoubleValue(fp
,*score
) == -1) goto werr
; 
2442                 dictReleaseIterator(di
); 
2447         dictReleaseIterator(di
); 
2450     if (rdbSaveType(fp
,REDIS_EOF
) == -1) goto werr
; 
2452     /* Make sure data will not remain on the OS's output buffers */ 
2457     /* Use RENAME to make sure the DB file is changed atomically only 
2458      * if the generate DB file is ok. */ 
2459     if (rename(tmpfile
,filename
) == -1) { 
2460         redisLog(REDIS_WARNING
,"Error moving temp DB file on the final destination: %s", strerror(errno
)); 
2464     redisLog(REDIS_NOTICE
,"DB saved on disk"); 
2466     server
.lastsave 
= time(NULL
); 
2472     redisLog(REDIS_WARNING
,"Write error saving DB on disk: %s", strerror(errno
)); 
2473     if (di
) dictReleaseIterator(di
); 
2477 static int rdbSaveBackground(char *filename
) { 
2480     if (server
.bgsaveinprogress
) return REDIS_ERR
; 
2481     if ((childpid 
= fork()) == 0) { 
2484         if (rdbSave(filename
) == REDIS_OK
) { 
2491         if (childpid 
== -1) { 
2492             redisLog(REDIS_WARNING
,"Can't save in background: fork: %s", 
2496         redisLog(REDIS_NOTICE
,"Background saving started by pid %d",childpid
); 
2497         server
.bgsaveinprogress 
= 1; 
2498         server
.bgsavechildpid 
= childpid
; 
2501     return REDIS_OK
; /* unreached */ 
2504 static void rdbRemoveTempFile(pid_t childpid
) { 
2507     snprintf(tmpfile
,256,"temp-%d.rdb", (int) childpid
); 
2511 static int rdbLoadType(FILE *fp
) { 
2513     if (fread(&type
,1,1,fp
) == 0) return -1; 
2517 static time_t rdbLoadTime(FILE *fp
) { 
2519     if (fread(&t32
,4,1,fp
) == 0) return -1; 
2520     return (time_t) t32
; 
2523 /* Load an encoded length from the DB, see the REDIS_RDB_* defines on the top 
2524  * of this file for a description of how this are stored on disk. 
2526  * isencoded is set to 1 if the readed length is not actually a length but 
2527  * an "encoding type", check the above comments for more info */ 
2528 static uint32_t rdbLoadLen(FILE *fp
, int rdbver
, int *isencoded
) { 
2529     unsigned char buf
[2]; 
2532     if (isencoded
) *isencoded 
= 0; 
2534         if (fread(&len
,4,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2539         if (fread(buf
,1,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2540         type 
= (buf
[0]&0xC0)>>6; 
2541         if (type 
== REDIS_RDB_6BITLEN
) { 
2542             /* Read a 6 bit len */ 
2544         } else if (type 
== REDIS_RDB_ENCVAL
) { 
2545             /* Read a 6 bit len encoding type */ 
2546             if (isencoded
) *isencoded 
= 1; 
2548         } else if (type 
== REDIS_RDB_14BITLEN
) { 
2549             /* Read a 14 bit len */ 
2550             if (fread(buf
+1,1,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2551             return ((buf
[0]&0x3F)<<8)|buf
[1]; 
2553             /* Read a 32 bit len */ 
2554             if (fread(&len
,4,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2560 static robj 
*rdbLoadIntegerObject(FILE *fp
, int enctype
) { 
2561     unsigned char enc
[4]; 
2564     if (enctype 
== REDIS_RDB_ENC_INT8
) { 
2565         if (fread(enc
,1,1,fp
) == 0) return NULL
; 
2566         val 
= (signed char)enc
[0]; 
2567     } else if (enctype 
== REDIS_RDB_ENC_INT16
) { 
2569         if (fread(enc
,2,1,fp
) == 0) return NULL
; 
2570         v 
= enc
[0]|(enc
[1]<<8); 
2572     } else if (enctype 
== REDIS_RDB_ENC_INT32
) { 
2574         if (fread(enc
,4,1,fp
) == 0) return NULL
; 
2575         v 
= enc
[0]|(enc
[1]<<8)|(enc
[2]<<16)|(enc
[3]<<24); 
2578         val 
= 0; /* anti-warning */ 
2581     return createObject(REDIS_STRING
,sdscatprintf(sdsempty(),"%lld",val
)); 
2584 static robj 
*rdbLoadLzfStringObject(FILE*fp
, int rdbver
) { 
2585     unsigned int len
, clen
; 
2586     unsigned char *c 
= NULL
; 
2589     if ((clen 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
2590     if ((len 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
2591     if ((c 
= zmalloc(clen
)) == NULL
) goto err
; 
2592     if ((val 
= sdsnewlen(NULL
,len
)) == NULL
) goto err
; 
2593     if (fread(c
,clen
,1,fp
) == 0) goto err
; 
2594     if (lzf_decompress(c
,clen
,val
,len
) == 0) goto err
; 
2596     return createObject(REDIS_STRING
,val
); 
2603 static robj 
*rdbLoadStringObject(FILE*fp
, int rdbver
) { 
2608     len 
= rdbLoadLen(fp
,rdbver
,&isencoded
); 
2611         case REDIS_RDB_ENC_INT8
: 
2612         case REDIS_RDB_ENC_INT16
: 
2613         case REDIS_RDB_ENC_INT32
: 
2614             return tryObjectSharing(rdbLoadIntegerObject(fp
,len
)); 
2615         case REDIS_RDB_ENC_LZF
: 
2616             return tryObjectSharing(rdbLoadLzfStringObject(fp
,rdbver
)); 
2622     if (len 
== REDIS_RDB_LENERR
) return NULL
; 
2623     val 
= sdsnewlen(NULL
,len
); 
2624     if (len 
&& fread(val
,len
,1,fp
) == 0) { 
2628     return tryObjectSharing(createObject(REDIS_STRING
,val
)); 
2631 /* For information about double serialization check rdbSaveDoubleValue() */ 
2632 static int rdbLoadDoubleValue(FILE *fp
, double *val
) { 
2636     if (fread(&len
,1,1,fp
) == 0) return -1; 
2638     case 255: *val 
= R_NegInf
; return 0; 
2639     case 254: *val 
= R_PosInf
; return 0; 
2640     case 253: *val 
= R_Nan
; return 0; 
2642         if (fread(buf
,len
,1,fp
) == 0) return -1; 
2643         sscanf(buf
, "%lg", val
); 
2648 static int rdbLoad(char *filename
) { 
2650     robj 
*keyobj 
= NULL
; 
2652     int type
, retval
, rdbver
; 
2653     dict 
*d 
= server
.db
[0].dict
; 
2654     redisDb 
*db 
= server
.db
+0; 
2656     time_t expiretime 
= -1, now 
= time(NULL
); 
2658     fp 
= fopen(filename
,"r"); 
2659     if (!fp
) return REDIS_ERR
; 
2660     if (fread(buf
,9,1,fp
) == 0) goto eoferr
; 
2662     if (memcmp(buf
,"REDIS",5) != 0) { 
2664         redisLog(REDIS_WARNING
,"Wrong signature trying to load DB from file"); 
2667     rdbver 
= atoi(buf
+5); 
2670         redisLog(REDIS_WARNING
,"Can't handle RDB format version %d",rdbver
); 
2677         if ((type 
= rdbLoadType(fp
)) == -1) goto eoferr
; 
2678         if (type 
== REDIS_EXPIRETIME
) { 
2679             if ((expiretime 
= rdbLoadTime(fp
)) == -1) goto eoferr
; 
2680             /* We read the time so we need to read the object type again */ 
2681             if ((type 
= rdbLoadType(fp
)) == -1) goto eoferr
; 
2683         if (type 
== REDIS_EOF
) break; 
2684         /* Handle SELECT DB opcode as a special case */ 
2685         if (type 
== REDIS_SELECTDB
) { 
2686             if ((dbid 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) 
2688             if (dbid 
>= (unsigned)server
.dbnum
) { 
2689                 redisLog(REDIS_WARNING
,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server
.dbnum
); 
2692             db 
= server
.db
+dbid
; 
2697         if ((keyobj 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2699         if (type 
== REDIS_STRING
) { 
2700             /* Read string value */ 
2701             if ((o 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2702             tryObjectEncoding(o
); 
2703         } else if (type 
== REDIS_LIST 
|| type 
== REDIS_SET
) { 
2704             /* Read list/set value */ 
2707             if ((listlen 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) 
2709             o 
= (type 
== REDIS_LIST
) ? createListObject() : createSetObject(); 
2710             /* Load every single element of the list/set */ 
2714                 if ((ele 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2715                 tryObjectEncoding(ele
); 
2716                 if (type 
== REDIS_LIST
) { 
2717                     listAddNodeTail((list
*)o
->ptr
,ele
); 
2719                     dictAdd((dict
*)o
->ptr
,ele
,NULL
); 
2722         } else if (type 
== REDIS_ZSET
) { 
2723             /* Read list/set value */ 
2727             if ((zsetlen 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) 
2729             o 
= createZsetObject(); 
2731             /* Load every single element of the list/set */ 
2734                 double *score 
= zmalloc(sizeof(double)); 
2736                 if ((ele 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2737                 tryObjectEncoding(ele
); 
2738                 if (rdbLoadDoubleValue(fp
,score
) == -1) goto eoferr
; 
2739                 dictAdd(zs
->dict
,ele
,score
); 
2740                 zslInsert(zs
->zsl
,*score
,ele
); 
2741                 incrRefCount(ele
); /* added to skiplist */ 
2746         /* Add the new object in the hash table */ 
2747         retval 
= dictAdd(d
,keyobj
,o
); 
2748         if (retval 
== DICT_ERR
) { 
2749             redisLog(REDIS_WARNING
,"Loading DB, duplicated key (%s) found! Unrecoverable error, exiting now.", keyobj
->ptr
); 
2752         /* Set the expire time if needed */ 
2753         if (expiretime 
!= -1) { 
2754             setExpire(db
,keyobj
,expiretime
); 
2755             /* Delete this key if already expired */ 
2756             if (expiretime 
< now
) deleteKey(db
,keyobj
); 
2764 eoferr
: /* unexpected end of file is handled here with a fatal exit */ 
2765     if (keyobj
) decrRefCount(keyobj
); 
2766     redisLog(REDIS_WARNING
,"Short read or OOM loading DB. Unrecoverable error, aborting now."); 
2768     return REDIS_ERR
; /* Just to avoid warning */ 
2771 /*================================== Commands =============================== */ 
2773 static void authCommand(redisClient 
*c
) { 
2774     if (!server
.requirepass 
|| !strcmp(c
->argv
[1]->ptr
, server
.requirepass
)) { 
2775       c
->authenticated 
= 1; 
2776       addReply(c
,shared
.ok
); 
2778       c
->authenticated 
= 0; 
2779       addReplySds(c
,sdscatprintf(sdsempty(),"-ERR invalid password\r\n")); 
2783 static void pingCommand(redisClient 
*c
) { 
2784     addReply(c
,shared
.pong
); 
2787 static void echoCommand(redisClient 
*c
) { 
2788     addReplyBulkLen(c
,c
->argv
[1]); 
2789     addReply(c
,c
->argv
[1]); 
2790     addReply(c
,shared
.crlf
); 
2793 /*=================================== Strings =============================== */ 
2795 static void setGenericCommand(redisClient 
*c
, int nx
) { 
2798     retval 
= dictAdd(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2799     if (retval 
== DICT_ERR
) { 
2801             dictReplace(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2802             incrRefCount(c
->argv
[2]); 
2804             addReply(c
,shared
.czero
); 
2808         incrRefCount(c
->argv
[1]); 
2809         incrRefCount(c
->argv
[2]); 
2812     removeExpire(c
->db
,c
->argv
[1]); 
2813     addReply(c
, nx 
? shared
.cone 
: shared
.ok
); 
2816 static void setCommand(redisClient 
*c
) { 
2817     setGenericCommand(c
,0); 
2820 static void setnxCommand(redisClient 
*c
) { 
2821     setGenericCommand(c
,1); 
2824 static void getCommand(redisClient 
*c
) { 
2825     robj 
*o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
2828         addReply(c
,shared
.nullbulk
); 
2830         if (o
->type 
!= REDIS_STRING
) { 
2831             addReply(c
,shared
.wrongtypeerr
); 
2833             addReplyBulkLen(c
,o
); 
2835             addReply(c
,shared
.crlf
); 
2840 static void getsetCommand(redisClient 
*c
) { 
2842     if (dictAdd(c
->db
->dict
,c
->argv
[1],c
->argv
[2]) == DICT_ERR
) { 
2843         dictReplace(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2845         incrRefCount(c
->argv
[1]); 
2847     incrRefCount(c
->argv
[2]); 
2849     removeExpire(c
->db
,c
->argv
[1]); 
2852 static void mgetCommand(redisClient 
*c
) { 
2855     addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",c
->argc
-1)); 
2856     for (j 
= 1; j 
< c
->argc
; j
++) { 
2857         robj 
*o 
= lookupKeyRead(c
->db
,c
->argv
[j
]); 
2859             addReply(c
,shared
.nullbulk
); 
2861             if (o
->type 
!= REDIS_STRING
) { 
2862                 addReply(c
,shared
.nullbulk
); 
2864                 addReplyBulkLen(c
,o
); 
2866                 addReply(c
,shared
.crlf
); 
2872 static void incrDecrCommand(redisClient 
*c
, long long incr
) { 
2877     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2881         if (o
->type 
!= REDIS_STRING
) { 
2886             if (o
->encoding 
== REDIS_ENCODING_RAW
) 
2887                 value 
= strtoll(o
->ptr
, &eptr
, 10); 
2888             else if (o
->encoding 
== REDIS_ENCODING_INT
) 
2889                 value 
= (long)o
->ptr
; 
2896     o 
= createObject(REDIS_STRING
,sdscatprintf(sdsempty(),"%lld",value
)); 
2897     tryObjectEncoding(o
); 
2898     retval 
= dictAdd(c
->db
->dict
,c
->argv
[1],o
); 
2899     if (retval 
== DICT_ERR
) { 
2900         dictReplace(c
->db
->dict
,c
->argv
[1],o
); 
2901         removeExpire(c
->db
,c
->argv
[1]); 
2903         incrRefCount(c
->argv
[1]); 
2906     addReply(c
,shared
.colon
); 
2908     addReply(c
,shared
.crlf
); 
2911 static void incrCommand(redisClient 
*c
) { 
2912     incrDecrCommand(c
,1); 
2915 static void decrCommand(redisClient 
*c
) { 
2916     incrDecrCommand(c
,-1); 
2919 static void incrbyCommand(redisClient 
*c
) { 
2920     long long incr 
= strtoll(c
->argv
[2]->ptr
, NULL
, 10); 
2921     incrDecrCommand(c
,incr
); 
2924 static void decrbyCommand(redisClient 
*c
) { 
2925     long long incr 
= strtoll(c
->argv
[2]->ptr
, NULL
, 10); 
2926     incrDecrCommand(c
,-incr
); 
2929 /* ========================= Type agnostic commands ========================= */ 
2931 static void delCommand(redisClient 
*c
) { 
2934     for (j 
= 1; j 
< c
->argc
; j
++) { 
2935         if (deleteKey(c
->db
,c
->argv
[j
])) { 
2942         addReply(c
,shared
.czero
); 
2945         addReply(c
,shared
.cone
); 
2948         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",deleted
)); 
2953 static void existsCommand(redisClient 
*c
) { 
2954     addReply(c
,lookupKeyRead(c
->db
,c
->argv
[1]) ? shared
.cone 
: shared
.czero
); 
2957 static void selectCommand(redisClient 
*c
) { 
2958     int id 
= atoi(c
->argv
[1]->ptr
); 
2960     if (selectDb(c
,id
) == REDIS_ERR
) { 
2961         addReplySds(c
,sdsnew("-ERR invalid DB index\r\n")); 
2963         addReply(c
,shared
.ok
); 
2967 static void randomkeyCommand(redisClient 
*c
) { 
2971         de 
= dictGetRandomKey(c
->db
->dict
); 
2972         if (!de 
|| expireIfNeeded(c
->db
,dictGetEntryKey(de
)) == 0) break; 
2975         addReply(c
,shared
.plus
); 
2976         addReply(c
,shared
.crlf
); 
2978         addReply(c
,shared
.plus
); 
2979         addReply(c
,dictGetEntryKey(de
)); 
2980         addReply(c
,shared
.crlf
); 
2984 static void keysCommand(redisClient 
*c
) { 
2987     sds pattern 
= c
->argv
[1]->ptr
; 
2988     int plen 
= sdslen(pattern
); 
2989     int numkeys 
= 0, keyslen 
= 0; 
2990     robj 
*lenobj 
= createObject(REDIS_STRING
,NULL
); 
2992     di 
= dictGetIterator(c
->db
->dict
); 
2994     decrRefCount(lenobj
); 
2995     while((de 
= dictNext(di
)) != NULL
) { 
2996         robj 
*keyobj 
= dictGetEntryKey(de
); 
2998         sds key 
= keyobj
->ptr
; 
2999         if ((pattern
[0] == '*' && pattern
[1] == '\0') || 
3000             stringmatchlen(pattern
,plen
,key
,sdslen(key
),0)) { 
3001             if (expireIfNeeded(c
->db
,keyobj
) == 0) { 
3003                     addReply(c
,shared
.space
); 
3006                 keyslen 
+= sdslen(key
); 
3010     dictReleaseIterator(di
); 
3011     lenobj
->ptr 
= sdscatprintf(sdsempty(),"$%lu\r\n",keyslen
+(numkeys 
? (numkeys
-1) : 0)); 
3012     addReply(c
,shared
.crlf
); 
3015 static void dbsizeCommand(redisClient 
*c
) { 
3017         sdscatprintf(sdsempty(),":%lu\r\n",dictSize(c
->db
->dict
))); 
3020 static void lastsaveCommand(redisClient 
*c
) { 
3022         sdscatprintf(sdsempty(),":%lu\r\n",server
.lastsave
)); 
3025 static void typeCommand(redisClient 
*c
) { 
3029     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3034         case REDIS_STRING
: type 
= "+string"; break; 
3035         case REDIS_LIST
: type 
= "+list"; break; 
3036         case REDIS_SET
: type 
= "+set"; break; 
3037         case REDIS_ZSET
: type 
= "+zset"; break; 
3038         default: type 
= "unknown"; break; 
3041     addReplySds(c
,sdsnew(type
)); 
3042     addReply(c
,shared
.crlf
); 
3045 static void saveCommand(redisClient 
*c
) { 
3046     if (server
.bgsaveinprogress
) { 
3047         addReplySds(c
,sdsnew("-ERR background save in progress\r\n")); 
3050     if (rdbSave(server
.dbfilename
) == REDIS_OK
) { 
3051         addReply(c
,shared
.ok
); 
3053         addReply(c
,shared
.err
); 
3057 static void bgsaveCommand(redisClient 
*c
) { 
3058     if (server
.bgsaveinprogress
) { 
3059         addReplySds(c
,sdsnew("-ERR background save already in progress\r\n")); 
3062     if (rdbSaveBackground(server
.dbfilename
) == REDIS_OK
) { 
3063         addReply(c
,shared
.ok
); 
3065         addReply(c
,shared
.err
); 
3069 static void shutdownCommand(redisClient 
*c
) { 
3070     redisLog(REDIS_WARNING
,"User requested shutdown, saving DB..."); 
3071     /* Kill the saving child if there is a background saving in progress. 
3072        We want to avoid race conditions, for instance our saving child may 
3073        overwrite the synchronous saving did by SHUTDOWN. */ 
3074     if (server
.bgsaveinprogress
) { 
3075         redisLog(REDIS_WARNING
,"There is a live saving child. Killing it!"); 
3076         kill(server
.bgsavechildpid
,SIGKILL
); 
3077         rdbRemoveTempFile(server
.bgsavechildpid
); 
3080     if (rdbSave(server
.dbfilename
) == REDIS_OK
) { 
3081         if (server
.daemonize
) 
3082             unlink(server
.pidfile
); 
3083         redisLog(REDIS_WARNING
,"%zu bytes used at exit",zmalloc_used_memory()); 
3084         redisLog(REDIS_WARNING
,"Server exit now, bye bye..."); 
3087         /* Ooops.. error saving! The best we can do is to continue operating. 
3088          * Note that if there was a background saving process, in the next 
3089          * cron() Redis will be notified that the background saving aborted, 
3090          * handling special stuff like slaves pending for synchronization... */ 
3091         redisLog(REDIS_WARNING
,"Error trying to save the DB, can't exit");  
3092         addReplySds(c
,sdsnew("-ERR can't quit, problems saving the DB\r\n")); 
3096 static void renameGenericCommand(redisClient 
*c
, int nx
) { 
3099     /* To use the same key as src and dst is probably an error */ 
3100     if (sdscmp(c
->argv
[1]->ptr
,c
->argv
[2]->ptr
) == 0) { 
3101         addReply(c
,shared
.sameobjecterr
); 
3105     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3107         addReply(c
,shared
.nokeyerr
); 
3111     deleteIfVolatile(c
->db
,c
->argv
[2]); 
3112     if (dictAdd(c
->db
->dict
,c
->argv
[2],o
) == DICT_ERR
) { 
3115             addReply(c
,shared
.czero
); 
3118         dictReplace(c
->db
->dict
,c
->argv
[2],o
); 
3120         incrRefCount(c
->argv
[2]); 
3122     deleteKey(c
->db
,c
->argv
[1]); 
3124     addReply(c
,nx 
? shared
.cone 
: shared
.ok
); 
3127 static void renameCommand(redisClient 
*c
) { 
3128     renameGenericCommand(c
,0); 
3131 static void renamenxCommand(redisClient 
*c
) { 
3132     renameGenericCommand(c
,1); 
3135 static void moveCommand(redisClient 
*c
) { 
3140     /* Obtain source and target DB pointers */ 
3143     if (selectDb(c
,atoi(c
->argv
[2]->ptr
)) == REDIS_ERR
) { 
3144         addReply(c
,shared
.outofrangeerr
); 
3148     selectDb(c
,srcid
); /* Back to the source DB */ 
3150     /* If the user is moving using as target the same 
3151      * DB as the source DB it is probably an error. */ 
3153         addReply(c
,shared
.sameobjecterr
); 
3157     /* Check if the element exists and get a reference */ 
3158     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3160         addReply(c
,shared
.czero
); 
3164     /* Try to add the element to the target DB */ 
3165     deleteIfVolatile(dst
,c
->argv
[1]); 
3166     if (dictAdd(dst
->dict
,c
->argv
[1],o
) == DICT_ERR
) { 
3167         addReply(c
,shared
.czero
); 
3170     incrRefCount(c
->argv
[1]); 
3173     /* OK! key moved, free the entry in the source DB */ 
3174     deleteKey(src
,c
->argv
[1]); 
3176     addReply(c
,shared
.cone
); 
3179 /* =================================== Lists ================================ */ 
3180 static void pushGenericCommand(redisClient 
*c
, int where
) { 
3184     lobj 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3186         lobj 
= createListObject(); 
3188         if (where 
== REDIS_HEAD
) { 
3189             listAddNodeHead(list
,c
->argv
[2]); 
3191             listAddNodeTail(list
,c
->argv
[2]); 
3193         dictAdd(c
->db
->dict
,c
->argv
[1],lobj
); 
3194         incrRefCount(c
->argv
[1]); 
3195         incrRefCount(c
->argv
[2]); 
3197         if (lobj
->type 
!= REDIS_LIST
) { 
3198             addReply(c
,shared
.wrongtypeerr
); 
3202         if (where 
== REDIS_HEAD
) { 
3203             listAddNodeHead(list
,c
->argv
[2]); 
3205             listAddNodeTail(list
,c
->argv
[2]); 
3207         incrRefCount(c
->argv
[2]); 
3210     addReply(c
,shared
.ok
); 
3213 static void lpushCommand(redisClient 
*c
) { 
3214     pushGenericCommand(c
,REDIS_HEAD
); 
3217 static void rpushCommand(redisClient 
*c
) { 
3218     pushGenericCommand(c
,REDIS_TAIL
); 
3221 static void llenCommand(redisClient 
*c
) { 
3225     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3227         addReply(c
,shared
.czero
); 
3230         if (o
->type 
!= REDIS_LIST
) { 
3231             addReply(c
,shared
.wrongtypeerr
); 
3234             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",listLength(l
))); 
3239 static void lindexCommand(redisClient 
*c
) { 
3241     int index 
= atoi(c
->argv
[2]->ptr
); 
3243     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3245         addReply(c
,shared
.nullbulk
); 
3247         if (o
->type 
!= REDIS_LIST
) { 
3248             addReply(c
,shared
.wrongtypeerr
); 
3250             list 
*list 
= o
->ptr
; 
3253             ln 
= listIndex(list
, index
); 
3255                 addReply(c
,shared
.nullbulk
); 
3257                 robj 
*ele 
= listNodeValue(ln
); 
3258                 addReplyBulkLen(c
,ele
); 
3260                 addReply(c
,shared
.crlf
); 
3266 static void lsetCommand(redisClient 
*c
) { 
3268     int index 
= atoi(c
->argv
[2]->ptr
); 
3270     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3272         addReply(c
,shared
.nokeyerr
); 
3274         if (o
->type 
!= REDIS_LIST
) { 
3275             addReply(c
,shared
.wrongtypeerr
); 
3277             list 
*list 
= o
->ptr
; 
3280             ln 
= listIndex(list
, index
); 
3282                 addReply(c
,shared
.outofrangeerr
); 
3284                 robj 
*ele 
= listNodeValue(ln
); 
3287                 listNodeValue(ln
) = c
->argv
[3]; 
3288                 incrRefCount(c
->argv
[3]); 
3289                 addReply(c
,shared
.ok
); 
3296 static void popGenericCommand(redisClient 
*c
, int where
) { 
3299     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3301         addReply(c
,shared
.nullbulk
); 
3303         if (o
->type 
!= REDIS_LIST
) { 
3304             addReply(c
,shared
.wrongtypeerr
); 
3306             list 
*list 
= o
->ptr
; 
3309             if (where 
== REDIS_HEAD
) 
3310                 ln 
= listFirst(list
); 
3312                 ln 
= listLast(list
); 
3315                 addReply(c
,shared
.nullbulk
); 
3317                 robj 
*ele 
= listNodeValue(ln
); 
3318                 addReplyBulkLen(c
,ele
); 
3320                 addReply(c
,shared
.crlf
); 
3321                 listDelNode(list
,ln
); 
3328 static void lpopCommand(redisClient 
*c
) { 
3329     popGenericCommand(c
,REDIS_HEAD
); 
3332 static void rpopCommand(redisClient 
*c
) { 
3333     popGenericCommand(c
,REDIS_TAIL
); 
3336 static void lrangeCommand(redisClient 
*c
) { 
3338     int start 
= atoi(c
->argv
[2]->ptr
); 
3339     int end 
= atoi(c
->argv
[3]->ptr
); 
3341     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3343         addReply(c
,shared
.nullmultibulk
); 
3345         if (o
->type 
!= REDIS_LIST
) { 
3346             addReply(c
,shared
.wrongtypeerr
); 
3348             list 
*list 
= o
->ptr
; 
3350             int llen 
= listLength(list
); 
3354             /* convert negative indexes */ 
3355             if (start 
< 0) start 
= llen
+start
; 
3356             if (end 
< 0) end 
= llen
+end
; 
3357             if (start 
< 0) start 
= 0; 
3358             if (end 
< 0) end 
= 0; 
3360             /* indexes sanity checks */ 
3361             if (start 
> end 
|| start 
>= llen
) { 
3362                 /* Out of range start or start > end result in empty list */ 
3363                 addReply(c
,shared
.emptymultibulk
); 
3366             if (end 
>= llen
) end 
= llen
-1; 
3367             rangelen 
= (end
-start
)+1; 
3369             /* Return the result in form of a multi-bulk reply */ 
3370             ln 
= listIndex(list
, start
); 
3371             addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",rangelen
)); 
3372             for (j 
= 0; j 
< rangelen
; j
++) { 
3373                 ele 
= listNodeValue(ln
); 
3374                 addReplyBulkLen(c
,ele
); 
3376                 addReply(c
,shared
.crlf
); 
3383 static void ltrimCommand(redisClient 
*c
) { 
3385     int start 
= atoi(c
->argv
[2]->ptr
); 
3386     int end 
= atoi(c
->argv
[3]->ptr
); 
3388     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3390         addReply(c
,shared
.nokeyerr
); 
3392         if (o
->type 
!= REDIS_LIST
) { 
3393             addReply(c
,shared
.wrongtypeerr
); 
3395             list 
*list 
= o
->ptr
; 
3397             int llen 
= listLength(list
); 
3398             int j
, ltrim
, rtrim
; 
3400             /* convert negative indexes */ 
3401             if (start 
< 0) start 
= llen
+start
; 
3402             if (end 
< 0) end 
= llen
+end
; 
3403             if (start 
< 0) start 
= 0; 
3404             if (end 
< 0) end 
= 0; 
3406             /* indexes sanity checks */ 
3407             if (start 
> end 
|| start 
>= llen
) { 
3408                 /* Out of range start or start > end result in empty list */ 
3412                 if (end 
>= llen
) end 
= llen
-1; 
3417             /* Remove list elements to perform the trim */ 
3418             for (j 
= 0; j 
< ltrim
; j
++) { 
3419                 ln 
= listFirst(list
); 
3420                 listDelNode(list
,ln
); 
3422             for (j 
= 0; j 
< rtrim
; j
++) { 
3423                 ln 
= listLast(list
); 
3424                 listDelNode(list
,ln
); 
3427             addReply(c
,shared
.ok
); 
3432 static void lremCommand(redisClient 
*c
) { 
3435     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3437         addReply(c
,shared
.czero
); 
3439         if (o
->type 
!= REDIS_LIST
) { 
3440             addReply(c
,shared
.wrongtypeerr
); 
3442             list 
*list 
= o
->ptr
; 
3443             listNode 
*ln
, *next
; 
3444             int toremove 
= atoi(c
->argv
[2]->ptr
); 
3449                 toremove 
= -toremove
; 
3452             ln 
= fromtail 
? list
->tail 
: list
->head
; 
3454                 robj 
*ele 
= listNodeValue(ln
); 
3456                 next 
= fromtail 
? ln
->prev 
: ln
->next
; 
3457                 if (compareStringObjects(ele
,c
->argv
[3]) == 0) { 
3458                     listDelNode(list
,ln
); 
3461                     if (toremove 
&& removed 
== toremove
) break; 
3465             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",removed
)); 
3470 /* ==================================== Sets ================================ */ 
3472 static void saddCommand(redisClient 
*c
) { 
3475     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3477         set 
= createSetObject(); 
3478         dictAdd(c
->db
->dict
,c
->argv
[1],set
); 
3479         incrRefCount(c
->argv
[1]); 
3481         if (set
->type 
!= REDIS_SET
) { 
3482             addReply(c
,shared
.wrongtypeerr
); 
3486     if (dictAdd(set
->ptr
,c
->argv
[2],NULL
) == DICT_OK
) { 
3487         incrRefCount(c
->argv
[2]); 
3489         addReply(c
,shared
.cone
); 
3491         addReply(c
,shared
.czero
); 
3495 static void sremCommand(redisClient 
*c
) { 
3498     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3500         addReply(c
,shared
.czero
); 
3502         if (set
->type 
!= REDIS_SET
) { 
3503             addReply(c
,shared
.wrongtypeerr
); 
3506         if (dictDelete(set
->ptr
,c
->argv
[2]) == DICT_OK
) { 
3508             if (htNeedsResize(set
->ptr
)) dictResize(set
->ptr
); 
3509             addReply(c
,shared
.cone
); 
3511             addReply(c
,shared
.czero
); 
3516 static void smoveCommand(redisClient 
*c
) { 
3517     robj 
*srcset
, *dstset
; 
3519     srcset 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3520     dstset 
= lookupKeyWrite(c
->db
,c
->argv
[2]); 
3522     /* If the source key does not exist return 0, if it's of the wrong type 
3524     if (srcset 
== NULL 
|| srcset
->type 
!= REDIS_SET
) { 
3525         addReply(c
, srcset 
? shared
.wrongtypeerr 
: shared
.czero
); 
3528     /* Error if the destination key is not a set as well */ 
3529     if (dstset 
&& dstset
->type 
!= REDIS_SET
) { 
3530         addReply(c
,shared
.wrongtypeerr
); 
3533     /* Remove the element from the source set */ 
3534     if (dictDelete(srcset
->ptr
,c
->argv
[3]) == DICT_ERR
) { 
3535         /* Key not found in the src set! return zero */ 
3536         addReply(c
,shared
.czero
); 
3540     /* Add the element to the destination set */ 
3542         dstset 
= createSetObject(); 
3543         dictAdd(c
->db
->dict
,c
->argv
[2],dstset
); 
3544         incrRefCount(c
->argv
[2]); 
3546     if (dictAdd(dstset
->ptr
,c
->argv
[3],NULL
) == DICT_OK
) 
3547         incrRefCount(c
->argv
[3]); 
3548     addReply(c
,shared
.cone
); 
3551 static void sismemberCommand(redisClient 
*c
) { 
3554     set 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3556         addReply(c
,shared
.czero
); 
3558         if (set
->type 
!= REDIS_SET
) { 
3559             addReply(c
,shared
.wrongtypeerr
); 
3562         if (dictFind(set
->ptr
,c
->argv
[2])) 
3563             addReply(c
,shared
.cone
); 
3565             addReply(c
,shared
.czero
); 
3569 static void scardCommand(redisClient 
*c
) { 
3573     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3575         addReply(c
,shared
.czero
); 
3578         if (o
->type 
!= REDIS_SET
) { 
3579             addReply(c
,shared
.wrongtypeerr
); 
3582             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3588 static void spopCommand(redisClient 
*c
) { 
3592     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3594         addReply(c
,shared
.nullbulk
); 
3596         if (set
->type 
!= REDIS_SET
) { 
3597             addReply(c
,shared
.wrongtypeerr
); 
3600         de 
= dictGetRandomKey(set
->ptr
); 
3602             addReply(c
,shared
.nullbulk
); 
3604             robj 
*ele 
= dictGetEntryKey(de
); 
3606             addReplyBulkLen(c
,ele
); 
3608             addReply(c
,shared
.crlf
); 
3609             dictDelete(set
->ptr
,ele
); 
3610             if (htNeedsResize(set
->ptr
)) dictResize(set
->ptr
); 
3616 static void srandmemberCommand(redisClient 
*c
) { 
3620     set 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3622         addReply(c
,shared
.nullbulk
); 
3624         if (set
->type 
!= REDIS_SET
) { 
3625             addReply(c
,shared
.wrongtypeerr
); 
3628         de 
= dictGetRandomKey(set
->ptr
); 
3630             addReply(c
,shared
.nullbulk
); 
3632             robj 
*ele 
= dictGetEntryKey(de
); 
3634             addReplyBulkLen(c
,ele
); 
3636             addReply(c
,shared
.crlf
); 
3641 static int qsortCompareSetsByCardinality(const void *s1
, const void *s2
) { 
3642     dict 
**d1 
= (void*) s1
, **d2 
= (void*) s2
; 
3644     return dictSize(*d1
)-dictSize(*d2
); 
3647 static void sinterGenericCommand(redisClient 
*c
, robj 
**setskeys
, int setsnum
, robj 
*dstkey
) { 
3648     dict 
**dv 
= zmalloc(sizeof(dict
*)*setsnum
); 
3651     robj 
*lenobj 
= NULL
, *dstset 
= NULL
; 
3652     int j
, cardinality 
= 0; 
3654     for (j 
= 0; j 
< setsnum
; j
++) { 
3658                     lookupKeyWrite(c
->db
,setskeys
[j
]) : 
3659                     lookupKeyRead(c
->db
,setskeys
[j
]); 
3663                 deleteKey(c
->db
,dstkey
); 
3664                 addReply(c
,shared
.ok
); 
3666                 addReply(c
,shared
.nullmultibulk
); 
3670         if (setobj
->type 
!= REDIS_SET
) { 
3672             addReply(c
,shared
.wrongtypeerr
); 
3675         dv
[j
] = setobj
->ptr
; 
3677     /* Sort sets from the smallest to largest, this will improve our 
3678      * algorithm's performace */ 
3679     qsort(dv
,setsnum
,sizeof(dict
*),qsortCompareSetsByCardinality
); 
3681     /* The first thing we should output is the total number of elements... 
3682      * since this is a multi-bulk write, but at this stage we don't know 
3683      * the intersection set size, so we use a trick, append an empty object 
3684      * to the output list and save the pointer to later modify it with the 
3687         lenobj 
= createObject(REDIS_STRING
,NULL
); 
3689         decrRefCount(lenobj
); 
3691         /* If we have a target key where to store the resulting set 
3692          * create this key with an empty set inside */ 
3693         dstset 
= createSetObject(); 
3696     /* Iterate all the elements of the first (smallest) set, and test 
3697      * the element against all the other sets, if at least one set does 
3698      * not include the element it is discarded */ 
3699     di 
= dictGetIterator(dv
[0]); 
3701     while((de 
= dictNext(di
)) != NULL
) { 
3704         for (j 
= 1; j 
< setsnum
; j
++) 
3705             if (dictFind(dv
[j
],dictGetEntryKey(de
)) == NULL
) break; 
3707             continue; /* at least one set does not contain the member */ 
3708         ele 
= dictGetEntryKey(de
); 
3710             addReplyBulkLen(c
,ele
); 
3712             addReply(c
,shared
.crlf
); 
3715             dictAdd(dstset
->ptr
,ele
,NULL
); 
3719     dictReleaseIterator(di
); 
3722         /* Store the resulting set into the target */ 
3723         deleteKey(c
->db
,dstkey
); 
3724         dictAdd(c
->db
->dict
,dstkey
,dstset
); 
3725         incrRefCount(dstkey
); 
3729         lenobj
->ptr 
= sdscatprintf(sdsempty(),"*%d\r\n",cardinality
); 
3731         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3732             dictSize((dict
*)dstset
->ptr
))); 
3738 static void sinterCommand(redisClient 
*c
) { 
3739     sinterGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
); 
3742 static void sinterstoreCommand(redisClient 
*c
) { 
3743     sinterGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1]); 
3746 #define REDIS_OP_UNION 0 
3747 #define REDIS_OP_DIFF 1 
3749 static void sunionDiffGenericCommand(redisClient 
*c
, robj 
**setskeys
, int setsnum
, robj 
*dstkey
, int op
) { 
3750     dict 
**dv 
= zmalloc(sizeof(dict
*)*setsnum
); 
3753     robj 
*dstset 
= NULL
; 
3754     int j
, cardinality 
= 0; 
3756     for (j 
= 0; j 
< setsnum
; j
++) { 
3760                     lookupKeyWrite(c
->db
,setskeys
[j
]) : 
3761                     lookupKeyRead(c
->db
,setskeys
[j
]); 
3766         if (setobj
->type 
!= REDIS_SET
) { 
3768             addReply(c
,shared
.wrongtypeerr
); 
3771         dv
[j
] = setobj
->ptr
; 
3774     /* We need a temp set object to store our union. If the dstkey 
3775      * is not NULL (that is, we are inside an SUNIONSTORE operation) then 
3776      * this set object will be the resulting object to set into the target key*/ 
3777     dstset 
= createSetObject(); 
3779     /* Iterate all the elements of all the sets, add every element a single 
3780      * time to the result set */ 
3781     for (j 
= 0; j 
< setsnum
; j
++) { 
3782         if (op 
== REDIS_OP_DIFF 
&& j 
== 0 && !dv
[j
]) break; /* result set is empty */ 
3783         if (!dv
[j
]) continue; /* non existing keys are like empty sets */ 
3785         di 
= dictGetIterator(dv
[j
]); 
3787         while((de 
= dictNext(di
)) != NULL
) { 
3790             /* dictAdd will not add the same element multiple times */ 
3791             ele 
= dictGetEntryKey(de
); 
3792             if (op 
== REDIS_OP_UNION 
|| j 
== 0) { 
3793                 if (dictAdd(dstset
->ptr
,ele
,NULL
) == DICT_OK
) { 
3797             } else if (op 
== REDIS_OP_DIFF
) { 
3798                 if (dictDelete(dstset
->ptr
,ele
) == DICT_OK
) { 
3803         dictReleaseIterator(di
); 
3805         if (op 
== REDIS_OP_DIFF 
&& cardinality 
== 0) break; /* result set is empty */ 
3808     /* Output the content of the resulting set, if not in STORE mode */ 
3810         addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",cardinality
)); 
3811         di 
= dictGetIterator(dstset
->ptr
); 
3812         while((de 
= dictNext(di
)) != NULL
) { 
3815             ele 
= dictGetEntryKey(de
); 
3816             addReplyBulkLen(c
,ele
); 
3818             addReply(c
,shared
.crlf
); 
3820         dictReleaseIterator(di
); 
3822         /* If we have a target key where to store the resulting set 
3823          * create this key with the result set inside */ 
3824         deleteKey(c
->db
,dstkey
); 
3825         dictAdd(c
->db
->dict
,dstkey
,dstset
); 
3826         incrRefCount(dstkey
); 
3831         decrRefCount(dstset
); 
3833         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3834             dictSize((dict
*)dstset
->ptr
))); 
3840 static void sunionCommand(redisClient 
*c
) { 
3841     sunionDiffGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
,REDIS_OP_UNION
); 
3844 static void sunionstoreCommand(redisClient 
*c
) { 
3845     sunionDiffGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1],REDIS_OP_UNION
); 
3848 static void sdiffCommand(redisClient 
*c
) { 
3849     sunionDiffGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
,REDIS_OP_DIFF
); 
3852 static void sdiffstoreCommand(redisClient 
*c
) { 
3853     sunionDiffGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1],REDIS_OP_DIFF
); 
3856 /* ==================================== ZSets =============================== */ 
3858 /* ZSETs are ordered sets using two data structures to hold the same elements 
3859  * in order to get O(log(N)) INSERT and REMOVE operations into a sorted 
3862  * The elements are added to an hash table mapping Redis objects to scores. 
3863  * At the same time the elements are added to a skip list mapping scores 
3864  * to Redis objects (so objects are sorted by scores in this "view"). */ 
3866 /* This skiplist implementation is almost a C translation of the original 
3867  * algorithm described by William Pugh in "Skip Lists: A Probabilistic 
3868  * Alternative to Balanced Trees", modified in three ways: 
3869  * a) this implementation allows for repeated values. 
3870  * b) the comparison is not just by key (our 'score') but by satellite data. 
3871  * c) there is a back pointer, so it's a doubly linked list with the back 
3872  * pointers being only at "level 1". This allows to traverse the list 
3873  * from tail to head, useful for ZREVRANGE. */ 
3875 static zskiplistNode 
*zslCreateNode(int level
, double score
, robj 
*obj
) { 
3876     zskiplistNode 
*zn 
= zmalloc(sizeof(*zn
)); 
3878     zn
->forward 
= zmalloc(sizeof(zskiplistNode
*) * level
); 
3884 static zskiplist 
*zslCreate(void) { 
3888     zsl 
= zmalloc(sizeof(*zsl
)); 
3891     zsl
->header 
= zslCreateNode(ZSKIPLIST_MAXLEVEL
,0,NULL
); 
3892     for (j 
= 0; j 
< ZSKIPLIST_MAXLEVEL
; j
++) 
3893         zsl
->header
->forward
[j
] = NULL
; 
3894     zsl
->header
->backward 
= NULL
; 
3899 static void zslFreeNode(zskiplistNode 
*node
) { 
3900     decrRefCount(node
->obj
); 
3901     zfree(node
->forward
); 
3905 static void zslFree(zskiplist 
*zsl
) { 
3906     zskiplistNode 
*node 
= zsl
->header
->forward
[0], *next
; 
3908     zfree(zsl
->header
->forward
); 
3911         next 
= node
->forward
[0]; 
3918 static int zslRandomLevel(void) { 
3920     while ((random()&0xFFFF) < (ZSKIPLIST_P 
* 0xFFFF)) 
3925 static void zslInsert(zskiplist 
*zsl
, double score
, robj 
*obj
) { 
3926     zskiplistNode 
*update
[ZSKIPLIST_MAXLEVEL
], *x
; 
3930     for (i 
= zsl
->level
-1; i 
>= 0; i
--) { 
3931         while (x
->forward
[i
] && 
3932             (x
->forward
[i
]->score 
< score 
|| 
3933                 (x
->forward
[i
]->score 
== score 
&& 
3934                 compareStringObjects(x
->forward
[i
]->obj
,obj
) < 0))) 
3938     /* we assume the key is not already inside, since we allow duplicated 
3939      * scores, and the re-insertion of score and redis object should never 
3940      * happpen since the caller of zslInsert() should test in the hash table 
3941      * if the element is already inside or not. */ 
3942     level 
= zslRandomLevel(); 
3943     if (level 
> zsl
->level
) { 
3944         for (i 
= zsl
->level
; i 
< level
; i
++) 
3945             update
[i
] = zsl
->header
; 
3948     x 
= zslCreateNode(level
,score
,obj
); 
3949     for (i 
= 0; i 
< level
; i
++) { 
3950         x
->forward
[i
] = update
[i
]->forward
[i
]; 
3951         update
[i
]->forward
[i
] = x
; 
3953     x
->backward 
= (update
[0] == zsl
->header
) ? NULL 
: update
[0]; 
3955         x
->forward
[0]->backward 
= x
; 
3961 /* Delete an element with matching score/object from the skiplist. */ 
3962 static int zslDelete(zskiplist 
*zsl
, double score
, robj 
*obj
) { 
3963     zskiplistNode 
*update
[ZSKIPLIST_MAXLEVEL
], *x
; 
3967     for (i 
= zsl
->level
-1; i 
>= 0; i
--) { 
3968         while (x
->forward
[i
] && 
3969             (x
->forward
[i
]->score 
< score 
|| 
3970                 (x
->forward
[i
]->score 
== score 
&& 
3971                 compareStringObjects(x
->forward
[i
]->obj
,obj
) < 0))) 
3975     /* We may have multiple elements with the same score, what we need 
3976      * is to find the element with both the right score and object. */ 
3978     if (x 
&& score 
== x
->score 
&& compareStringObjects(x
->obj
,obj
) == 0) { 
3979         for (i 
= 0; i 
< zsl
->level
; i
++) { 
3980             if (update
[i
]->forward
[i
] != x
) break; 
3981             update
[i
]->forward
[i
] = x
->forward
[i
]; 
3983         if (x
->forward
[0]) { 
3984             x
->forward
[0]->backward 
= (x
->backward 
== zsl
->header
) ? 
3987             zsl
->tail 
= x
->backward
; 
3990         while(zsl
->level 
> 1 && zsl
->header
->forward
[zsl
->level
-1] == NULL
) 
3995         return 0; /* not found */ 
3997     return 0; /* not found */ 
4000 /* Delete all the elements with score between min and max from the skiplist. 
4001  * Min and mx are inclusive, so a score >= min || score <= max is deleted. 
4002  * Note that this function takes the reference to the hash table view of the 
4003  * sorted set, in order to remove the elements from the hash table too. */ 
4004 static unsigned long zslDeleteRange(zskiplist 
*zsl
, double min
, double max
, dict 
*dict
) { 
4005     zskiplistNode 
*update
[ZSKIPLIST_MAXLEVEL
], *x
; 
4006     unsigned long removed 
= 0; 
4010     for (i 
= zsl
->level
-1; i 
>= 0; i
--) { 
4011         while (x
->forward
[i
] && x
->forward
[i
]->score 
< min
) 
4015     /* We may have multiple elements with the same score, what we need 
4016      * is to find the element with both the right score and object. */ 
4018     while (x 
&& x
->score 
<= max
) { 
4019         zskiplistNode 
*next
; 
4021         for (i 
= 0; i 
< zsl
->level
; i
++) { 
4022             if (update
[i
]->forward
[i
] != x
) break; 
4023             update
[i
]->forward
[i
] = x
->forward
[i
]; 
4025         if (x
->forward
[0]) { 
4026             x
->forward
[0]->backward 
= (x
->backward 
== zsl
->header
) ? 
4029             zsl
->tail 
= x
->backward
; 
4031         next 
= x
->forward
[0]; 
4032         dictDelete(dict
,x
->obj
); 
4034         while(zsl
->level 
> 1 && zsl
->header
->forward
[zsl
->level
-1] == NULL
) 
4040     return removed
; /* not found */ 
4043 /* Find the first node having a score equal or greater than the specified one. 
4044  * Returns NULL if there is no match. */ 
4045 static zskiplistNode 
*zslFirstWithScore(zskiplist 
*zsl
, double score
) { 
4050     for (i 
= zsl
->level
-1; i 
>= 0; i
--) { 
4051         while (x
->forward
[i
] && x
->forward
[i
]->score 
< score
) 
4054     /* We may have multiple elements with the same score, what we need 
4055      * is to find the element with both the right score and object. */ 
4056     return x
->forward
[0]; 
4059 /* The actual Z-commands implementations */ 
4061 static void zaddCommand(redisClient 
*c
) { 
4066     zsetobj 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
4067     if (zsetobj 
== NULL
) { 
4068         zsetobj 
= createZsetObject(); 
4069         dictAdd(c
->db
->dict
,c
->argv
[1],zsetobj
); 
4070         incrRefCount(c
->argv
[1]); 
4072         if (zsetobj
->type 
!= REDIS_ZSET
) { 
4073             addReply(c
,shared
.wrongtypeerr
); 
4077     score 
= zmalloc(sizeof(double)); 
4078     *score 
= strtod(c
->argv
[2]->ptr
,NULL
); 
4080     if (dictAdd(zs
->dict
,c
->argv
[3],score
) == DICT_OK
) { 
4081         /* case 1: New element */ 
4082         incrRefCount(c
->argv
[3]); /* added to hash */ 
4083         zslInsert(zs
->zsl
,*score
,c
->argv
[3]); 
4084         incrRefCount(c
->argv
[3]); /* added to skiplist */ 
4086         addReply(c
,shared
.cone
); 
4091         /* case 2: Score update operation */ 
4092         de 
= dictFind(zs
->dict
,c
->argv
[3]); 
4094         oldscore 
= dictGetEntryVal(de
); 
4095         if (*score 
!= *oldscore
) { 
4098             deleted 
= zslDelete(zs
->zsl
,*oldscore
,c
->argv
[3]); 
4099             assert(deleted 
!= 0); 
4100             zslInsert(zs
->zsl
,*score
,c
->argv
[3]); 
4101             incrRefCount(c
->argv
[3]); 
4102             dictReplace(zs
->dict
,c
->argv
[3],score
); 
4107         addReply(c
,shared
.czero
); 
4111 static void zremCommand(redisClient 
*c
) { 
4115     zsetobj 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
4116     if (zsetobj 
== NULL
) { 
4117         addReply(c
,shared
.czero
); 
4123         if (zsetobj
->type 
!= REDIS_ZSET
) { 
4124             addReply(c
,shared
.wrongtypeerr
); 
4128         de 
= dictFind(zs
->dict
,c
->argv
[2]); 
4130             addReply(c
,shared
.czero
); 
4133         /* Delete from the skiplist */ 
4134         oldscore 
= dictGetEntryVal(de
); 
4135         deleted 
= zslDelete(zs
->zsl
,*oldscore
,c
->argv
[2]); 
4136         assert(deleted 
!= 0); 
4138         /* Delete from the hash table */ 
4139         dictDelete(zs
->dict
,c
->argv
[2]); 
4140         if (htNeedsResize(zs
->dict
)) dictResize(zs
->dict
); 
4142         addReply(c
,shared
.cone
); 
4146 static void zremrangebyscoreCommand(redisClient 
*c
) { 
4147     double min 
= strtod(c
->argv
[2]->ptr
,NULL
); 
4148     double max 
= strtod(c
->argv
[3]->ptr
,NULL
); 
4152     zsetobj 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
4153     if (zsetobj 
== NULL
) { 
4154         addReply(c
,shared
.czero
); 
4158         if (zsetobj
->type 
!= REDIS_ZSET
) { 
4159             addReply(c
,shared
.wrongtypeerr
); 
4163         deleted 
= zslDeleteRange(zs
->zsl
,min
,max
,zs
->dict
); 
4164         if (htNeedsResize(zs
->dict
)) dictResize(zs
->dict
); 
4165         server
.dirty 
+= deleted
; 
4166         addReplySds(c
,sdscatprintf(sdsempty(),":%lu\r\n",deleted
)); 
4170 static void zrangeGenericCommand(redisClient 
*c
, int reverse
) { 
4172     int start 
= atoi(c
->argv
[2]->ptr
); 
4173     int end 
= atoi(c
->argv
[3]->ptr
); 
4175     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4177         addReply(c
,shared
.nullmultibulk
); 
4179         if (o
->type 
!= REDIS_ZSET
) { 
4180             addReply(c
,shared
.wrongtypeerr
); 
4182             zset 
*zsetobj 
= o
->ptr
; 
4183             zskiplist 
*zsl 
= zsetobj
->zsl
; 
4186             int llen 
= zsl
->length
; 
4190             /* convert negative indexes */ 
4191             if (start 
< 0) start 
= llen
+start
; 
4192             if (end 
< 0) end 
= llen
+end
; 
4193             if (start 
< 0) start 
= 0; 
4194             if (end 
< 0) end 
= 0; 
4196             /* indexes sanity checks */ 
4197             if (start 
> end 
|| start 
>= llen
) { 
4198                 /* Out of range start or start > end result in empty list */ 
4199                 addReply(c
,shared
.emptymultibulk
); 
4202             if (end 
>= llen
) end 
= llen
-1; 
4203             rangelen 
= (end
-start
)+1; 
4205             /* Return the result in form of a multi-bulk reply */ 
4211                 ln 
= zsl
->header
->forward
[0]; 
4213                     ln 
= ln
->forward
[0]; 
4216             addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",rangelen
)); 
4217             for (j 
= 0; j 
< rangelen
; j
++) { 
4219                 addReplyBulkLen(c
,ele
); 
4221                 addReply(c
,shared
.crlf
); 
4222                 ln 
= reverse 
? ln
->backward 
: ln
->forward
[0]; 
4228 static void zrangeCommand(redisClient 
*c
) { 
4229     zrangeGenericCommand(c
,0); 
4232 static void zrevrangeCommand(redisClient 
*c
) { 
4233     zrangeGenericCommand(c
,1); 
4236 static void zrangebyscoreCommand(redisClient 
*c
) { 
4238     double min 
= strtod(c
->argv
[2]->ptr
,NULL
); 
4239     double max 
= strtod(c
->argv
[3]->ptr
,NULL
); 
4241     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4243         addReply(c
,shared
.nullmultibulk
); 
4245         if (o
->type 
!= REDIS_ZSET
) { 
4246             addReply(c
,shared
.wrongtypeerr
); 
4248             zset 
*zsetobj 
= o
->ptr
; 
4249             zskiplist 
*zsl 
= zsetobj
->zsl
; 
4252             unsigned int rangelen 
= 0; 
4254             /* Get the first node with the score >= min */ 
4255             ln 
= zslFirstWithScore(zsl
,min
); 
4257                 /* No element matching the speciifed interval */ 
4258                 addReply(c
,shared
.emptymultibulk
); 
4262             /* We don't know in advance how many matching elements there 
4263              * are in the list, so we push this object that will represent 
4264              * the multi-bulk length in the output buffer, and will "fix" 
4266             lenobj 
= createObject(REDIS_STRING
,NULL
); 
4269             while(ln 
&& ln
->score 
<= max
) { 
4271                 addReplyBulkLen(c
,ele
); 
4273                 addReply(c
,shared
.crlf
); 
4274                 ln 
= ln
->forward
[0]; 
4277             lenobj
->ptr 
= sdscatprintf(sdsempty(),"*%d\r\n",rangelen
); 
4282 static void zcardCommand(redisClient 
*c
) { 
4286     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4288         addReply(c
,shared
.czero
); 
4291         if (o
->type 
!= REDIS_ZSET
) { 
4292             addReply(c
,shared
.wrongtypeerr
); 
4295             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",zs
->zsl
->length
)); 
4300 static void zscoreCommand(redisClient 
*c
) { 
4304     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4306         addReply(c
,shared
.czero
); 
4309         if (o
->type 
!= REDIS_ZSET
) { 
4310             addReply(c
,shared
.wrongtypeerr
); 
4315             de 
= dictFind(zs
->dict
,c
->argv
[2]); 
4317                 addReply(c
,shared
.nullbulk
); 
4320                 double *score 
= dictGetEntryVal(de
); 
4322                 snprintf(buf
,sizeof(buf
),"%.17g",*score
); 
4323                 addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n%s\r\n", 
4330 /* ========================= Non type-specific commands  ==================== */ 
4332 static void flushdbCommand(redisClient 
*c
) { 
4333     server
.dirty 
+= dictSize(c
->db
->dict
); 
4334     dictEmpty(c
->db
->dict
); 
4335     dictEmpty(c
->db
->expires
); 
4336     addReply(c
,shared
.ok
); 
4339 static void flushallCommand(redisClient 
*c
) { 
4340     server
.dirty 
+= emptyDb(); 
4341     addReply(c
,shared
.ok
); 
4342     rdbSave(server
.dbfilename
); 
4346 static redisSortOperation 
*createSortOperation(int type
, robj 
*pattern
) { 
4347     redisSortOperation 
*so 
= zmalloc(sizeof(*so
)); 
4349     so
->pattern 
= pattern
; 
4353 /* Return the value associated to the key with a name obtained 
4354  * substituting the first occurence of '*' in 'pattern' with 'subst' */ 
4355 static robj 
*lookupKeyByPattern(redisDb 
*db
, robj 
*pattern
, robj 
*subst
) { 
4359     int prefixlen
, sublen
, postfixlen
; 
4360     /* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */ 
4364         char buf
[REDIS_SORTKEY_MAX
+1]; 
4367     if (subst
->encoding 
== REDIS_ENCODING_RAW
) 
4368         incrRefCount(subst
); 
4370         subst 
= getDecodedObject(subst
); 
4373     spat 
= pattern
->ptr
; 
4375     if (sdslen(spat
)+sdslen(ssub
)-1 > REDIS_SORTKEY_MAX
) return NULL
; 
4376     p 
= strchr(spat
,'*'); 
4377     if (!p
) return NULL
; 
4380     sublen 
= sdslen(ssub
); 
4381     postfixlen 
= sdslen(spat
)-(prefixlen
+1); 
4382     memcpy(keyname
.buf
,spat
,prefixlen
); 
4383     memcpy(keyname
.buf
+prefixlen
,ssub
,sublen
); 
4384     memcpy(keyname
.buf
+prefixlen
+sublen
,p
+1,postfixlen
); 
4385     keyname
.buf
[prefixlen
+sublen
+postfixlen
] = '\0'; 
4386     keyname
.len 
= prefixlen
+sublen
+postfixlen
; 
4388     keyobj
.refcount 
= 1; 
4389     keyobj
.type 
= REDIS_STRING
; 
4390     keyobj
.ptr 
= ((char*)&keyname
)+(sizeof(long)*2); 
4392     decrRefCount(subst
); 
4394     /* printf("lookup '%s' => %p\n", keyname.buf,de); */ 
4395     return lookupKeyRead(db
,&keyobj
); 
4398 /* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with 
4399  * the additional parameter is not standard but a BSD-specific we have to 
4400  * pass sorting parameters via the global 'server' structure */ 
4401 static int sortCompare(const void *s1
, const void *s2
) { 
4402     const redisSortObject 
*so1 
= s1
, *so2 
= s2
; 
4405     if (!server
.sort_alpha
) { 
4406         /* Numeric sorting. Here it's trivial as we precomputed scores */ 
4407         if (so1
->u
.score 
> so2
->u
.score
) { 
4409         } else if (so1
->u
.score 
< so2
->u
.score
) { 
4415         /* Alphanumeric sorting */ 
4416         if (server
.sort_bypattern
) { 
4417             if (!so1
->u
.cmpobj 
|| !so2
->u
.cmpobj
) { 
4418                 /* At least one compare object is NULL */ 
4419                 if (so1
->u
.cmpobj 
== so2
->u
.cmpobj
) 
4421                 else if (so1
->u
.cmpobj 
== NULL
) 
4426                 /* We have both the objects, use strcoll */ 
4427                 cmp 
= strcoll(so1
->u
.cmpobj
->ptr
,so2
->u
.cmpobj
->ptr
); 
4430             /* Compare elements directly */ 
4431             if (so1
->obj
->encoding 
== REDIS_ENCODING_RAW 
&& 
4432                 so2
->obj
->encoding 
== REDIS_ENCODING_RAW
) { 
4433                 cmp 
= strcoll(so1
->obj
->ptr
,so2
->obj
->ptr
); 
4437                 dec1 
= so1
->obj
->encoding 
== REDIS_ENCODING_RAW 
? 
4438                     so1
->obj 
: getDecodedObject(so1
->obj
); 
4439                 dec2 
= so2
->obj
->encoding 
== REDIS_ENCODING_RAW 
? 
4440                     so2
->obj 
: getDecodedObject(so2
->obj
); 
4441                 cmp 
= strcoll(dec1
->ptr
,dec2
->ptr
); 
4442                 if (dec1 
!= so1
->obj
) decrRefCount(dec1
); 
4443                 if (dec2 
!= so2
->obj
) decrRefCount(dec2
); 
4447     return server
.sort_desc 
? -cmp 
: cmp
; 
4450 /* The SORT command is the most complex command in Redis. Warning: this code 
4451  * is optimized for speed and a bit less for readability */ 
4452 static void sortCommand(redisClient 
*c
) { 
4455     int desc 
= 0, alpha 
= 0; 
4456     int limit_start 
= 0, limit_count 
= -1, start
, end
; 
4457     int j
, dontsort 
= 0, vectorlen
; 
4458     int getop 
= 0; /* GET operation counter */ 
4459     robj 
*sortval
, *sortby 
= NULL
, *storekey 
= NULL
; 
4460     redisSortObject 
*vector
; /* Resulting vector to sort */ 
4462     /* Lookup the key to sort. It must be of the right types */ 
4463     sortval 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4464     if (sortval 
== NULL
) { 
4465         addReply(c
,shared
.nokeyerr
); 
4468     if (sortval
->type 
!= REDIS_SET 
&& sortval
->type 
!= REDIS_LIST
) { 
4469         addReply(c
,shared
.wrongtypeerr
); 
4473     /* Create a list of operations to perform for every sorted element. 
4474      * Operations can be GET/DEL/INCR/DECR */ 
4475     operations 
= listCreate(); 
4476     listSetFreeMethod(operations
,zfree
); 
4479     /* Now we need to protect sortval incrementing its count, in the future 
4480      * SORT may have options able to overwrite/delete keys during the sorting 
4481      * and the sorted key itself may get destroied */ 
4482     incrRefCount(sortval
); 
4484     /* The SORT command has an SQL-alike syntax, parse it */ 
4485     while(j 
< c
->argc
) { 
4486         int leftargs 
= c
->argc
-j
-1; 
4487         if (!strcasecmp(c
->argv
[j
]->ptr
,"asc")) { 
4489         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"desc")) { 
4491         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"alpha")) { 
4493         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"limit") && leftargs 
>= 2) { 
4494             limit_start 
= atoi(c
->argv
[j
+1]->ptr
); 
4495             limit_count 
= atoi(c
->argv
[j
+2]->ptr
); 
4497         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"store") && leftargs 
>= 1) { 
4498             storekey 
= c
->argv
[j
+1]; 
4500         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"by") && leftargs 
>= 1) { 
4501             sortby 
= c
->argv
[j
+1]; 
4502             /* If the BY pattern does not contain '*', i.e. it is constant, 
4503              * we don't need to sort nor to lookup the weight keys. */ 
4504             if (strchr(c
->argv
[j
+1]->ptr
,'*') == NULL
) dontsort 
= 1; 
4506         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"get") && leftargs 
>= 1) { 
4507             listAddNodeTail(operations
,createSortOperation( 
4508                 REDIS_SORT_GET
,c
->argv
[j
+1])); 
4512             decrRefCount(sortval
); 
4513             listRelease(operations
); 
4514             addReply(c
,shared
.syntaxerr
); 
4520     /* Load the sorting vector with all the objects to sort */ 
4521     vectorlen 
= (sortval
->type 
== REDIS_LIST
) ? 
4522         listLength((list
*)sortval
->ptr
) : 
4523         dictSize((dict
*)sortval
->ptr
); 
4524     vector 
= zmalloc(sizeof(redisSortObject
)*vectorlen
); 
4526     if (sortval
->type 
== REDIS_LIST
) { 
4527         list 
*list 
= sortval
->ptr
; 
4531         while((ln 
= listYield(list
))) { 
4532             robj 
*ele 
= ln
->value
; 
4533             vector
[j
].obj 
= ele
; 
4534             vector
[j
].u
.score 
= 0; 
4535             vector
[j
].u
.cmpobj 
= NULL
; 
4539         dict 
*set 
= sortval
->ptr
; 
4543         di 
= dictGetIterator(set
); 
4544         while((setele 
= dictNext(di
)) != NULL
) { 
4545             vector
[j
].obj 
= dictGetEntryKey(setele
); 
4546             vector
[j
].u
.score 
= 0; 
4547             vector
[j
].u
.cmpobj 
= NULL
; 
4550         dictReleaseIterator(di
); 
4552     assert(j 
== vectorlen
); 
4554     /* Now it's time to load the right scores in the sorting vector */ 
4555     if (dontsort 
== 0) { 
4556         for (j 
= 0; j 
< vectorlen
; j
++) { 
4560                 byval 
= lookupKeyByPattern(c
->db
,sortby
,vector
[j
].obj
); 
4561                 if (!byval 
|| byval
->type 
!= REDIS_STRING
) continue; 
4563                     if (byval
->encoding 
== REDIS_ENCODING_RAW
) { 
4564                         vector
[j
].u
.cmpobj 
= byval
; 
4565                         incrRefCount(byval
); 
4567                         vector
[j
].u
.cmpobj 
= getDecodedObject(byval
); 
4570                     if (byval
->encoding 
== REDIS_ENCODING_RAW
) { 
4571                         vector
[j
].u
.score 
= strtod(byval
->ptr
,NULL
); 
4573                         if (byval
->encoding 
== REDIS_ENCODING_INT
) { 
4574                             vector
[j
].u
.score 
= (long)byval
->ptr
; 
4581                     if (vector
[j
].obj
->encoding 
== REDIS_ENCODING_RAW
) 
4582                         vector
[j
].u
.score 
= strtod(vector
[j
].obj
->ptr
,NULL
); 
4584                         if (vector
[j
].obj
->encoding 
== REDIS_ENCODING_INT
) 
4585                             vector
[j
].u
.score 
= (long) vector
[j
].obj
->ptr
; 
4594     /* We are ready to sort the vector... perform a bit of sanity check 
4595      * on the LIMIT option too. We'll use a partial version of quicksort. */ 
4596     start 
= (limit_start 
< 0) ? 0 : limit_start
; 
4597     end 
= (limit_count 
< 0) ? vectorlen
-1 : start
+limit_count
-1; 
4598     if (start 
>= vectorlen
) { 
4599         start 
= vectorlen
-1; 
4602     if (end 
>= vectorlen
) end 
= vectorlen
-1; 
4604     if (dontsort 
== 0) { 
4605         server
.sort_desc 
= desc
; 
4606         server
.sort_alpha 
= alpha
; 
4607         server
.sort_bypattern 
= sortby 
? 1 : 0; 
4608         if (sortby 
&& (start 
!= 0 || end 
!= vectorlen
-1)) 
4609             pqsort(vector
,vectorlen
,sizeof(redisSortObject
),sortCompare
, start
,end
); 
4611             qsort(vector
,vectorlen
,sizeof(redisSortObject
),sortCompare
); 
4614     /* Send command output to the output buffer, performing the specified 
4615      * GET/DEL/INCR/DECR operations if any. */ 
4616     outputlen 
= getop 
? getop
*(end
-start
+1) : end
-start
+1; 
4617     if (storekey 
== NULL
) { 
4618         /* STORE option not specified, sent the sorting result to client */ 
4619         addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",outputlen
)); 
4620         for (j 
= start
; j 
<= end
; j
++) { 
4623                 addReplyBulkLen(c
,vector
[j
].obj
); 
4624                 addReply(c
,vector
[j
].obj
); 
4625                 addReply(c
,shared
.crlf
); 
4627             listRewind(operations
); 
4628             while((ln 
= listYield(operations
))) { 
4629                 redisSortOperation 
*sop 
= ln
->value
; 
4630                 robj 
*val 
= lookupKeyByPattern(c
->db
,sop
->pattern
, 
4633                 if (sop
->type 
== REDIS_SORT_GET
) { 
4634                     if (!val 
|| val
->type 
!= REDIS_STRING
) { 
4635                         addReply(c
,shared
.nullbulk
); 
4637                         addReplyBulkLen(c
,val
); 
4639                         addReply(c
,shared
.crlf
); 
4642                     assert(sop
->type 
== REDIS_SORT_GET
); /* always fails */ 
4647         robj 
*listObject 
= createListObject(); 
4648         list 
*listPtr 
= (list
*) listObject
->ptr
; 
4650         /* STORE option specified, set the sorting result as a List object */ 
4651         for (j 
= start
; j 
<= end
; j
++) { 
4654                 listAddNodeTail(listPtr
,vector
[j
].obj
); 
4655                 incrRefCount(vector
[j
].obj
); 
4657             listRewind(operations
); 
4658             while((ln 
= listYield(operations
))) { 
4659                 redisSortOperation 
*sop 
= ln
->value
; 
4660                 robj 
*val 
= lookupKeyByPattern(c
->db
,sop
->pattern
, 
4663                 if (sop
->type 
== REDIS_SORT_GET
) { 
4664                     if (!val 
|| val
->type 
!= REDIS_STRING
) { 
4665                         listAddNodeTail(listPtr
,createStringObject("",0)); 
4667                         listAddNodeTail(listPtr
,val
); 
4671                     assert(sop
->type 
== REDIS_SORT_GET
); /* always fails */ 
4675         if (dictReplace(c
->db
->dict
,storekey
,listObject
)) { 
4676             incrRefCount(storekey
); 
4678         /* Note: we add 1 because the DB is dirty anyway since even if the 
4679          * SORT result is empty a new key is set and maybe the old content 
4681         server
.dirty 
+= 1+outputlen
; 
4682         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",outputlen
)); 
4686     decrRefCount(sortval
); 
4687     listRelease(operations
); 
4688     for (j 
= 0; j 
< vectorlen
; j
++) { 
4689         if (sortby 
&& alpha 
&& vector
[j
].u
.cmpobj
) 
4690             decrRefCount(vector
[j
].u
.cmpobj
); 
4695 static void infoCommand(redisClient 
*c
) { 
4697     time_t uptime 
= time(NULL
)-server
.stat_starttime
; 
4700     info 
= sdscatprintf(sdsempty(), 
4701         "redis_version:%s\r\n" 
4703         "uptime_in_seconds:%d\r\n" 
4704         "uptime_in_days:%d\r\n" 
4705         "connected_clients:%d\r\n" 
4706         "connected_slaves:%d\r\n" 
4707         "used_memory:%zu\r\n" 
4708         "changes_since_last_save:%lld\r\n" 
4709         "bgsave_in_progress:%d\r\n" 
4710         "last_save_time:%d\r\n" 
4711         "total_connections_received:%lld\r\n" 
4712         "total_commands_processed:%lld\r\n" 
4715         (sizeof(long) == 8) ? "64" : "32", 
4718         listLength(server
.clients
)-listLength(server
.slaves
), 
4719         listLength(server
.slaves
), 
4722         server
.bgsaveinprogress
, 
4724         server
.stat_numconnections
, 
4725         server
.stat_numcommands
, 
4726         server
.masterhost 
== NULL 
? "master" : "slave" 
4728     if (server
.masterhost
) { 
4729         info 
= sdscatprintf(info
, 
4730             "master_host:%s\r\n" 
4731             "master_port:%d\r\n" 
4732             "master_link_status:%s\r\n" 
4733             "master_last_io_seconds_ago:%d\r\n" 
4736             (server
.replstate 
== REDIS_REPL_CONNECTED
) ? 
4738             server
.master 
? ((int)(time(NULL
)-server
.master
->lastinteraction
)) : -1 
4741     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
4742         long long keys
, vkeys
; 
4744         keys 
= dictSize(server
.db
[j
].dict
); 
4745         vkeys 
= dictSize(server
.db
[j
].expires
); 
4746         if (keys 
|| vkeys
) { 
4747             info 
= sdscatprintf(info
, "db%d: keys=%lld,expires=%lld\r\n", 
4751     addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",sdslen(info
))); 
4752     addReplySds(c
,info
); 
4753     addReply(c
,shared
.crlf
); 
4756 static void monitorCommand(redisClient 
*c
) { 
4757     /* ignore MONITOR if aleady slave or in monitor mode */ 
4758     if (c
->flags 
& REDIS_SLAVE
) return; 
4760     c
->flags 
|= (REDIS_SLAVE
|REDIS_MONITOR
); 
4762     listAddNodeTail(server
.monitors
,c
); 
4763     addReply(c
,shared
.ok
); 
4766 /* ================================= Expire ================================= */ 
4767 static int removeExpire(redisDb 
*db
, robj 
*key
) { 
4768     if (dictDelete(db
->expires
,key
) == DICT_OK
) { 
4775 static int setExpire(redisDb 
*db
, robj 
*key
, time_t when
) { 
4776     if (dictAdd(db
->expires
,key
,(void*)when
) == DICT_ERR
) { 
4784 /* Return the expire time of the specified key, or -1 if no expire 
4785  * is associated with this key (i.e. the key is non volatile) */ 
4786 static time_t getExpire(redisDb 
*db
, robj 
*key
) { 
4789     /* No expire? return ASAP */ 
4790     if (dictSize(db
->expires
) == 0 || 
4791        (de 
= dictFind(db
->expires
,key
)) == NULL
) return -1; 
4793     return (time_t) dictGetEntryVal(de
); 
4796 static int expireIfNeeded(redisDb 
*db
, robj 
*key
) { 
4800     /* No expire? return ASAP */ 
4801     if (dictSize(db
->expires
) == 0 || 
4802        (de 
= dictFind(db
->expires
,key
)) == NULL
) return 0; 
4804     /* Lookup the expire */ 
4805     when 
= (time_t) dictGetEntryVal(de
); 
4806     if (time(NULL
) <= when
) return 0; 
4808     /* Delete the key */ 
4809     dictDelete(db
->expires
,key
); 
4810     return dictDelete(db
->dict
,key
) == DICT_OK
; 
4813 static int deleteIfVolatile(redisDb 
*db
, robj 
*key
) { 
4816     /* No expire? return ASAP */ 
4817     if (dictSize(db
->expires
) == 0 || 
4818        (de 
= dictFind(db
->expires
,key
)) == NULL
) return 0; 
4820     /* Delete the key */ 
4822     dictDelete(db
->expires
,key
); 
4823     return dictDelete(db
->dict
,key
) == DICT_OK
; 
4826 static void expireGenericCommand(redisClient 
*c
, robj 
*key
, time_t seconds
) { 
4829     de 
= dictFind(c
->db
->dict
,key
); 
4831         addReply(c
,shared
.czero
); 
4835         if (deleteKey(c
->db
,key
)) server
.dirty
++; 
4836         addReply(c
, shared
.cone
); 
4839         time_t when 
= time(NULL
)+seconds
; 
4840         if (setExpire(c
->db
,key
,when
)) { 
4841             addReply(c
,shared
.cone
); 
4844             addReply(c
,shared
.czero
); 
4850 static void expireCommand(redisClient 
*c
) { 
4851     expireGenericCommand(c
,c
->argv
[1],strtol(c
->argv
[2]->ptr
,NULL
,10)); 
4854 static void expireatCommand(redisClient 
*c
) { 
4855     expireGenericCommand(c
,c
->argv
[1],strtol(c
->argv
[2]->ptr
,NULL
,10)-time(NULL
)); 
4858 static void ttlCommand(redisClient 
*c
) { 
4862     expire 
= getExpire(c
->db
,c
->argv
[1]); 
4864         ttl 
= (int) (expire
-time(NULL
)); 
4865         if (ttl 
< 0) ttl 
= -1; 
4867     addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",ttl
)); 
4870 static void msetGenericCommand(redisClient 
*c
, int nx
) { 
4873     if ((c
->argc 
% 2) == 0) { 
4874         addReplySds(c
,sdsnew("-ERR wrong number of arguments\r\n")); 
4877     /* Handle the NX flag. The MSETNX semantic is to return zero and don't 
4878      * set nothing at all if at least one already key exists. */ 
4880         for (j 
= 1; j 
< c
->argc
; j 
+= 2) { 
4881             if (dictFind(c
->db
->dict
,c
->argv
[j
]) != NULL
) { 
4882                 addReply(c
, shared
.czero
); 
4888     for (j 
= 1; j 
< c
->argc
; j 
+= 2) { 
4891         retval 
= dictAdd(c
->db
->dict
,c
->argv
[j
],c
->argv
[j
+1]); 
4892         if (retval 
== DICT_ERR
) { 
4893             dictReplace(c
->db
->dict
,c
->argv
[j
],c
->argv
[j
+1]); 
4894             incrRefCount(c
->argv
[j
+1]); 
4896             incrRefCount(c
->argv
[j
]); 
4897             incrRefCount(c
->argv
[j
+1]); 
4899         removeExpire(c
->db
,c
->argv
[j
]); 
4901     server
.dirty 
+= (c
->argc
-1)/2; 
4902     addReply(c
, nx 
? shared
.cone 
: shared
.ok
); 
4905 static void msetCommand(redisClient 
*c
) { 
4906     msetGenericCommand(c
,0); 
4909 static void msetnxCommand(redisClient 
*c
) { 
4910     msetGenericCommand(c
,1); 
4913 /* =============================== Replication  ============================= */ 
4915 static int syncWrite(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
4916     ssize_t nwritten
, ret 
= size
; 
4917     time_t start 
= time(NULL
); 
4921         if (aeWait(fd
,AE_WRITABLE
,1000) & AE_WRITABLE
) { 
4922             nwritten 
= write(fd
,ptr
,size
); 
4923             if (nwritten 
== -1) return -1; 
4927         if ((time(NULL
)-start
) > timeout
) { 
4935 static int syncRead(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
4936     ssize_t nread
, totread 
= 0; 
4937     time_t start 
= time(NULL
); 
4941         if (aeWait(fd
,AE_READABLE
,1000) & AE_READABLE
) { 
4942             nread 
= read(fd
,ptr
,size
); 
4943             if (nread 
== -1) return -1; 
4948         if ((time(NULL
)-start
) > timeout
) { 
4956 static int syncReadLine(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
4963         if (syncRead(fd
,&c
,1,timeout
) == -1) return -1; 
4966             if (nread 
&& *(ptr
-1) == '\r') *(ptr
-1) = '\0'; 
4977 static void syncCommand(redisClient 
*c
) { 
4978     /* ignore SYNC if aleady slave or in monitor mode */ 
4979     if (c
->flags 
& REDIS_SLAVE
) return; 
4981     /* SYNC can't be issued when the server has pending data to send to 
4982      * the client about already issued commands. We need a fresh reply 
4983      * buffer registering the differences between the BGSAVE and the current 
4984      * dataset, so that we can copy to other slaves if needed. */ 
4985     if (listLength(c
->reply
) != 0) { 
4986         addReplySds(c
,sdsnew("-ERR SYNC is invalid with pending input\r\n")); 
4990     redisLog(REDIS_NOTICE
,"Slave ask for synchronization"); 
4991     /* Here we need to check if there is a background saving operation 
4992      * in progress, or if it is required to start one */ 
4993     if (server
.bgsaveinprogress
) { 
4994         /* Ok a background save is in progress. Let's check if it is a good 
4995          * one for replication, i.e. if there is another slave that is 
4996          * registering differences since the server forked to save */ 
5000         listRewind(server
.slaves
); 
5001         while((ln 
= listYield(server
.slaves
))) { 
5003             if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_END
) break; 
5006             /* Perfect, the server is already registering differences for 
5007              * another slave. Set the right state, and copy the buffer. */ 
5008             listRelease(c
->reply
); 
5009             c
->reply 
= listDup(slave
->reply
); 
5010             c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
5011             redisLog(REDIS_NOTICE
,"Waiting for end of BGSAVE for SYNC"); 
5013             /* No way, we need to wait for the next BGSAVE in order to 
5014              * register differences */ 
5015             c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_START
; 
5016             redisLog(REDIS_NOTICE
,"Waiting for next BGSAVE for SYNC"); 
5019         /* Ok we don't have a BGSAVE in progress, let's start one */ 
5020         redisLog(REDIS_NOTICE
,"Starting BGSAVE for SYNC"); 
5021         if (rdbSaveBackground(server
.dbfilename
) != REDIS_OK
) { 
5022             redisLog(REDIS_NOTICE
,"Replication failed, can't BGSAVE"); 
5023             addReplySds(c
,sdsnew("-ERR Unalbe to perform background save\r\n")); 
5026         c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
5029     c
->flags 
|= REDIS_SLAVE
; 
5031     listAddNodeTail(server
.slaves
,c
); 
5035 static void sendBulkToSlave(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
5036     redisClient 
*slave 
= privdata
; 
5038     REDIS_NOTUSED(mask
); 
5039     char buf
[REDIS_IOBUF_LEN
]; 
5040     ssize_t nwritten
, buflen
; 
5042     if (slave
->repldboff 
== 0) { 
5043         /* Write the bulk write count before to transfer the DB. In theory here 
5044          * we don't know how much room there is in the output buffer of the 
5045          * socket, but in pratice SO_SNDLOWAT (the minimum count for output 
5046          * operations) will never be smaller than the few bytes we need. */ 
5049         bulkcount 
= sdscatprintf(sdsempty(),"$%lld\r\n",(unsigned long long) 
5051         if (write(fd
,bulkcount
,sdslen(bulkcount
)) != (signed)sdslen(bulkcount
)) 
5059     lseek(slave
->repldbfd
,slave
->repldboff
,SEEK_SET
); 
5060     buflen 
= read(slave
->repldbfd
,buf
,REDIS_IOBUF_LEN
); 
5062         redisLog(REDIS_WARNING
,"Read error sending DB to slave: %s", 
5063             (buflen 
== 0) ? "premature EOF" : strerror(errno
)); 
5067     if ((nwritten 
= write(fd
,buf
,buflen
)) == -1) { 
5068         redisLog(REDIS_DEBUG
,"Write error sending DB to slave: %s", 
5073     slave
->repldboff 
+= nwritten
; 
5074     if (slave
->repldboff 
== slave
->repldbsize
) { 
5075         close(slave
->repldbfd
); 
5076         slave
->repldbfd 
= -1; 
5077         aeDeleteFileEvent(server
.el
,slave
->fd
,AE_WRITABLE
); 
5078         slave
->replstate 
= REDIS_REPL_ONLINE
; 
5079         if (aeCreateFileEvent(server
.el
, slave
->fd
, AE_WRITABLE
, 
5080             sendReplyToClient
, slave
, NULL
) == AE_ERR
) { 
5084         addReplySds(slave
,sdsempty()); 
5085         redisLog(REDIS_NOTICE
,"Synchronization with slave succeeded"); 
5089 /* This function is called at the end of every backgrond saving. 
5090  * The argument bgsaveerr is REDIS_OK if the background saving succeeded 
5091  * otherwise REDIS_ERR is passed to the function. 
5093  * The goal of this function is to handle slaves waiting for a successful 
5094  * background saving in order to perform non-blocking synchronization. */ 
5095 static void updateSlavesWaitingBgsave(int bgsaveerr
) { 
5097     int startbgsave 
= 0; 
5099     listRewind(server
.slaves
); 
5100     while((ln 
= listYield(server
.slaves
))) { 
5101         redisClient 
*slave 
= ln
->value
; 
5103         if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) { 
5105             slave
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
5106         } else if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_END
) { 
5107             struct redis_stat buf
; 
5109             if (bgsaveerr 
!= REDIS_OK
) { 
5111                 redisLog(REDIS_WARNING
,"SYNC failed. BGSAVE child returned an error"); 
5114             if ((slave
->repldbfd 
= open(server
.dbfilename
,O_RDONLY
)) == -1 || 
5115                 redis_fstat(slave
->repldbfd
,&buf
) == -1) { 
5117                 redisLog(REDIS_WARNING
,"SYNC failed. Can't open/stat DB after BGSAVE: %s", strerror(errno
)); 
5120             slave
->repldboff 
= 0; 
5121             slave
->repldbsize 
= buf
.st_size
; 
5122             slave
->replstate 
= REDIS_REPL_SEND_BULK
; 
5123             aeDeleteFileEvent(server
.el
,slave
->fd
,AE_WRITABLE
); 
5124             if (aeCreateFileEvent(server
.el
, slave
->fd
, AE_WRITABLE
, sendBulkToSlave
, slave
, NULL
) == AE_ERR
) { 
5131         if (rdbSaveBackground(server
.dbfilename
) != REDIS_OK
) { 
5132             listRewind(server
.slaves
); 
5133             redisLog(REDIS_WARNING
,"SYNC failed. BGSAVE failed"); 
5134             while((ln 
= listYield(server
.slaves
))) { 
5135                 redisClient 
*slave 
= ln
->value
; 
5137                 if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) 
5144 static int syncWithMaster(void) { 
5145     char buf
[1024], tmpfile
[256], authcmd
[1024]; 
5147     int fd 
= anetTcpConnect(NULL
,server
.masterhost
,server
.masterport
); 
5151         redisLog(REDIS_WARNING
,"Unable to connect to MASTER: %s", 
5156     /* AUTH with the master if required. */ 
5157     if(server
.masterauth
) { 
5158         snprintf(authcmd
, 1024, "AUTH %s\r\n", server
.masterauth
); 
5159         if (syncWrite(fd
, authcmd
, strlen(server
.masterauth
)+7, 5) == -1) { 
5161             redisLog(REDIS_WARNING
,"Unable to AUTH to MASTER: %s", 
5165         /* Read the AUTH result.  */ 
5166         if (syncReadLine(fd
,buf
,1024,3600) == -1) { 
5168             redisLog(REDIS_WARNING
,"I/O error reading auth result from MASTER: %s", 
5172         if (buf
[0] != '+') { 
5174             redisLog(REDIS_WARNING
,"Cannot AUTH to MASTER, is the masterauth password correct?"); 
5179     /* Issue the SYNC command */ 
5180     if (syncWrite(fd
,"SYNC \r\n",7,5) == -1) { 
5182         redisLog(REDIS_WARNING
,"I/O error writing to MASTER: %s", 
5186     /* Read the bulk write count */ 
5187     if (syncReadLine(fd
,buf
,1024,3600) == -1) { 
5189         redisLog(REDIS_WARNING
,"I/O error reading bulk count from MASTER: %s", 
5193     if (buf
[0] != '$') { 
5195         redisLog(REDIS_WARNING
,"Bad protocol from MASTER, the first byte is not '$', are you sure the host and port are right?"); 
5198     dumpsize 
= atoi(buf
+1); 
5199     redisLog(REDIS_NOTICE
,"Receiving %d bytes data dump from MASTER",dumpsize
); 
5200     /* Read the bulk write data on a temp file */ 
5201     snprintf(tmpfile
,256,"temp-%d.%ld.rdb",(int)time(NULL
),(long int)random()); 
5202     dfd 
= open(tmpfile
,O_CREAT
|O_WRONLY
,0644); 
5205         redisLog(REDIS_WARNING
,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno
)); 
5209         int nread
, nwritten
; 
5211         nread 
= read(fd
,buf
,(dumpsize 
< 1024)?dumpsize
:1024); 
5213             redisLog(REDIS_WARNING
,"I/O error trying to sync with MASTER: %s", 
5219         nwritten 
= write(dfd
,buf
,nread
); 
5220         if (nwritten 
== -1) { 
5221             redisLog(REDIS_WARNING
,"Write error writing to the DB dump file needed for MASTER <-> SLAVE synchrnonization: %s", strerror(errno
)); 
5229     if (rename(tmpfile
,server
.dbfilename
) == -1) { 
5230         redisLog(REDIS_WARNING
,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", strerror(errno
)); 
5236     if (rdbLoad(server
.dbfilename
) != REDIS_OK
) { 
5237         redisLog(REDIS_WARNING
,"Failed trying to load the MASTER synchronization DB from disk"); 
5241     server
.master 
= createClient(fd
); 
5242     server
.master
->flags 
|= REDIS_MASTER
; 
5243     server
.replstate 
= REDIS_REPL_CONNECTED
; 
5247 static void slaveofCommand(redisClient 
*c
) { 
5248     if (!strcasecmp(c
->argv
[1]->ptr
,"no") && 
5249         !strcasecmp(c
->argv
[2]->ptr
,"one")) { 
5250         if (server
.masterhost
) { 
5251             sdsfree(server
.masterhost
); 
5252             server
.masterhost 
= NULL
; 
5253             if (server
.master
) freeClient(server
.master
); 
5254             server
.replstate 
= REDIS_REPL_NONE
; 
5255             redisLog(REDIS_NOTICE
,"MASTER MODE enabled (user request)"); 
5258         sdsfree(server
.masterhost
); 
5259         server
.masterhost 
= sdsdup(c
->argv
[1]->ptr
); 
5260         server
.masterport 
= atoi(c
->argv
[2]->ptr
); 
5261         if (server
.master
) freeClient(server
.master
); 
5262         server
.replstate 
= REDIS_REPL_CONNECT
; 
5263         redisLog(REDIS_NOTICE
,"SLAVE OF %s:%d enabled (user request)", 
5264             server
.masterhost
, server
.masterport
); 
5266     addReply(c
,shared
.ok
); 
5269 /* ============================ Maxmemory directive  ======================== */ 
5271 /* This function gets called when 'maxmemory' is set on the config file to limit 
5272  * the max memory used by the server, and we are out of memory. 
5273  * This function will try to, in order: 
5275  * - Free objects from the free list 
5276  * - Try to remove keys with an EXPIRE set 
5278  * It is not possible to free enough memory to reach used-memory < maxmemory 
5279  * the server will start refusing commands that will enlarge even more the 
5282 static void freeMemoryIfNeeded(void) { 
5283     while (server
.maxmemory 
&& zmalloc_used_memory() > server
.maxmemory
) { 
5284         if (listLength(server
.objfreelist
)) { 
5287             listNode 
*head 
= listFirst(server
.objfreelist
); 
5288             o 
= listNodeValue(head
); 
5289             listDelNode(server
.objfreelist
,head
); 
5292             int j
, k
, freed 
= 0; 
5294             for (j 
= 0; j 
< server
.dbnum
; j
++) { 
5296                 robj 
*minkey 
= NULL
; 
5297                 struct dictEntry 
*de
; 
5299                 if (dictSize(server
.db
[j
].expires
)) { 
5301                     /* From a sample of three keys drop the one nearest to 
5302                      * the natural expire */ 
5303                     for (k 
= 0; k 
< 3; k
++) { 
5306                         de 
= dictGetRandomKey(server
.db
[j
].expires
); 
5307                         t 
= (time_t) dictGetEntryVal(de
); 
5308                         if (minttl 
== -1 || t 
< minttl
) { 
5309                             minkey 
= dictGetEntryKey(de
); 
5313                     deleteKey(server
.db
+j
,minkey
); 
5316             if (!freed
) return; /* nothing to free... */ 
5321 /* ============================== Append Only file ========================== */ 
5323 static void feedAppendOnlyFile(struct redisCommand 
*cmd
, int dictid
, robj 
**argv
, int argc
) { 
5324     sds buf 
= sdsempty(); 
5330     /* The DB this command was targetting is not the same as the last command 
5331      * we appendend. To issue a SELECT command is needed. */ 
5332     if (dictid 
!= server
.appendseldb
) { 
5335         snprintf(seldb
,sizeof(seldb
),"%d",dictid
); 
5336         buf 
= sdscatprintf(buf
,"*2\r\n$6\r\nSELECT\r\n$%d\r\n%s\r\n", 
5337             strlen(seldb
),seldb
); 
5338         server
.appendseldb 
= dictid
; 
5341     /* "Fix" the argv vector if the command is EXPIRE. We want to translate 
5342      * EXPIREs into EXPIREATs calls */ 
5343     if (cmd
->proc 
== expireCommand
) { 
5346         tmpargv
[0] = createStringObject("EXPIREAT",8); 
5347         tmpargv
[1] = argv
[1]; 
5348         incrRefCount(argv
[1]); 
5349         when 
= time(NULL
)+strtol(argv
[2]->ptr
,NULL
,10); 
5350         tmpargv
[2] = createObject(REDIS_STRING
, 
5351             sdscatprintf(sdsempty(),"%ld",when
)); 
5355     /* Append the actual command */ 
5356     buf 
= sdscatprintf(buf
,"*%d\r\n",argc
); 
5357     for (j 
= 0; j 
< argc
; j
++) { 
5360         if (o
->encoding 
!= REDIS_ENCODING_RAW
) 
5361             o 
= getDecodedObject(o
); 
5362         buf 
= sdscatprintf(buf
,"$%d\r\n",sdslen(o
->ptr
)); 
5363         buf 
= sdscatlen(buf
,o
->ptr
,sdslen(o
->ptr
)); 
5364         buf 
= sdscatlen(buf
,"\r\n",2); 
5369     /* Free the objects from the modified argv for EXPIREAT */ 
5370     if (cmd
->proc 
== expireCommand
) { 
5371         for (j 
= 0; j 
< 3; j
++) 
5372             decrRefCount(argv
[j
]); 
5375     /* We want to perform a single write. This should be guaranteed atomic 
5376      * at least if the filesystem we are writing is a real physical one. 
5377      * While this will save us against the server being killed I don't think 
5378      * there is much to do about the whole server stopping for power problems 
5380      nwritten 
= write(server
.appendfd
,buf
,sdslen(buf
)); 
5381      if (nwritten 
!= (signed)sdslen(buf
)) { 
5382         /* Ooops, we are in troubles. The best thing to do for now is 
5383          * to simply exit instead to give the illusion that everything is 
5384          * working as expected. */ 
5385          if (nwritten 
== -1) { 
5386             redisLog(REDIS_WARNING
,"Exiting on error writing to the append-only file: %s",strerror(errno
)); 
5388             redisLog(REDIS_WARNING
,"Exiting on short write while writing to the append-only file: %s",strerror(errno
)); 
5393     if (server
.appendfsync 
== APPENDFSYNC_ALWAYS 
|| 
5394         (server
.appendfsync 
== APPENDFSYNC_EVERYSEC 
&& 
5395          now
-server
.lastfsync 
> 1)) 
5397         fsync(server
.appendfd
); /* Let's try to get this data on the disk */ 
5398         server
.lastfsync 
= now
; 
5402 /* In Redis commands are always executed in the context of a client, so in 
5403  * order to load the append only file we need to create a fake client. */ 
5404 static struct redisClient 
*createFakeClient(void) { 
5405     struct redisClient 
*c 
= zmalloc(sizeof(*c
)); 
5409     c
->querybuf 
= sdsempty(); 
5413     /* We set the fake client as a slave waiting for the synchronization 
5414      * so that Redis will not try to send replies to this client. */ 
5415     c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_START
; 
5416     c
->reply 
= listCreate(); 
5417     listSetFreeMethod(c
->reply
,decrRefCount
); 
5418     listSetDupMethod(c
->reply
,dupClientReplyValue
); 
5422 static void freeFakeClient(struct redisClient 
*c
) { 
5423     sdsfree(c
->querybuf
); 
5424     listRelease(c
->reply
); 
5428 /* Replay the append log file. On error REDIS_OK is returned. On non fatal 
5429  * error (the append only file is zero-length) REDIS_ERR is returned. On 
5430  * fatal error an error message is logged and the program exists. */ 
5431 int loadAppendOnlyFile(char *filename
) { 
5432     struct redisClient 
*fakeClient
; 
5433     FILE *fp 
= fopen(filename
,"r"); 
5434     struct redis_stat sb
; 
5436     if (redis_fstat(fileno(fp
),&sb
) != -1 && sb
.st_size 
== 0) 
5440         redisLog(REDIS_WARNING
,"Fatal error: can't open the append log file for reading: %s",strerror(errno
)); 
5444     fakeClient 
= createFakeClient(); 
5451         struct redisCommand 
*cmd
; 
5453         if (fgets(buf
,sizeof(buf
),fp
) == NULL
) { 
5459         if (buf
[0] != '*') goto fmterr
; 
5461         argv 
= zmalloc(sizeof(robj
*)*argc
); 
5462         for (j 
= 0; j 
< argc
; j
++) { 
5463             if (fgets(buf
,sizeof(buf
),fp
) == NULL
) goto readerr
; 
5464             if (buf
[0] != '$') goto fmterr
; 
5465             len 
= strtol(buf
+1,NULL
,10); 
5466             argsds 
= sdsnewlen(NULL
,len
); 
5467             if (fread(argsds
,len
,1,fp
) == 0) goto fmterr
; 
5468             argv
[j
] = createObject(REDIS_STRING
,argsds
); 
5469             if (fread(buf
,2,1,fp
) == 0) goto fmterr
; /* discard CRLF */ 
5472         /* Command lookup */ 
5473         cmd 
= lookupCommand(argv
[0]->ptr
); 
5475             redisLog(REDIS_WARNING
,"Unknown command '%s' reading the append only file", argv
[0]->ptr
); 
5478         /* Try object sharing and encoding */ 
5479         if (server
.shareobjects
) { 
5481             for(j 
= 1; j 
< argc
; j
++) 
5482                 argv
[j
] = tryObjectSharing(argv
[j
]); 
5484         if (cmd
->flags 
& REDIS_CMD_BULK
) 
5485             tryObjectEncoding(argv
[argc
-1]); 
5486         /* Run the command in the context of a fake client */ 
5487         fakeClient
->argc 
= argc
; 
5488         fakeClient
->argv 
= argv
; 
5489         cmd
->proc(fakeClient
); 
5490         /* Discard the reply objects list from the fake client */ 
5491         while(listLength(fakeClient
->reply
)) 
5492             listDelNode(fakeClient
->reply
,listFirst(fakeClient
->reply
)); 
5493         /* Clean up, ready for the next command */ 
5494         for (j 
= 0; j 
< argc
; j
++) decrRefCount(argv
[j
]); 
5498     freeFakeClient(fakeClient
); 
5503         redisLog(REDIS_WARNING
,"Unexpected end of file reading the append only file"); 
5505         redisLog(REDIS_WARNING
,"Unrecoverable error reading the append only file: %s", strerror(errno
)); 
5509     redisLog(REDIS_WARNING
,"Bad file format reading the append only file"); 
5513 /* ================================= Debugging ============================== */ 
5515 static void debugCommand(redisClient 
*c
) { 
5516     if (!strcasecmp(c
->argv
[1]->ptr
,"segfault")) { 
5518     } else if (!strcasecmp(c
->argv
[1]->ptr
,"object") && c
->argc 
== 3) { 
5519         dictEntry 
*de 
= dictFind(c
->db
->dict
,c
->argv
[2]); 
5523             addReply(c
,shared
.nokeyerr
); 
5526         key 
= dictGetEntryKey(de
); 
5527         val 
= dictGetEntryVal(de
); 
5528         addReplySds(c
,sdscatprintf(sdsempty(), 
5529             "+Key at:%p refcount:%d, value at:%p refcount:%d encoding:%d\r\n", 
5530                 key
, key
->refcount
, val
, val
->refcount
, val
->encoding
)); 
5532         addReplySds(c
,sdsnew( 
5533             "-ERR Syntax error, try DEBUG [SEGFAULT|OBJECT <key>]\r\n")); 
5537 #ifdef HAVE_BACKTRACE 
5538 static struct redisFunctionSym symsTable
[] = { 
5539 {"compareStringObjects", (unsigned long)compareStringObjects
}, 
5540 {"isStringRepresentableAsLong", (unsigned long)isStringRepresentableAsLong
}, 
5541 {"dictEncObjKeyCompare", (unsigned long)dictEncObjKeyCompare
}, 
5542 {"dictEncObjHash", (unsigned long)dictEncObjHash
}, 
5543 {"incrDecrCommand", (unsigned long)incrDecrCommand
}, 
5544 {"freeStringObject", (unsigned long)freeStringObject
}, 
5545 {"freeListObject", (unsigned long)freeListObject
}, 
5546 {"freeSetObject", (unsigned long)freeSetObject
}, 
5547 {"decrRefCount", (unsigned long)decrRefCount
}, 
5548 {"createObject", (unsigned long)createObject
}, 
5549 {"freeClient", (unsigned long)freeClient
}, 
5550 {"rdbLoad", (unsigned long)rdbLoad
}, 
5551 {"rdbSaveStringObject", (unsigned long)rdbSaveStringObject
}, 
5552 {"rdbSaveStringObjectRaw", (unsigned long)rdbSaveStringObjectRaw
}, 
5553 {"addReply", (unsigned long)addReply
}, 
5554 {"addReplySds", (unsigned long)addReplySds
}, 
5555 {"incrRefCount", (unsigned long)incrRefCount
}, 
5556 {"rdbSaveBackground", (unsigned long)rdbSaveBackground
}, 
5557 {"createStringObject", (unsigned long)createStringObject
}, 
5558 {"replicationFeedSlaves", (unsigned long)replicationFeedSlaves
}, 
5559 {"syncWithMaster", (unsigned long)syncWithMaster
}, 
5560 {"tryObjectSharing", (unsigned long)tryObjectSharing
}, 
5561 {"tryObjectEncoding", (unsigned long)tryObjectEncoding
}, 
5562 {"getDecodedObject", (unsigned long)getDecodedObject
}, 
5563 {"removeExpire", (unsigned long)removeExpire
}, 
5564 {"expireIfNeeded", (unsigned long)expireIfNeeded
}, 
5565 {"deleteIfVolatile", (unsigned long)deleteIfVolatile
}, 
5566 {"deleteKey", (unsigned long)deleteKey
}, 
5567 {"getExpire", (unsigned long)getExpire
}, 
5568 {"setExpire", (unsigned long)setExpire
}, 
5569 {"updateSlavesWaitingBgsave", (unsigned long)updateSlavesWaitingBgsave
}, 
5570 {"freeMemoryIfNeeded", (unsigned long)freeMemoryIfNeeded
}, 
5571 {"authCommand", (unsigned long)authCommand
}, 
5572 {"pingCommand", (unsigned long)pingCommand
}, 
5573 {"echoCommand", (unsigned long)echoCommand
}, 
5574 {"setCommand", (unsigned long)setCommand
}, 
5575 {"setnxCommand", (unsigned long)setnxCommand
}, 
5576 {"getCommand", (unsigned long)getCommand
}, 
5577 {"delCommand", (unsigned long)delCommand
}, 
5578 {"existsCommand", (unsigned long)existsCommand
}, 
5579 {"incrCommand", (unsigned long)incrCommand
}, 
5580 {"decrCommand", (unsigned long)decrCommand
}, 
5581 {"incrbyCommand", (unsigned long)incrbyCommand
}, 
5582 {"decrbyCommand", (unsigned long)decrbyCommand
}, 
5583 {"selectCommand", (unsigned long)selectCommand
}, 
5584 {"randomkeyCommand", (unsigned long)randomkeyCommand
}, 
5585 {"keysCommand", (unsigned long)keysCommand
}, 
5586 {"dbsizeCommand", (unsigned long)dbsizeCommand
}, 
5587 {"lastsaveCommand", (unsigned long)lastsaveCommand
}, 
5588 {"saveCommand", (unsigned long)saveCommand
}, 
5589 {"bgsaveCommand", (unsigned long)bgsaveCommand
}, 
5590 {"shutdownCommand", (unsigned long)shutdownCommand
}, 
5591 {"moveCommand", (unsigned long)moveCommand
}, 
5592 {"renameCommand", (unsigned long)renameCommand
}, 
5593 {"renamenxCommand", (unsigned long)renamenxCommand
}, 
5594 {"lpushCommand", (unsigned long)lpushCommand
}, 
5595 {"rpushCommand", (unsigned long)rpushCommand
}, 
5596 {"lpopCommand", (unsigned long)lpopCommand
}, 
5597 {"rpopCommand", (unsigned long)rpopCommand
}, 
5598 {"llenCommand", (unsigned long)llenCommand
}, 
5599 {"lindexCommand", (unsigned long)lindexCommand
}, 
5600 {"lrangeCommand", (unsigned long)lrangeCommand
}, 
5601 {"ltrimCommand", (unsigned long)ltrimCommand
}, 
5602 {"typeCommand", (unsigned long)typeCommand
}, 
5603 {"lsetCommand", (unsigned long)lsetCommand
}, 
5604 {"saddCommand", (unsigned long)saddCommand
}, 
5605 {"sremCommand", (unsigned long)sremCommand
}, 
5606 {"smoveCommand", (unsigned long)smoveCommand
}, 
5607 {"sismemberCommand", (unsigned long)sismemberCommand
}, 
5608 {"scardCommand", (unsigned long)scardCommand
}, 
5609 {"spopCommand", (unsigned long)spopCommand
}, 
5610 {"srandmemberCommand", (unsigned long)srandmemberCommand
}, 
5611 {"sinterCommand", (unsigned long)sinterCommand
}, 
5612 {"sinterstoreCommand", (unsigned long)sinterstoreCommand
}, 
5613 {"sunionCommand", (unsigned long)sunionCommand
}, 
5614 {"sunionstoreCommand", (unsigned long)sunionstoreCommand
}, 
5615 {"sdiffCommand", (unsigned long)sdiffCommand
}, 
5616 {"sdiffstoreCommand", (unsigned long)sdiffstoreCommand
}, 
5617 {"syncCommand", (unsigned long)syncCommand
}, 
5618 {"flushdbCommand", (unsigned long)flushdbCommand
}, 
5619 {"flushallCommand", (unsigned long)flushallCommand
}, 
5620 {"sortCommand", (unsigned long)sortCommand
}, 
5621 {"lremCommand", (unsigned long)lremCommand
}, 
5622 {"infoCommand", (unsigned long)infoCommand
}, 
5623 {"mgetCommand", (unsigned long)mgetCommand
}, 
5624 {"monitorCommand", (unsigned long)monitorCommand
}, 
5625 {"expireCommand", (unsigned long)expireCommand
}, 
5626 {"expireatCommand", (unsigned long)expireatCommand
}, 
5627 {"getsetCommand", (unsigned long)getsetCommand
}, 
5628 {"ttlCommand", (unsigned long)ttlCommand
}, 
5629 {"slaveofCommand", (unsigned long)slaveofCommand
}, 
5630 {"debugCommand", (unsigned long)debugCommand
}, 
5631 {"processCommand", (unsigned long)processCommand
}, 
5632 {"setupSigSegvAction", (unsigned long)setupSigSegvAction
}, 
5633 {"readQueryFromClient", (unsigned long)readQueryFromClient
}, 
5634 {"rdbRemoveTempFile", (unsigned long)rdbRemoveTempFile
}, 
5635 {"msetGenericCommand", (unsigned long)msetGenericCommand
}, 
5636 {"msetCommand", (unsigned long)msetCommand
}, 
5637 {"msetnxCommand", (unsigned long)msetnxCommand
}, 
5638 {"zslCreateNode", (unsigned long)zslCreateNode
}, 
5639 {"zslCreate", (unsigned long)zslCreate
}, 
5640 {"zslFreeNode",(unsigned long)zslFreeNode
}, 
5641 {"zslFree",(unsigned long)zslFree
}, 
5642 {"zslRandomLevel",(unsigned long)zslRandomLevel
}, 
5643 {"zslInsert",(unsigned long)zslInsert
}, 
5644 {"zslDelete",(unsigned long)zslDelete
}, 
5645 {"createZsetObject",(unsigned long)createZsetObject
}, 
5646 {"zaddCommand",(unsigned long)zaddCommand
}, 
5647 {"zrangeGenericCommand",(unsigned long)zrangeGenericCommand
}, 
5648 {"zrangeCommand",(unsigned long)zrangeCommand
}, 
5649 {"zrevrangeCommand",(unsigned long)zrevrangeCommand
}, 
5650 {"zremCommand",(unsigned long)zremCommand
}, 
5651 {"rdbSaveDoubleValue",(unsigned long)rdbSaveDoubleValue
}, 
5652 {"rdbLoadDoubleValue",(unsigned long)rdbLoadDoubleValue
}, 
5653 {"feedAppendOnlyFile",(unsigned long)feedAppendOnlyFile
}, 
5657 /* This function try to convert a pointer into a function name. It's used in 
5658  * oreder to provide a backtrace under segmentation fault that's able to 
5659  * display functions declared as static (otherwise the backtrace is useless). */ 
5660 static char *findFuncName(void *pointer
, unsigned long *offset
){ 
5662     unsigned long off
, minoff 
= 0; 
5664     /* Try to match against the Symbol with the smallest offset */ 
5665     for (i
=0; symsTable
[i
].pointer
; i
++) { 
5666         unsigned long lp 
= (unsigned long) pointer
; 
5668         if (lp 
!= (unsigned long)-1 && lp 
>= symsTable
[i
].pointer
) { 
5669             off
=lp
-symsTable
[i
].pointer
; 
5670             if (ret 
< 0 || off 
< minoff
) { 
5676     if (ret 
== -1) return NULL
; 
5678     return symsTable
[ret
].name
; 
5681 static void *getMcontextEip(ucontext_t 
*uc
) { 
5682 #if defined(__FreeBSD__) 
5683     return (void*) uc
->uc_mcontext
.mc_eip
; 
5684 #elif defined(__dietlibc__) 
5685     return (void*) uc
->uc_mcontext
.eip
; 
5686 #elif defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6) 
5687     return (void*) uc
->uc_mcontext
->__ss
.__eip
; 
5688 #elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6) 
5689   #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__) 
5690     return (void*) uc
->uc_mcontext
->__ss
.__rip
; 
5692     return (void*) uc
->uc_mcontext
->__ss
.__eip
; 
5694 #elif defined(__i386__) || defined(__X86_64__) /* Linux x86 */ 
5695     return (void*) uc
->uc_mcontext
.gregs
[REG_EIP
]; 
5696 #elif defined(__ia64__) /* Linux IA64 */ 
5697     return (void*) uc
->uc_mcontext
.sc_ip
; 
5703 static void segvHandler(int sig
, siginfo_t 
*info
, void *secret
) { 
5705     char **messages 
= NULL
; 
5706     int i
, trace_size 
= 0; 
5707     unsigned long offset
=0; 
5708     time_t uptime 
= time(NULL
)-server
.stat_starttime
; 
5709     ucontext_t 
*uc 
= (ucontext_t
*) secret
; 
5710     REDIS_NOTUSED(info
); 
5712     redisLog(REDIS_WARNING
, 
5713         "======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION
, sig
); 
5714     redisLog(REDIS_WARNING
, "%s", sdscatprintf(sdsempty(), 
5715         "redis_version:%s; " 
5716         "uptime_in_seconds:%d; " 
5717         "connected_clients:%d; " 
5718         "connected_slaves:%d; " 
5720         "changes_since_last_save:%lld; " 
5721         "bgsave_in_progress:%d; " 
5722         "last_save_time:%d; " 
5723         "total_connections_received:%lld; " 
5724         "total_commands_processed:%lld; " 
5728         listLength(server
.clients
)-listLength(server
.slaves
), 
5729         listLength(server
.slaves
), 
5732         server
.bgsaveinprogress
, 
5734         server
.stat_numconnections
, 
5735         server
.stat_numcommands
, 
5736         server
.masterhost 
== NULL 
? "master" : "slave" 
5739     trace_size 
= backtrace(trace
, 100); 
5740     /* overwrite sigaction with caller's address */ 
5741     if (getMcontextEip(uc
) != NULL
) { 
5742         trace
[1] = getMcontextEip(uc
); 
5744     messages 
= backtrace_symbols(trace
, trace_size
); 
5746     for (i
=1; i
<trace_size
; ++i
) { 
5747         char *fn 
= findFuncName(trace
[i
], &offset
), *p
; 
5749         p 
= strchr(messages
[i
],'+'); 
5750         if (!fn 
|| (p 
&& ((unsigned long)strtol(p
+1,NULL
,10)) < offset
)) { 
5751             redisLog(REDIS_WARNING
,"%s", messages
[i
]); 
5753             redisLog(REDIS_WARNING
,"%d redis-server %p %s + %d", i
, trace
[i
], fn
, (unsigned int)offset
); 
5760 static void setupSigSegvAction(void) { 
5761     struct sigaction act
; 
5763     sigemptyset (&act
.sa_mask
); 
5764     /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction 
5765      * is used. Otherwise, sa_handler is used */ 
5766     act
.sa_flags 
= SA_NODEFER 
| SA_ONSTACK 
| SA_RESETHAND 
| SA_SIGINFO
; 
5767     act
.sa_sigaction 
= segvHandler
; 
5768     sigaction (SIGSEGV
, &act
, NULL
); 
5769     sigaction (SIGBUS
, &act
, NULL
); 
5770     sigaction (SIGFPE
, &act
, NULL
); 
5771     sigaction (SIGILL
, &act
, NULL
); 
5772     sigaction (SIGBUS
, &act
, NULL
); 
5775 #else /* HAVE_BACKTRACE */ 
5776 static void setupSigSegvAction(void) { 
5778 #endif /* HAVE_BACKTRACE */ 
5780 /* =================================== Main! ================================ */ 
5783 int linuxOvercommitMemoryValue(void) { 
5784     FILE *fp 
= fopen("/proc/sys/vm/overcommit_memory","r"); 
5788     if (fgets(buf
,64,fp
) == NULL
) { 
5797 void linuxOvercommitMemoryWarning(void) { 
5798     if (linuxOvercommitMemoryValue() == 0) { 
5799         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."); 
5802 #endif /* __linux__ */ 
5804 static void daemonize(void) { 
5808     if (fork() != 0) exit(0); /* parent exits */ 
5809     setsid(); /* create a new session */ 
5811     /* Every output goes to /dev/null. If Redis is daemonized but 
5812      * the 'logfile' is set to 'stdout' in the configuration file 
5813      * it will not log at all. */ 
5814     if ((fd 
= open("/dev/null", O_RDWR
, 0)) != -1) { 
5815         dup2(fd
, STDIN_FILENO
); 
5816         dup2(fd
, STDOUT_FILENO
); 
5817         dup2(fd
, STDERR_FILENO
); 
5818         if (fd 
> STDERR_FILENO
) close(fd
); 
5820     /* Try to write the pid file */ 
5821     fp 
= fopen(server
.pidfile
,"w"); 
5823         fprintf(fp
,"%d\n",getpid()); 
5828 int main(int argc
, char **argv
) { 
5831         ResetServerSaveParams(); 
5832         loadServerConfig(argv
[1]); 
5833     } else if (argc 
> 2) { 
5834         fprintf(stderr
,"Usage: ./redis-server [/path/to/redis.conf]\n"); 
5837         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'"); 
5840     if (server
.daemonize
) daemonize(); 
5841     redisLog(REDIS_NOTICE
,"Server started, Redis version " REDIS_VERSION
); 
5843     linuxOvercommitMemoryWarning(); 
5845     if (server
.appendonly
) { 
5846         if (loadAppendOnlyFile(server
.appendfilename
) == REDIS_OK
) 
5847             redisLog(REDIS_NOTICE
,"DB loaded from append only file"); 
5849         if (rdbLoad(server
.dbfilename
) == REDIS_OK
) 
5850             redisLog(REDIS_NOTICE
,"DB loaded from disk"); 
5852     if (aeCreateFileEvent(server
.el
, server
.fd
, AE_READABLE
, 
5853         acceptHandler
, NULL
, NULL
) == AE_ERR
) oom("creating file event"); 
5854     redisLog(REDIS_NOTICE
,"The server is now ready to accept connections on port %d", server
.port
); 
5856     aeDeleteEventLoop(server
.el
);