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_DEL 1 
 176 #define REDIS_SORT_INCR 2 
 177 #define REDIS_SORT_DECR 3 
 178 #define REDIS_SORT_ASC 4 
 179 #define REDIS_SORT_DESC 5 
 180 #define REDIS_SORTKEY_MAX 1024 
 183 #define REDIS_DEBUG 0 
 184 #define REDIS_NOTICE 1 
 185 #define REDIS_WARNING 2 
 187 /* Anti-warning macro... */ 
 188 #define REDIS_NOTUSED(V) ((void) V) 
 190 #define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^32 elements */ 
 191 #define ZSKIPLIST_P 0.25      /* Skiplist P = 1/4 */ 
 193 /*================================= Data types ============================== */ 
 195 /* A redis object, that is a type able to hold a string / list / set */ 
 196 typedef struct redisObject 
{ 
 199     unsigned char encoding
; 
 200     unsigned char notused
[2]; 
 204 typedef struct redisDb 
{ 
 210 /* With multiplexing we need to take per-clinet state. 
 211  * Clients are taken in a liked list. */ 
 212 typedef struct redisClient 
{ 
 217     robj 
**argv
, **mbargv
; 
 219     int bulklen
;            /* bulk read len. -1 if not in bulk read mode */ 
 220     int multibulk
;          /* multi bulk command format active */ 
 223     time_t lastinteraction
; /* time of the last interaction, used for timeout */ 
 224     int flags
;              /* REDIS_CLOSE | REDIS_SLAVE | REDIS_MONITOR */ 
 225     int slaveseldb
;         /* slave selected db, if this client is a slave */ 
 226     int authenticated
;      /* when requirepass is non-NULL */ 
 227     int replstate
;          /* replication state if this is a slave */ 
 228     int repldbfd
;           /* replication DB file descriptor */ 
 229     long repldboff
;          /* replication DB file offset */ 
 230     off_t repldbsize
;       /* replication DB file size */ 
 238 /* Global server state structure */ 
 244     unsigned int sharingpoolsize
; 
 245     long long dirty
;            /* changes to DB from the last save */ 
 247     list 
*slaves
, *monitors
; 
 248     char neterr
[ANET_ERR_LEN
]; 
 250     int cronloops
;              /* number of times the cron function run */ 
 251     list 
*objfreelist
;          /* A list of freed objects to avoid malloc() */ 
 252     time_t lastsave
;            /* Unix time of last save succeeede */ 
 253     size_t usedmemory
;             /* Used memory in megabytes */ 
 254     /* Fields used only for stats */ 
 255     time_t stat_starttime
;         /* server start time */ 
 256     long long stat_numcommands
;    /* number of processed commands */ 
 257     long long stat_numconnections
; /* number of connections received */ 
 265     int bgsaveinprogress
; 
 266     pid_t bgsavechildpid
; 
 267     struct saveparam 
*saveparams
; 
 274     /* Replication related */ 
 278     redisClient 
*master
;    /* client that is master for this slave */ 
 280     unsigned int maxclients
; 
 281     unsigned long maxmemory
; 
 282     /* Sort parameters - qsort_r() is only available under BSD so we 
 283      * have to take this state global, in order to pass it to sortCompare() */ 
 289 typedef void redisCommandProc(redisClient 
*c
); 
 290 struct redisCommand 
{ 
 292     redisCommandProc 
*proc
; 
 297 struct redisFunctionSym 
{ 
 299     unsigned long pointer
; 
 302 typedef struct _redisSortObject 
{ 
 310 typedef struct _redisSortOperation 
{ 
 313 } redisSortOperation
; 
 315 /* ZSETs use a specialized version of Skiplists */ 
 317 typedef struct zskiplistNode 
{ 
 318     struct zskiplistNode 
**forward
; 
 319     struct zskiplistNode 
*backward
; 
 324 typedef struct zskiplist 
{ 
 325     struct zskiplistNode 
*header
, *tail
; 
 330 typedef struct zset 
{ 
 335 /* Our shared "common" objects */ 
 337 struct sharedObjectsStruct 
{ 
 338     robj 
*crlf
, *ok
, *err
, *emptybulk
, *czero
, *cone
, *pong
, *space
, 
 339     *colon
, *nullbulk
, *nullmultibulk
, 
 340     *emptymultibulk
, *wrongtypeerr
, *nokeyerr
, *syntaxerr
, *sameobjecterr
, 
 341     *outofrangeerr
, *plus
, 
 342     *select0
, *select1
, *select2
, *select3
, *select4
, 
 343     *select5
, *select6
, *select7
, *select8
, *select9
; 
 346 /* Global vars that are actally used as constants. The following double 
 347  * values are used for double on-disk serialization, and are initialized 
 348  * at runtime to avoid strange compiler optimizations. */ 
 350 static double R_Zero
, R_PosInf
, R_NegInf
, R_Nan
; 
 352 /*================================ Prototypes =============================== */ 
 354 static void freeStringObject(robj 
*o
); 
 355 static void freeListObject(robj 
*o
); 
 356 static void freeSetObject(robj 
*o
); 
 357 static void decrRefCount(void *o
); 
 358 static robj 
*createObject(int type
, void *ptr
); 
 359 static void freeClient(redisClient 
*c
); 
 360 static int rdbLoad(char *filename
); 
 361 static void addReply(redisClient 
*c
, robj 
*obj
); 
 362 static void addReplySds(redisClient 
*c
, sds s
); 
 363 static void incrRefCount(robj 
*o
); 
 364 static int rdbSaveBackground(char *filename
); 
 365 static robj 
*createStringObject(char *ptr
, size_t len
); 
 366 static void replicationFeedSlaves(list 
*slaves
, struct redisCommand 
*cmd
, int dictid
, robj 
**argv
, int argc
); 
 367 static int syncWithMaster(void); 
 368 static robj 
*tryObjectSharing(robj 
*o
); 
 369 static int tryObjectEncoding(robj 
*o
); 
 370 static robj 
*getDecodedObject(const robj 
*o
); 
 371 static int removeExpire(redisDb 
*db
, robj 
*key
); 
 372 static int expireIfNeeded(redisDb 
*db
, robj 
*key
); 
 373 static int deleteIfVolatile(redisDb 
*db
, robj 
*key
); 
 374 static int deleteKey(redisDb 
*db
, robj 
*key
); 
 375 static time_t getExpire(redisDb 
*db
, robj 
*key
); 
 376 static int setExpire(redisDb 
*db
, robj 
*key
, time_t when
); 
 377 static void updateSlavesWaitingBgsave(int bgsaveerr
); 
 378 static void freeMemoryIfNeeded(void); 
 379 static int processCommand(redisClient 
*c
); 
 380 static void setupSigSegvAction(void); 
 381 static void rdbRemoveTempFile(pid_t childpid
); 
 382 static size_t stringObjectLen(robj 
*o
); 
 383 static void processInputBuffer(redisClient 
*c
); 
 384 static zskiplist 
*zslCreate(void); 
 385 static void zslFree(zskiplist 
*zsl
); 
 386 static void zslInsert(zskiplist 
*zsl
, double score
, robj 
*obj
); 
 388 static void authCommand(redisClient 
*c
); 
 389 static void pingCommand(redisClient 
*c
); 
 390 static void echoCommand(redisClient 
*c
); 
 391 static void setCommand(redisClient 
*c
); 
 392 static void setnxCommand(redisClient 
*c
); 
 393 static void getCommand(redisClient 
*c
); 
 394 static void delCommand(redisClient 
*c
); 
 395 static void existsCommand(redisClient 
*c
); 
 396 static void incrCommand(redisClient 
*c
); 
 397 static void decrCommand(redisClient 
*c
); 
 398 static void incrbyCommand(redisClient 
*c
); 
 399 static void decrbyCommand(redisClient 
*c
); 
 400 static void selectCommand(redisClient 
*c
); 
 401 static void randomkeyCommand(redisClient 
*c
); 
 402 static void keysCommand(redisClient 
*c
); 
 403 static void dbsizeCommand(redisClient 
*c
); 
 404 static void lastsaveCommand(redisClient 
*c
); 
 405 static void saveCommand(redisClient 
*c
); 
 406 static void bgsaveCommand(redisClient 
*c
); 
 407 static void shutdownCommand(redisClient 
*c
); 
 408 static void moveCommand(redisClient 
*c
); 
 409 static void renameCommand(redisClient 
*c
); 
 410 static void renamenxCommand(redisClient 
*c
); 
 411 static void lpushCommand(redisClient 
*c
); 
 412 static void rpushCommand(redisClient 
*c
); 
 413 static void lpopCommand(redisClient 
*c
); 
 414 static void rpopCommand(redisClient 
*c
); 
 415 static void llenCommand(redisClient 
*c
); 
 416 static void lindexCommand(redisClient 
*c
); 
 417 static void lrangeCommand(redisClient 
*c
); 
 418 static void ltrimCommand(redisClient 
*c
); 
 419 static void typeCommand(redisClient 
*c
); 
 420 static void lsetCommand(redisClient 
*c
); 
 421 static void saddCommand(redisClient 
*c
); 
 422 static void sremCommand(redisClient 
*c
); 
 423 static void smoveCommand(redisClient 
*c
); 
 424 static void sismemberCommand(redisClient 
*c
); 
 425 static void scardCommand(redisClient 
*c
); 
 426 static void spopCommand(redisClient 
*c
); 
 427 static void srandmemberCommand(redisClient 
*c
); 
 428 static void sinterCommand(redisClient 
*c
); 
 429 static void sinterstoreCommand(redisClient 
*c
); 
 430 static void sunionCommand(redisClient 
*c
); 
 431 static void sunionstoreCommand(redisClient 
*c
); 
 432 static void sdiffCommand(redisClient 
*c
); 
 433 static void sdiffstoreCommand(redisClient 
*c
); 
 434 static void syncCommand(redisClient 
*c
); 
 435 static void flushdbCommand(redisClient 
*c
); 
 436 static void flushallCommand(redisClient 
*c
); 
 437 static void sortCommand(redisClient 
*c
); 
 438 static void lremCommand(redisClient 
*c
); 
 439 static void infoCommand(redisClient 
*c
); 
 440 static void mgetCommand(redisClient 
*c
); 
 441 static void monitorCommand(redisClient 
*c
); 
 442 static void expireCommand(redisClient 
*c
); 
 443 static void getsetCommand(redisClient 
*c
); 
 444 static void ttlCommand(redisClient 
*c
); 
 445 static void slaveofCommand(redisClient 
*c
); 
 446 static void debugCommand(redisClient 
*c
); 
 447 static void msetCommand(redisClient 
*c
); 
 448 static void msetnxCommand(redisClient 
*c
); 
 449 static void zaddCommand(redisClient 
*c
); 
 450 static void zrangeCommand(redisClient 
*c
); 
 451 static void zrangebyscoreCommand(redisClient 
*c
); 
 452 static void zrevrangeCommand(redisClient 
*c
); 
 453 static void zcardCommand(redisClient 
*c
); 
 454 static void zremCommand(redisClient 
*c
); 
 455 static void zscoreCommand(redisClient 
*c
); 
 457 /*================================= Globals ================================= */ 
 460 static struct redisServer server
; /* server global state */ 
 461 static struct redisCommand cmdTable
[] = { 
 462     {"get",getCommand
,2,REDIS_CMD_INLINE
}, 
 463     {"set",setCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 464     {"setnx",setnxCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 465     {"del",delCommand
,-2,REDIS_CMD_INLINE
}, 
 466     {"exists",existsCommand
,2,REDIS_CMD_INLINE
}, 
 467     {"incr",incrCommand
,2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 468     {"decr",decrCommand
,2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 469     {"mget",mgetCommand
,-2,REDIS_CMD_INLINE
}, 
 470     {"rpush",rpushCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 471     {"lpush",lpushCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 472     {"rpop",rpopCommand
,2,REDIS_CMD_INLINE
}, 
 473     {"lpop",lpopCommand
,2,REDIS_CMD_INLINE
}, 
 474     {"llen",llenCommand
,2,REDIS_CMD_INLINE
}, 
 475     {"lindex",lindexCommand
,3,REDIS_CMD_INLINE
}, 
 476     {"lset",lsetCommand
,4,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 477     {"lrange",lrangeCommand
,4,REDIS_CMD_INLINE
}, 
 478     {"ltrim",ltrimCommand
,4,REDIS_CMD_INLINE
}, 
 479     {"lrem",lremCommand
,4,REDIS_CMD_BULK
}, 
 480     {"sadd",saddCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 481     {"srem",sremCommand
,3,REDIS_CMD_BULK
}, 
 482     {"smove",smoveCommand
,4,REDIS_CMD_BULK
}, 
 483     {"sismember",sismemberCommand
,3,REDIS_CMD_BULK
}, 
 484     {"scard",scardCommand
,2,REDIS_CMD_INLINE
}, 
 485     {"spop",spopCommand
,2,REDIS_CMD_INLINE
}, 
 486     {"srandmember",srandmemberCommand
,2,REDIS_CMD_INLINE
}, 
 487     {"sinter",sinterCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 488     {"sinterstore",sinterstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 489     {"sunion",sunionCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 490     {"sunionstore",sunionstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 491     {"sdiff",sdiffCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 492     {"sdiffstore",sdiffstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 493     {"smembers",sinterCommand
,2,REDIS_CMD_INLINE
}, 
 494     {"zadd",zaddCommand
,4,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 495     {"zrem",zremCommand
,3,REDIS_CMD_BULK
}, 
 496     {"zrange",zrangeCommand
,4,REDIS_CMD_INLINE
}, 
 497     {"zrangebyscore",zrangebyscoreCommand
,4,REDIS_CMD_INLINE
}, 
 498     {"zrevrange",zrevrangeCommand
,4,REDIS_CMD_INLINE
}, 
 499     {"zcard",zcardCommand
,2,REDIS_CMD_INLINE
}, 
 500     {"zscore",zscoreCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 501     {"incrby",incrbyCommand
,3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 502     {"decrby",decrbyCommand
,3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 503     {"getset",getsetCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 504     {"mset",msetCommand
,-3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 505     {"msetnx",msetnxCommand
,-3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 506     {"randomkey",randomkeyCommand
,1,REDIS_CMD_INLINE
}, 
 507     {"select",selectCommand
,2,REDIS_CMD_INLINE
}, 
 508     {"move",moveCommand
,3,REDIS_CMD_INLINE
}, 
 509     {"rename",renameCommand
,3,REDIS_CMD_INLINE
}, 
 510     {"renamenx",renamenxCommand
,3,REDIS_CMD_INLINE
}, 
 511     {"expire",expireCommand
,3,REDIS_CMD_INLINE
}, 
 512     {"keys",keysCommand
,2,REDIS_CMD_INLINE
}, 
 513     {"dbsize",dbsizeCommand
,1,REDIS_CMD_INLINE
}, 
 514     {"auth",authCommand
,2,REDIS_CMD_INLINE
}, 
 515     {"ping",pingCommand
,1,REDIS_CMD_INLINE
}, 
 516     {"echo",echoCommand
,2,REDIS_CMD_BULK
}, 
 517     {"save",saveCommand
,1,REDIS_CMD_INLINE
}, 
 518     {"bgsave",bgsaveCommand
,1,REDIS_CMD_INLINE
}, 
 519     {"shutdown",shutdownCommand
,1,REDIS_CMD_INLINE
}, 
 520     {"lastsave",lastsaveCommand
,1,REDIS_CMD_INLINE
}, 
 521     {"type",typeCommand
,2,REDIS_CMD_INLINE
}, 
 522     {"sync",syncCommand
,1,REDIS_CMD_INLINE
}, 
 523     {"flushdb",flushdbCommand
,1,REDIS_CMD_INLINE
}, 
 524     {"flushall",flushallCommand
,1,REDIS_CMD_INLINE
}, 
 525     {"sort",sortCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 526     {"info",infoCommand
,1,REDIS_CMD_INLINE
}, 
 527     {"monitor",monitorCommand
,1,REDIS_CMD_INLINE
}, 
 528     {"ttl",ttlCommand
,2,REDIS_CMD_INLINE
}, 
 529     {"slaveof",slaveofCommand
,3,REDIS_CMD_INLINE
}, 
 530     {"debug",debugCommand
,-2,REDIS_CMD_INLINE
}, 
 533 /*============================ Utility functions ============================ */ 
 535 /* Glob-style pattern matching. */ 
 536 int stringmatchlen(const char *pattern
, int patternLen
, 
 537         const char *string
, int stringLen
, int nocase
) 
 542             while (pattern
[1] == '*') { 
 547                 return 1; /* match */ 
 549                 if (stringmatchlen(pattern
+1, patternLen
-1, 
 550                             string
, stringLen
, nocase
)) 
 551                     return 1; /* match */ 
 555             return 0; /* no match */ 
 559                 return 0; /* no match */ 
 569             not = pattern
[0] == '^'; 
 576                 if (pattern
[0] == '\\') { 
 579                     if (pattern
[0] == string
[0]) 
 581                 } else if (pattern
[0] == ']') { 
 583                 } else if (patternLen 
== 0) { 
 587                 } else if (pattern
[1] == '-' && patternLen 
>= 3) { 
 588                     int start 
= pattern
[0]; 
 589                     int end 
= pattern
[2]; 
 597                         start 
= tolower(start
); 
 603                     if (c 
>= start 
&& c 
<= end
) 
 607                         if (pattern
[0] == string
[0]) 
 610                         if (tolower((int)pattern
[0]) == tolower((int)string
[0])) 
 620                 return 0; /* no match */ 
 626             if (patternLen 
>= 2) { 
 633                 if (pattern
[0] != string
[0]) 
 634                     return 0; /* no match */ 
 636                 if (tolower((int)pattern
[0]) != tolower((int)string
[0])) 
 637                     return 0; /* no match */ 
 645         if (stringLen 
== 0) { 
 646             while(*pattern 
== '*') { 
 653     if (patternLen 
== 0 && stringLen 
== 0) 
 658 static void redisLog(int level
, const char *fmt
, ...) { 
 662     fp 
= (server
.logfile 
== NULL
) ? stdout 
: fopen(server
.logfile
,"a"); 
 666     if (level 
>= server
.verbosity
) { 
 672         strftime(buf
,64,"%d %b %H:%M:%S",gmtime(&now
)); 
 673         fprintf(fp
,"%s %c ",buf
,c
[level
]); 
 674         vfprintf(fp
, fmt
, ap
); 
 680     if (server
.logfile
) fclose(fp
); 
 683 /*====================== Hash table type implementation  ==================== */ 
 685 /* This is an hash table type that uses the SDS dynamic strings libary as 
 686  * keys and radis objects as values (objects can hold SDS strings, 
 689 static void dictVanillaFree(void *privdata
, void *val
) 
 691     DICT_NOTUSED(privdata
); 
 695 static int sdsDictKeyCompare(void *privdata
, const void *key1
, 
 699     DICT_NOTUSED(privdata
); 
 701     l1 
= sdslen((sds
)key1
); 
 702     l2 
= sdslen((sds
)key2
); 
 703     if (l1 
!= l2
) return 0; 
 704     return memcmp(key1
, key2
, l1
) == 0; 
 707 static void dictRedisObjectDestructor(void *privdata
, void *val
) 
 709     DICT_NOTUSED(privdata
); 
 714 static int dictObjKeyCompare(void *privdata
, const void *key1
, 
 717     const robj 
*o1 
= key1
, *o2 
= key2
; 
 718     return sdsDictKeyCompare(privdata
,o1
->ptr
,o2
->ptr
); 
 721 static unsigned int dictObjHash(const void *key
) { 
 723     return dictGenHashFunction(o
->ptr
, sdslen((sds
)o
->ptr
)); 
 726 static int dictEncObjKeyCompare(void *privdata
, const void *key1
, 
 729     const robj 
*o1 
= key1
, *o2 
= key2
; 
 731     if (o1
->encoding 
== REDIS_ENCODING_RAW 
&& 
 732         o2
->encoding 
== REDIS_ENCODING_RAW
) 
 733         return sdsDictKeyCompare(privdata
,o1
->ptr
,o2
->ptr
); 
 738         dec1 
= o1
->encoding 
!= REDIS_ENCODING_RAW 
? 
 739             getDecodedObject(o1
) : (robj
*)o1
; 
 740         dec2 
= o2
->encoding 
!= REDIS_ENCODING_RAW 
? 
 741             getDecodedObject(o2
) : (robj
*)o2
; 
 742         cmp 
= sdsDictKeyCompare(privdata
,dec1
->ptr
,dec2
->ptr
); 
 743         if (dec1 
!= o1
) decrRefCount(dec1
); 
 744         if (dec2 
!= o2
) decrRefCount(dec2
); 
 749 static unsigned int dictEncObjHash(const void *key
) { 
 752     if (o
->encoding 
== REDIS_ENCODING_RAW
) 
 753         return dictGenHashFunction(o
->ptr
, sdslen((sds
)o
->ptr
)); 
 755         robj 
*dec 
= getDecodedObject(o
); 
 756         unsigned int hash 
= dictGenHashFunction(dec
->ptr
, sdslen((sds
)dec
->ptr
)); 
 762 static dictType setDictType 
= { 
 763     dictEncObjHash
,            /* hash function */ 
 766     dictEncObjKeyCompare
,      /* key compare */ 
 767     dictRedisObjectDestructor
, /* key destructor */ 
 768     NULL                       
/* val destructor */ 
 771 static dictType zsetDictType 
= { 
 772     dictEncObjHash
,            /* hash function */ 
 775     dictEncObjKeyCompare
,      /* key compare */ 
 776     dictRedisObjectDestructor
, /* key destructor */ 
 777     dictVanillaFree            
/* val destructor */ 
 780 static dictType hashDictType 
= { 
 781     dictObjHash
,                /* hash function */ 
 784     dictObjKeyCompare
,          /* key compare */ 
 785     dictRedisObjectDestructor
,  /* key destructor */ 
 786     dictRedisObjectDestructor   
/* val destructor */ 
 789 /* ========================= Random utility functions ======================= */ 
 791 /* Redis generally does not try to recover from out of memory conditions 
 792  * when allocating objects or strings, it is not clear if it will be possible 
 793  * to report this condition to the client since the networking layer itself 
 794  * is based on heap allocation for send buffers, so we simply abort. 
 795  * At least the code will be simpler to read... */ 
 796 static void oom(const char *msg
) { 
 797     fprintf(stderr
, "%s: Out of memory\n",msg
); 
 803 /* ====================== Redis server networking stuff ===================== */ 
 804 static void closeTimedoutClients(void) { 
 807     time_t now 
= time(NULL
); 
 809     listRewind(server
.clients
); 
 810     while ((ln 
= listYield(server
.clients
)) != NULL
) { 
 811         c 
= listNodeValue(ln
); 
 812         if (!(c
->flags 
& REDIS_SLAVE
) &&    /* no timeout for slaves */ 
 813             !(c
->flags 
& REDIS_MASTER
) &&   /* no timeout for masters */ 
 814              (now 
- c
->lastinteraction 
> server
.maxidletime
)) { 
 815             redisLog(REDIS_DEBUG
,"Closing idle client"); 
 821 static int htNeedsResize(dict 
*dict
) { 
 822     long long size
, used
; 
 824     size 
= dictSlots(dict
); 
 825     used 
= dictSize(dict
); 
 826     return (size 
&& used 
&& size 
> DICT_HT_INITIAL_SIZE 
&& 
 827             (used
*100/size 
< REDIS_HT_MINFILL
)); 
 830 /* If the percentage of used slots in the HT reaches REDIS_HT_MINFILL 
 831  * we resize the hash table to save memory */ 
 832 static void tryResizeHashTables(void) { 
 835     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 836         if (htNeedsResize(server
.db
[j
].dict
)) { 
 837             redisLog(REDIS_DEBUG
,"The hash table %d is too sparse, resize it...",j
); 
 838             dictResize(server
.db
[j
].dict
); 
 839             redisLog(REDIS_DEBUG
,"Hash table %d resized.",j
); 
 841         if (htNeedsResize(server
.db
[j
].expires
)) 
 842             dictResize(server
.db
[j
].expires
); 
 846 static int serverCron(struct aeEventLoop 
*eventLoop
, long long id
, void *clientData
) { 
 847     int j
, loops 
= server
.cronloops
++; 
 848     REDIS_NOTUSED(eventLoop
); 
 850     REDIS_NOTUSED(clientData
); 
 852     /* Update the global state with the amount of used memory */ 
 853     server
.usedmemory 
= zmalloc_used_memory(); 
 855     /* Show some info about non-empty databases */ 
 856     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 857         long long size
, used
, vkeys
; 
 859         size 
= dictSlots(server
.db
[j
].dict
); 
 860         used 
= dictSize(server
.db
[j
].dict
); 
 861         vkeys 
= dictSize(server
.db
[j
].expires
); 
 862         if (!(loops 
% 5) && (used 
|| vkeys
)) { 
 863             redisLog(REDIS_DEBUG
,"DB %d: %lld keys (%lld volatile) in %lld slots HT.",j
,used
,vkeys
,size
); 
 864             /* dictPrintStats(server.dict); */ 
 868     /* We don't want to resize the hash tables while a bacground saving 
 869      * is in progress: the saving child is created using fork() that is 
 870      * implemented with a copy-on-write semantic in most modern systems, so 
 871      * if we resize the HT while there is the saving child at work actually 
 872      * a lot of memory movements in the parent will cause a lot of pages 
 874     if (!server
.bgsaveinprogress
) tryResizeHashTables(); 
 876     /* Show information about connected clients */ 
 878         redisLog(REDIS_DEBUG
,"%d clients connected (%d slaves), %zu bytes in use, %d shared objects", 
 879             listLength(server
.clients
)-listLength(server
.slaves
), 
 880             listLength(server
.slaves
), 
 882             dictSize(server
.sharingpool
)); 
 885     /* Close connections of timedout clients */ 
 886     if (server
.maxidletime 
&& !(loops 
% 10)) 
 887         closeTimedoutClients(); 
 889     /* Check if a background saving in progress terminated */ 
 890     if (server
.bgsaveinprogress
) { 
 892         if (wait4(-1,&statloc
,WNOHANG
,NULL
)) { 
 893             int exitcode 
= WEXITSTATUS(statloc
); 
 894             int bysignal 
= WIFSIGNALED(statloc
); 
 896             if (!bysignal 
&& exitcode 
== 0) { 
 897                 redisLog(REDIS_NOTICE
, 
 898                     "Background saving terminated with success"); 
 900                 server
.lastsave 
= time(NULL
); 
 901             } else if (!bysignal 
&& exitcode 
!= 0) { 
 902                 redisLog(REDIS_WARNING
, "Background saving error"); 
 904                 redisLog(REDIS_WARNING
, 
 905                     "Background saving terminated by signal"); 
 906                 rdbRemoveTempFile(server
.bgsavechildpid
); 
 908             server
.bgsaveinprogress 
= 0; 
 909             server
.bgsavechildpid 
= -1; 
 910             updateSlavesWaitingBgsave(exitcode 
== 0 ? REDIS_OK 
: REDIS_ERR
); 
 913         /* If there is not a background saving in progress check if 
 914          * we have to save now */ 
 915          time_t now 
= time(NULL
); 
 916          for (j 
= 0; j 
< server
.saveparamslen
; j
++) { 
 917             struct saveparam 
*sp 
= server
.saveparams
+j
; 
 919             if (server
.dirty 
>= sp
->changes 
&& 
 920                 now
-server
.lastsave 
> sp
->seconds
) { 
 921                 redisLog(REDIS_NOTICE
,"%d changes in %d seconds. Saving...", 
 922                     sp
->changes
, sp
->seconds
); 
 923                 rdbSaveBackground(server
.dbfilename
); 
 929     /* Try to expire a few timed out keys */ 
 930     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 931         redisDb 
*db 
= server
.db
+j
; 
 932         int num 
= dictSize(db
->expires
); 
 935             time_t now 
= time(NULL
); 
 937             if (num 
> REDIS_EXPIRELOOKUPS_PER_CRON
) 
 938                 num 
= REDIS_EXPIRELOOKUPS_PER_CRON
; 
 943                 if ((de 
= dictGetRandomKey(db
->expires
)) == NULL
) break; 
 944                 t 
= (time_t) dictGetEntryVal(de
); 
 946                     deleteKey(db
,dictGetEntryKey(de
)); 
 952     /* Check if we should connect to a MASTER */ 
 953     if (server
.replstate 
== REDIS_REPL_CONNECT
) { 
 954         redisLog(REDIS_NOTICE
,"Connecting to MASTER..."); 
 955         if (syncWithMaster() == REDIS_OK
) { 
 956             redisLog(REDIS_NOTICE
,"MASTER <-> SLAVE sync succeeded"); 
 962 static void createSharedObjects(void) { 
 963     shared
.crlf 
= createObject(REDIS_STRING
,sdsnew("\r\n")); 
 964     shared
.ok 
= createObject(REDIS_STRING
,sdsnew("+OK\r\n")); 
 965     shared
.err 
= createObject(REDIS_STRING
,sdsnew("-ERR\r\n")); 
 966     shared
.emptybulk 
= createObject(REDIS_STRING
,sdsnew("$0\r\n\r\n")); 
 967     shared
.czero 
= createObject(REDIS_STRING
,sdsnew(":0\r\n")); 
 968     shared
.cone 
= createObject(REDIS_STRING
,sdsnew(":1\r\n")); 
 969     shared
.nullbulk 
= createObject(REDIS_STRING
,sdsnew("$-1\r\n")); 
 970     shared
.nullmultibulk 
= createObject(REDIS_STRING
,sdsnew("*-1\r\n")); 
 971     shared
.emptymultibulk 
= createObject(REDIS_STRING
,sdsnew("*0\r\n")); 
 973     shared
.pong 
= createObject(REDIS_STRING
,sdsnew("+PONG\r\n")); 
 974     shared
.wrongtypeerr 
= createObject(REDIS_STRING
,sdsnew( 
 975         "-ERR Operation against a key holding the wrong kind of value\r\n")); 
 976     shared
.nokeyerr 
= createObject(REDIS_STRING
,sdsnew( 
 977         "-ERR no such key\r\n")); 
 978     shared
.syntaxerr 
= createObject(REDIS_STRING
,sdsnew( 
 979         "-ERR syntax error\r\n")); 
 980     shared
.sameobjecterr 
= createObject(REDIS_STRING
,sdsnew( 
 981         "-ERR source and destination objects are the same\r\n")); 
 982     shared
.outofrangeerr 
= createObject(REDIS_STRING
,sdsnew( 
 983         "-ERR index out of range\r\n")); 
 984     shared
.space 
= createObject(REDIS_STRING
,sdsnew(" ")); 
 985     shared
.colon 
= createObject(REDIS_STRING
,sdsnew(":")); 
 986     shared
.plus 
= createObject(REDIS_STRING
,sdsnew("+")); 
 987     shared
.select0 
= createStringObject("select 0\r\n",10); 
 988     shared
.select1 
= createStringObject("select 1\r\n",10); 
 989     shared
.select2 
= createStringObject("select 2\r\n",10); 
 990     shared
.select3 
= createStringObject("select 3\r\n",10); 
 991     shared
.select4 
= createStringObject("select 4\r\n",10); 
 992     shared
.select5 
= createStringObject("select 5\r\n",10); 
 993     shared
.select6 
= createStringObject("select 6\r\n",10); 
 994     shared
.select7 
= createStringObject("select 7\r\n",10); 
 995     shared
.select8 
= createStringObject("select 8\r\n",10); 
 996     shared
.select9 
= createStringObject("select 9\r\n",10); 
 999 static void appendServerSaveParams(time_t seconds
, int changes
) { 
1000     server
.saveparams 
= zrealloc(server
.saveparams
,sizeof(struct saveparam
)*(server
.saveparamslen
+1)); 
1001     server
.saveparams
[server
.saveparamslen
].seconds 
= seconds
; 
1002     server
.saveparams
[server
.saveparamslen
].changes 
= changes
; 
1003     server
.saveparamslen
++; 
1006 static void ResetServerSaveParams() { 
1007     zfree(server
.saveparams
); 
1008     server
.saveparams 
= NULL
; 
1009     server
.saveparamslen 
= 0; 
1012 static void initServerConfig() { 
1013     server
.dbnum 
= REDIS_DEFAULT_DBNUM
; 
1014     server
.port 
= REDIS_SERVERPORT
; 
1015     server
.verbosity 
= REDIS_DEBUG
; 
1016     server
.maxidletime 
= REDIS_MAXIDLETIME
; 
1017     server
.saveparams 
= NULL
; 
1018     server
.logfile 
= NULL
; /* NULL = log on standard output */ 
1019     server
.bindaddr 
= NULL
; 
1020     server
.glueoutputbuf 
= 1; 
1021     server
.daemonize 
= 0; 
1022     server
.pidfile 
= "/var/run/redis.pid"; 
1023     server
.dbfilename 
= "dump.rdb"; 
1024     server
.requirepass 
= NULL
; 
1025     server
.shareobjects 
= 0; 
1026     server
.sharingpoolsize 
= 1024; 
1027     server
.maxclients 
= 0; 
1028     server
.maxmemory 
= 0; 
1029     ResetServerSaveParams(); 
1031     appendServerSaveParams(60*60,1);  /* save after 1 hour and 1 change */ 
1032     appendServerSaveParams(300,100);  /* save after 5 minutes and 100 changes */ 
1033     appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */ 
1034     /* Replication related */ 
1036     server
.masterhost 
= NULL
; 
1037     server
.masterport 
= 6379; 
1038     server
.master 
= NULL
; 
1039     server
.replstate 
= REDIS_REPL_NONE
; 
1041     /* Double constants initialization */ 
1043     R_PosInf 
= 1.0/R_Zero
; 
1044     R_NegInf 
= -1.0/R_Zero
; 
1045     R_Nan 
= R_Zero
/R_Zero
; 
1048 static void initServer() { 
1051     signal(SIGHUP
, SIG_IGN
); 
1052     signal(SIGPIPE
, SIG_IGN
); 
1053     setupSigSegvAction(); 
1055     server
.clients 
= listCreate(); 
1056     server
.slaves 
= listCreate(); 
1057     server
.monitors 
= listCreate(); 
1058     server
.objfreelist 
= listCreate(); 
1059     createSharedObjects(); 
1060     server
.el 
= aeCreateEventLoop(); 
1061     server
.db 
= zmalloc(sizeof(redisDb
)*server
.dbnum
); 
1062     server
.sharingpool 
= dictCreate(&setDictType
,NULL
); 
1063     server
.fd 
= anetTcpServer(server
.neterr
, server
.port
, server
.bindaddr
); 
1064     if (server
.fd 
== -1) { 
1065         redisLog(REDIS_WARNING
, "Opening TCP port: %s", server
.neterr
); 
1068     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
1069         server
.db
[j
].dict 
= dictCreate(&hashDictType
,NULL
); 
1070         server
.db
[j
].expires 
= dictCreate(&setDictType
,NULL
); 
1071         server
.db
[j
].id 
= j
; 
1073     server
.cronloops 
= 0; 
1074     server
.bgsaveinprogress 
= 0; 
1075     server
.bgsavechildpid 
= -1; 
1076     server
.lastsave 
= time(NULL
); 
1078     server
.usedmemory 
= 0; 
1079     server
.stat_numcommands 
= 0; 
1080     server
.stat_numconnections 
= 0; 
1081     server
.stat_starttime 
= time(NULL
); 
1082     aeCreateTimeEvent(server
.el
, 1000, serverCron
, NULL
, NULL
); 
1085 /* Empty the whole database */ 
1086 static long long emptyDb() { 
1088     long long removed 
= 0; 
1090     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
1091         removed 
+= dictSize(server
.db
[j
].dict
); 
1092         dictEmpty(server
.db
[j
].dict
); 
1093         dictEmpty(server
.db
[j
].expires
); 
1098 static int yesnotoi(char *s
) { 
1099     if (!strcasecmp(s
,"yes")) return 1; 
1100     else if (!strcasecmp(s
,"no")) return 0; 
1104 /* I agree, this is a very rudimental way to load a configuration... 
1105    will improve later if the config gets more complex */ 
1106 static void loadServerConfig(char *filename
) { 
1108     char buf
[REDIS_CONFIGLINE_MAX
+1], *err 
= NULL
; 
1112     if (filename
[0] == '-' && filename
[1] == '\0') 
1115         if ((fp 
= fopen(filename
,"r")) == NULL
) { 
1116             redisLog(REDIS_WARNING
,"Fatal error, can't open config file"); 
1121     while(fgets(buf
,REDIS_CONFIGLINE_MAX
+1,fp
) != NULL
) { 
1127         line 
= sdstrim(line
," \t\r\n"); 
1129         /* Skip comments and blank lines*/ 
1130         if (line
[0] == '#' || line
[0] == '\0') { 
1135         /* Split into arguments */ 
1136         argv 
= sdssplitlen(line
,sdslen(line
)," ",1,&argc
); 
1137         sdstolower(argv
[0]); 
1139         /* Execute config directives */ 
1140         if (!strcasecmp(argv
[0],"timeout") && argc 
== 2) { 
1141             server
.maxidletime 
= atoi(argv
[1]); 
1142             if (server
.maxidletime 
< 0) { 
1143                 err 
= "Invalid timeout value"; goto loaderr
; 
1145         } else if (!strcasecmp(argv
[0],"port") && argc 
== 2) { 
1146             server
.port 
= atoi(argv
[1]); 
1147             if (server
.port 
< 1 || server
.port 
> 65535) { 
1148                 err 
= "Invalid port"; goto loaderr
; 
1150         } else if (!strcasecmp(argv
[0],"bind") && argc 
== 2) { 
1151             server
.bindaddr 
= zstrdup(argv
[1]); 
1152         } else if (!strcasecmp(argv
[0],"save") && argc 
== 3) { 
1153             int seconds 
= atoi(argv
[1]); 
1154             int changes 
= atoi(argv
[2]); 
1155             if (seconds 
< 1 || changes 
< 0) { 
1156                 err 
= "Invalid save parameters"; goto loaderr
; 
1158             appendServerSaveParams(seconds
,changes
); 
1159         } else if (!strcasecmp(argv
[0],"dir") && argc 
== 2) { 
1160             if (chdir(argv
[1]) == -1) { 
1161                 redisLog(REDIS_WARNING
,"Can't chdir to '%s': %s", 
1162                     argv
[1], strerror(errno
)); 
1165         } else if (!strcasecmp(argv
[0],"loglevel") && argc 
== 2) { 
1166             if (!strcasecmp(argv
[1],"debug")) server
.verbosity 
= REDIS_DEBUG
; 
1167             else if (!strcasecmp(argv
[1],"notice")) server
.verbosity 
= REDIS_NOTICE
; 
1168             else if (!strcasecmp(argv
[1],"warning")) server
.verbosity 
= REDIS_WARNING
; 
1170                 err 
= "Invalid log level. Must be one of debug, notice, warning"; 
1173         } else if (!strcasecmp(argv
[0],"logfile") && argc 
== 2) { 
1176             server
.logfile 
= zstrdup(argv
[1]); 
1177             if (!strcasecmp(server
.logfile
,"stdout")) { 
1178                 zfree(server
.logfile
); 
1179                 server
.logfile 
= NULL
; 
1181             if (server
.logfile
) { 
1182                 /* Test if we are able to open the file. The server will not 
1183                  * be able to abort just for this problem later... */ 
1184                 logfp 
= fopen(server
.logfile
,"a"); 
1185                 if (logfp 
== NULL
) { 
1186                     err 
= sdscatprintf(sdsempty(), 
1187                         "Can't open the log file: %s", strerror(errno
)); 
1192         } else if (!strcasecmp(argv
[0],"databases") && argc 
== 2) { 
1193             server
.dbnum 
= atoi(argv
[1]); 
1194             if (server
.dbnum 
< 1) { 
1195                 err 
= "Invalid number of databases"; goto loaderr
; 
1197         } else if (!strcasecmp(argv
[0],"maxclients") && argc 
== 2) { 
1198             server
.maxclients 
= atoi(argv
[1]); 
1199         } else if (!strcasecmp(argv
[0],"maxmemory") && argc 
== 2) { 
1200             server
.maxmemory 
= strtoll(argv
[1], NULL
, 10); 
1201         } else if (!strcasecmp(argv
[0],"slaveof") && argc 
== 3) { 
1202             server
.masterhost 
= sdsnew(argv
[1]); 
1203             server
.masterport 
= atoi(argv
[2]); 
1204             server
.replstate 
= REDIS_REPL_CONNECT
; 
1205         } else if (!strcasecmp(argv
[0],"glueoutputbuf") && argc 
== 2) { 
1206             if ((server
.glueoutputbuf 
= yesnotoi(argv
[1])) == -1) { 
1207                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1209         } else if (!strcasecmp(argv
[0],"shareobjects") && argc 
== 2) { 
1210             if ((server
.shareobjects 
= yesnotoi(argv
[1])) == -1) { 
1211                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1213         } else if (!strcasecmp(argv
[0],"shareobjectspoolsize") && argc 
== 2) { 
1214             server
.sharingpoolsize 
= atoi(argv
[1]); 
1215             if (server
.sharingpoolsize 
< 1) { 
1216                 err 
= "invalid object sharing pool size"; goto loaderr
; 
1218         } else if (!strcasecmp(argv
[0],"daemonize") && argc 
== 2) { 
1219             if ((server
.daemonize 
= yesnotoi(argv
[1])) == -1) { 
1220                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1222         } else if (!strcasecmp(argv
[0],"requirepass") && argc 
== 2) { 
1223           server
.requirepass 
= zstrdup(argv
[1]); 
1224         } else if (!strcasecmp(argv
[0],"pidfile") && argc 
== 2) { 
1225           server
.pidfile 
= zstrdup(argv
[1]); 
1226         } else if (!strcasecmp(argv
[0],"dbfilename") && argc 
== 2) { 
1227           server
.dbfilename 
= zstrdup(argv
[1]); 
1229             err 
= "Bad directive or wrong number of arguments"; goto loaderr
; 
1231         for (j 
= 0; j 
< argc
; j
++) 
1236     if (fp 
!= stdin
) fclose(fp
); 
1240     fprintf(stderr
, "\n*** FATAL CONFIG FILE ERROR ***\n"); 
1241     fprintf(stderr
, "Reading the configuration file, at line %d\n", linenum
); 
1242     fprintf(stderr
, ">>> '%s'\n", line
); 
1243     fprintf(stderr
, "%s\n", err
); 
1247 static void freeClientArgv(redisClient 
*c
) { 
1250     for (j 
= 0; j 
< c
->argc
; j
++) 
1251         decrRefCount(c
->argv
[j
]); 
1252     for (j 
= 0; j 
< c
->mbargc
; j
++) 
1253         decrRefCount(c
->mbargv
[j
]); 
1258 static void freeClient(redisClient 
*c
) { 
1261     aeDeleteFileEvent(server
.el
,c
->fd
,AE_READABLE
); 
1262     aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
1263     sdsfree(c
->querybuf
); 
1264     listRelease(c
->reply
); 
1267     ln 
= listSearchKey(server
.clients
,c
); 
1269     listDelNode(server
.clients
,ln
); 
1270     if (c
->flags 
& REDIS_SLAVE
) { 
1271         if (c
->replstate 
== REDIS_REPL_SEND_BULK 
&& c
->repldbfd 
!= -1) 
1273         list 
*l 
= (c
->flags 
& REDIS_MONITOR
) ? server
.monitors 
: server
.slaves
; 
1274         ln 
= listSearchKey(l
,c
); 
1278     if (c
->flags 
& REDIS_MASTER
) { 
1279         server
.master 
= NULL
; 
1280         server
.replstate 
= REDIS_REPL_CONNECT
; 
1287 static void glueReplyBuffersIfNeeded(redisClient 
*c
) { 
1292     listRewind(c
->reply
); 
1293     while((ln 
= listYield(c
->reply
))) { 
1295         totlen 
+= sdslen(o
->ptr
); 
1296         /* This optimization makes more sense if we don't have to copy 
1298         if (totlen 
> 1024) return; 
1304         listRewind(c
->reply
); 
1305         while((ln 
= listYield(c
->reply
))) { 
1307             memcpy(buf
+copylen
,o
->ptr
,sdslen(o
->ptr
)); 
1308             copylen 
+= sdslen(o
->ptr
); 
1309             listDelNode(c
->reply
,ln
); 
1311         /* Now the output buffer is empty, add the new single element */ 
1312         o 
= createObject(REDIS_STRING
,sdsnewlen(buf
,totlen
)); 
1313         listAddNodeTail(c
->reply
,o
); 
1317 static void sendReplyToClient(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1318     redisClient 
*c 
= privdata
; 
1319     int nwritten 
= 0, totwritten 
= 0, objlen
; 
1322     REDIS_NOTUSED(mask
); 
1324     if (server
.glueoutputbuf 
&& listLength(c
->reply
) > 1) 
1325         glueReplyBuffersIfNeeded(c
); 
1326     while(listLength(c
->reply
)) { 
1327         o 
= listNodeValue(listFirst(c
->reply
)); 
1328         objlen 
= sdslen(o
->ptr
); 
1331             listDelNode(c
->reply
,listFirst(c
->reply
)); 
1335         if (c
->flags 
& REDIS_MASTER
) { 
1336             /* Don't reply to a master */ 
1337             nwritten 
= objlen 
- c
->sentlen
; 
1339             nwritten 
= write(fd
, ((char*)o
->ptr
)+c
->sentlen
, objlen 
- c
->sentlen
); 
1340             if (nwritten 
<= 0) break; 
1342         c
->sentlen 
+= nwritten
; 
1343         totwritten 
+= nwritten
; 
1344         /* If we fully sent the object on head go to the next one */ 
1345         if (c
->sentlen 
== objlen
) { 
1346             listDelNode(c
->reply
,listFirst(c
->reply
)); 
1349         /* Note that we avoid to send more thank REDIS_MAX_WRITE_PER_EVENT 
1350          * bytes, in a single threaded server it's a good idea to server 
1351          * other clients as well, even if a very large request comes from 
1352          * super fast link that is always able to accept data (in real world 
1353          * terms think to 'KEYS *' against the loopback interfae) */ 
1354         if (totwritten 
> REDIS_MAX_WRITE_PER_EVENT
) break; 
1356     if (nwritten 
== -1) { 
1357         if (errno 
== EAGAIN
) { 
1360             redisLog(REDIS_DEBUG
, 
1361                 "Error writing to client: %s", strerror(errno
)); 
1366     if (totwritten 
> 0) c
->lastinteraction 
= time(NULL
); 
1367     if (listLength(c
->reply
) == 0) { 
1369         aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
1373 static struct redisCommand 
*lookupCommand(char *name
) { 
1375     while(cmdTable
[j
].name 
!= NULL
) { 
1376         if (!strcasecmp(name
,cmdTable
[j
].name
)) return &cmdTable
[j
]; 
1382 /* resetClient prepare the client to process the next command */ 
1383 static void resetClient(redisClient 
*c
) { 
1389 /* If this function gets called we already read a whole 
1390  * command, argments are in the client argv/argc fields. 
1391  * processCommand() execute the command or prepare the 
1392  * server for a bulk read from the client. 
1394  * If 1 is returned the client is still alive and valid and 
1395  * and other operations can be performed by the caller. Otherwise 
1396  * if 0 is returned the client was destroied (i.e. after QUIT). */ 
1397 static int processCommand(redisClient 
*c
) { 
1398     struct redisCommand 
*cmd
; 
1401     /* Free some memory if needed (maxmemory setting) */ 
1402     if (server
.maxmemory
) freeMemoryIfNeeded(); 
1404     /* Handle the multi bulk command type. This is an alternative protocol 
1405      * supported by Redis in order to receive commands that are composed of 
1406      * multiple binary-safe "bulk" arguments. The latency of processing is 
1407      * a bit higher but this allows things like multi-sets, so if this 
1408      * protocol is used only for MSET and similar commands this is a big win. */ 
1409     if (c
->multibulk 
== 0 && c
->argc 
== 1 && ((char*)(c
->argv
[0]->ptr
))[0] == '*') { 
1410         c
->multibulk 
= atoi(((char*)c
->argv
[0]->ptr
)+1); 
1411         if (c
->multibulk 
<= 0) { 
1415             decrRefCount(c
->argv
[c
->argc
-1]); 
1419     } else if (c
->multibulk
) { 
1420         if (c
->bulklen 
== -1) { 
1421             if (((char*)c
->argv
[0]->ptr
)[0] != '$') { 
1422                 addReplySds(c
,sdsnew("-ERR multi bulk protocol error\r\n")); 
1426                 int bulklen 
= atoi(((char*)c
->argv
[0]->ptr
)+1); 
1427                 decrRefCount(c
->argv
[0]); 
1428                 if (bulklen 
< 0 || bulklen 
> 1024*1024*1024) { 
1430                     addReplySds(c
,sdsnew("-ERR invalid bulk write count\r\n")); 
1435                 c
->bulklen 
= bulklen
+2; /* add two bytes for CR+LF */ 
1439             c
->mbargv 
= zrealloc(c
->mbargv
,(sizeof(robj
*))*(c
->mbargc
+1)); 
1440             c
->mbargv
[c
->mbargc
] = c
->argv
[0]; 
1444             if (c
->multibulk 
== 0) { 
1448                 /* Here we need to swap the multi-bulk argc/argv with the 
1449                  * normal argc/argv of the client structure. */ 
1451                 c
->argv 
= c
->mbargv
; 
1452                 c
->mbargv 
= auxargv
; 
1455                 c
->argc 
= c
->mbargc
; 
1456                 c
->mbargc 
= auxargc
; 
1458                 /* We need to set bulklen to something different than -1 
1459                  * in order for the code below to process the command without 
1460                  * to try to read the last argument of a bulk command as 
1461                  * a special argument. */ 
1463                 /* continue below and process the command */ 
1470     /* -- end of multi bulk commands processing -- */ 
1472     /* The QUIT command is handled as a special case. Normal command 
1473      * procs are unable to close the client connection safely */ 
1474     if (!strcasecmp(c
->argv
[0]->ptr
,"quit")) { 
1478     cmd 
= lookupCommand(c
->argv
[0]->ptr
); 
1480         addReplySds(c
,sdsnew("-ERR unknown command\r\n")); 
1483     } else if ((cmd
->arity 
> 0 && cmd
->arity 
!= c
->argc
) || 
1484                (c
->argc 
< -cmd
->arity
)) { 
1485         addReplySds(c
,sdsnew("-ERR wrong number of arguments\r\n")); 
1488     } else if (server
.maxmemory 
&& cmd
->flags 
& REDIS_CMD_DENYOOM 
&& zmalloc_used_memory() > server
.maxmemory
) { 
1489         addReplySds(c
,sdsnew("-ERR command not allowed when used memory > 'maxmemory'\r\n")); 
1492     } else if (cmd
->flags 
& REDIS_CMD_BULK 
&& c
->bulklen 
== -1) { 
1493         int bulklen 
= atoi(c
->argv
[c
->argc
-1]->ptr
); 
1495         decrRefCount(c
->argv
[c
->argc
-1]); 
1496         if (bulklen 
< 0 || bulklen 
> 1024*1024*1024) { 
1498             addReplySds(c
,sdsnew("-ERR invalid bulk write count\r\n")); 
1503         c
->bulklen 
= bulklen
+2; /* add two bytes for CR+LF */ 
1504         /* It is possible that the bulk read is already in the 
1505          * buffer. Check this condition and handle it accordingly. 
1506          * This is just a fast path, alternative to call processInputBuffer(). 
1507          * It's a good idea since the code is small and this condition 
1508          * happens most of the times. */ 
1509         if ((signed)sdslen(c
->querybuf
) >= c
->bulklen
) { 
1510             c
->argv
[c
->argc
] = createStringObject(c
->querybuf
,c
->bulklen
-2); 
1512             c
->querybuf 
= sdsrange(c
->querybuf
,c
->bulklen
,-1); 
1517     /* Let's try to share objects on the command arguments vector */ 
1518     if (server
.shareobjects
) { 
1520         for(j 
= 1; j 
< c
->argc
; j
++) 
1521             c
->argv
[j
] = tryObjectSharing(c
->argv
[j
]); 
1523     /* Let's try to encode the bulk object to save space. */ 
1524     if (cmd
->flags 
& REDIS_CMD_BULK
) 
1525         tryObjectEncoding(c
->argv
[c
->argc
-1]); 
1527     /* Check if the user is authenticated */ 
1528     if (server
.requirepass 
&& !c
->authenticated 
&& cmd
->proc 
!= authCommand
) { 
1529         addReplySds(c
,sdsnew("-ERR operation not permitted\r\n")); 
1534     /* Exec the command */ 
1535     dirty 
= server
.dirty
; 
1537     if (server
.dirty
-dirty 
!= 0 && listLength(server
.slaves
)) 
1538         replicationFeedSlaves(server
.slaves
,cmd
,c
->db
->id
,c
->argv
,c
->argc
); 
1539     if (listLength(server
.monitors
)) 
1540         replicationFeedSlaves(server
.monitors
,cmd
,c
->db
->id
,c
->argv
,c
->argc
); 
1541     server
.stat_numcommands
++; 
1543     /* Prepare the client for the next command */ 
1544     if (c
->flags 
& REDIS_CLOSE
) { 
1552 static void replicationFeedSlaves(list 
*slaves
, struct redisCommand 
*cmd
, int dictid
, robj 
**argv
, int argc
) { 
1556     /* (args*2)+1 is enough room for args, spaces, newlines */ 
1557     robj 
*static_outv
[REDIS_STATIC_ARGS
*2+1]; 
1559     if (argc 
<= REDIS_STATIC_ARGS
) { 
1562         outv 
= zmalloc(sizeof(robj
*)*(argc
*2+1)); 
1565     for (j 
= 0; j 
< argc
; j
++) { 
1566         if (j 
!= 0) outv
[outc
++] = shared
.space
; 
1567         if ((cmd
->flags 
& REDIS_CMD_BULK
) && j 
== argc
-1) { 
1570             lenobj 
= createObject(REDIS_STRING
, 
1571                 sdscatprintf(sdsempty(),"%d\r\n", 
1572                     stringObjectLen(argv
[j
]))); 
1573             lenobj
->refcount 
= 0; 
1574             outv
[outc
++] = lenobj
; 
1576         outv
[outc
++] = argv
[j
]; 
1578     outv
[outc
++] = shared
.crlf
; 
1580     /* Increment all the refcounts at start and decrement at end in order to 
1581      * be sure to free objects if there is no slave in a replication state 
1582      * able to be feed with commands */ 
1583     for (j 
= 0; j 
< outc
; j
++) incrRefCount(outv
[j
]); 
1585     while((ln 
= listYield(slaves
))) { 
1586         redisClient 
*slave 
= ln
->value
; 
1588         /* Don't feed slaves that are still waiting for BGSAVE to start */ 
1589         if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) continue; 
1591         /* Feed all the other slaves, MONITORs and so on */ 
1592         if (slave
->slaveseldb 
!= dictid
) { 
1596             case 0: selectcmd 
= shared
.select0
; break; 
1597             case 1: selectcmd 
= shared
.select1
; break; 
1598             case 2: selectcmd 
= shared
.select2
; break; 
1599             case 3: selectcmd 
= shared
.select3
; break; 
1600             case 4: selectcmd 
= shared
.select4
; break; 
1601             case 5: selectcmd 
= shared
.select5
; break; 
1602             case 6: selectcmd 
= shared
.select6
; break; 
1603             case 7: selectcmd 
= shared
.select7
; break; 
1604             case 8: selectcmd 
= shared
.select8
; break; 
1605             case 9: selectcmd 
= shared
.select9
; break; 
1607                 selectcmd 
= createObject(REDIS_STRING
, 
1608                     sdscatprintf(sdsempty(),"select %d\r\n",dictid
)); 
1609                 selectcmd
->refcount 
= 0; 
1612             addReply(slave
,selectcmd
); 
1613             slave
->slaveseldb 
= dictid
; 
1615         for (j 
= 0; j 
< outc
; j
++) addReply(slave
,outv
[j
]); 
1617     for (j 
= 0; j 
< outc
; j
++) decrRefCount(outv
[j
]); 
1618     if (outv 
!= static_outv
) zfree(outv
); 
1621 static void processInputBuffer(redisClient 
*c
) { 
1623     if (c
->bulklen 
== -1) { 
1624         /* Read the first line of the query */ 
1625         char *p 
= strchr(c
->querybuf
,'\n'); 
1632             query 
= c
->querybuf
; 
1633             c
->querybuf 
= sdsempty(); 
1634             querylen 
= 1+(p
-(query
)); 
1635             if (sdslen(query
) > querylen
) { 
1636                 /* leave data after the first line of the query in the buffer */ 
1637                 c
->querybuf 
= sdscatlen(c
->querybuf
,query
+querylen
,sdslen(query
)-querylen
); 
1639             *p 
= '\0'; /* remove "\n" */ 
1640             if (*(p
-1) == '\r') *(p
-1) = '\0'; /* and "\r" if any */ 
1641             sdsupdatelen(query
); 
1643             /* Now we can split the query in arguments */ 
1644             if (sdslen(query
) == 0) { 
1645                 /* Ignore empty query */ 
1649             argv 
= sdssplitlen(query
,sdslen(query
)," ",1,&argc
); 
1652             if (c
->argv
) zfree(c
->argv
); 
1653             c
->argv 
= zmalloc(sizeof(robj
*)*argc
); 
1655             for (j 
= 0; j 
< argc
; j
++) { 
1656                 if (sdslen(argv
[j
])) { 
1657                     c
->argv
[c
->argc
] = createObject(REDIS_STRING
,argv
[j
]); 
1664             /* Execute the command. If the client is still valid 
1665              * after processCommand() return and there is something 
1666              * on the query buffer try to process the next command. */ 
1667             if (c
->argc 
&& processCommand(c
) && sdslen(c
->querybuf
)) goto again
; 
1669         } else if (sdslen(c
->querybuf
) >= REDIS_REQUEST_MAX_SIZE
) { 
1670             redisLog(REDIS_DEBUG
, "Client protocol error"); 
1675         /* Bulk read handling. Note that if we are at this point 
1676            the client already sent a command terminated with a newline, 
1677            we are reading the bulk data that is actually the last 
1678            argument of the command. */ 
1679         int qbl 
= sdslen(c
->querybuf
); 
1681         if (c
->bulklen 
<= qbl
) { 
1682             /* Copy everything but the final CRLF as final argument */ 
1683             c
->argv
[c
->argc
] = createStringObject(c
->querybuf
,c
->bulklen
-2); 
1685             c
->querybuf 
= sdsrange(c
->querybuf
,c
->bulklen
,-1); 
1686             /* Process the command. If the client is still valid after 
1687              * the processing and there is more data in the buffer 
1688              * try to parse it. */ 
1689             if (processCommand(c
) && sdslen(c
->querybuf
)) goto again
; 
1695 static void readQueryFromClient(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1696     redisClient 
*c 
= (redisClient
*) privdata
; 
1697     char buf
[REDIS_IOBUF_LEN
]; 
1700     REDIS_NOTUSED(mask
); 
1702     nread 
= read(fd
, buf
, REDIS_IOBUF_LEN
); 
1704         if (errno 
== EAGAIN
) { 
1707             redisLog(REDIS_DEBUG
, "Reading from client: %s",strerror(errno
)); 
1711     } else if (nread 
== 0) { 
1712         redisLog(REDIS_DEBUG
, "Client closed connection"); 
1717         c
->querybuf 
= sdscatlen(c
->querybuf
, buf
, nread
); 
1718         c
->lastinteraction 
= time(NULL
); 
1722     processInputBuffer(c
); 
1725 static int selectDb(redisClient 
*c
, int id
) { 
1726     if (id 
< 0 || id 
>= server
.dbnum
) 
1728     c
->db 
= &server
.db
[id
]; 
1732 static void *dupClientReplyValue(void *o
) { 
1733     incrRefCount((robj
*)o
); 
1737 static redisClient 
*createClient(int fd
) { 
1738     redisClient 
*c 
= zmalloc(sizeof(*c
)); 
1740     anetNonBlock(NULL
,fd
); 
1741     anetTcpNoDelay(NULL
,fd
); 
1742     if (!c
) return NULL
; 
1745     c
->querybuf 
= sdsempty(); 
1754     c
->lastinteraction 
= time(NULL
); 
1755     c
->authenticated 
= 0; 
1756     c
->replstate 
= REDIS_REPL_NONE
; 
1757     c
->reply 
= listCreate(); 
1758     listSetFreeMethod(c
->reply
,decrRefCount
); 
1759     listSetDupMethod(c
->reply
,dupClientReplyValue
); 
1760     if (aeCreateFileEvent(server
.el
, c
->fd
, AE_READABLE
, 
1761         readQueryFromClient
, c
, NULL
) == AE_ERR
) { 
1765     listAddNodeTail(server
.clients
,c
); 
1769 static void addReply(redisClient 
*c
, robj 
*obj
) { 
1770     if (listLength(c
->reply
) == 0 && 
1771         (c
->replstate 
== REDIS_REPL_NONE 
|| 
1772          c
->replstate 
== REDIS_REPL_ONLINE
) && 
1773         aeCreateFileEvent(server
.el
, c
->fd
, AE_WRITABLE
, 
1774         sendReplyToClient
, c
, NULL
) == AE_ERR
) return; 
1775     if (obj
->encoding 
!= REDIS_ENCODING_RAW
) { 
1776         obj 
= getDecodedObject(obj
); 
1780     listAddNodeTail(c
->reply
,obj
); 
1783 static void addReplySds(redisClient 
*c
, sds s
) { 
1784     robj 
*o 
= createObject(REDIS_STRING
,s
); 
1789 static void addReplyBulkLen(redisClient 
*c
, robj 
*obj
) { 
1792     if (obj
->encoding 
== REDIS_ENCODING_RAW
) { 
1793         len 
= sdslen(obj
->ptr
); 
1795         long n 
= (long)obj
->ptr
; 
1802         while((n 
= n
/10) != 0) { 
1806     addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",len
)); 
1809 static void acceptHandler(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1814     REDIS_NOTUSED(mask
); 
1815     REDIS_NOTUSED(privdata
); 
1817     cfd 
= anetAccept(server
.neterr
, fd
, cip
, &cport
); 
1818     if (cfd 
== AE_ERR
) { 
1819         redisLog(REDIS_DEBUG
,"Accepting client connection: %s", server
.neterr
); 
1822     redisLog(REDIS_DEBUG
,"Accepted %s:%d", cip
, cport
); 
1823     if ((c 
= createClient(cfd
)) == NULL
) { 
1824         redisLog(REDIS_WARNING
,"Error allocating resoures for the client"); 
1825         close(cfd
); /* May be already closed, just ingore errors */ 
1828     /* If maxclient directive is set and this is one client more... close the 
1829      * connection. Note that we create the client instead to check before 
1830      * for this condition, since now the socket is already set in nonblocking 
1831      * mode and we can send an error for free using the Kernel I/O */ 
1832     if (server
.maxclients 
&& listLength(server
.clients
) > server
.maxclients
) { 
1833         char *err 
= "-ERR max number of clients reached\r\n"; 
1835         /* That's a best effort error message, don't check write errors */ 
1836         (void) write(c
->fd
,err
,strlen(err
)); 
1840     server
.stat_numconnections
++; 
1843 /* ======================= Redis objects implementation ===================== */ 
1845 static robj 
*createObject(int type
, void *ptr
) { 
1848     if (listLength(server
.objfreelist
)) { 
1849         listNode 
*head 
= listFirst(server
.objfreelist
); 
1850         o 
= listNodeValue(head
); 
1851         listDelNode(server
.objfreelist
,head
); 
1853         o 
= zmalloc(sizeof(*o
)); 
1856     o
->encoding 
= REDIS_ENCODING_RAW
; 
1862 static robj 
*createStringObject(char *ptr
, size_t len
) { 
1863     return createObject(REDIS_STRING
,sdsnewlen(ptr
,len
)); 
1866 static robj 
*createListObject(void) { 
1867     list 
*l 
= listCreate(); 
1869     listSetFreeMethod(l
,decrRefCount
); 
1870     return createObject(REDIS_LIST
,l
); 
1873 static robj 
*createSetObject(void) { 
1874     dict 
*d 
= dictCreate(&setDictType
,NULL
); 
1875     return createObject(REDIS_SET
,d
); 
1878 static robj 
*createZsetObject(void) { 
1879     zset 
*zs 
= zmalloc(sizeof(*zs
)); 
1881     zs
->dict 
= dictCreate(&zsetDictType
,NULL
); 
1882     zs
->zsl 
= zslCreate(); 
1883     return createObject(REDIS_ZSET
,zs
); 
1886 static void freeStringObject(robj 
*o
) { 
1887     if (o
->encoding 
== REDIS_ENCODING_RAW
) { 
1892 static void freeListObject(robj 
*o
) { 
1893     listRelease((list
*) o
->ptr
); 
1896 static void freeSetObject(robj 
*o
) { 
1897     dictRelease((dict
*) o
->ptr
); 
1900 static void freeZsetObject(robj 
*o
) { 
1903     dictRelease(zs
->dict
); 
1908 static void freeHashObject(robj 
*o
) { 
1909     dictRelease((dict
*) o
->ptr
); 
1912 static void incrRefCount(robj 
*o
) { 
1914 #ifdef DEBUG_REFCOUNT 
1915     if (o
->type 
== REDIS_STRING
) 
1916         printf("Increment '%s'(%p), now is: %d\n",o
->ptr
,o
,o
->refcount
); 
1920 static void decrRefCount(void *obj
) { 
1923 #ifdef DEBUG_REFCOUNT 
1924     if (o
->type 
== REDIS_STRING
) 
1925         printf("Decrement '%s'(%p), now is: %d\n",o
->ptr
,o
,o
->refcount
-1); 
1927     if (--(o
->refcount
) == 0) { 
1929         case REDIS_STRING
: freeStringObject(o
); break; 
1930         case REDIS_LIST
: freeListObject(o
); break; 
1931         case REDIS_SET
: freeSetObject(o
); break; 
1932         case REDIS_ZSET
: freeZsetObject(o
); break; 
1933         case REDIS_HASH
: freeHashObject(o
); break; 
1934         default: assert(0 != 0); break; 
1936         if (listLength(server
.objfreelist
) > REDIS_OBJFREELIST_MAX 
|| 
1937             !listAddNodeHead(server
.objfreelist
,o
)) 
1942 static robj 
*lookupKey(redisDb 
*db
, robj 
*key
) { 
1943     dictEntry 
*de 
= dictFind(db
->dict
,key
); 
1944     return de 
? dictGetEntryVal(de
) : NULL
; 
1947 static robj 
*lookupKeyRead(redisDb 
*db
, robj 
*key
) { 
1948     expireIfNeeded(db
,key
); 
1949     return lookupKey(db
,key
); 
1952 static robj 
*lookupKeyWrite(redisDb 
*db
, robj 
*key
) { 
1953     deleteIfVolatile(db
,key
); 
1954     return lookupKey(db
,key
); 
1957 static int deleteKey(redisDb 
*db
, robj 
*key
) { 
1960     /* We need to protect key from destruction: after the first dictDelete() 
1961      * it may happen that 'key' is no longer valid if we don't increment 
1962      * it's count. This may happen when we get the object reference directly 
1963      * from the hash table with dictRandomKey() or dict iterators */ 
1965     if (dictSize(db
->expires
)) dictDelete(db
->expires
,key
); 
1966     retval 
= dictDelete(db
->dict
,key
); 
1969     return retval 
== DICT_OK
; 
1972 /* Try to share an object against the shared objects pool */ 
1973 static robj 
*tryObjectSharing(robj 
*o
) { 
1974     struct dictEntry 
*de
; 
1977     if (o 
== NULL 
|| server
.shareobjects 
== 0) return o
; 
1979     assert(o
->type 
== REDIS_STRING
); 
1980     de 
= dictFind(server
.sharingpool
,o
); 
1982         robj 
*shared 
= dictGetEntryKey(de
); 
1984         c 
= ((unsigned long) dictGetEntryVal(de
))+1; 
1985         dictGetEntryVal(de
) = (void*) c
; 
1986         incrRefCount(shared
); 
1990         /* Here we are using a stream algorihtm: Every time an object is 
1991          * shared we increment its count, everytime there is a miss we 
1992          * recrement the counter of a random object. If this object reaches 
1993          * zero we remove the object and put the current object instead. */ 
1994         if (dictSize(server
.sharingpool
) >= 
1995                 server
.sharingpoolsize
) { 
1996             de 
= dictGetRandomKey(server
.sharingpool
); 
1998             c 
= ((unsigned long) dictGetEntryVal(de
))-1; 
1999             dictGetEntryVal(de
) = (void*) c
; 
2001                 dictDelete(server
.sharingpool
,de
->key
); 
2004             c 
= 0; /* If the pool is empty we want to add this object */ 
2009             retval 
= dictAdd(server
.sharingpool
,o
,(void*)1); 
2010             assert(retval 
== DICT_OK
); 
2017 /* Check if the nul-terminated string 's' can be represented by a long 
2018  * (that is, is a number that fits into long without any other space or 
2019  * character before or after the digits). 
2021  * If so, the function returns REDIS_OK and *longval is set to the value 
2022  * of the number. Otherwise REDIS_ERR is returned */ 
2023 static int isStringRepresentableAsLong(sds s
, long *longval
) { 
2024     char buf
[32], *endptr
; 
2028     value 
= strtol(s
, &endptr
, 10); 
2029     if (endptr
[0] != '\0') return REDIS_ERR
; 
2030     slen 
= snprintf(buf
,32,"%ld",value
); 
2032     /* If the number converted back into a string is not identical 
2033      * then it's not possible to encode the string as integer */ 
2034     if (sdslen(s
) != (unsigned)slen 
|| memcmp(buf
,s
,slen
)) return REDIS_ERR
; 
2035     if (longval
) *longval 
= value
; 
2039 /* Try to encode a string object in order to save space */ 
2040 static int tryObjectEncoding(robj 
*o
) { 
2044     if (o
->encoding 
!= REDIS_ENCODING_RAW
) 
2045         return REDIS_ERR
; /* Already encoded */ 
2047     /* It's not save to encode shared objects: shared objects can be shared 
2048      * everywhere in the "object space" of Redis. Encoded objects can only 
2049      * appear as "values" (and not, for instance, as keys) */ 
2050      if (o
->refcount 
> 1) return REDIS_ERR
; 
2052     /* Currently we try to encode only strings */ 
2053     assert(o
->type 
== REDIS_STRING
); 
2055     /* Check if we can represent this string as a long integer */ 
2056     if (isStringRepresentableAsLong(s
,&value
) == REDIS_ERR
) return REDIS_ERR
; 
2058     /* Ok, this object can be encoded */ 
2059     o
->encoding 
= REDIS_ENCODING_INT
; 
2061     o
->ptr 
= (void*) value
; 
2065 /* Get a decoded version of an encoded object (returned as a new object) */ 
2066 static robj 
*getDecodedObject(const robj 
*o
) { 
2069     assert(o
->encoding 
!= REDIS_ENCODING_RAW
); 
2070     if (o
->type 
== REDIS_STRING 
&& o
->encoding 
== REDIS_ENCODING_INT
) { 
2073         snprintf(buf
,32,"%ld",(long)o
->ptr
); 
2074         dec 
= createStringObject(buf
,strlen(buf
)); 
2081 /* Compare two string objects via strcmp() or alike. 
2082  * Note that the objects may be integer-encoded. In such a case we 
2083  * use snprintf() to get a string representation of the numbers on the stack 
2084  * and compare the strings, it's much faster than calling getDecodedObject(). */ 
2085 static int compareStringObjects(robj 
*a
, robj 
*b
) { 
2086     assert(a
->type 
== REDIS_STRING 
&& b
->type 
== REDIS_STRING
); 
2087     char bufa
[128], bufb
[128], *astr
, *bstr
; 
2090     if (a 
== b
) return 0; 
2091     if (a
->encoding 
!= REDIS_ENCODING_RAW
) { 
2092         snprintf(bufa
,sizeof(bufa
),"%ld",(long) a
->ptr
); 
2098     if (b
->encoding 
!= REDIS_ENCODING_RAW
) { 
2099         snprintf(bufb
,sizeof(bufb
),"%ld",(long) b
->ptr
); 
2105     return bothsds 
? sdscmp(astr
,bstr
) : strcmp(astr
,bstr
); 
2108 static size_t stringObjectLen(robj 
*o
) { 
2109     assert(o
->type 
== REDIS_STRING
); 
2110     if (o
->encoding 
== REDIS_ENCODING_RAW
) { 
2111         return sdslen(o
->ptr
); 
2115         return snprintf(buf
,32,"%ld",(long)o
->ptr
); 
2119 /*============================ DB saving/loading ============================ */ 
2121 static int rdbSaveType(FILE *fp
, unsigned char type
) { 
2122     if (fwrite(&type
,1,1,fp
) == 0) return -1; 
2126 static int rdbSaveTime(FILE *fp
, time_t t
) { 
2127     int32_t t32 
= (int32_t) t
; 
2128     if (fwrite(&t32
,4,1,fp
) == 0) return -1; 
2132 /* check rdbLoadLen() comments for more info */ 
2133 static int rdbSaveLen(FILE *fp
, uint32_t len
) { 
2134     unsigned char buf
[2]; 
2137         /* Save a 6 bit len */ 
2138         buf
[0] = (len
&0xFF)|(REDIS_RDB_6BITLEN
<<6); 
2139         if (fwrite(buf
,1,1,fp
) == 0) return -1; 
2140     } else if (len 
< (1<<14)) { 
2141         /* Save a 14 bit len */ 
2142         buf
[0] = ((len
>>8)&0xFF)|(REDIS_RDB_14BITLEN
<<6); 
2144         if (fwrite(buf
,2,1,fp
) == 0) return -1; 
2146         /* Save a 32 bit len */ 
2147         buf
[0] = (REDIS_RDB_32BITLEN
<<6); 
2148         if (fwrite(buf
,1,1,fp
) == 0) return -1; 
2150         if (fwrite(&len
,4,1,fp
) == 0) return -1; 
2155 /* String objects in the form "2391" "-100" without any space and with a 
2156  * range of values that can fit in an 8, 16 or 32 bit signed value can be 
2157  * encoded as integers to save space */ 
2158 static int rdbTryIntegerEncoding(sds s
, unsigned char *enc
) { 
2160     char *endptr
, buf
[32]; 
2162     /* Check if it's possible to encode this value as a number */ 
2163     value 
= strtoll(s
, &endptr
, 10); 
2164     if (endptr
[0] != '\0') return 0; 
2165     snprintf(buf
,32,"%lld",value
); 
2167     /* If the number converted back into a string is not identical 
2168      * then it's not possible to encode the string as integer */ 
2169     if (strlen(buf
) != sdslen(s
) || memcmp(buf
,s
,sdslen(s
))) return 0; 
2171     /* Finally check if it fits in our ranges */ 
2172     if (value 
>= -(1<<7) && value 
<= (1<<7)-1) { 
2173         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT8
; 
2174         enc
[1] = value
&0xFF; 
2176     } else if (value 
>= -(1<<15) && value 
<= (1<<15)-1) { 
2177         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT16
; 
2178         enc
[1] = value
&0xFF; 
2179         enc
[2] = (value
>>8)&0xFF; 
2181     } else if (value 
>= -((long long)1<<31) && value 
<= ((long long)1<<31)-1) { 
2182         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT32
; 
2183         enc
[1] = value
&0xFF; 
2184         enc
[2] = (value
>>8)&0xFF; 
2185         enc
[3] = (value
>>16)&0xFF; 
2186         enc
[4] = (value
>>24)&0xFF; 
2193 static int rdbSaveLzfStringObject(FILE *fp
, robj 
*obj
) { 
2194     unsigned int comprlen
, outlen
; 
2198     /* We require at least four bytes compression for this to be worth it */ 
2199     outlen 
= sdslen(obj
->ptr
)-4; 
2200     if (outlen 
<= 0) return 0; 
2201     if ((out 
= zmalloc(outlen
+1)) == NULL
) return 0; 
2202     comprlen 
= lzf_compress(obj
->ptr
, sdslen(obj
->ptr
), out
, outlen
); 
2203     if (comprlen 
== 0) { 
2207     /* Data compressed! Let's save it on disk */ 
2208     byte 
= (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_LZF
; 
2209     if (fwrite(&byte
,1,1,fp
) == 0) goto writeerr
; 
2210     if (rdbSaveLen(fp
,comprlen
) == -1) goto writeerr
; 
2211     if (rdbSaveLen(fp
,sdslen(obj
->ptr
)) == -1) goto writeerr
; 
2212     if (fwrite(out
,comprlen
,1,fp
) == 0) goto writeerr
; 
2221 /* Save a string objet as [len][data] on disk. If the object is a string 
2222  * representation of an integer value we try to safe it in a special form */ 
2223 static int rdbSaveStringObjectRaw(FILE *fp
, robj 
*obj
) { 
2227     len 
= sdslen(obj
->ptr
); 
2229     /* Try integer encoding */ 
2231         unsigned char buf
[5]; 
2232         if ((enclen 
= rdbTryIntegerEncoding(obj
->ptr
,buf
)) > 0) { 
2233             if (fwrite(buf
,enclen
,1,fp
) == 0) return -1; 
2238     /* Try LZF compression - under 20 bytes it's unable to compress even 
2239      * aaaaaaaaaaaaaaaaaa so skip it */ 
2243         retval 
= rdbSaveLzfStringObject(fp
,obj
); 
2244         if (retval 
== -1) return -1; 
2245         if (retval 
> 0) return 0; 
2246         /* retval == 0 means data can't be compressed, save the old way */ 
2249     /* Store verbatim */ 
2250     if (rdbSaveLen(fp
,len
) == -1) return -1; 
2251     if (len 
&& fwrite(obj
->ptr
,len
,1,fp
) == 0) return -1; 
2255 /* Like rdbSaveStringObjectRaw() but handle encoded objects */ 
2256 static int rdbSaveStringObject(FILE *fp
, robj 
*obj
) { 
2260     if (obj
->encoding 
!= REDIS_ENCODING_RAW
) { 
2261         dec 
= getDecodedObject(obj
); 
2262         retval 
= rdbSaveStringObjectRaw(fp
,dec
); 
2266         return rdbSaveStringObjectRaw(fp
,obj
); 
2270 /* Save a double value. Doubles are saved as strings prefixed by an unsigned 
2271  * 8 bit integer specifing the length of the representation. 
2272  * This 8 bit integer has special values in order to specify the following 
2278 static int rdbSaveDoubleValue(FILE *fp
, double val
) { 
2279     unsigned char buf
[128]; 
2285     } else if (!isfinite(val
)) { 
2287         buf
[0] = (val 
< 0) ? 255 : 254; 
2289         snprintf((char*)buf
+1,sizeof(buf
)-1,"%.16g",val
); 
2290         buf
[0] = strlen((char*)buf
); 
2293     if (fwrite(buf
,len
,1,fp
) == 0) return -1; 
2297 /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */ 
2298 static int rdbSave(char *filename
) { 
2299     dictIterator 
*di 
= NULL
; 
2304     time_t now 
= time(NULL
); 
2306     snprintf(tmpfile
,256,"temp-%d.rdb", (int) getpid()); 
2307     fp 
= fopen(tmpfile
,"w"); 
2309         redisLog(REDIS_WARNING
, "Failed saving the DB: %s", strerror(errno
)); 
2312     if (fwrite("REDIS0001",9,1,fp
) == 0) goto werr
; 
2313     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
2314         redisDb 
*db 
= server
.db
+j
; 
2316         if (dictSize(d
) == 0) continue; 
2317         di 
= dictGetIterator(d
); 
2323         /* Write the SELECT DB opcode */ 
2324         if (rdbSaveType(fp
,REDIS_SELECTDB
) == -1) goto werr
; 
2325         if (rdbSaveLen(fp
,j
) == -1) goto werr
; 
2327         /* Iterate this DB writing every entry */ 
2328         while((de 
= dictNext(di
)) != NULL
) { 
2329             robj 
*key 
= dictGetEntryKey(de
); 
2330             robj 
*o 
= dictGetEntryVal(de
); 
2331             time_t expiretime 
= getExpire(db
,key
); 
2333             /* Save the expire time */ 
2334             if (expiretime 
!= -1) { 
2335                 /* If this key is already expired skip it */ 
2336                 if (expiretime 
< now
) continue; 
2337                 if (rdbSaveType(fp
,REDIS_EXPIRETIME
) == -1) goto werr
; 
2338                 if (rdbSaveTime(fp
,expiretime
) == -1) goto werr
; 
2340             /* Save the key and associated value */ 
2341             if (rdbSaveType(fp
,o
->type
) == -1) goto werr
; 
2342             if (rdbSaveStringObject(fp
,key
) == -1) goto werr
; 
2343             if (o
->type 
== REDIS_STRING
) { 
2344                 /* Save a string value */ 
2345                 if (rdbSaveStringObject(fp
,o
) == -1) goto werr
; 
2346             } else if (o
->type 
== REDIS_LIST
) { 
2347                 /* Save a list value */ 
2348                 list 
*list 
= o
->ptr
; 
2352                 if (rdbSaveLen(fp
,listLength(list
)) == -1) goto werr
; 
2353                 while((ln 
= listYield(list
))) { 
2354                     robj 
*eleobj 
= listNodeValue(ln
); 
2356                     if (rdbSaveStringObject(fp
,eleobj
) == -1) goto werr
; 
2358             } else if (o
->type 
== REDIS_SET
) { 
2359                 /* Save a set value */ 
2361                 dictIterator 
*di 
= dictGetIterator(set
); 
2364                 if (rdbSaveLen(fp
,dictSize(set
)) == -1) goto werr
; 
2365                 while((de 
= dictNext(di
)) != NULL
) { 
2366                     robj 
*eleobj 
= dictGetEntryKey(de
); 
2368                     if (rdbSaveStringObject(fp
,eleobj
) == -1) goto werr
; 
2370                 dictReleaseIterator(di
); 
2371             } else if (o
->type 
== REDIS_ZSET
) { 
2372                 /* Save a set value */ 
2374                 dictIterator 
*di 
= dictGetIterator(zs
->dict
); 
2377                 if (rdbSaveLen(fp
,dictSize(zs
->dict
)) == -1) goto werr
; 
2378                 while((de 
= dictNext(di
)) != NULL
) { 
2379                     robj 
*eleobj 
= dictGetEntryKey(de
); 
2380                     double *score 
= dictGetEntryVal(de
); 
2382                     if (rdbSaveStringObject(fp
,eleobj
) == -1) goto werr
; 
2383                     if (rdbSaveDoubleValue(fp
,*score
) == -1) goto werr
; 
2385                 dictReleaseIterator(di
); 
2390         dictReleaseIterator(di
); 
2393     if (rdbSaveType(fp
,REDIS_EOF
) == -1) goto werr
; 
2395     /* Make sure data will not remain on the OS's output buffers */ 
2400     /* Use RENAME to make sure the DB file is changed atomically only 
2401      * if the generate DB file is ok. */ 
2402     if (rename(tmpfile
,filename
) == -1) { 
2403         redisLog(REDIS_WARNING
,"Error moving temp DB file on the final destination: %s", strerror(errno
)); 
2407     redisLog(REDIS_NOTICE
,"DB saved on disk"); 
2409     server
.lastsave 
= time(NULL
); 
2415     redisLog(REDIS_WARNING
,"Write error saving DB on disk: %s", strerror(errno
)); 
2416     if (di
) dictReleaseIterator(di
); 
2420 static int rdbSaveBackground(char *filename
) { 
2423     if (server
.bgsaveinprogress
) return REDIS_ERR
; 
2424     if ((childpid 
= fork()) == 0) { 
2427         if (rdbSave(filename
) == REDIS_OK
) { 
2434         if (childpid 
== -1) { 
2435             redisLog(REDIS_WARNING
,"Can't save in background: fork: %s", 
2439         redisLog(REDIS_NOTICE
,"Background saving started by pid %d",childpid
); 
2440         server
.bgsaveinprogress 
= 1; 
2441         server
.bgsavechildpid 
= childpid
; 
2444     return REDIS_OK
; /* unreached */ 
2447 static void rdbRemoveTempFile(pid_t childpid
) { 
2450     snprintf(tmpfile
,256,"temp-%d.rdb", (int) childpid
); 
2454 static int rdbLoadType(FILE *fp
) { 
2456     if (fread(&type
,1,1,fp
) == 0) return -1; 
2460 static time_t rdbLoadTime(FILE *fp
) { 
2462     if (fread(&t32
,4,1,fp
) == 0) return -1; 
2463     return (time_t) t32
; 
2466 /* Load an encoded length from the DB, see the REDIS_RDB_* defines on the top 
2467  * of this file for a description of how this are stored on disk. 
2469  * isencoded is set to 1 if the readed length is not actually a length but 
2470  * an "encoding type", check the above comments for more info */ 
2471 static uint32_t rdbLoadLen(FILE *fp
, int rdbver
, int *isencoded
) { 
2472     unsigned char buf
[2]; 
2475     if (isencoded
) *isencoded 
= 0; 
2477         if (fread(&len
,4,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2482         if (fread(buf
,1,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2483         type 
= (buf
[0]&0xC0)>>6; 
2484         if (type 
== REDIS_RDB_6BITLEN
) { 
2485             /* Read a 6 bit len */ 
2487         } else if (type 
== REDIS_RDB_ENCVAL
) { 
2488             /* Read a 6 bit len encoding type */ 
2489             if (isencoded
) *isencoded 
= 1; 
2491         } else if (type 
== REDIS_RDB_14BITLEN
) { 
2492             /* Read a 14 bit len */ 
2493             if (fread(buf
+1,1,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2494             return ((buf
[0]&0x3F)<<8)|buf
[1]; 
2496             /* Read a 32 bit len */ 
2497             if (fread(&len
,4,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2503 static robj 
*rdbLoadIntegerObject(FILE *fp
, int enctype
) { 
2504     unsigned char enc
[4]; 
2507     if (enctype 
== REDIS_RDB_ENC_INT8
) { 
2508         if (fread(enc
,1,1,fp
) == 0) return NULL
; 
2509         val 
= (signed char)enc
[0]; 
2510     } else if (enctype 
== REDIS_RDB_ENC_INT16
) { 
2512         if (fread(enc
,2,1,fp
) == 0) return NULL
; 
2513         v 
= enc
[0]|(enc
[1]<<8); 
2515     } else if (enctype 
== REDIS_RDB_ENC_INT32
) { 
2517         if (fread(enc
,4,1,fp
) == 0) return NULL
; 
2518         v 
= enc
[0]|(enc
[1]<<8)|(enc
[2]<<16)|(enc
[3]<<24); 
2521         val 
= 0; /* anti-warning */ 
2524     return createObject(REDIS_STRING
,sdscatprintf(sdsempty(),"%lld",val
)); 
2527 static robj 
*rdbLoadLzfStringObject(FILE*fp
, int rdbver
) { 
2528     unsigned int len
, clen
; 
2529     unsigned char *c 
= NULL
; 
2532     if ((clen 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
2533     if ((len 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
2534     if ((c 
= zmalloc(clen
)) == NULL
) goto err
; 
2535     if ((val 
= sdsnewlen(NULL
,len
)) == NULL
) goto err
; 
2536     if (fread(c
,clen
,1,fp
) == 0) goto err
; 
2537     if (lzf_decompress(c
,clen
,val
,len
) == 0) goto err
; 
2539     return createObject(REDIS_STRING
,val
); 
2546 static robj 
*rdbLoadStringObject(FILE*fp
, int rdbver
) { 
2551     len 
= rdbLoadLen(fp
,rdbver
,&isencoded
); 
2554         case REDIS_RDB_ENC_INT8
: 
2555         case REDIS_RDB_ENC_INT16
: 
2556         case REDIS_RDB_ENC_INT32
: 
2557             return tryObjectSharing(rdbLoadIntegerObject(fp
,len
)); 
2558         case REDIS_RDB_ENC_LZF
: 
2559             return tryObjectSharing(rdbLoadLzfStringObject(fp
,rdbver
)); 
2565     if (len 
== REDIS_RDB_LENERR
) return NULL
; 
2566     val 
= sdsnewlen(NULL
,len
); 
2567     if (len 
&& fread(val
,len
,1,fp
) == 0) { 
2571     return tryObjectSharing(createObject(REDIS_STRING
,val
)); 
2574 /* For information about double serialization check rdbSaveDoubleValue() */ 
2575 static int rdbLoadDoubleValue(FILE *fp
, double *val
) { 
2579     if (fread(&len
,1,1,fp
) == 0) return -1; 
2581     case 255: *val 
= R_NegInf
; return 0; 
2582     case 254: *val 
= R_PosInf
; return 0; 
2583     case 253: *val 
= R_Nan
; return 0; 
2585         if (fread(buf
,len
,1,fp
) == 0) return -1; 
2586         sscanf(buf
, "%lg", val
); 
2591 static int rdbLoad(char *filename
) { 
2593     robj 
*keyobj 
= NULL
; 
2595     int type
, retval
, rdbver
; 
2596     dict 
*d 
= server
.db
[0].dict
; 
2597     redisDb 
*db 
= server
.db
+0; 
2599     time_t expiretime 
= -1, now 
= time(NULL
); 
2601     fp 
= fopen(filename
,"r"); 
2602     if (!fp
) return REDIS_ERR
; 
2603     if (fread(buf
,9,1,fp
) == 0) goto eoferr
; 
2605     if (memcmp(buf
,"REDIS",5) != 0) { 
2607         redisLog(REDIS_WARNING
,"Wrong signature trying to load DB from file"); 
2610     rdbver 
= atoi(buf
+5); 
2613         redisLog(REDIS_WARNING
,"Can't handle RDB format version %d",rdbver
); 
2620         if ((type 
= rdbLoadType(fp
)) == -1) goto eoferr
; 
2621         if (type 
== REDIS_EXPIRETIME
) { 
2622             if ((expiretime 
= rdbLoadTime(fp
)) == -1) goto eoferr
; 
2623             /* We read the time so we need to read the object type again */ 
2624             if ((type 
= rdbLoadType(fp
)) == -1) goto eoferr
; 
2626         if (type 
== REDIS_EOF
) break; 
2627         /* Handle SELECT DB opcode as a special case */ 
2628         if (type 
== REDIS_SELECTDB
) { 
2629             if ((dbid 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) 
2631             if (dbid 
>= (unsigned)server
.dbnum
) { 
2632                 redisLog(REDIS_WARNING
,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server
.dbnum
); 
2635             db 
= server
.db
+dbid
; 
2640         if ((keyobj 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2642         if (type 
== REDIS_STRING
) { 
2643             /* Read string value */ 
2644             if ((o 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2645             tryObjectEncoding(o
); 
2646         } else if (type 
== REDIS_LIST 
|| type 
== REDIS_SET
) { 
2647             /* Read list/set value */ 
2650             if ((listlen 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) 
2652             o 
= (type 
== REDIS_LIST
) ? createListObject() : createSetObject(); 
2653             /* Load every single element of the list/set */ 
2657                 if ((ele 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2658                 tryObjectEncoding(ele
); 
2659                 if (type 
== REDIS_LIST
) { 
2660                     listAddNodeTail((list
*)o
->ptr
,ele
); 
2662                     dictAdd((dict
*)o
->ptr
,ele
,NULL
); 
2665         } else if (type 
== REDIS_ZSET
) { 
2666             /* Read list/set value */ 
2670             if ((zsetlen 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) 
2672             o 
= createZsetObject(); 
2674             /* Load every single element of the list/set */ 
2677                 double *score 
= zmalloc(sizeof(double)); 
2679                 if ((ele 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2680                 tryObjectEncoding(ele
); 
2681                 if (rdbLoadDoubleValue(fp
,score
) == -1) goto eoferr
; 
2682                 dictAdd(zs
->dict
,ele
,score
); 
2683                 zslInsert(zs
->zsl
,*score
,ele
); 
2684                 incrRefCount(ele
); /* added to skiplist */ 
2689         /* Add the new object in the hash table */ 
2690         retval 
= dictAdd(d
,keyobj
,o
); 
2691         if (retval 
== DICT_ERR
) { 
2692             redisLog(REDIS_WARNING
,"Loading DB, duplicated key (%s) found! Unrecoverable error, exiting now.", keyobj
->ptr
); 
2695         /* Set the expire time if needed */ 
2696         if (expiretime 
!= -1) { 
2697             setExpire(db
,keyobj
,expiretime
); 
2698             /* Delete this key if already expired */ 
2699             if (expiretime 
< now
) deleteKey(db
,keyobj
); 
2707 eoferr
: /* unexpected end of file is handled here with a fatal exit */ 
2708     if (keyobj
) decrRefCount(keyobj
); 
2709     redisLog(REDIS_WARNING
,"Short read or OOM loading DB. Unrecoverable error, exiting now."); 
2711     return REDIS_ERR
; /* Just to avoid warning */ 
2714 /*================================== Commands =============================== */ 
2716 static void authCommand(redisClient 
*c
) { 
2717     if (!server
.requirepass 
|| !strcmp(c
->argv
[1]->ptr
, server
.requirepass
)) { 
2718       c
->authenticated 
= 1; 
2719       addReply(c
,shared
.ok
); 
2721       c
->authenticated 
= 0; 
2722       addReply(c
,shared
.err
); 
2726 static void pingCommand(redisClient 
*c
) { 
2727     addReply(c
,shared
.pong
); 
2730 static void echoCommand(redisClient 
*c
) { 
2731     addReplyBulkLen(c
,c
->argv
[1]); 
2732     addReply(c
,c
->argv
[1]); 
2733     addReply(c
,shared
.crlf
); 
2736 /*=================================== Strings =============================== */ 
2738 static void setGenericCommand(redisClient 
*c
, int nx
) { 
2741     retval 
= dictAdd(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2742     if (retval 
== DICT_ERR
) { 
2744             dictReplace(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2745             incrRefCount(c
->argv
[2]); 
2747             addReply(c
,shared
.czero
); 
2751         incrRefCount(c
->argv
[1]); 
2752         incrRefCount(c
->argv
[2]); 
2755     removeExpire(c
->db
,c
->argv
[1]); 
2756     addReply(c
, nx 
? shared
.cone 
: shared
.ok
); 
2759 static void setCommand(redisClient 
*c
) { 
2760     setGenericCommand(c
,0); 
2763 static void setnxCommand(redisClient 
*c
) { 
2764     setGenericCommand(c
,1); 
2767 static void getCommand(redisClient 
*c
) { 
2768     robj 
*o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
2771         addReply(c
,shared
.nullbulk
); 
2773         if (o
->type 
!= REDIS_STRING
) { 
2774             addReply(c
,shared
.wrongtypeerr
); 
2776             addReplyBulkLen(c
,o
); 
2778             addReply(c
,shared
.crlf
); 
2783 static void getsetCommand(redisClient 
*c
) { 
2785     if (dictAdd(c
->db
->dict
,c
->argv
[1],c
->argv
[2]) == DICT_ERR
) { 
2786         dictReplace(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2788         incrRefCount(c
->argv
[1]); 
2790     incrRefCount(c
->argv
[2]); 
2792     removeExpire(c
->db
,c
->argv
[1]); 
2795 static void mgetCommand(redisClient 
*c
) { 
2798     addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",c
->argc
-1)); 
2799     for (j 
= 1; j 
< c
->argc
; j
++) { 
2800         robj 
*o 
= lookupKeyRead(c
->db
,c
->argv
[j
]); 
2802             addReply(c
,shared
.nullbulk
); 
2804             if (o
->type 
!= REDIS_STRING
) { 
2805                 addReply(c
,shared
.nullbulk
); 
2807                 addReplyBulkLen(c
,o
); 
2809                 addReply(c
,shared
.crlf
); 
2815 static void incrDecrCommand(redisClient 
*c
, long long incr
) { 
2820     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2824         if (o
->type 
!= REDIS_STRING
) { 
2829             if (o
->encoding 
== REDIS_ENCODING_RAW
) 
2830                 value 
= strtoll(o
->ptr
, &eptr
, 10); 
2831             else if (o
->encoding 
== REDIS_ENCODING_INT
) 
2832                 value 
= (long)o
->ptr
; 
2839     o 
= createObject(REDIS_STRING
,sdscatprintf(sdsempty(),"%lld",value
)); 
2840     tryObjectEncoding(o
); 
2841     retval 
= dictAdd(c
->db
->dict
,c
->argv
[1],o
); 
2842     if (retval 
== DICT_ERR
) { 
2843         dictReplace(c
->db
->dict
,c
->argv
[1],o
); 
2844         removeExpire(c
->db
,c
->argv
[1]); 
2846         incrRefCount(c
->argv
[1]); 
2849     addReply(c
,shared
.colon
); 
2851     addReply(c
,shared
.crlf
); 
2854 static void incrCommand(redisClient 
*c
) { 
2855     incrDecrCommand(c
,1); 
2858 static void decrCommand(redisClient 
*c
) { 
2859     incrDecrCommand(c
,-1); 
2862 static void incrbyCommand(redisClient 
*c
) { 
2863     long long incr 
= strtoll(c
->argv
[2]->ptr
, NULL
, 10); 
2864     incrDecrCommand(c
,incr
); 
2867 static void decrbyCommand(redisClient 
*c
) { 
2868     long long incr 
= strtoll(c
->argv
[2]->ptr
, NULL
, 10); 
2869     incrDecrCommand(c
,-incr
); 
2872 /* ========================= Type agnostic commands ========================= */ 
2874 static void delCommand(redisClient 
*c
) { 
2877     for (j 
= 1; j 
< c
->argc
; j
++) { 
2878         if (deleteKey(c
->db
,c
->argv
[j
])) { 
2885         addReply(c
,shared
.czero
); 
2888         addReply(c
,shared
.cone
); 
2891         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",deleted
)); 
2896 static void existsCommand(redisClient 
*c
) { 
2897     addReply(c
,lookupKeyRead(c
->db
,c
->argv
[1]) ? shared
.cone 
: shared
.czero
); 
2900 static void selectCommand(redisClient 
*c
) { 
2901     int id 
= atoi(c
->argv
[1]->ptr
); 
2903     if (selectDb(c
,id
) == REDIS_ERR
) { 
2904         addReplySds(c
,sdsnew("-ERR invalid DB index\r\n")); 
2906         addReply(c
,shared
.ok
); 
2910 static void randomkeyCommand(redisClient 
*c
) { 
2914         de 
= dictGetRandomKey(c
->db
->dict
); 
2915         if (!de 
|| expireIfNeeded(c
->db
,dictGetEntryKey(de
)) == 0) break; 
2918         addReply(c
,shared
.plus
); 
2919         addReply(c
,shared
.crlf
); 
2921         addReply(c
,shared
.plus
); 
2922         addReply(c
,dictGetEntryKey(de
)); 
2923         addReply(c
,shared
.crlf
); 
2927 static void keysCommand(redisClient 
*c
) { 
2930     sds pattern 
= c
->argv
[1]->ptr
; 
2931     int plen 
= sdslen(pattern
); 
2932     int numkeys 
= 0, keyslen 
= 0; 
2933     robj 
*lenobj 
= createObject(REDIS_STRING
,NULL
); 
2935     di 
= dictGetIterator(c
->db
->dict
); 
2937     decrRefCount(lenobj
); 
2938     while((de 
= dictNext(di
)) != NULL
) { 
2939         robj 
*keyobj 
= dictGetEntryKey(de
); 
2941         sds key 
= keyobj
->ptr
; 
2942         if ((pattern
[0] == '*' && pattern
[1] == '\0') || 
2943             stringmatchlen(pattern
,plen
,key
,sdslen(key
),0)) { 
2944             if (expireIfNeeded(c
->db
,keyobj
) == 0) { 
2946                     addReply(c
,shared
.space
); 
2949                 keyslen 
+= sdslen(key
); 
2953     dictReleaseIterator(di
); 
2954     lenobj
->ptr 
= sdscatprintf(sdsempty(),"$%lu\r\n",keyslen
+(numkeys 
? (numkeys
-1) : 0)); 
2955     addReply(c
,shared
.crlf
); 
2958 static void dbsizeCommand(redisClient 
*c
) { 
2960         sdscatprintf(sdsempty(),":%lu\r\n",dictSize(c
->db
->dict
))); 
2963 static void lastsaveCommand(redisClient 
*c
) { 
2965         sdscatprintf(sdsempty(),":%lu\r\n",server
.lastsave
)); 
2968 static void typeCommand(redisClient 
*c
) { 
2972     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
2977         case REDIS_STRING
: type 
= "+string"; break; 
2978         case REDIS_LIST
: type 
= "+list"; break; 
2979         case REDIS_SET
: type 
= "+set"; break; 
2980         default: type 
= "unknown"; break; 
2983     addReplySds(c
,sdsnew(type
)); 
2984     addReply(c
,shared
.crlf
); 
2987 static void saveCommand(redisClient 
*c
) { 
2988     if (server
.bgsaveinprogress
) { 
2989         addReplySds(c
,sdsnew("-ERR background save in progress\r\n")); 
2992     if (rdbSave(server
.dbfilename
) == REDIS_OK
) { 
2993         addReply(c
,shared
.ok
); 
2995         addReply(c
,shared
.err
); 
2999 static void bgsaveCommand(redisClient 
*c
) { 
3000     if (server
.bgsaveinprogress
) { 
3001         addReplySds(c
,sdsnew("-ERR background save already in progress\r\n")); 
3004     if (rdbSaveBackground(server
.dbfilename
) == REDIS_OK
) { 
3005         addReply(c
,shared
.ok
); 
3007         addReply(c
,shared
.err
); 
3011 static void shutdownCommand(redisClient 
*c
) { 
3012     redisLog(REDIS_WARNING
,"User requested shutdown, saving DB..."); 
3013     /* Kill the saving child if there is a background saving in progress. 
3014        We want to avoid race conditions, for instance our saving child may 
3015        overwrite the synchronous saving did by SHUTDOWN. */ 
3016     if (server
.bgsaveinprogress
) { 
3017         redisLog(REDIS_WARNING
,"There is a live saving child. Killing it!"); 
3018         kill(server
.bgsavechildpid
,SIGKILL
); 
3019         rdbRemoveTempFile(server
.bgsavechildpid
); 
3022     if (rdbSave(server
.dbfilename
) == REDIS_OK
) { 
3023         if (server
.daemonize
) 
3024             unlink(server
.pidfile
); 
3025         redisLog(REDIS_WARNING
,"%zu bytes used at exit",zmalloc_used_memory()); 
3026         redisLog(REDIS_WARNING
,"Server exit now, bye bye..."); 
3029         /* Ooops.. error saving! The best we can do is to continue operating. 
3030          * Note that if there was a background saving process, in the next 
3031          * cron() Redis will be notified that the background saving aborted, 
3032          * handling special stuff like slaves pending for synchronization... */ 
3033         redisLog(REDIS_WARNING
,"Error trying to save the DB, can't exit");  
3034         addReplySds(c
,sdsnew("-ERR can't quit, problems saving the DB\r\n")); 
3038 static void renameGenericCommand(redisClient 
*c
, int nx
) { 
3041     /* To use the same key as src and dst is probably an error */ 
3042     if (sdscmp(c
->argv
[1]->ptr
,c
->argv
[2]->ptr
) == 0) { 
3043         addReply(c
,shared
.sameobjecterr
); 
3047     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3049         addReply(c
,shared
.nokeyerr
); 
3053     deleteIfVolatile(c
->db
,c
->argv
[2]); 
3054     if (dictAdd(c
->db
->dict
,c
->argv
[2],o
) == DICT_ERR
) { 
3057             addReply(c
,shared
.czero
); 
3060         dictReplace(c
->db
->dict
,c
->argv
[2],o
); 
3062         incrRefCount(c
->argv
[2]); 
3064     deleteKey(c
->db
,c
->argv
[1]); 
3066     addReply(c
,nx 
? shared
.cone 
: shared
.ok
); 
3069 static void renameCommand(redisClient 
*c
) { 
3070     renameGenericCommand(c
,0); 
3073 static void renamenxCommand(redisClient 
*c
) { 
3074     renameGenericCommand(c
,1); 
3077 static void moveCommand(redisClient 
*c
) { 
3082     /* Obtain source and target DB pointers */ 
3085     if (selectDb(c
,atoi(c
->argv
[2]->ptr
)) == REDIS_ERR
) { 
3086         addReply(c
,shared
.outofrangeerr
); 
3090     selectDb(c
,srcid
); /* Back to the source DB */ 
3092     /* If the user is moving using as target the same 
3093      * DB as the source DB it is probably an error. */ 
3095         addReply(c
,shared
.sameobjecterr
); 
3099     /* Check if the element exists and get a reference */ 
3100     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3102         addReply(c
,shared
.czero
); 
3106     /* Try to add the element to the target DB */ 
3107     deleteIfVolatile(dst
,c
->argv
[1]); 
3108     if (dictAdd(dst
->dict
,c
->argv
[1],o
) == DICT_ERR
) { 
3109         addReply(c
,shared
.czero
); 
3112     incrRefCount(c
->argv
[1]); 
3115     /* OK! key moved, free the entry in the source DB */ 
3116     deleteKey(src
,c
->argv
[1]); 
3118     addReply(c
,shared
.cone
); 
3121 /* =================================== Lists ================================ */ 
3122 static void pushGenericCommand(redisClient 
*c
, int where
) { 
3126     lobj 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3128         lobj 
= createListObject(); 
3130         if (where 
== REDIS_HEAD
) { 
3131             listAddNodeHead(list
,c
->argv
[2]); 
3133             listAddNodeTail(list
,c
->argv
[2]); 
3135         dictAdd(c
->db
->dict
,c
->argv
[1],lobj
); 
3136         incrRefCount(c
->argv
[1]); 
3137         incrRefCount(c
->argv
[2]); 
3139         if (lobj
->type 
!= REDIS_LIST
) { 
3140             addReply(c
,shared
.wrongtypeerr
); 
3144         if (where 
== REDIS_HEAD
) { 
3145             listAddNodeHead(list
,c
->argv
[2]); 
3147             listAddNodeTail(list
,c
->argv
[2]); 
3149         incrRefCount(c
->argv
[2]); 
3152     addReply(c
,shared
.ok
); 
3155 static void lpushCommand(redisClient 
*c
) { 
3156     pushGenericCommand(c
,REDIS_HEAD
); 
3159 static void rpushCommand(redisClient 
*c
) { 
3160     pushGenericCommand(c
,REDIS_TAIL
); 
3163 static void llenCommand(redisClient 
*c
) { 
3167     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3169         addReply(c
,shared
.czero
); 
3172         if (o
->type 
!= REDIS_LIST
) { 
3173             addReply(c
,shared
.wrongtypeerr
); 
3176             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",listLength(l
))); 
3181 static void lindexCommand(redisClient 
*c
) { 
3183     int index 
= atoi(c
->argv
[2]->ptr
); 
3185     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3187         addReply(c
,shared
.nullbulk
); 
3189         if (o
->type 
!= REDIS_LIST
) { 
3190             addReply(c
,shared
.wrongtypeerr
); 
3192             list 
*list 
= o
->ptr
; 
3195             ln 
= listIndex(list
, index
); 
3197                 addReply(c
,shared
.nullbulk
); 
3199                 robj 
*ele 
= listNodeValue(ln
); 
3200                 addReplyBulkLen(c
,ele
); 
3202                 addReply(c
,shared
.crlf
); 
3208 static void lsetCommand(redisClient 
*c
) { 
3210     int index 
= atoi(c
->argv
[2]->ptr
); 
3212     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3214         addReply(c
,shared
.nokeyerr
); 
3216         if (o
->type 
!= REDIS_LIST
) { 
3217             addReply(c
,shared
.wrongtypeerr
); 
3219             list 
*list 
= o
->ptr
; 
3222             ln 
= listIndex(list
, index
); 
3224                 addReply(c
,shared
.outofrangeerr
); 
3226                 robj 
*ele 
= listNodeValue(ln
); 
3229                 listNodeValue(ln
) = c
->argv
[3]; 
3230                 incrRefCount(c
->argv
[3]); 
3231                 addReply(c
,shared
.ok
); 
3238 static void popGenericCommand(redisClient 
*c
, int where
) { 
3241     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3243         addReply(c
,shared
.nullbulk
); 
3245         if (o
->type 
!= REDIS_LIST
) { 
3246             addReply(c
,shared
.wrongtypeerr
); 
3248             list 
*list 
= o
->ptr
; 
3251             if (where 
== REDIS_HEAD
) 
3252                 ln 
= listFirst(list
); 
3254                 ln 
= listLast(list
); 
3257                 addReply(c
,shared
.nullbulk
); 
3259                 robj 
*ele 
= listNodeValue(ln
); 
3260                 addReplyBulkLen(c
,ele
); 
3262                 addReply(c
,shared
.crlf
); 
3263                 listDelNode(list
,ln
); 
3270 static void lpopCommand(redisClient 
*c
) { 
3271     popGenericCommand(c
,REDIS_HEAD
); 
3274 static void rpopCommand(redisClient 
*c
) { 
3275     popGenericCommand(c
,REDIS_TAIL
); 
3278 static void lrangeCommand(redisClient 
*c
) { 
3280     int start 
= atoi(c
->argv
[2]->ptr
); 
3281     int end 
= atoi(c
->argv
[3]->ptr
); 
3283     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3285         addReply(c
,shared
.nullmultibulk
); 
3287         if (o
->type 
!= REDIS_LIST
) { 
3288             addReply(c
,shared
.wrongtypeerr
); 
3290             list 
*list 
= o
->ptr
; 
3292             int llen 
= listLength(list
); 
3296             /* convert negative indexes */ 
3297             if (start 
< 0) start 
= llen
+start
; 
3298             if (end 
< 0) end 
= llen
+end
; 
3299             if (start 
< 0) start 
= 0; 
3300             if (end 
< 0) end 
= 0; 
3302             /* indexes sanity checks */ 
3303             if (start 
> end 
|| start 
>= llen
) { 
3304                 /* Out of range start or start > end result in empty list */ 
3305                 addReply(c
,shared
.emptymultibulk
); 
3308             if (end 
>= llen
) end 
= llen
-1; 
3309             rangelen 
= (end
-start
)+1; 
3311             /* Return the result in form of a multi-bulk reply */ 
3312             ln 
= listIndex(list
, start
); 
3313             addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",rangelen
)); 
3314             for (j 
= 0; j 
< rangelen
; j
++) { 
3315                 ele 
= listNodeValue(ln
); 
3316                 addReplyBulkLen(c
,ele
); 
3318                 addReply(c
,shared
.crlf
); 
3325 static void ltrimCommand(redisClient 
*c
) { 
3327     int start 
= atoi(c
->argv
[2]->ptr
); 
3328     int end 
= atoi(c
->argv
[3]->ptr
); 
3330     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3332         addReply(c
,shared
.nokeyerr
); 
3334         if (o
->type 
!= REDIS_LIST
) { 
3335             addReply(c
,shared
.wrongtypeerr
); 
3337             list 
*list 
= o
->ptr
; 
3339             int llen 
= listLength(list
); 
3340             int j
, ltrim
, rtrim
; 
3342             /* convert negative indexes */ 
3343             if (start 
< 0) start 
= llen
+start
; 
3344             if (end 
< 0) end 
= llen
+end
; 
3345             if (start 
< 0) start 
= 0; 
3346             if (end 
< 0) end 
= 0; 
3348             /* indexes sanity checks */ 
3349             if (start 
> end 
|| start 
>= llen
) { 
3350                 /* Out of range start or start > end result in empty list */ 
3354                 if (end 
>= llen
) end 
= llen
-1; 
3359             /* Remove list elements to perform the trim */ 
3360             for (j 
= 0; j 
< ltrim
; j
++) { 
3361                 ln 
= listFirst(list
); 
3362                 listDelNode(list
,ln
); 
3364             for (j 
= 0; j 
< rtrim
; j
++) { 
3365                 ln 
= listLast(list
); 
3366                 listDelNode(list
,ln
); 
3369             addReply(c
,shared
.ok
); 
3374 static void lremCommand(redisClient 
*c
) { 
3377     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3379         addReply(c
,shared
.czero
); 
3381         if (o
->type 
!= REDIS_LIST
) { 
3382             addReply(c
,shared
.wrongtypeerr
); 
3384             list 
*list 
= o
->ptr
; 
3385             listNode 
*ln
, *next
; 
3386             int toremove 
= atoi(c
->argv
[2]->ptr
); 
3391                 toremove 
= -toremove
; 
3394             ln 
= fromtail 
? list
->tail 
: list
->head
; 
3396                 robj 
*ele 
= listNodeValue(ln
); 
3398                 next 
= fromtail 
? ln
->prev 
: ln
->next
; 
3399                 if (compareStringObjects(ele
,c
->argv
[3]) == 0) { 
3400                     listDelNode(list
,ln
); 
3403                     if (toremove 
&& removed 
== toremove
) break; 
3407             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",removed
)); 
3412 /* ==================================== Sets ================================ */ 
3414 static void saddCommand(redisClient 
*c
) { 
3417     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3419         set 
= createSetObject(); 
3420         dictAdd(c
->db
->dict
,c
->argv
[1],set
); 
3421         incrRefCount(c
->argv
[1]); 
3423         if (set
->type 
!= REDIS_SET
) { 
3424             addReply(c
,shared
.wrongtypeerr
); 
3428     if (dictAdd(set
->ptr
,c
->argv
[2],NULL
) == DICT_OK
) { 
3429         incrRefCount(c
->argv
[2]); 
3431         addReply(c
,shared
.cone
); 
3433         addReply(c
,shared
.czero
); 
3437 static void sremCommand(redisClient 
*c
) { 
3440     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3442         addReply(c
,shared
.czero
); 
3444         if (set
->type 
!= REDIS_SET
) { 
3445             addReply(c
,shared
.wrongtypeerr
); 
3448         if (dictDelete(set
->ptr
,c
->argv
[2]) == DICT_OK
) { 
3450             if (htNeedsResize(set
->ptr
)) dictResize(set
->ptr
); 
3451             addReply(c
,shared
.cone
); 
3453             addReply(c
,shared
.czero
); 
3458 static void smoveCommand(redisClient 
*c
) { 
3459     robj 
*srcset
, *dstset
; 
3461     srcset 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3462     dstset 
= lookupKeyWrite(c
->db
,c
->argv
[2]); 
3464     /* If the source key does not exist return 0, if it's of the wrong type 
3466     if (srcset 
== NULL 
|| srcset
->type 
!= REDIS_SET
) { 
3467         addReply(c
, srcset 
? shared
.wrongtypeerr 
: shared
.czero
); 
3470     /* Error if the destination key is not a set as well */ 
3471     if (dstset 
&& dstset
->type 
!= REDIS_SET
) { 
3472         addReply(c
,shared
.wrongtypeerr
); 
3475     /* Remove the element from the source set */ 
3476     if (dictDelete(srcset
->ptr
,c
->argv
[3]) == DICT_ERR
) { 
3477         /* Key not found in the src set! return zero */ 
3478         addReply(c
,shared
.czero
); 
3482     /* Add the element to the destination set */ 
3484         dstset 
= createSetObject(); 
3485         dictAdd(c
->db
->dict
,c
->argv
[2],dstset
); 
3486         incrRefCount(c
->argv
[2]); 
3488     if (dictAdd(dstset
->ptr
,c
->argv
[3],NULL
) == DICT_OK
) 
3489         incrRefCount(c
->argv
[3]); 
3490     addReply(c
,shared
.cone
); 
3493 static void sismemberCommand(redisClient 
*c
) { 
3496     set 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3498         addReply(c
,shared
.czero
); 
3500         if (set
->type 
!= REDIS_SET
) { 
3501             addReply(c
,shared
.wrongtypeerr
); 
3504         if (dictFind(set
->ptr
,c
->argv
[2])) 
3505             addReply(c
,shared
.cone
); 
3507             addReply(c
,shared
.czero
); 
3511 static void scardCommand(redisClient 
*c
) { 
3515     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3517         addReply(c
,shared
.czero
); 
3520         if (o
->type 
!= REDIS_SET
) { 
3521             addReply(c
,shared
.wrongtypeerr
); 
3524             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3530 static void spopCommand(redisClient 
*c
) { 
3534     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3536         addReply(c
,shared
.nullbulk
); 
3538         if (set
->type 
!= REDIS_SET
) { 
3539             addReply(c
,shared
.wrongtypeerr
); 
3542         de 
= dictGetRandomKey(set
->ptr
); 
3544             addReply(c
,shared
.nullbulk
); 
3546             robj 
*ele 
= dictGetEntryKey(de
); 
3548             addReplyBulkLen(c
,ele
); 
3550             addReply(c
,shared
.crlf
); 
3551             dictDelete(set
->ptr
,ele
); 
3552             if (htNeedsResize(set
->ptr
)) dictResize(set
->ptr
); 
3558 static void srandmemberCommand(redisClient 
*c
) { 
3562     set 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3564         addReply(c
,shared
.nullbulk
); 
3566         if (set
->type 
!= REDIS_SET
) { 
3567             addReply(c
,shared
.wrongtypeerr
); 
3570         de 
= dictGetRandomKey(set
->ptr
); 
3572             addReply(c
,shared
.nullbulk
); 
3574             robj 
*ele 
= dictGetEntryKey(de
); 
3576             addReplyBulkLen(c
,ele
); 
3578             addReply(c
,shared
.crlf
); 
3583 static int qsortCompareSetsByCardinality(const void *s1
, const void *s2
) { 
3584     dict 
**d1 
= (void*) s1
, **d2 
= (void*) s2
; 
3586     return dictSize(*d1
)-dictSize(*d2
); 
3589 static void sinterGenericCommand(redisClient 
*c
, robj 
**setskeys
, int setsnum
, robj 
*dstkey
) { 
3590     dict 
**dv 
= zmalloc(sizeof(dict
*)*setsnum
); 
3593     robj 
*lenobj 
= NULL
, *dstset 
= NULL
; 
3594     int j
, cardinality 
= 0; 
3596     for (j 
= 0; j 
< setsnum
; j
++) { 
3600                     lookupKeyWrite(c
->db
,setskeys
[j
]) : 
3601                     lookupKeyRead(c
->db
,setskeys
[j
]); 
3605                 deleteKey(c
->db
,dstkey
); 
3606                 addReply(c
,shared
.ok
); 
3608                 addReply(c
,shared
.nullmultibulk
); 
3612         if (setobj
->type 
!= REDIS_SET
) { 
3614             addReply(c
,shared
.wrongtypeerr
); 
3617         dv
[j
] = setobj
->ptr
; 
3619     /* Sort sets from the smallest to largest, this will improve our 
3620      * algorithm's performace */ 
3621     qsort(dv
,setsnum
,sizeof(dict
*),qsortCompareSetsByCardinality
); 
3623     /* The first thing we should output is the total number of elements... 
3624      * since this is a multi-bulk write, but at this stage we don't know 
3625      * the intersection set size, so we use a trick, append an empty object 
3626      * to the output list and save the pointer to later modify it with the 
3629         lenobj 
= createObject(REDIS_STRING
,NULL
); 
3631         decrRefCount(lenobj
); 
3633         /* If we have a target key where to store the resulting set 
3634          * create this key with an empty set inside */ 
3635         dstset 
= createSetObject(); 
3638     /* Iterate all the elements of the first (smallest) set, and test 
3639      * the element against all the other sets, if at least one set does 
3640      * not include the element it is discarded */ 
3641     di 
= dictGetIterator(dv
[0]); 
3643     while((de 
= dictNext(di
)) != NULL
) { 
3646         for (j 
= 1; j 
< setsnum
; j
++) 
3647             if (dictFind(dv
[j
],dictGetEntryKey(de
)) == NULL
) break; 
3649             continue; /* at least one set does not contain the member */ 
3650         ele 
= dictGetEntryKey(de
); 
3652             addReplyBulkLen(c
,ele
); 
3654             addReply(c
,shared
.crlf
); 
3657             dictAdd(dstset
->ptr
,ele
,NULL
); 
3661     dictReleaseIterator(di
); 
3664         /* Store the resulting set into the target */ 
3665         deleteKey(c
->db
,dstkey
); 
3666         dictAdd(c
->db
->dict
,dstkey
,dstset
); 
3667         incrRefCount(dstkey
); 
3671         lenobj
->ptr 
= sdscatprintf(sdsempty(),"*%d\r\n",cardinality
); 
3673         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3674             dictSize((dict
*)dstset
->ptr
))); 
3680 static void sinterCommand(redisClient 
*c
) { 
3681     sinterGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
); 
3684 static void sinterstoreCommand(redisClient 
*c
) { 
3685     sinterGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1]); 
3688 #define REDIS_OP_UNION 0 
3689 #define REDIS_OP_DIFF 1 
3691 static void sunionDiffGenericCommand(redisClient 
*c
, robj 
**setskeys
, int setsnum
, robj 
*dstkey
, int op
) { 
3692     dict 
**dv 
= zmalloc(sizeof(dict
*)*setsnum
); 
3695     robj 
*dstset 
= NULL
; 
3696     int j
, cardinality 
= 0; 
3698     for (j 
= 0; j 
< setsnum
; j
++) { 
3702                     lookupKeyWrite(c
->db
,setskeys
[j
]) : 
3703                     lookupKeyRead(c
->db
,setskeys
[j
]); 
3708         if (setobj
->type 
!= REDIS_SET
) { 
3710             addReply(c
,shared
.wrongtypeerr
); 
3713         dv
[j
] = setobj
->ptr
; 
3716     /* We need a temp set object to store our union. If the dstkey 
3717      * is not NULL (that is, we are inside an SUNIONSTORE operation) then 
3718      * this set object will be the resulting object to set into the target key*/ 
3719     dstset 
= createSetObject(); 
3721     /* Iterate all the elements of all the sets, add every element a single 
3722      * time to the result set */ 
3723     for (j 
= 0; j 
< setsnum
; j
++) { 
3724         if (op 
== REDIS_OP_DIFF 
&& j 
== 0 && !dv
[j
]) break; /* result set is empty */ 
3725         if (!dv
[j
]) continue; /* non existing keys are like empty sets */ 
3727         di 
= dictGetIterator(dv
[j
]); 
3729         while((de 
= dictNext(di
)) != NULL
) { 
3732             /* dictAdd will not add the same element multiple times */ 
3733             ele 
= dictGetEntryKey(de
); 
3734             if (op 
== REDIS_OP_UNION 
|| j 
== 0) { 
3735                 if (dictAdd(dstset
->ptr
,ele
,NULL
) == DICT_OK
) { 
3739             } else if (op 
== REDIS_OP_DIFF
) { 
3740                 if (dictDelete(dstset
->ptr
,ele
) == DICT_OK
) { 
3745         dictReleaseIterator(di
); 
3747         if (op 
== REDIS_OP_DIFF 
&& cardinality 
== 0) break; /* result set is empty */ 
3750     /* Output the content of the resulting set, if not in STORE mode */ 
3752         addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",cardinality
)); 
3753         di 
= dictGetIterator(dstset
->ptr
); 
3754         while((de 
= dictNext(di
)) != NULL
) { 
3757             ele 
= dictGetEntryKey(de
); 
3758             addReplyBulkLen(c
,ele
); 
3760             addReply(c
,shared
.crlf
); 
3762         dictReleaseIterator(di
); 
3764         /* If we have a target key where to store the resulting set 
3765          * create this key with the result set inside */ 
3766         deleteKey(c
->db
,dstkey
); 
3767         dictAdd(c
->db
->dict
,dstkey
,dstset
); 
3768         incrRefCount(dstkey
); 
3773         decrRefCount(dstset
); 
3775         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3776             dictSize((dict
*)dstset
->ptr
))); 
3782 static void sunionCommand(redisClient 
*c
) { 
3783     sunionDiffGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
,REDIS_OP_UNION
); 
3786 static void sunionstoreCommand(redisClient 
*c
) { 
3787     sunionDiffGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1],REDIS_OP_UNION
); 
3790 static void sdiffCommand(redisClient 
*c
) { 
3791     sunionDiffGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
,REDIS_OP_DIFF
); 
3794 static void sdiffstoreCommand(redisClient 
*c
) { 
3795     sunionDiffGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1],REDIS_OP_DIFF
); 
3798 /* ==================================== ZSets =============================== */ 
3800 /* ZSETs are ordered sets using two data structures to hold the same elements 
3801  * in order to get O(log(N)) INSERT and REMOVE operations into a sorted 
3804  * The elements are added to an hash table mapping Redis objects to scores. 
3805  * At the same time the elements are added to a skip list mapping scores 
3806  * to Redis objects (so objects are sorted by scores in this "view"). */ 
3808 /* This skiplist implementation is almost a C translation of the original 
3809  * algorithm described by William Pugh in "Skip Lists: A Probabilistic 
3810  * Alternative to Balanced Trees", modified in three ways: 
3811  * a) this implementation allows for repeated values. 
3812  * b) the comparison is not just by key (our 'score') but by satellite data. 
3813  * c) there is a back pointer, so it's a doubly linked list with the back 
3814  * pointers being only at "level 1". This allows to traverse the list 
3815  * from tail to head, useful for ZREVRANGE. */ 
3817 static zskiplistNode 
*zslCreateNode(int level
, double score
, robj 
*obj
) { 
3818     zskiplistNode 
*zn 
= zmalloc(sizeof(*zn
)); 
3820     zn
->forward 
= zmalloc(sizeof(zskiplistNode
*) * level
); 
3826 static zskiplist 
*zslCreate(void) { 
3830     zsl 
= zmalloc(sizeof(*zsl
)); 
3833     zsl
->header 
= zslCreateNode(ZSKIPLIST_MAXLEVEL
,0,NULL
); 
3834     for (j 
= 0; j 
< ZSKIPLIST_MAXLEVEL
; j
++) 
3835         zsl
->header
->forward
[j
] = NULL
; 
3836     zsl
->header
->backward 
= NULL
; 
3841 static void zslFreeNode(zskiplistNode 
*node
) { 
3842     decrRefCount(node
->obj
); 
3843     zfree(node
->forward
); 
3847 static void zslFree(zskiplist 
*zsl
) { 
3848     zskiplistNode 
*node 
= zsl
->header
->forward
[0], *next
; 
3850     zfree(zsl
->header
->forward
); 
3853         next 
= node
->forward
[0]; 
3860 static int zslRandomLevel(void) { 
3862     while ((random()&0xFFFF) < (ZSKIPLIST_P 
* 0xFFFF)) 
3867 static void zslInsert(zskiplist 
*zsl
, double score
, robj 
*obj
) { 
3868     zskiplistNode 
*update
[ZSKIPLIST_MAXLEVEL
], *x
; 
3872     for (i 
= zsl
->level
-1; i 
>= 0; i
--) { 
3873         while (x
->forward
[i
] && 
3874             (x
->forward
[i
]->score 
< score 
|| 
3875                 (x
->forward
[i
]->score 
== score 
&& 
3876                 compareStringObjects(x
->forward
[i
]->obj
,obj
) < 0))) 
3880     /* we assume the key is not already inside, since we allow duplicated 
3881      * scores, and the re-insertion of score and redis object should never 
3882      * happpen since the caller of zslInsert() should test in the hash table 
3883      * if the element is already inside or not. */ 
3884     level 
= zslRandomLevel(); 
3885     if (level 
> zsl
->level
) { 
3886         for (i 
= zsl
->level
; i 
< level
; i
++) 
3887             update
[i
] = zsl
->header
; 
3890     x 
= zslCreateNode(level
,score
,obj
); 
3891     for (i 
= 0; i 
< level
; i
++) { 
3892         x
->forward
[i
] = update
[i
]->forward
[i
]; 
3893         update
[i
]->forward
[i
] = x
; 
3895     x
->backward 
= (update
[0] == zsl
->header
) ? NULL 
: update
[0]; 
3897         x
->forward
[0]->backward 
= x
; 
3903 /* Delete an element with matching score/object from the skiplist. */ 
3904 static int zslDelete(zskiplist 
*zsl
, double score
, robj 
*obj
) { 
3905     zskiplistNode 
*update
[ZSKIPLIST_MAXLEVEL
], *x
; 
3909     for (i 
= zsl
->level
-1; i 
>= 0; i
--) { 
3910         while (x
->forward
[i
] && 
3911             (x
->forward
[i
]->score 
< score 
|| 
3912                 (x
->forward
[i
]->score 
== score 
&& 
3913                 compareStringObjects(x
->forward
[i
]->obj
,obj
) < 0))) 
3917     /* We may have multiple elements with the same score, what we need 
3918      * is to find the element with both the right score and object. */ 
3920     if (x 
&& score 
== x
->score 
&& compareStringObjects(x
->obj
,obj
) == 0) { 
3921         for (i 
= 0; i 
< zsl
->level
; i
++) { 
3922             if (update
[i
]->forward
[i
] != x
) break; 
3923             update
[i
]->forward
[i
] = x
->forward
[i
]; 
3925         if (x
->forward
[0]) { 
3926             x
->forward
[0]->backward 
= (x
->backward 
== zsl
->header
) ? 
3929             zsl
->tail 
= x
->backward
; 
3932         while(zsl
->level 
> 1 && zsl
->header
->forward
[zsl
->level
-1] == NULL
) 
3937         return 0; /* not found */ 
3939     return 0; /* not found */ 
3942 /* Find the first node having a score equal or greater than the specified one. 
3943  * Returns NULL if there is no match. */ 
3944 static zskiplistNode 
*zslFirstWithScore(zskiplist 
*zsl
, double score
) { 
3949     for (i 
= zsl
->level
-1; i 
>= 0; i
--) { 
3950         while (x
->forward
[i
] && x
->forward
[i
]->score 
< score
) 
3953     /* We may have multiple elements with the same score, what we need 
3954      * is to find the element with both the right score and object. */ 
3955     return x
->forward
[0]; 
3958 /* The actual Z-commands implementations */ 
3960 static void zaddCommand(redisClient 
*c
) { 
3965     zsetobj 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3966     if (zsetobj 
== NULL
) { 
3967         zsetobj 
= createZsetObject(); 
3968         dictAdd(c
->db
->dict
,c
->argv
[1],zsetobj
); 
3969         incrRefCount(c
->argv
[1]); 
3971         if (zsetobj
->type 
!= REDIS_ZSET
) { 
3972             addReply(c
,shared
.wrongtypeerr
); 
3976     score 
= zmalloc(sizeof(double)); 
3977     *score 
= strtod(c
->argv
[2]->ptr
,NULL
); 
3979     if (dictAdd(zs
->dict
,c
->argv
[3],score
) == DICT_OK
) { 
3980         /* case 1: New element */ 
3981         incrRefCount(c
->argv
[3]); /* added to hash */ 
3982         zslInsert(zs
->zsl
,*score
,c
->argv
[3]); 
3983         incrRefCount(c
->argv
[3]); /* added to skiplist */ 
3985         addReply(c
,shared
.cone
); 
3990         /* case 2: Score update operation */ 
3991         de 
= dictFind(zs
->dict
,c
->argv
[3]); 
3993         oldscore 
= dictGetEntryVal(de
); 
3994         if (*score 
!= *oldscore
) { 
3997             deleted 
= zslDelete(zs
->zsl
,*oldscore
,c
->argv
[3]); 
3998             assert(deleted 
!= 0); 
3999             zslInsert(zs
->zsl
,*score
,c
->argv
[3]); 
4000             incrRefCount(c
->argv
[3]); 
4001             dictReplace(zs
->dict
,c
->argv
[3],score
); 
4006         addReply(c
,shared
.czero
); 
4010 static void zremCommand(redisClient 
*c
) { 
4014     zsetobj 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
4015     if (zsetobj 
== NULL
) { 
4016         addReply(c
,shared
.czero
); 
4022         if (zsetobj
->type 
!= REDIS_ZSET
) { 
4023             addReply(c
,shared
.wrongtypeerr
); 
4027         de 
= dictFind(zs
->dict
,c
->argv
[2]); 
4029             addReply(c
,shared
.czero
); 
4032         /* Delete from the skiplist */ 
4033         oldscore 
= dictGetEntryVal(de
); 
4034         deleted 
= zslDelete(zs
->zsl
,*oldscore
,c
->argv
[2]); 
4035         assert(deleted 
!= 0); 
4037         /* Delete from the hash table */ 
4038         dictDelete(zs
->dict
,c
->argv
[2]); 
4039         if (htNeedsResize(zs
->dict
)) dictResize(zs
->dict
); 
4041         addReply(c
,shared
.cone
); 
4045 static void zrangeGenericCommand(redisClient 
*c
, int reverse
) { 
4047     int start 
= atoi(c
->argv
[2]->ptr
); 
4048     int end 
= atoi(c
->argv
[3]->ptr
); 
4050     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4052         addReply(c
,shared
.nullmultibulk
); 
4054         if (o
->type 
!= REDIS_ZSET
) { 
4055             addReply(c
,shared
.wrongtypeerr
); 
4057             zset 
*zsetobj 
= o
->ptr
; 
4058             zskiplist 
*zsl 
= zsetobj
->zsl
; 
4061             int llen 
= zsl
->length
; 
4065             /* convert negative indexes */ 
4066             if (start 
< 0) start 
= llen
+start
; 
4067             if (end 
< 0) end 
= llen
+end
; 
4068             if (start 
< 0) start 
= 0; 
4069             if (end 
< 0) end 
= 0; 
4071             /* indexes sanity checks */ 
4072             if (start 
> end 
|| start 
>= llen
) { 
4073                 /* Out of range start or start > end result in empty list */ 
4074                 addReply(c
,shared
.emptymultibulk
); 
4077             if (end 
>= llen
) end 
= llen
-1; 
4078             rangelen 
= (end
-start
)+1; 
4080             /* Return the result in form of a multi-bulk reply */ 
4086                 ln 
= zsl
->header
->forward
[0]; 
4088                     ln 
= ln
->forward
[0]; 
4091             addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",rangelen
)); 
4092             for (j 
= 0; j 
< rangelen
; j
++) { 
4094                 addReplyBulkLen(c
,ele
); 
4096                 addReply(c
,shared
.crlf
); 
4097                 ln 
= reverse 
? ln
->backward 
: ln
->forward
[0]; 
4103 static void zrangeCommand(redisClient 
*c
) { 
4104     zrangeGenericCommand(c
,0); 
4107 static void zrevrangeCommand(redisClient 
*c
) { 
4108     zrangeGenericCommand(c
,1); 
4111 static void zrangebyscoreCommand(redisClient 
*c
) { 
4113     double min 
= strtod(c
->argv
[2]->ptr
,NULL
); 
4114     double max 
= strtod(c
->argv
[3]->ptr
,NULL
); 
4116     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4118         addReply(c
,shared
.nullmultibulk
); 
4120         if (o
->type 
!= REDIS_ZSET
) { 
4121             addReply(c
,shared
.wrongtypeerr
); 
4123             zset 
*zsetobj 
= o
->ptr
; 
4124             zskiplist 
*zsl 
= zsetobj
->zsl
; 
4127             unsigned int rangelen 
= 0; 
4129             /* Get the first node with the score >= min */ 
4130             ln 
= zslFirstWithScore(zsl
,min
); 
4132                 /* No element matching the speciifed interval */ 
4133                 addReply(c
,shared
.emptymultibulk
); 
4137             /* We don't know in advance how many matching elements there 
4138              * are in the list, so we push this object that will represent 
4139              * the multi-bulk length in the output buffer, and will "fix" 
4141             lenobj 
= createObject(REDIS_STRING
,NULL
); 
4144             while(ln 
&& ln
->score 
<= max
) { 
4146                 addReplyBulkLen(c
,ele
); 
4148                 addReply(c
,shared
.crlf
); 
4149                 ln 
= ln
->forward
[0]; 
4152             lenobj
->ptr 
= sdscatprintf(sdsempty(),"*%d\r\n",rangelen
); 
4157 static void zcardCommand(redisClient 
*c
) { 
4161     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4163         addReply(c
,shared
.czero
); 
4166         if (o
->type 
!= REDIS_ZSET
) { 
4167             addReply(c
,shared
.wrongtypeerr
); 
4170             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",zs
->zsl
->length
)); 
4175 static void zscoreCommand(redisClient 
*c
) { 
4179     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4181         addReply(c
,shared
.czero
); 
4184         if (o
->type 
!= REDIS_ZSET
) { 
4185             addReply(c
,shared
.wrongtypeerr
); 
4190             de 
= dictFind(zs
->dict
,c
->argv
[2]); 
4192                 addReply(c
,shared
.nullbulk
); 
4195                 double *score 
= dictGetEntryVal(de
); 
4197                 snprintf(buf
,sizeof(buf
),"%.16g",*score
); 
4198                 addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n%s\r\n", 
4205 /* ========================= Non type-specific commands  ==================== */ 
4207 static void flushdbCommand(redisClient 
*c
) { 
4208     server
.dirty 
+= dictSize(c
->db
->dict
); 
4209     dictEmpty(c
->db
->dict
); 
4210     dictEmpty(c
->db
->expires
); 
4211     addReply(c
,shared
.ok
); 
4214 static void flushallCommand(redisClient 
*c
) { 
4215     server
.dirty 
+= emptyDb(); 
4216     addReply(c
,shared
.ok
); 
4217     rdbSave(server
.dbfilename
); 
4221 static redisSortOperation 
*createSortOperation(int type
, robj 
*pattern
) { 
4222     redisSortOperation 
*so 
= zmalloc(sizeof(*so
)); 
4224     so
->pattern 
= pattern
; 
4228 /* Return the value associated to the key with a name obtained 
4229  * substituting the first occurence of '*' in 'pattern' with 'subst' */ 
4230 static robj 
*lookupKeyByPattern(redisDb 
*db
, robj 
*pattern
, robj 
*subst
) { 
4234     int prefixlen
, sublen
, postfixlen
; 
4235     /* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */ 
4239         char buf
[REDIS_SORTKEY_MAX
+1]; 
4242     if (subst
->encoding 
== REDIS_ENCODING_RAW
) 
4243         incrRefCount(subst
); 
4245         subst 
= getDecodedObject(subst
); 
4248     spat 
= pattern
->ptr
; 
4250     if (sdslen(spat
)+sdslen(ssub
)-1 > REDIS_SORTKEY_MAX
) return NULL
; 
4251     p 
= strchr(spat
,'*'); 
4252     if (!p
) return NULL
; 
4255     sublen 
= sdslen(ssub
); 
4256     postfixlen 
= sdslen(spat
)-(prefixlen
+1); 
4257     memcpy(keyname
.buf
,spat
,prefixlen
); 
4258     memcpy(keyname
.buf
+prefixlen
,ssub
,sublen
); 
4259     memcpy(keyname
.buf
+prefixlen
+sublen
,p
+1,postfixlen
); 
4260     keyname
.buf
[prefixlen
+sublen
+postfixlen
] = '\0'; 
4261     keyname
.len 
= prefixlen
+sublen
+postfixlen
; 
4263     keyobj
.refcount 
= 1; 
4264     keyobj
.type 
= REDIS_STRING
; 
4265     keyobj
.ptr 
= ((char*)&keyname
)+(sizeof(long)*2); 
4267     decrRefCount(subst
); 
4269     /* printf("lookup '%s' => %p\n", keyname.buf,de); */ 
4270     return lookupKeyRead(db
,&keyobj
); 
4273 /* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with 
4274  * the additional parameter is not standard but a BSD-specific we have to 
4275  * pass sorting parameters via the global 'server' structure */ 
4276 static int sortCompare(const void *s1
, const void *s2
) { 
4277     const redisSortObject 
*so1 
= s1
, *so2 
= s2
; 
4280     if (!server
.sort_alpha
) { 
4281         /* Numeric sorting. Here it's trivial as we precomputed scores */ 
4282         if (so1
->u
.score 
> so2
->u
.score
) { 
4284         } else if (so1
->u
.score 
< so2
->u
.score
) { 
4290         /* Alphanumeric sorting */ 
4291         if (server
.sort_bypattern
) { 
4292             if (!so1
->u
.cmpobj 
|| !so2
->u
.cmpobj
) { 
4293                 /* At least one compare object is NULL */ 
4294                 if (so1
->u
.cmpobj 
== so2
->u
.cmpobj
) 
4296                 else if (so1
->u
.cmpobj 
== NULL
) 
4301                 /* We have both the objects, use strcoll */ 
4302                 cmp 
= strcoll(so1
->u
.cmpobj
->ptr
,so2
->u
.cmpobj
->ptr
); 
4305             /* Compare elements directly */ 
4306             if (so1
->obj
->encoding 
== REDIS_ENCODING_RAW 
&& 
4307                 so2
->obj
->encoding 
== REDIS_ENCODING_RAW
) { 
4308                 cmp 
= strcoll(so1
->obj
->ptr
,so2
->obj
->ptr
); 
4312                 dec1 
= so1
->obj
->encoding 
== REDIS_ENCODING_RAW 
? 
4313                     so1
->obj 
: getDecodedObject(so1
->obj
); 
4314                 dec2 
= so2
->obj
->encoding 
== REDIS_ENCODING_RAW 
? 
4315                     so2
->obj 
: getDecodedObject(so2
->obj
); 
4316                 cmp 
= strcoll(dec1
->ptr
,dec2
->ptr
); 
4317                 if (dec1 
!= so1
->obj
) decrRefCount(dec1
); 
4318                 if (dec2 
!= so2
->obj
) decrRefCount(dec2
); 
4322     return server
.sort_desc 
? -cmp 
: cmp
; 
4325 /* The SORT command is the most complex command in Redis. Warning: this code 
4326  * is optimized for speed and a bit less for readability */ 
4327 static void sortCommand(redisClient 
*c
) { 
4330     int desc 
= 0, alpha 
= 0; 
4331     int limit_start 
= 0, limit_count 
= -1, start
, end
; 
4332     int j
, dontsort 
= 0, vectorlen
; 
4333     int getop 
= 0; /* GET operation counter */ 
4334     robj 
*sortval
, *sortby 
= NULL
; 
4335     redisSortObject 
*vector
; /* Resulting vector to sort */ 
4337     /* Lookup the key to sort. It must be of the right types */ 
4338     sortval 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
4339     if (sortval 
== NULL
) { 
4340         addReply(c
,shared
.nokeyerr
); 
4343     if (sortval
->type 
!= REDIS_SET 
&& sortval
->type 
!= REDIS_LIST
) { 
4344         addReply(c
,shared
.wrongtypeerr
); 
4348     /* Create a list of operations to perform for every sorted element. 
4349      * Operations can be GET/DEL/INCR/DECR */ 
4350     operations 
= listCreate(); 
4351     listSetFreeMethod(operations
,zfree
); 
4354     /* Now we need to protect sortval incrementing its count, in the future 
4355      * SORT may have options able to overwrite/delete keys during the sorting 
4356      * and the sorted key itself may get destroied */ 
4357     incrRefCount(sortval
); 
4359     /* The SORT command has an SQL-alike syntax, parse it */ 
4360     while(j 
< c
->argc
) { 
4361         int leftargs 
= c
->argc
-j
-1; 
4362         if (!strcasecmp(c
->argv
[j
]->ptr
,"asc")) { 
4364         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"desc")) { 
4366         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"alpha")) { 
4368         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"limit") && leftargs 
>= 2) { 
4369             limit_start 
= atoi(c
->argv
[j
+1]->ptr
); 
4370             limit_count 
= atoi(c
->argv
[j
+2]->ptr
); 
4372         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"by") && leftargs 
>= 1) { 
4373             sortby 
= c
->argv
[j
+1]; 
4374             /* If the BY pattern does not contain '*', i.e. it is constant, 
4375              * we don't need to sort nor to lookup the weight keys. */ 
4376             if (strchr(c
->argv
[j
+1]->ptr
,'*') == NULL
) dontsort 
= 1; 
4378         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"get") && leftargs 
>= 1) { 
4379             listAddNodeTail(operations
,createSortOperation( 
4380                 REDIS_SORT_GET
,c
->argv
[j
+1])); 
4383         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"del") && leftargs 
>= 1) { 
4384             listAddNodeTail(operations
,createSortOperation( 
4385                 REDIS_SORT_DEL
,c
->argv
[j
+1])); 
4387         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"incr") && leftargs 
>= 1) { 
4388             listAddNodeTail(operations
,createSortOperation( 
4389                 REDIS_SORT_INCR
,c
->argv
[j
+1])); 
4391         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"get") && leftargs 
>= 1) { 
4392             listAddNodeTail(operations
,createSortOperation( 
4393                 REDIS_SORT_DECR
,c
->argv
[j
+1])); 
4396             decrRefCount(sortval
); 
4397             listRelease(operations
); 
4398             addReply(c
,shared
.syntaxerr
); 
4404     /* Load the sorting vector with all the objects to sort */ 
4405     vectorlen 
= (sortval
->type 
== REDIS_LIST
) ? 
4406         listLength((list
*)sortval
->ptr
) : 
4407         dictSize((dict
*)sortval
->ptr
); 
4408     vector 
= zmalloc(sizeof(redisSortObject
)*vectorlen
); 
4410     if (sortval
->type 
== REDIS_LIST
) { 
4411         list 
*list 
= sortval
->ptr
; 
4415         while((ln 
= listYield(list
))) { 
4416             robj 
*ele 
= ln
->value
; 
4417             vector
[j
].obj 
= ele
; 
4418             vector
[j
].u
.score 
= 0; 
4419             vector
[j
].u
.cmpobj 
= NULL
; 
4423         dict 
*set 
= sortval
->ptr
; 
4427         di 
= dictGetIterator(set
); 
4428         while((setele 
= dictNext(di
)) != NULL
) { 
4429             vector
[j
].obj 
= dictGetEntryKey(setele
); 
4430             vector
[j
].u
.score 
= 0; 
4431             vector
[j
].u
.cmpobj 
= NULL
; 
4434         dictReleaseIterator(di
); 
4436     assert(j 
== vectorlen
); 
4438     /* Now it's time to load the right scores in the sorting vector */ 
4439     if (dontsort 
== 0) { 
4440         for (j 
= 0; j 
< vectorlen
; j
++) { 
4444                 byval 
= lookupKeyByPattern(c
->db
,sortby
,vector
[j
].obj
); 
4445                 if (!byval 
|| byval
->type 
!= REDIS_STRING
) continue; 
4447                     if (byval
->encoding 
== REDIS_ENCODING_RAW
) { 
4448                         vector
[j
].u
.cmpobj 
= byval
; 
4449                         incrRefCount(byval
); 
4451                         vector
[j
].u
.cmpobj 
= getDecodedObject(byval
); 
4454                     if (byval
->encoding 
== REDIS_ENCODING_RAW
) { 
4455                         vector
[j
].u
.score 
= strtod(byval
->ptr
,NULL
); 
4457                         if (byval
->encoding 
== REDIS_ENCODING_INT
) { 
4458                             vector
[j
].u
.score 
= (long)byval
->ptr
; 
4465                     if (vector
[j
].obj
->encoding 
== REDIS_ENCODING_RAW
) 
4466                         vector
[j
].u
.score 
= strtod(vector
[j
].obj
->ptr
,NULL
); 
4468                         if (vector
[j
].obj
->encoding 
== REDIS_ENCODING_INT
) 
4469                             vector
[j
].u
.score 
= (long) vector
[j
].obj
->ptr
; 
4478     /* We are ready to sort the vector... perform a bit of sanity check 
4479      * on the LIMIT option too. We'll use a partial version of quicksort. */ 
4480     start 
= (limit_start 
< 0) ? 0 : limit_start
; 
4481     end 
= (limit_count 
< 0) ? vectorlen
-1 : start
+limit_count
-1; 
4482     if (start 
>= vectorlen
) { 
4483         start 
= vectorlen
-1; 
4486     if (end 
>= vectorlen
) end 
= vectorlen
-1; 
4488     if (dontsort 
== 0) { 
4489         server
.sort_desc 
= desc
; 
4490         server
.sort_alpha 
= alpha
; 
4491         server
.sort_bypattern 
= sortby 
? 1 : 0; 
4492         if (sortby 
&& (start 
!= 0 || end 
!= vectorlen
-1)) 
4493             pqsort(vector
,vectorlen
,sizeof(redisSortObject
),sortCompare
, start
,end
); 
4495             qsort(vector
,vectorlen
,sizeof(redisSortObject
),sortCompare
); 
4498     /* Send command output to the output buffer, performing the specified 
4499      * GET/DEL/INCR/DECR operations if any. */ 
4500     outputlen 
= getop 
? getop
*(end
-start
+1) : end
-start
+1; 
4501     addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",outputlen
)); 
4502     for (j 
= start
; j 
<= end
; j
++) { 
4505             addReplyBulkLen(c
,vector
[j
].obj
); 
4506             addReply(c
,vector
[j
].obj
); 
4507             addReply(c
,shared
.crlf
); 
4509         listRewind(operations
); 
4510         while((ln 
= listYield(operations
))) { 
4511             redisSortOperation 
*sop 
= ln
->value
; 
4512             robj 
*val 
= lookupKeyByPattern(c
->db
,sop
->pattern
, 
4515             if (sop
->type 
== REDIS_SORT_GET
) { 
4516                 if (!val 
|| val
->type 
!= REDIS_STRING
) { 
4517                     addReply(c
,shared
.nullbulk
); 
4519                     addReplyBulkLen(c
,val
); 
4521                     addReply(c
,shared
.crlf
); 
4523             } else if (sop
->type 
== REDIS_SORT_DEL
) { 
4530     decrRefCount(sortval
); 
4531     listRelease(operations
); 
4532     for (j 
= 0; j 
< vectorlen
; j
++) { 
4533         if (sortby 
&& alpha 
&& vector
[j
].u
.cmpobj
) 
4534             decrRefCount(vector
[j
].u
.cmpobj
); 
4539 static void infoCommand(redisClient 
*c
) { 
4541     time_t uptime 
= time(NULL
)-server
.stat_starttime
; 
4544     info 
= sdscatprintf(sdsempty(), 
4545         "redis_version:%s\r\n" 
4547         "uptime_in_seconds:%d\r\n" 
4548         "uptime_in_days:%d\r\n" 
4549         "connected_clients:%d\r\n" 
4550         "connected_slaves:%d\r\n" 
4551         "used_memory:%zu\r\n" 
4552         "changes_since_last_save:%lld\r\n" 
4553         "bgsave_in_progress:%d\r\n" 
4554         "last_save_time:%d\r\n" 
4555         "total_connections_received:%lld\r\n" 
4556         "total_commands_processed:%lld\r\n" 
4559         (sizeof(long) == 8) ? "64" : "32", 
4562         listLength(server
.clients
)-listLength(server
.slaves
), 
4563         listLength(server
.slaves
), 
4566         server
.bgsaveinprogress
, 
4568         server
.stat_numconnections
, 
4569         server
.stat_numcommands
, 
4570         server
.masterhost 
== NULL 
? "master" : "slave" 
4572     if (server
.masterhost
) { 
4573         info 
= sdscatprintf(info
, 
4574             "master_host:%s\r\n" 
4575             "master_port:%d\r\n" 
4576             "master_link_status:%s\r\n" 
4577             "master_last_io_seconds_ago:%d\r\n" 
4580             (server
.replstate 
== REDIS_REPL_CONNECTED
) ? 
4582             (int)(time(NULL
)-server
.master
->lastinteraction
) 
4585     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
4586         long long keys
, vkeys
; 
4588         keys 
= dictSize(server
.db
[j
].dict
); 
4589         vkeys 
= dictSize(server
.db
[j
].expires
); 
4590         if (keys 
|| vkeys
) { 
4591             info 
= sdscatprintf(info
, "db%d: keys=%lld,expires=%lld\r\n", 
4595     addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",sdslen(info
))); 
4596     addReplySds(c
,info
); 
4597     addReply(c
,shared
.crlf
); 
4600 static void monitorCommand(redisClient 
*c
) { 
4601     /* ignore MONITOR if aleady slave or in monitor mode */ 
4602     if (c
->flags 
& REDIS_SLAVE
) return; 
4604     c
->flags 
|= (REDIS_SLAVE
|REDIS_MONITOR
); 
4606     listAddNodeTail(server
.monitors
,c
); 
4607     addReply(c
,shared
.ok
); 
4610 /* ================================= Expire ================================= */ 
4611 static int removeExpire(redisDb 
*db
, robj 
*key
) { 
4612     if (dictDelete(db
->expires
,key
) == DICT_OK
) { 
4619 static int setExpire(redisDb 
*db
, robj 
*key
, time_t when
) { 
4620     if (dictAdd(db
->expires
,key
,(void*)when
) == DICT_ERR
) { 
4628 /* Return the expire time of the specified key, or -1 if no expire 
4629  * is associated with this key (i.e. the key is non volatile) */ 
4630 static time_t getExpire(redisDb 
*db
, robj 
*key
) { 
4633     /* No expire? return ASAP */ 
4634     if (dictSize(db
->expires
) == 0 || 
4635        (de 
= dictFind(db
->expires
,key
)) == NULL
) return -1; 
4637     return (time_t) dictGetEntryVal(de
); 
4640 static int expireIfNeeded(redisDb 
*db
, robj 
*key
) { 
4644     /* No expire? return ASAP */ 
4645     if (dictSize(db
->expires
) == 0 || 
4646        (de 
= dictFind(db
->expires
,key
)) == NULL
) return 0; 
4648     /* Lookup the expire */ 
4649     when 
= (time_t) dictGetEntryVal(de
); 
4650     if (time(NULL
) <= when
) return 0; 
4652     /* Delete the key */ 
4653     dictDelete(db
->expires
,key
); 
4654     return dictDelete(db
->dict
,key
) == DICT_OK
; 
4657 static int deleteIfVolatile(redisDb 
*db
, robj 
*key
) { 
4660     /* No expire? return ASAP */ 
4661     if (dictSize(db
->expires
) == 0 || 
4662        (de 
= dictFind(db
->expires
,key
)) == NULL
) return 0; 
4664     /* Delete the key */ 
4666     dictDelete(db
->expires
,key
); 
4667     return dictDelete(db
->dict
,key
) == DICT_OK
; 
4670 static void expireCommand(redisClient 
*c
) { 
4672     int seconds 
= atoi(c
->argv
[2]->ptr
); 
4674     de 
= dictFind(c
->db
->dict
,c
->argv
[1]); 
4676         addReply(c
,shared
.czero
); 
4680         addReply(c
, shared
.czero
); 
4683         time_t when 
= time(NULL
)+seconds
; 
4684         if (setExpire(c
->db
,c
->argv
[1],when
)) { 
4685             addReply(c
,shared
.cone
); 
4688             addReply(c
,shared
.czero
); 
4694 static void ttlCommand(redisClient 
*c
) { 
4698     expire 
= getExpire(c
->db
,c
->argv
[1]); 
4700         ttl 
= (int) (expire
-time(NULL
)); 
4701         if (ttl 
< 0) ttl 
= -1; 
4703     addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",ttl
)); 
4706 static void msetGenericCommand(redisClient 
*c
, int nx
) { 
4709     if ((c
->argc 
% 2) == 0) { 
4710         addReplySds(c
,sdsnew("-ERR wrong number of arguments\r\n")); 
4713     /* Handle the NX flag. The MSETNX semantic is to return zero and don't 
4714      * set nothing at all if at least one already key exists. */ 
4716         for (j 
= 1; j 
< c
->argc
; j 
+= 2) { 
4717             if (dictFind(c
->db
->dict
,c
->argv
[j
]) != NULL
) { 
4718                 addReply(c
, shared
.czero
); 
4724     for (j 
= 1; j 
< c
->argc
; j 
+= 2) { 
4727         retval 
= dictAdd(c
->db
->dict
,c
->argv
[j
],c
->argv
[j
+1]); 
4728         if (retval 
== DICT_ERR
) { 
4729             dictReplace(c
->db
->dict
,c
->argv
[j
],c
->argv
[j
+1]); 
4730             incrRefCount(c
->argv
[j
+1]); 
4732             incrRefCount(c
->argv
[j
]); 
4733             incrRefCount(c
->argv
[j
+1]); 
4735         removeExpire(c
->db
,c
->argv
[j
]); 
4737     server
.dirty 
+= (c
->argc
-1)/2; 
4738     addReply(c
, nx 
? shared
.cone 
: shared
.ok
); 
4741 static void msetCommand(redisClient 
*c
) { 
4742     msetGenericCommand(c
,0); 
4745 static void msetnxCommand(redisClient 
*c
) { 
4746     msetGenericCommand(c
,1); 
4749 /* =============================== Replication  ============================= */ 
4751 static int syncWrite(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
4752     ssize_t nwritten
, ret 
= size
; 
4753     time_t start 
= time(NULL
); 
4757         if (aeWait(fd
,AE_WRITABLE
,1000) & AE_WRITABLE
) { 
4758             nwritten 
= write(fd
,ptr
,size
); 
4759             if (nwritten 
== -1) return -1; 
4763         if ((time(NULL
)-start
) > timeout
) { 
4771 static int syncRead(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
4772     ssize_t nread
, totread 
= 0; 
4773     time_t start 
= time(NULL
); 
4777         if (aeWait(fd
,AE_READABLE
,1000) & AE_READABLE
) { 
4778             nread 
= read(fd
,ptr
,size
); 
4779             if (nread 
== -1) return -1; 
4784         if ((time(NULL
)-start
) > timeout
) { 
4792 static int syncReadLine(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
4799         if (syncRead(fd
,&c
,1,timeout
) == -1) return -1; 
4802             if (nread 
&& *(ptr
-1) == '\r') *(ptr
-1) = '\0'; 
4813 static void syncCommand(redisClient 
*c
) { 
4814     /* ignore SYNC if aleady slave or in monitor mode */ 
4815     if (c
->flags 
& REDIS_SLAVE
) return; 
4817     /* SYNC can't be issued when the server has pending data to send to 
4818      * the client about already issued commands. We need a fresh reply 
4819      * buffer registering the differences between the BGSAVE and the current 
4820      * dataset, so that we can copy to other slaves if needed. */ 
4821     if (listLength(c
->reply
) != 0) { 
4822         addReplySds(c
,sdsnew("-ERR SYNC is invalid with pending input\r\n")); 
4826     redisLog(REDIS_NOTICE
,"Slave ask for synchronization"); 
4827     /* Here we need to check if there is a background saving operation 
4828      * in progress, or if it is required to start one */ 
4829     if (server
.bgsaveinprogress
) { 
4830         /* Ok a background save is in progress. Let's check if it is a good 
4831          * one for replication, i.e. if there is another slave that is 
4832          * registering differences since the server forked to save */ 
4836         listRewind(server
.slaves
); 
4837         while((ln 
= listYield(server
.slaves
))) { 
4839             if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_END
) break; 
4842             /* Perfect, the server is already registering differences for 
4843              * another slave. Set the right state, and copy the buffer. */ 
4844             listRelease(c
->reply
); 
4845             c
->reply 
= listDup(slave
->reply
); 
4846             c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
4847             redisLog(REDIS_NOTICE
,"Waiting for end of BGSAVE for SYNC"); 
4849             /* No way, we need to wait for the next BGSAVE in order to 
4850              * register differences */ 
4851             c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_START
; 
4852             redisLog(REDIS_NOTICE
,"Waiting for next BGSAVE for SYNC"); 
4855         /* Ok we don't have a BGSAVE in progress, let's start one */ 
4856         redisLog(REDIS_NOTICE
,"Starting BGSAVE for SYNC"); 
4857         if (rdbSaveBackground(server
.dbfilename
) != REDIS_OK
) { 
4858             redisLog(REDIS_NOTICE
,"Replication failed, can't BGSAVE"); 
4859             addReplySds(c
,sdsnew("-ERR Unalbe to perform background save\r\n")); 
4862         c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
4865     c
->flags 
|= REDIS_SLAVE
; 
4867     listAddNodeTail(server
.slaves
,c
); 
4871 static void sendBulkToSlave(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
4872     redisClient 
*slave 
= privdata
; 
4874     REDIS_NOTUSED(mask
); 
4875     char buf
[REDIS_IOBUF_LEN
]; 
4876     ssize_t nwritten
, buflen
; 
4878     if (slave
->repldboff 
== 0) { 
4879         /* Write the bulk write count before to transfer the DB. In theory here 
4880          * we don't know how much room there is in the output buffer of the 
4881          * socket, but in pratice SO_SNDLOWAT (the minimum count for output 
4882          * operations) will never be smaller than the few bytes we need. */ 
4885         bulkcount 
= sdscatprintf(sdsempty(),"$%lld\r\n",(unsigned long long) 
4887         if (write(fd
,bulkcount
,sdslen(bulkcount
)) != (signed)sdslen(bulkcount
)) 
4895     lseek(slave
->repldbfd
,slave
->repldboff
,SEEK_SET
); 
4896     buflen 
= read(slave
->repldbfd
,buf
,REDIS_IOBUF_LEN
); 
4898         redisLog(REDIS_WARNING
,"Read error sending DB to slave: %s", 
4899             (buflen 
== 0) ? "premature EOF" : strerror(errno
)); 
4903     if ((nwritten 
= write(fd
,buf
,buflen
)) == -1) { 
4904         redisLog(REDIS_DEBUG
,"Write error sending DB to slave: %s", 
4909     slave
->repldboff 
+= nwritten
; 
4910     if (slave
->repldboff 
== slave
->repldbsize
) { 
4911         close(slave
->repldbfd
); 
4912         slave
->repldbfd 
= -1; 
4913         aeDeleteFileEvent(server
.el
,slave
->fd
,AE_WRITABLE
); 
4914         slave
->replstate 
= REDIS_REPL_ONLINE
; 
4915         if (aeCreateFileEvent(server
.el
, slave
->fd
, AE_WRITABLE
, 
4916             sendReplyToClient
, slave
, NULL
) == AE_ERR
) { 
4920         addReplySds(slave
,sdsempty()); 
4921         redisLog(REDIS_NOTICE
,"Synchronization with slave succeeded"); 
4925 /* This function is called at the end of every backgrond saving. 
4926  * The argument bgsaveerr is REDIS_OK if the background saving succeeded 
4927  * otherwise REDIS_ERR is passed to the function. 
4929  * The goal of this function is to handle slaves waiting for a successful 
4930  * background saving in order to perform non-blocking synchronization. */ 
4931 static void updateSlavesWaitingBgsave(int bgsaveerr
) { 
4933     int startbgsave 
= 0; 
4935     listRewind(server
.slaves
); 
4936     while((ln 
= listYield(server
.slaves
))) { 
4937         redisClient 
*slave 
= ln
->value
; 
4939         if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) { 
4941             slave
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
4942         } else if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_END
) { 
4943             struct redis_stat buf
; 
4945             if (bgsaveerr 
!= REDIS_OK
) { 
4947                 redisLog(REDIS_WARNING
,"SYNC failed. BGSAVE child returned an error"); 
4950             if ((slave
->repldbfd 
= open(server
.dbfilename
,O_RDONLY
)) == -1 || 
4951                 redis_fstat(slave
->repldbfd
,&buf
) == -1) { 
4953                 redisLog(REDIS_WARNING
,"SYNC failed. Can't open/stat DB after BGSAVE: %s", strerror(errno
)); 
4956             slave
->repldboff 
= 0; 
4957             slave
->repldbsize 
= buf
.st_size
; 
4958             slave
->replstate 
= REDIS_REPL_SEND_BULK
; 
4959             aeDeleteFileEvent(server
.el
,slave
->fd
,AE_WRITABLE
); 
4960             if (aeCreateFileEvent(server
.el
, slave
->fd
, AE_WRITABLE
, sendBulkToSlave
, slave
, NULL
) == AE_ERR
) { 
4967         if (rdbSaveBackground(server
.dbfilename
) != REDIS_OK
) { 
4968             listRewind(server
.slaves
); 
4969             redisLog(REDIS_WARNING
,"SYNC failed. BGSAVE failed"); 
4970             while((ln 
= listYield(server
.slaves
))) { 
4971                 redisClient 
*slave 
= ln
->value
; 
4973                 if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) 
4980 static int syncWithMaster(void) { 
4981     char buf
[1024], tmpfile
[256]; 
4983     int fd 
= anetTcpConnect(NULL
,server
.masterhost
,server
.masterport
); 
4987         redisLog(REDIS_WARNING
,"Unable to connect to MASTER: %s", 
4991     /* Issue the SYNC command */ 
4992     if (syncWrite(fd
,"SYNC \r\n",7,5) == -1) { 
4994         redisLog(REDIS_WARNING
,"I/O error writing to MASTER: %s", 
4998     /* Read the bulk write count */ 
4999     if (syncReadLine(fd
,buf
,1024,3600) == -1) { 
5001         redisLog(REDIS_WARNING
,"I/O error reading bulk count from MASTER: %s", 
5005     dumpsize 
= atoi(buf
+1); 
5006     redisLog(REDIS_NOTICE
,"Receiving %d bytes data dump from MASTER",dumpsize
); 
5007     /* Read the bulk write data on a temp file */ 
5008     snprintf(tmpfile
,256,"temp-%d.%ld.rdb",(int)time(NULL
),(long int)random()); 
5009     dfd 
= open(tmpfile
,O_CREAT
|O_WRONLY
,0644); 
5012         redisLog(REDIS_WARNING
,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno
)); 
5016         int nread
, nwritten
; 
5018         nread 
= read(fd
,buf
,(dumpsize 
< 1024)?dumpsize
:1024); 
5020             redisLog(REDIS_WARNING
,"I/O error trying to sync with MASTER: %s", 
5026         nwritten 
= write(dfd
,buf
,nread
); 
5027         if (nwritten 
== -1) { 
5028             redisLog(REDIS_WARNING
,"Write error writing to the DB dump file needed for MASTER <-> SLAVE synchrnonization: %s", strerror(errno
)); 
5036     if (rename(tmpfile
,server
.dbfilename
) == -1) { 
5037         redisLog(REDIS_WARNING
,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", strerror(errno
)); 
5043     if (rdbLoad(server
.dbfilename
) != REDIS_OK
) { 
5044         redisLog(REDIS_WARNING
,"Failed trying to load the MASTER synchronization DB from disk"); 
5048     server
.master 
= createClient(fd
); 
5049     server
.master
->flags 
|= REDIS_MASTER
; 
5050     server
.replstate 
= REDIS_REPL_CONNECTED
; 
5054 static void slaveofCommand(redisClient 
*c
) { 
5055     if (!strcasecmp(c
->argv
[1]->ptr
,"no") && 
5056         !strcasecmp(c
->argv
[2]->ptr
,"one")) { 
5057         if (server
.masterhost
) { 
5058             sdsfree(server
.masterhost
); 
5059             server
.masterhost 
= NULL
; 
5060             if (server
.master
) freeClient(server
.master
); 
5061             server
.replstate 
= REDIS_REPL_NONE
; 
5062             redisLog(REDIS_NOTICE
,"MASTER MODE enabled (user request)"); 
5065         sdsfree(server
.masterhost
); 
5066         server
.masterhost 
= sdsdup(c
->argv
[1]->ptr
); 
5067         server
.masterport 
= atoi(c
->argv
[2]->ptr
); 
5068         if (server
.master
) freeClient(server
.master
); 
5069         server
.replstate 
= REDIS_REPL_CONNECT
; 
5070         redisLog(REDIS_NOTICE
,"SLAVE OF %s:%d enabled (user request)", 
5071             server
.masterhost
, server
.masterport
); 
5073     addReply(c
,shared
.ok
); 
5076 /* ============================ Maxmemory directive  ======================== */ 
5078 /* This function gets called when 'maxmemory' is set on the config file to limit 
5079  * the max memory used by the server, and we are out of memory. 
5080  * This function will try to, in order: 
5082  * - Free objects from the free list 
5083  * - Try to remove keys with an EXPIRE set 
5085  * It is not possible to free enough memory to reach used-memory < maxmemory 
5086  * the server will start refusing commands that will enlarge even more the 
5089 static void freeMemoryIfNeeded(void) { 
5090     while (server
.maxmemory 
&& zmalloc_used_memory() > server
.maxmemory
) { 
5091         if (listLength(server
.objfreelist
)) { 
5094             listNode 
*head 
= listFirst(server
.objfreelist
); 
5095             o 
= listNodeValue(head
); 
5096             listDelNode(server
.objfreelist
,head
); 
5099             int j
, k
, freed 
= 0; 
5101             for (j 
= 0; j 
< server
.dbnum
; j
++) { 
5103                 robj 
*minkey 
= NULL
; 
5104                 struct dictEntry 
*de
; 
5106                 if (dictSize(server
.db
[j
].expires
)) { 
5108                     /* From a sample of three keys drop the one nearest to 
5109                      * the natural expire */ 
5110                     for (k 
= 0; k 
< 3; k
++) { 
5113                         de 
= dictGetRandomKey(server
.db
[j
].expires
); 
5114                         t 
= (time_t) dictGetEntryVal(de
); 
5115                         if (minttl 
== -1 || t 
< minttl
) { 
5116                             minkey 
= dictGetEntryKey(de
); 
5120                     deleteKey(server
.db
+j
,minkey
); 
5123             if (!freed
) return; /* nothing to free... */ 
5128 /* ================================= Debugging ============================== */ 
5130 static void debugCommand(redisClient 
*c
) { 
5131     if (!strcasecmp(c
->argv
[1]->ptr
,"segfault")) { 
5133     } else if (!strcasecmp(c
->argv
[1]->ptr
,"object") && c
->argc 
== 3) { 
5134         dictEntry 
*de 
= dictFind(c
->db
->dict
,c
->argv
[2]); 
5138             addReply(c
,shared
.nokeyerr
); 
5141         key 
= dictGetEntryKey(de
); 
5142         val 
= dictGetEntryVal(de
); 
5143         addReplySds(c
,sdscatprintf(sdsempty(), 
5144             "+Key at:%p refcount:%d, value at:%p refcount:%d encoding:%d\r\n", 
5145                 key
, key
->refcount
, val
, val
->refcount
, val
->encoding
)); 
5147         addReplySds(c
,sdsnew( 
5148             "-ERR Syntax error, try DEBUG [SEGFAULT|OBJECT <key>]\r\n")); 
5152 #ifdef HAVE_BACKTRACE 
5153 static struct redisFunctionSym symsTable
[] = { 
5154 {"compareStringObjects", (unsigned long)compareStringObjects
}, 
5155 {"isStringRepresentableAsLong", (unsigned long)isStringRepresentableAsLong
}, 
5156 {"dictEncObjKeyCompare", (unsigned long)dictEncObjKeyCompare
}, 
5157 {"dictEncObjHash", (unsigned long)dictEncObjHash
}, 
5158 {"incrDecrCommand", (unsigned long)incrDecrCommand
}, 
5159 {"freeStringObject", (unsigned long)freeStringObject
}, 
5160 {"freeListObject", (unsigned long)freeListObject
}, 
5161 {"freeSetObject", (unsigned long)freeSetObject
}, 
5162 {"decrRefCount", (unsigned long)decrRefCount
}, 
5163 {"createObject", (unsigned long)createObject
}, 
5164 {"freeClient", (unsigned long)freeClient
}, 
5165 {"rdbLoad", (unsigned long)rdbLoad
}, 
5166 {"rdbSaveStringObject", (unsigned long)rdbSaveStringObject
}, 
5167 {"rdbSaveStringObjectRaw", (unsigned long)rdbSaveStringObjectRaw
}, 
5168 {"addReply", (unsigned long)addReply
}, 
5169 {"addReplySds", (unsigned long)addReplySds
}, 
5170 {"incrRefCount", (unsigned long)incrRefCount
}, 
5171 {"rdbSaveBackground", (unsigned long)rdbSaveBackground
}, 
5172 {"createStringObject", (unsigned long)createStringObject
}, 
5173 {"replicationFeedSlaves", (unsigned long)replicationFeedSlaves
}, 
5174 {"syncWithMaster", (unsigned long)syncWithMaster
}, 
5175 {"tryObjectSharing", (unsigned long)tryObjectSharing
}, 
5176 {"tryObjectEncoding", (unsigned long)tryObjectEncoding
}, 
5177 {"getDecodedObject", (unsigned long)getDecodedObject
}, 
5178 {"removeExpire", (unsigned long)removeExpire
}, 
5179 {"expireIfNeeded", (unsigned long)expireIfNeeded
}, 
5180 {"deleteIfVolatile", (unsigned long)deleteIfVolatile
}, 
5181 {"deleteKey", (unsigned long)deleteKey
}, 
5182 {"getExpire", (unsigned long)getExpire
}, 
5183 {"setExpire", (unsigned long)setExpire
}, 
5184 {"updateSlavesWaitingBgsave", (unsigned long)updateSlavesWaitingBgsave
}, 
5185 {"freeMemoryIfNeeded", (unsigned long)freeMemoryIfNeeded
}, 
5186 {"authCommand", (unsigned long)authCommand
}, 
5187 {"pingCommand", (unsigned long)pingCommand
}, 
5188 {"echoCommand", (unsigned long)echoCommand
}, 
5189 {"setCommand", (unsigned long)setCommand
}, 
5190 {"setnxCommand", (unsigned long)setnxCommand
}, 
5191 {"getCommand", (unsigned long)getCommand
}, 
5192 {"delCommand", (unsigned long)delCommand
}, 
5193 {"existsCommand", (unsigned long)existsCommand
}, 
5194 {"incrCommand", (unsigned long)incrCommand
}, 
5195 {"decrCommand", (unsigned long)decrCommand
}, 
5196 {"incrbyCommand", (unsigned long)incrbyCommand
}, 
5197 {"decrbyCommand", (unsigned long)decrbyCommand
}, 
5198 {"selectCommand", (unsigned long)selectCommand
}, 
5199 {"randomkeyCommand", (unsigned long)randomkeyCommand
}, 
5200 {"keysCommand", (unsigned long)keysCommand
}, 
5201 {"dbsizeCommand", (unsigned long)dbsizeCommand
}, 
5202 {"lastsaveCommand", (unsigned long)lastsaveCommand
}, 
5203 {"saveCommand", (unsigned long)saveCommand
}, 
5204 {"bgsaveCommand", (unsigned long)bgsaveCommand
}, 
5205 {"shutdownCommand", (unsigned long)shutdownCommand
}, 
5206 {"moveCommand", (unsigned long)moveCommand
}, 
5207 {"renameCommand", (unsigned long)renameCommand
}, 
5208 {"renamenxCommand", (unsigned long)renamenxCommand
}, 
5209 {"lpushCommand", (unsigned long)lpushCommand
}, 
5210 {"rpushCommand", (unsigned long)rpushCommand
}, 
5211 {"lpopCommand", (unsigned long)lpopCommand
}, 
5212 {"rpopCommand", (unsigned long)rpopCommand
}, 
5213 {"llenCommand", (unsigned long)llenCommand
}, 
5214 {"lindexCommand", (unsigned long)lindexCommand
}, 
5215 {"lrangeCommand", (unsigned long)lrangeCommand
}, 
5216 {"ltrimCommand", (unsigned long)ltrimCommand
}, 
5217 {"typeCommand", (unsigned long)typeCommand
}, 
5218 {"lsetCommand", (unsigned long)lsetCommand
}, 
5219 {"saddCommand", (unsigned long)saddCommand
}, 
5220 {"sremCommand", (unsigned long)sremCommand
}, 
5221 {"smoveCommand", (unsigned long)smoveCommand
}, 
5222 {"sismemberCommand", (unsigned long)sismemberCommand
}, 
5223 {"scardCommand", (unsigned long)scardCommand
}, 
5224 {"spopCommand", (unsigned long)spopCommand
}, 
5225 {"srandmemberCommand", (unsigned long)srandmemberCommand
}, 
5226 {"sinterCommand", (unsigned long)sinterCommand
}, 
5227 {"sinterstoreCommand", (unsigned long)sinterstoreCommand
}, 
5228 {"sunionCommand", (unsigned long)sunionCommand
}, 
5229 {"sunionstoreCommand", (unsigned long)sunionstoreCommand
}, 
5230 {"sdiffCommand", (unsigned long)sdiffCommand
}, 
5231 {"sdiffstoreCommand", (unsigned long)sdiffstoreCommand
}, 
5232 {"syncCommand", (unsigned long)syncCommand
}, 
5233 {"flushdbCommand", (unsigned long)flushdbCommand
}, 
5234 {"flushallCommand", (unsigned long)flushallCommand
}, 
5235 {"sortCommand", (unsigned long)sortCommand
}, 
5236 {"lremCommand", (unsigned long)lremCommand
}, 
5237 {"infoCommand", (unsigned long)infoCommand
}, 
5238 {"mgetCommand", (unsigned long)mgetCommand
}, 
5239 {"monitorCommand", (unsigned long)monitorCommand
}, 
5240 {"expireCommand", (unsigned long)expireCommand
}, 
5241 {"getsetCommand", (unsigned long)getsetCommand
}, 
5242 {"ttlCommand", (unsigned long)ttlCommand
}, 
5243 {"slaveofCommand", (unsigned long)slaveofCommand
}, 
5244 {"debugCommand", (unsigned long)debugCommand
}, 
5245 {"processCommand", (unsigned long)processCommand
}, 
5246 {"setupSigSegvAction", (unsigned long)setupSigSegvAction
}, 
5247 {"readQueryFromClient", (unsigned long)readQueryFromClient
}, 
5248 {"rdbRemoveTempFile", (unsigned long)rdbRemoveTempFile
}, 
5249 {"msetGenericCommand", (unsigned long)msetGenericCommand
}, 
5250 {"msetCommand", (unsigned long)msetCommand
}, 
5251 {"msetnxCommand", (unsigned long)msetnxCommand
}, 
5252 {"zslCreateNode", (unsigned long)zslCreateNode
}, 
5253 {"zslCreate", (unsigned long)zslCreate
}, 
5254 {"zslFreeNode",(unsigned long)zslFreeNode
}, 
5255 {"zslFree",(unsigned long)zslFree
}, 
5256 {"zslRandomLevel",(unsigned long)zslRandomLevel
}, 
5257 {"zslInsert",(unsigned long)zslInsert
}, 
5258 {"zslDelete",(unsigned long)zslDelete
}, 
5259 {"createZsetObject",(unsigned long)createZsetObject
}, 
5260 {"zaddCommand",(unsigned long)zaddCommand
}, 
5261 {"zrangeGenericCommand",(unsigned long)zrangeGenericCommand
}, 
5262 {"zrangeCommand",(unsigned long)zrangeCommand
}, 
5263 {"zrevrangeCommand",(unsigned long)zrevrangeCommand
}, 
5264 {"zremCommand",(unsigned long)zremCommand
}, 
5265 {"rdbSaveDoubleValue",(unsigned long)rdbSaveDoubleValue
}, 
5266 {"rdbLoadDoubleValue",(unsigned long)rdbLoadDoubleValue
}, 
5270 /* This function try to convert a pointer into a function name. It's used in 
5271  * oreder to provide a backtrace under segmentation fault that's able to 
5272  * display functions declared as static (otherwise the backtrace is useless). */ 
5273 static char *findFuncName(void *pointer
, unsigned long *offset
){ 
5275     unsigned long off
, minoff 
= 0; 
5277     /* Try to match against the Symbol with the smallest offset */ 
5278     for (i
=0; symsTable
[i
].pointer
; i
++) { 
5279         unsigned long lp 
= (unsigned long) pointer
; 
5281         if (lp 
!= (unsigned long)-1 && lp 
>= symsTable
[i
].pointer
) { 
5282             off
=lp
-symsTable
[i
].pointer
; 
5283             if (ret 
< 0 || off 
< minoff
) { 
5289     if (ret 
== -1) return NULL
; 
5291     return symsTable
[ret
].name
; 
5294 static void *getMcontextEip(ucontext_t 
*uc
) { 
5295 #if defined(__FreeBSD__) 
5296     return (void*) uc
->uc_mcontext
.mc_eip
; 
5297 #elif defined(__dietlibc__) 
5298     return (void*) uc
->uc_mcontext
.eip
; 
5299 #elif defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6) 
5300     return (void*) uc
->uc_mcontext
->__ss
.__eip
; 
5301 #elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6) 
5302   #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__) 
5303     return (void*) uc
->uc_mcontext
->__ss
.__rip
; 
5305     return (void*) uc
->uc_mcontext
->__ss
.__eip
; 
5307 #elif defined(__i386__) || defined(__X86_64__) /* Linux x86 */ 
5308     return (void*) uc
->uc_mcontext
.gregs
[REG_EIP
]; 
5309 #elif defined(__ia64__) /* Linux IA64 */ 
5310     return (void*) uc
->uc_mcontext
.sc_ip
; 
5316 static void segvHandler(int sig
, siginfo_t 
*info
, void *secret
) { 
5318     char **messages 
= NULL
; 
5319     int i
, trace_size 
= 0; 
5320     unsigned long offset
=0; 
5321     time_t uptime 
= time(NULL
)-server
.stat_starttime
; 
5322     ucontext_t 
*uc 
= (ucontext_t
*) secret
; 
5323     REDIS_NOTUSED(info
); 
5325     redisLog(REDIS_WARNING
, 
5326         "======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION
, sig
); 
5327     redisLog(REDIS_WARNING
, "%s", sdscatprintf(sdsempty(), 
5328         "redis_version:%s; " 
5329         "uptime_in_seconds:%d; " 
5330         "connected_clients:%d; " 
5331         "connected_slaves:%d; " 
5333         "changes_since_last_save:%lld; " 
5334         "bgsave_in_progress:%d; " 
5335         "last_save_time:%d; " 
5336         "total_connections_received:%lld; " 
5337         "total_commands_processed:%lld; " 
5341         listLength(server
.clients
)-listLength(server
.slaves
), 
5342         listLength(server
.slaves
), 
5345         server
.bgsaveinprogress
, 
5347         server
.stat_numconnections
, 
5348         server
.stat_numcommands
, 
5349         server
.masterhost 
== NULL 
? "master" : "slave" 
5352     trace_size 
= backtrace(trace
, 100); 
5353     /* overwrite sigaction with caller's address */ 
5354     if (getMcontextEip(uc
) != NULL
) { 
5355         trace
[1] = getMcontextEip(uc
); 
5357     messages 
= backtrace_symbols(trace
, trace_size
); 
5359     for (i
=1; i
<trace_size
; ++i
) { 
5360         char *fn 
= findFuncName(trace
[i
], &offset
), *p
; 
5362         p 
= strchr(messages
[i
],'+'); 
5363         if (!fn 
|| (p 
&& ((unsigned long)strtol(p
+1,NULL
,10)) < offset
)) { 
5364             redisLog(REDIS_WARNING
,"%s", messages
[i
]); 
5366             redisLog(REDIS_WARNING
,"%d redis-server %p %s + %d", i
, trace
[i
], fn
, (unsigned int)offset
); 
5373 static void setupSigSegvAction(void) { 
5374     struct sigaction act
; 
5376     sigemptyset (&act
.sa_mask
); 
5377     /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction 
5378      * is used. Otherwise, sa_handler is used */ 
5379     act
.sa_flags 
= SA_NODEFER 
| SA_ONSTACK 
| SA_RESETHAND 
| SA_SIGINFO
; 
5380     act
.sa_sigaction 
= segvHandler
; 
5381     sigaction (SIGSEGV
, &act
, NULL
); 
5382     sigaction (SIGBUS
, &act
, NULL
); 
5383     sigaction (SIGFPE
, &act
, NULL
); 
5384     sigaction (SIGILL
, &act
, NULL
); 
5385     sigaction (SIGBUS
, &act
, NULL
); 
5388 #else /* HAVE_BACKTRACE */ 
5389 static void setupSigSegvAction(void) { 
5391 #endif /* HAVE_BACKTRACE */ 
5393 /* =================================== Main! ================================ */ 
5396 int linuxOvercommitMemoryValue(void) { 
5397     FILE *fp 
= fopen("/proc/sys/vm/overcommit_memory","r"); 
5401     if (fgets(buf
,64,fp
) == NULL
) { 
5410 void linuxOvercommitMemoryWarning(void) { 
5411     if (linuxOvercommitMemoryValue() == 0) { 
5412         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."); 
5415 #endif /* __linux__ */ 
5417 static void daemonize(void) { 
5421     if (fork() != 0) exit(0); /* parent exits */ 
5422     setsid(); /* create a new session */ 
5424     /* Every output goes to /dev/null. If Redis is daemonized but 
5425      * the 'logfile' is set to 'stdout' in the configuration file 
5426      * it will not log at all. */ 
5427     if ((fd 
= open("/dev/null", O_RDWR
, 0)) != -1) { 
5428         dup2(fd
, STDIN_FILENO
); 
5429         dup2(fd
, STDOUT_FILENO
); 
5430         dup2(fd
, STDERR_FILENO
); 
5431         if (fd 
> STDERR_FILENO
) close(fd
); 
5433     /* Try to write the pid file */ 
5434     fp 
= fopen(server
.pidfile
,"w"); 
5436         fprintf(fp
,"%d\n",getpid()); 
5441 int main(int argc
, char **argv
) { 
5444         ResetServerSaveParams(); 
5445         loadServerConfig(argv
[1]); 
5446     } else if (argc 
> 2) { 
5447         fprintf(stderr
,"Usage: ./redis-server [/path/to/redis.conf]\n"); 
5450         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'"); 
5453     if (server
.daemonize
) daemonize(); 
5454     redisLog(REDIS_NOTICE
,"Server started, Redis version " REDIS_VERSION
); 
5456     linuxOvercommitMemoryWarning(); 
5458     if (rdbLoad(server
.dbfilename
) == REDIS_OK
) 
5459         redisLog(REDIS_NOTICE
,"DB loaded from disk"); 
5460     if (aeCreateFileEvent(server
.el
, server
.fd
, AE_READABLE
, 
5461         acceptHandler
, NULL
, NULL
) == AE_ERR
) oom("creating file event"); 
5462     redisLog(REDIS_NOTICE
,"The server is now ready to accept connections on port %d", server
.port
); 
5464     aeDeleteEventLoop(server
.el
);