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 "0.900" 
  40 #define __USE_POSIX199309 
  46 #endif /* HAVE_BACKTRACE */ 
  54 #include <arpa/inet.h> 
  58 #include <sys/resource.h> 
  62 #include "ae.h"     /* Event driven programming library */ 
  63 #include "sds.h"    /* Dynamic safe strings */ 
  64 #include "anet.h"   /* Networking the easy way */ 
  65 #include "dict.h"   /* Hash tables */ 
  66 #include "adlist.h" /* Linked lists */ 
  67 #include "zmalloc.h" /* total memory usage aware version of malloc/free */ 
  68 #include "lzf.h"    /* LZF compression library */ 
  69 #include "pqsort.h" /* Partial qsort for SORT+LIMIT */ 
  75 /* Static server configuration */ 
  76 #define REDIS_SERVERPORT        6379    /* TCP port */ 
  77 #define REDIS_MAXIDLETIME       (60*5)  /* default client timeout */ 
  78 #define REDIS_IOBUF_LEN         1024 
  79 #define REDIS_LOADBUF_LEN       1024 
  80 #define REDIS_STATIC_ARGS       4 
  81 #define REDIS_DEFAULT_DBNUM     16 
  82 #define REDIS_CONFIGLINE_MAX    1024 
  83 #define REDIS_OBJFREELIST_MAX   1000000 /* Max number of objects to cache */ 
  84 #define REDIS_MAX_SYNC_TIME     60      /* Slave can't take more to sync */ 
  85 #define REDIS_EXPIRELOOKUPS_PER_CRON    100 /* try to expire 100 keys/second */ 
  86 #define REDIS_MAX_WRITE_PER_EVENT (1024*64) 
  87 #define REDIS_REQUEST_MAX_SIZE  (1024*1024*256) /* max bytes in inline command */ 
  89 /* Hash table parameters */ 
  90 #define REDIS_HT_MINFILL        10      /* Minimal hash table fill 10% */ 
  93 #define REDIS_CMD_BULK          1       /* Bulk write command */ 
  94 #define REDIS_CMD_INLINE        2       /* Inline command */ 
  95 /* REDIS_CMD_DENYOOM reserves a longer comment: all the commands marked with 
  96    this flags will return an error when the 'maxmemory' option is set in the 
  97    config file and the server is using more than maxmemory bytes of memory. 
  98    In short this commands are denied on low memory conditions. */ 
  99 #define REDIS_CMD_DENYOOM       4 
 102 #define REDIS_STRING 0 
 107 /* Object types only used for dumping to disk */ 
 108 #define REDIS_EXPIRETIME 253 
 109 #define REDIS_SELECTDB 254 
 110 #define REDIS_EOF 255 
 112 /* Defines related to the dump file format. To store 32 bits lengths for short 
 113  * keys requires a lot of space, so we check the most significant 2 bits of 
 114  * the first byte to interpreter the length: 
 116  * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte 
 117  * 01|000000 00000000 =>  01, the len is 14 byes, 6 bits + 8 bits of next byte 
 118  * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow 
 119  * 11|000000 this means: specially encoded object will follow. The six bits 
 120  *           number specify the kind of object that follows. 
 121  *           See the REDIS_RDB_ENC_* defines. 
 123  * Lenghts up to 63 are stored using a single byte, most DB keys, and may 
 124  * values, will fit inside. */ 
 125 #define REDIS_RDB_6BITLEN 0 
 126 #define REDIS_RDB_14BITLEN 1 
 127 #define REDIS_RDB_32BITLEN 2 
 128 #define REDIS_RDB_ENCVAL 3 
 129 #define REDIS_RDB_LENERR UINT_MAX 
 131 /* When a length of a string object stored on disk has the first two bits 
 132  * set, the remaining two bits specify a special encoding for the object 
 133  * accordingly to the following defines: */ 
 134 #define REDIS_RDB_ENC_INT8 0        /* 8 bit signed integer */ 
 135 #define REDIS_RDB_ENC_INT16 1       /* 16 bit signed integer */ 
 136 #define REDIS_RDB_ENC_INT32 2       /* 32 bit signed integer */ 
 137 #define REDIS_RDB_ENC_LZF 3         /* string compressed with FASTLZ */ 
 140 #define REDIS_CLOSE 1       /* This client connection should be closed ASAP */ 
 141 #define REDIS_SLAVE 2       /* This client is a slave server */ 
 142 #define REDIS_MASTER 4      /* This client is a master server */ 
 143 #define REDIS_MONITOR 8      /* This client is a slave monitor, see MONITOR */ 
 145 /* Slave replication state - slave side */ 
 146 #define REDIS_REPL_NONE 0   /* No active replication */ 
 147 #define REDIS_REPL_CONNECT 1    /* Must connect to master */ 
 148 #define REDIS_REPL_CONNECTED 2  /* Connected to master */ 
 150 /* Slave replication state - from the point of view of master 
 151  * Note that in SEND_BULK and ONLINE state the slave receives new updates 
 152  * in its output queue. In the WAIT_BGSAVE state instead the server is waiting 
 153  * to start the next background saving in order to send updates to it. */ 
 154 #define REDIS_REPL_WAIT_BGSAVE_START 3 /* master waits bgsave to start feeding it */ 
 155 #define REDIS_REPL_WAIT_BGSAVE_END 4 /* master waits bgsave to start bulk DB transmission */ 
 156 #define REDIS_REPL_SEND_BULK 5 /* master is sending the bulk DB */ 
 157 #define REDIS_REPL_ONLINE 6 /* bulk DB already transmitted, receive updates */ 
 159 /* List related stuff */ 
 163 /* Sort operations */ 
 164 #define REDIS_SORT_GET 0 
 165 #define REDIS_SORT_DEL 1 
 166 #define REDIS_SORT_INCR 2 
 167 #define REDIS_SORT_DECR 3 
 168 #define REDIS_SORT_ASC 4 
 169 #define REDIS_SORT_DESC 5 
 170 #define REDIS_SORTKEY_MAX 1024 
 173 #define REDIS_DEBUG 0 
 174 #define REDIS_NOTICE 1 
 175 #define REDIS_WARNING 2 
 177 /* Anti-warning macro... */ 
 178 #define REDIS_NOTUSED(V) ((void) V) 
 181 /*================================= Data types ============================== */ 
 183 /* A redis object, that is a type able to hold a string / list / set */ 
 184 typedef struct redisObject 
{ 
 190 typedef struct redisDb 
{ 
 196 /* With multiplexing we need to take per-clinet state. 
 197  * Clients are taken in a liked list. */ 
 198 typedef struct redisClient 
{ 
 205     int bulklen
;            /* bulk read len. -1 if not in bulk read mode */ 
 208     time_t lastinteraction
; /* time of the last interaction, used for timeout */ 
 209     int flags
;              /* REDIS_CLOSE | REDIS_SLAVE | REDIS_MONITOR */ 
 210     int slaveseldb
;         /* slave selected db, if this client is a slave */ 
 211     int authenticated
;      /* when requirepass is non-NULL */ 
 212     int replstate
;          /* replication state if this is a slave */ 
 213     int repldbfd
;           /* replication DB file descriptor */ 
 214     long repldboff
;          /* replication DB file offset */ 
 215     off_t repldbsize
;       /* replication DB file size */ 
 223 /* Global server state structure */ 
 229     unsigned int sharingpoolsize
; 
 230     long long dirty
;            /* changes to DB from the last save */ 
 232     list 
*slaves
, *monitors
; 
 233     char neterr
[ANET_ERR_LEN
]; 
 235     int cronloops
;              /* number of times the cron function run */ 
 236     list 
*objfreelist
;          /* A list of freed objects to avoid malloc() */ 
 237     time_t lastsave
;            /* Unix time of last save succeeede */ 
 238     size_t usedmemory
;             /* Used memory in megabytes */ 
 239     /* Fields used only for stats */ 
 240     time_t stat_starttime
;         /* server start time */ 
 241     long long stat_numcommands
;    /* number of processed commands */ 
 242     long long stat_numconnections
; /* number of connections received */ 
 250     int bgsaveinprogress
; 
 251     pid_t bgsavechildpid
; 
 252     struct saveparam 
*saveparams
; 
 259     /* Replication related */ 
 263     redisClient 
*master
;    /* client that is master for this slave */ 
 265     unsigned int maxclients
; 
 266     unsigned int maxmemory
; 
 267     /* Sort parameters - qsort_r() is only available under BSD so we 
 268      * have to take this state global, in order to pass it to sortCompare() */ 
 274 typedef void redisCommandProc(redisClient 
*c
); 
 275 struct redisCommand 
{ 
 277     redisCommandProc 
*proc
; 
 282 struct redisFunctionSym 
{ 
 284     unsigned long pointer
; 
 287 typedef struct _redisSortObject 
{ 
 295 typedef struct _redisSortOperation 
{ 
 298 } redisSortOperation
; 
 300 struct sharedObjectsStruct 
{ 
 301     robj 
*crlf
, *ok
, *err
, *emptybulk
, *czero
, *cone
, *pong
, *space
, 
 302     *colon
, *nullbulk
, *nullmultibulk
, 
 303     *emptymultibulk
, *wrongtypeerr
, *nokeyerr
, *syntaxerr
, *sameobjecterr
, 
 304     *outofrangeerr
, *plus
, 
 305     *select0
, *select1
, *select2
, *select3
, *select4
, 
 306     *select5
, *select6
, *select7
, *select8
, *select9
; 
 309 /*================================ Prototypes =============================== */ 
 311 static void freeStringObject(robj 
*o
); 
 312 static void freeListObject(robj 
*o
); 
 313 static void freeSetObject(robj 
*o
); 
 314 static void decrRefCount(void *o
); 
 315 static robj 
*createObject(int type
, void *ptr
); 
 316 static void freeClient(redisClient 
*c
); 
 317 static int rdbLoad(char *filename
); 
 318 static void addReply(redisClient 
*c
, robj 
*obj
); 
 319 static void addReplySds(redisClient 
*c
, sds s
); 
 320 static void incrRefCount(robj 
*o
); 
 321 static int rdbSaveBackground(char *filename
); 
 322 static robj 
*createStringObject(char *ptr
, size_t len
); 
 323 static void replicationFeedSlaves(list 
*slaves
, struct redisCommand 
*cmd
, int dictid
, robj 
**argv
, int argc
); 
 324 static int syncWithMaster(void); 
 325 static robj 
*tryObjectSharing(robj 
*o
); 
 326 static int removeExpire(redisDb 
*db
, robj 
*key
); 
 327 static int expireIfNeeded(redisDb 
*db
, robj 
*key
); 
 328 static int deleteIfVolatile(redisDb 
*db
, robj 
*key
); 
 329 static int deleteKey(redisDb 
*db
, robj 
*key
); 
 330 static time_t getExpire(redisDb 
*db
, robj 
*key
); 
 331 static int setExpire(redisDb 
*db
, robj 
*key
, time_t when
); 
 332 static void updateSlavesWaitingBgsave(int bgsaveerr
); 
 333 static void freeMemoryIfNeeded(void); 
 334 static int processCommand(redisClient 
*c
); 
 335 static void setupSigSegvAction(void); 
 336 static void rdbRemoveTempFile(pid_t childpid
); 
 338 static void authCommand(redisClient 
*c
); 
 339 static void pingCommand(redisClient 
*c
); 
 340 static void echoCommand(redisClient 
*c
); 
 341 static void setCommand(redisClient 
*c
); 
 342 static void setnxCommand(redisClient 
*c
); 
 343 static void getCommand(redisClient 
*c
); 
 344 static void delCommand(redisClient 
*c
); 
 345 static void existsCommand(redisClient 
*c
); 
 346 static void incrCommand(redisClient 
*c
); 
 347 static void decrCommand(redisClient 
*c
); 
 348 static void incrbyCommand(redisClient 
*c
); 
 349 static void decrbyCommand(redisClient 
*c
); 
 350 static void selectCommand(redisClient 
*c
); 
 351 static void randomkeyCommand(redisClient 
*c
); 
 352 static void keysCommand(redisClient 
*c
); 
 353 static void dbsizeCommand(redisClient 
*c
); 
 354 static void lastsaveCommand(redisClient 
*c
); 
 355 static void saveCommand(redisClient 
*c
); 
 356 static void bgsaveCommand(redisClient 
*c
); 
 357 static void shutdownCommand(redisClient 
*c
); 
 358 static void moveCommand(redisClient 
*c
); 
 359 static void renameCommand(redisClient 
*c
); 
 360 static void renamenxCommand(redisClient 
*c
); 
 361 static void lpushCommand(redisClient 
*c
); 
 362 static void rpushCommand(redisClient 
*c
); 
 363 static void lpopCommand(redisClient 
*c
); 
 364 static void rpopCommand(redisClient 
*c
); 
 365 static void llenCommand(redisClient 
*c
); 
 366 static void lindexCommand(redisClient 
*c
); 
 367 static void lrangeCommand(redisClient 
*c
); 
 368 static void ltrimCommand(redisClient 
*c
); 
 369 static void typeCommand(redisClient 
*c
); 
 370 static void lsetCommand(redisClient 
*c
); 
 371 static void saddCommand(redisClient 
*c
); 
 372 static void sremCommand(redisClient 
*c
); 
 373 static void smoveCommand(redisClient 
*c
); 
 374 static void sismemberCommand(redisClient 
*c
); 
 375 static void scardCommand(redisClient 
*c
); 
 376 static void spopCommand(redisClient 
*c
); 
 377 static void sinterCommand(redisClient 
*c
); 
 378 static void sinterstoreCommand(redisClient 
*c
); 
 379 static void sunionCommand(redisClient 
*c
); 
 380 static void sunionstoreCommand(redisClient 
*c
); 
 381 static void sdiffCommand(redisClient 
*c
); 
 382 static void sdiffstoreCommand(redisClient 
*c
); 
 383 static void syncCommand(redisClient 
*c
); 
 384 static void flushdbCommand(redisClient 
*c
); 
 385 static void flushallCommand(redisClient 
*c
); 
 386 static void sortCommand(redisClient 
*c
); 
 387 static void lremCommand(redisClient 
*c
); 
 388 static void infoCommand(redisClient 
*c
); 
 389 static void mgetCommand(redisClient 
*c
); 
 390 static void monitorCommand(redisClient 
*c
); 
 391 static void expireCommand(redisClient 
*c
); 
 392 static void getSetCommand(redisClient 
*c
); 
 393 static void ttlCommand(redisClient 
*c
); 
 394 static void slaveofCommand(redisClient 
*c
); 
 395 static void debugCommand(redisClient 
*c
); 
 396 /*================================= Globals ================================= */ 
 399 static struct redisServer server
; /* server global state */ 
 400 static struct redisCommand cmdTable
[] = { 
 401     {"get",getCommand
,2,REDIS_CMD_INLINE
}, 
 402     {"set",setCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 403     {"setnx",setnxCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 404     {"del",delCommand
,-2,REDIS_CMD_INLINE
}, 
 405     {"exists",existsCommand
,2,REDIS_CMD_INLINE
}, 
 406     {"incr",incrCommand
,2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 407     {"decr",decrCommand
,2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 408     {"mget",mgetCommand
,-2,REDIS_CMD_INLINE
}, 
 409     {"rpush",rpushCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 410     {"lpush",lpushCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 411     {"rpop",rpopCommand
,2,REDIS_CMD_INLINE
}, 
 412     {"lpop",lpopCommand
,2,REDIS_CMD_INLINE
}, 
 413     {"llen",llenCommand
,2,REDIS_CMD_INLINE
}, 
 414     {"lindex",lindexCommand
,3,REDIS_CMD_INLINE
}, 
 415     {"lset",lsetCommand
,4,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 416     {"lrange",lrangeCommand
,4,REDIS_CMD_INLINE
}, 
 417     {"ltrim",ltrimCommand
,4,REDIS_CMD_INLINE
}, 
 418     {"lrem",lremCommand
,4,REDIS_CMD_BULK
}, 
 419     {"sadd",saddCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 420     {"srem",sremCommand
,3,REDIS_CMD_BULK
}, 
 421     {"smove",smoveCommand
,4,REDIS_CMD_BULK
}, 
 422     {"sismember",sismemberCommand
,3,REDIS_CMD_BULK
}, 
 423     {"scard",scardCommand
,2,REDIS_CMD_INLINE
}, 
 424     {"spop",spopCommand
,2,REDIS_CMD_INLINE
}, 
 425     {"sinter",sinterCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 426     {"sinterstore",sinterstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 427     {"sunion",sunionCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 428     {"sunionstore",sunionstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 429     {"sdiff",sdiffCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 430     {"sdiffstore",sdiffstoreCommand
,-3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 431     {"smembers",sinterCommand
,2,REDIS_CMD_INLINE
}, 
 432     {"incrby",incrbyCommand
,3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 433     {"decrby",decrbyCommand
,3,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 434     {"getset",getSetCommand
,3,REDIS_CMD_BULK
|REDIS_CMD_DENYOOM
}, 
 435     {"randomkey",randomkeyCommand
,1,REDIS_CMD_INLINE
}, 
 436     {"select",selectCommand
,2,REDIS_CMD_INLINE
}, 
 437     {"move",moveCommand
,3,REDIS_CMD_INLINE
}, 
 438     {"rename",renameCommand
,3,REDIS_CMD_INLINE
}, 
 439     {"renamenx",renamenxCommand
,3,REDIS_CMD_INLINE
}, 
 440     {"expire",expireCommand
,3,REDIS_CMD_INLINE
}, 
 441     {"keys",keysCommand
,2,REDIS_CMD_INLINE
}, 
 442     {"dbsize",dbsizeCommand
,1,REDIS_CMD_INLINE
}, 
 443     {"auth",authCommand
,2,REDIS_CMD_INLINE
}, 
 444     {"ping",pingCommand
,1,REDIS_CMD_INLINE
}, 
 445     {"echo",echoCommand
,2,REDIS_CMD_BULK
}, 
 446     {"save",saveCommand
,1,REDIS_CMD_INLINE
}, 
 447     {"bgsave",bgsaveCommand
,1,REDIS_CMD_INLINE
}, 
 448     {"shutdown",shutdownCommand
,1,REDIS_CMD_INLINE
}, 
 449     {"lastsave",lastsaveCommand
,1,REDIS_CMD_INLINE
}, 
 450     {"type",typeCommand
,2,REDIS_CMD_INLINE
}, 
 451     {"sync",syncCommand
,1,REDIS_CMD_INLINE
}, 
 452     {"flushdb",flushdbCommand
,1,REDIS_CMD_INLINE
}, 
 453     {"flushall",flushallCommand
,1,REDIS_CMD_INLINE
}, 
 454     {"sort",sortCommand
,-2,REDIS_CMD_INLINE
|REDIS_CMD_DENYOOM
}, 
 455     {"info",infoCommand
,1,REDIS_CMD_INLINE
}, 
 456     {"monitor",monitorCommand
,1,REDIS_CMD_INLINE
}, 
 457     {"ttl",ttlCommand
,2,REDIS_CMD_INLINE
}, 
 458     {"slaveof",slaveofCommand
,3,REDIS_CMD_INLINE
}, 
 459     {"debug",debugCommand
,-2,REDIS_CMD_INLINE
}, 
 462 /*============================ Utility functions ============================ */ 
 464 /* Glob-style pattern matching. */ 
 465 int stringmatchlen(const char *pattern
, int patternLen
, 
 466         const char *string
, int stringLen
, int nocase
) 
 471             while (pattern
[1] == '*') { 
 476                 return 1; /* match */ 
 478                 if (stringmatchlen(pattern
+1, patternLen
-1, 
 479                             string
, stringLen
, nocase
)) 
 480                     return 1; /* match */ 
 484             return 0; /* no match */ 
 488                 return 0; /* no match */ 
 498             not = pattern
[0] == '^'; 
 505                 if (pattern
[0] == '\\') { 
 508                     if (pattern
[0] == string
[0]) 
 510                 } else if (pattern
[0] == ']') { 
 512                 } else if (patternLen 
== 0) { 
 516                 } else if (pattern
[1] == '-' && patternLen 
>= 3) { 
 517                     int start 
= pattern
[0]; 
 518                     int end 
= pattern
[2]; 
 526                         start 
= tolower(start
); 
 532                     if (c 
>= start 
&& c 
<= end
) 
 536                         if (pattern
[0] == string
[0]) 
 539                         if (tolower((int)pattern
[0]) == tolower((int)string
[0])) 
 549                 return 0; /* no match */ 
 555             if (patternLen 
>= 2) { 
 562                 if (pattern
[0] != string
[0]) 
 563                     return 0; /* no match */ 
 565                 if (tolower((int)pattern
[0]) != tolower((int)string
[0])) 
 566                     return 0; /* no match */ 
 574         if (stringLen 
== 0) { 
 575             while(*pattern 
== '*') { 
 582     if (patternLen 
== 0 && stringLen 
== 0) 
 587 static void redisLog(int level
, const char *fmt
, ...) { 
 591     fp 
= (server
.logfile 
== NULL
) ? stdout 
: fopen(server
.logfile
,"a"); 
 595     if (level 
>= server
.verbosity
) { 
 601         strftime(buf
,64,"%d %b %H:%M:%S",gmtime(&now
)); 
 602         fprintf(fp
,"%s %c ",buf
,c
[level
]); 
 603         vfprintf(fp
, fmt
, ap
); 
 609     if (server
.logfile
) fclose(fp
); 
 612 /*====================== Hash table type implementation  ==================== */ 
 614 /* This is an hash table type that uses the SDS dynamic strings libary as 
 615  * keys and radis objects as values (objects can hold SDS strings, 
 618 static int sdsDictKeyCompare(void *privdata
, const void *key1
, 
 622     DICT_NOTUSED(privdata
); 
 624     l1 
= sdslen((sds
)key1
); 
 625     l2 
= sdslen((sds
)key2
); 
 626     if (l1 
!= l2
) return 0; 
 627     return memcmp(key1
, key2
, l1
) == 0; 
 630 static void dictRedisObjectDestructor(void *privdata
, void *val
) 
 632     DICT_NOTUSED(privdata
); 
 637 static int dictSdsKeyCompare(void *privdata
, const void *key1
, 
 640     const robj 
*o1 
= key1
, *o2 
= key2
; 
 641     return sdsDictKeyCompare(privdata
,o1
->ptr
,o2
->ptr
); 
 644 static unsigned int dictSdsHash(const void *key
) { 
 646     return dictGenHashFunction(o
->ptr
, sdslen((sds
)o
->ptr
)); 
 649 static dictType setDictType 
= { 
 650     dictSdsHash
,               /* hash function */ 
 653     dictSdsKeyCompare
,         /* key compare */ 
 654     dictRedisObjectDestructor
, /* key destructor */ 
 655     NULL                       
/* val destructor */ 
 658 static dictType hashDictType 
= { 
 659     dictSdsHash
,                /* hash function */ 
 662     dictSdsKeyCompare
,          /* key compare */ 
 663     dictRedisObjectDestructor
,  /* key destructor */ 
 664     dictRedisObjectDestructor   
/* val destructor */ 
 667 /* ========================= Random utility functions ======================= */ 
 669 /* Redis generally does not try to recover from out of memory conditions 
 670  * when allocating objects or strings, it is not clear if it will be possible 
 671  * to report this condition to the client since the networking layer itself 
 672  * is based on heap allocation for send buffers, so we simply abort. 
 673  * At least the code will be simpler to read... */ 
 674 static void oom(const char *msg
) { 
 675     fprintf(stderr
, "%s: Out of memory\n",msg
); 
 681 /* ====================== Redis server networking stuff ===================== */ 
 682 static void closeTimedoutClients(void) { 
 685     time_t now 
= time(NULL
); 
 687     listRewind(server
.clients
); 
 688     while ((ln 
= listYield(server
.clients
)) != NULL
) { 
 689         c 
= listNodeValue(ln
); 
 690         if (!(c
->flags 
& REDIS_SLAVE
) &&    /* no timeout for slaves */ 
 691             !(c
->flags 
& REDIS_MASTER
) &&   /* no timeout for masters */ 
 692              (now 
- c
->lastinteraction 
> server
.maxidletime
)) { 
 693             redisLog(REDIS_DEBUG
,"Closing idle client"); 
 699 static int htNeedsResize(dict 
*dict
) { 
 700     long long size
, used
; 
 702     size 
= dictSlots(dict
); 
 703     used 
= dictSize(dict
); 
 704     return (size 
&& used 
&& size 
> DICT_HT_INITIAL_SIZE 
&& 
 705             (used
*100/size 
< REDIS_HT_MINFILL
)); 
 708 /* If the percentage of used slots in the HT reaches REDIS_HT_MINFILL 
 709  * we resize the hash table to save memory */ 
 710 static void tryResizeHashTables(void) { 
 713     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 714         if (htNeedsResize(server
.db
[j
].dict
)) { 
 715             redisLog(REDIS_DEBUG
,"The hash table %d is too sparse, resize it...",j
); 
 716             dictResize(server
.db
[j
].dict
); 
 717             redisLog(REDIS_DEBUG
,"Hash table %d resized.",j
); 
 719         if (htNeedsResize(server
.db
[j
].expires
)) 
 720             dictResize(server
.db
[j
].expires
); 
 724 static int serverCron(struct aeEventLoop 
*eventLoop
, long long id
, void *clientData
) { 
 725     int j
, loops 
= server
.cronloops
++; 
 726     REDIS_NOTUSED(eventLoop
); 
 728     REDIS_NOTUSED(clientData
); 
 730     /* Update the global state with the amount of used memory */ 
 731     server
.usedmemory 
= zmalloc_used_memory(); 
 733     /* Show some info about non-empty databases */ 
 734     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 735         long long size
, used
, vkeys
; 
 737         size 
= dictSlots(server
.db
[j
].dict
); 
 738         used 
= dictSize(server
.db
[j
].dict
); 
 739         vkeys 
= dictSize(server
.db
[j
].expires
); 
 740         if (!(loops 
% 5) && (used 
|| vkeys
)) { 
 741             redisLog(REDIS_DEBUG
,"DB %d: %lld keys (%lld volatile) in %lld slots HT.",j
,used
,vkeys
,size
); 
 742             /* dictPrintStats(server.dict); */ 
 746     /* We don't want to resize the hash tables while a bacground saving 
 747      * is in progress: the saving child is created using fork() that is 
 748      * implemented with a copy-on-write semantic in most modern systems, so 
 749      * if we resize the HT while there is the saving child at work actually 
 750      * a lot of memory movements in the parent will cause a lot of pages 
 752     if (!server
.bgsaveinprogress
) tryResizeHashTables(); 
 754     /* Show information about connected clients */ 
 756         redisLog(REDIS_DEBUG
,"%d clients connected (%d slaves), %zu bytes in use, %d shared objects", 
 757             listLength(server
.clients
)-listLength(server
.slaves
), 
 758             listLength(server
.slaves
), 
 760             dictSize(server
.sharingpool
)); 
 763     /* Close connections of timedout clients */ 
 764     if (server
.maxidletime 
&& !(loops 
% 10)) 
 765         closeTimedoutClients(); 
 767     /* Check if a background saving in progress terminated */ 
 768     if (server
.bgsaveinprogress
) { 
 770         if (wait4(-1,&statloc
,WNOHANG
,NULL
)) { 
 771             int exitcode 
= WEXITSTATUS(statloc
); 
 772             int bysignal 
= WIFSIGNALED(statloc
); 
 774             if (!bysignal 
&& exitcode 
== 0) { 
 775                 redisLog(REDIS_NOTICE
, 
 776                     "Background saving terminated with success"); 
 778                 server
.lastsave 
= time(NULL
); 
 779             } else if (!bysignal 
&& exitcode 
!= 0) { 
 780                 redisLog(REDIS_WARNING
, "Background saving error"); 
 782                 redisLog(REDIS_WARNING
, 
 783                     "Background saving terminated by signal"); 
 784                 rdbRemoveTempFile(server
.bgsavechildpid
); 
 786             server
.bgsaveinprogress 
= 0; 
 787             server
.bgsavechildpid 
= -1; 
 788             updateSlavesWaitingBgsave(exitcode 
== 0 ? REDIS_OK 
: REDIS_ERR
); 
 791         /* If there is not a background saving in progress check if 
 792          * we have to save now */ 
 793          time_t now 
= time(NULL
); 
 794          for (j 
= 0; j 
< server
.saveparamslen
; j
++) { 
 795             struct saveparam 
*sp 
= server
.saveparams
+j
; 
 797             if (server
.dirty 
>= sp
->changes 
&& 
 798                 now
-server
.lastsave 
> sp
->seconds
) { 
 799                 redisLog(REDIS_NOTICE
,"%d changes in %d seconds. Saving...", 
 800                     sp
->changes
, sp
->seconds
); 
 801                 rdbSaveBackground(server
.dbfilename
); 
 807     /* Try to expire a few timed out keys */ 
 808     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 809         redisDb 
*db 
= server
.db
+j
; 
 810         int num 
= dictSize(db
->expires
); 
 813             time_t now 
= time(NULL
); 
 815             if (num 
> REDIS_EXPIRELOOKUPS_PER_CRON
) 
 816                 num 
= REDIS_EXPIRELOOKUPS_PER_CRON
; 
 821                 if ((de 
= dictGetRandomKey(db
->expires
)) == NULL
) break; 
 822                 t 
= (time_t) dictGetEntryVal(de
); 
 824                     deleteKey(db
,dictGetEntryKey(de
)); 
 830     /* Check if we should connect to a MASTER */ 
 831     if (server
.replstate 
== REDIS_REPL_CONNECT
) { 
 832         redisLog(REDIS_NOTICE
,"Connecting to MASTER..."); 
 833         if (syncWithMaster() == REDIS_OK
) { 
 834             redisLog(REDIS_NOTICE
,"MASTER <-> SLAVE sync succeeded"); 
 840 static void createSharedObjects(void) { 
 841     shared
.crlf 
= createObject(REDIS_STRING
,sdsnew("\r\n")); 
 842     shared
.ok 
= createObject(REDIS_STRING
,sdsnew("+OK\r\n")); 
 843     shared
.err 
= createObject(REDIS_STRING
,sdsnew("-ERR\r\n")); 
 844     shared
.emptybulk 
= createObject(REDIS_STRING
,sdsnew("$0\r\n\r\n")); 
 845     shared
.czero 
= createObject(REDIS_STRING
,sdsnew(":0\r\n")); 
 846     shared
.cone 
= createObject(REDIS_STRING
,sdsnew(":1\r\n")); 
 847     shared
.nullbulk 
= createObject(REDIS_STRING
,sdsnew("$-1\r\n")); 
 848     shared
.nullmultibulk 
= createObject(REDIS_STRING
,sdsnew("*-1\r\n")); 
 849     shared
.emptymultibulk 
= createObject(REDIS_STRING
,sdsnew("*0\r\n")); 
 851     shared
.pong 
= createObject(REDIS_STRING
,sdsnew("+PONG\r\n")); 
 852     shared
.wrongtypeerr 
= createObject(REDIS_STRING
,sdsnew( 
 853         "-ERR Operation against a key holding the wrong kind of value\r\n")); 
 854     shared
.nokeyerr 
= createObject(REDIS_STRING
,sdsnew( 
 855         "-ERR no such key\r\n")); 
 856     shared
.syntaxerr 
= createObject(REDIS_STRING
,sdsnew( 
 857         "-ERR syntax error\r\n")); 
 858     shared
.sameobjecterr 
= createObject(REDIS_STRING
,sdsnew( 
 859         "-ERR source and destination objects are the same\r\n")); 
 860     shared
.outofrangeerr 
= createObject(REDIS_STRING
,sdsnew( 
 861         "-ERR index out of range\r\n")); 
 862     shared
.space 
= createObject(REDIS_STRING
,sdsnew(" ")); 
 863     shared
.colon 
= createObject(REDIS_STRING
,sdsnew(":")); 
 864     shared
.plus 
= createObject(REDIS_STRING
,sdsnew("+")); 
 865     shared
.select0 
= createStringObject("select 0\r\n",10); 
 866     shared
.select1 
= createStringObject("select 1\r\n",10); 
 867     shared
.select2 
= createStringObject("select 2\r\n",10); 
 868     shared
.select3 
= createStringObject("select 3\r\n",10); 
 869     shared
.select4 
= createStringObject("select 4\r\n",10); 
 870     shared
.select5 
= createStringObject("select 5\r\n",10); 
 871     shared
.select6 
= createStringObject("select 6\r\n",10); 
 872     shared
.select7 
= createStringObject("select 7\r\n",10); 
 873     shared
.select8 
= createStringObject("select 8\r\n",10); 
 874     shared
.select9 
= createStringObject("select 9\r\n",10); 
 877 static void appendServerSaveParams(time_t seconds
, int changes
) { 
 878     server
.saveparams 
= zrealloc(server
.saveparams
,sizeof(struct saveparam
)*(server
.saveparamslen
+1)); 
 879     if (server
.saveparams 
== NULL
) oom("appendServerSaveParams"); 
 880     server
.saveparams
[server
.saveparamslen
].seconds 
= seconds
; 
 881     server
.saveparams
[server
.saveparamslen
].changes 
= changes
; 
 882     server
.saveparamslen
++; 
 885 static void ResetServerSaveParams() { 
 886     zfree(server
.saveparams
); 
 887     server
.saveparams 
= NULL
; 
 888     server
.saveparamslen 
= 0; 
 891 static void initServerConfig() { 
 892     server
.dbnum 
= REDIS_DEFAULT_DBNUM
; 
 893     server
.port 
= REDIS_SERVERPORT
; 
 894     server
.verbosity 
= REDIS_DEBUG
; 
 895     server
.maxidletime 
= REDIS_MAXIDLETIME
; 
 896     server
.saveparams 
= NULL
; 
 897     server
.logfile 
= NULL
; /* NULL = log on standard output */ 
 898     server
.bindaddr 
= NULL
; 
 899     server
.glueoutputbuf 
= 1; 
 900     server
.daemonize 
= 0; 
 901     server
.pidfile 
= "/var/run/redis.pid"; 
 902     server
.dbfilename 
= "dump.rdb"; 
 903     server
.requirepass 
= NULL
; 
 904     server
.shareobjects 
= 0; 
 905     server
.sharingpoolsize 
= 1024; 
 906     server
.maxclients 
= 0; 
 907     server
.maxmemory 
= 0; 
 908     ResetServerSaveParams(); 
 910     appendServerSaveParams(60*60,1);  /* save after 1 hour and 1 change */ 
 911     appendServerSaveParams(300,100);  /* save after 5 minutes and 100 changes */ 
 912     appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */ 
 913     /* Replication related */ 
 915     server
.masterhost 
= NULL
; 
 916     server
.masterport 
= 6379; 
 917     server
.master 
= NULL
; 
 918     server
.replstate 
= REDIS_REPL_NONE
; 
 921 static void initServer() { 
 924     signal(SIGHUP
, SIG_IGN
); 
 925     signal(SIGPIPE
, SIG_IGN
); 
 926     setupSigSegvAction(); 
 928     server
.clients 
= listCreate(); 
 929     server
.slaves 
= listCreate(); 
 930     server
.monitors 
= listCreate(); 
 931     server
.objfreelist 
= listCreate(); 
 932     createSharedObjects(); 
 933     server
.el 
= aeCreateEventLoop(); 
 934     server
.db 
= zmalloc(sizeof(redisDb
)*server
.dbnum
); 
 935     server
.sharingpool 
= dictCreate(&setDictType
,NULL
); 
 936     if (!server
.db 
|| !server
.clients 
|| !server
.slaves 
|| !server
.monitors 
|| !server
.el 
|| !server
.objfreelist
) 
 937         oom("server initialization"); /* Fatal OOM */ 
 938     server
.fd 
= anetTcpServer(server
.neterr
, server
.port
, server
.bindaddr
); 
 939     if (server
.fd 
== -1) { 
 940         redisLog(REDIS_WARNING
, "Opening TCP port: %s", server
.neterr
); 
 943     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 944         server
.db
[j
].dict 
= dictCreate(&hashDictType
,NULL
); 
 945         server
.db
[j
].expires 
= dictCreate(&setDictType
,NULL
); 
 948     server
.cronloops 
= 0; 
 949     server
.bgsaveinprogress 
= 0; 
 950     server
.bgsavechildpid 
= -1; 
 951     server
.lastsave 
= time(NULL
); 
 953     server
.usedmemory 
= 0; 
 954     server
.stat_numcommands 
= 0; 
 955     server
.stat_numconnections 
= 0; 
 956     server
.stat_starttime 
= time(NULL
); 
 957     aeCreateTimeEvent(server
.el
, 1000, serverCron
, NULL
, NULL
); 
 960 /* Empty the whole database */ 
 961 static long long emptyDb() { 
 963     long long removed 
= 0; 
 965     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 966         removed 
+= dictSize(server
.db
[j
].dict
); 
 967         dictEmpty(server
.db
[j
].dict
); 
 968         dictEmpty(server
.db
[j
].expires
); 
 973 static int yesnotoi(char *s
) { 
 974     if (!strcasecmp(s
,"yes")) return 1; 
 975     else if (!strcasecmp(s
,"no")) return 0; 
 979 /* I agree, this is a very rudimental way to load a configuration... 
 980    will improve later if the config gets more complex */ 
 981 static void loadServerConfig(char *filename
) { 
 983     char buf
[REDIS_CONFIGLINE_MAX
+1], *err 
= NULL
; 
 987     if (filename
[0] == '-' && filename
[1] == '\0') 
 990         if ((fp 
= fopen(filename
,"r")) == NULL
) { 
 991             redisLog(REDIS_WARNING
,"Fatal error, can't open config file"); 
 996     while(fgets(buf
,REDIS_CONFIGLINE_MAX
+1,fp
) != NULL
) { 
1002         line 
= sdstrim(line
," \t\r\n"); 
1004         /* Skip comments and blank lines*/ 
1005         if (line
[0] == '#' || line
[0] == '\0') { 
1010         /* Split into arguments */ 
1011         argv 
= sdssplitlen(line
,sdslen(line
)," ",1,&argc
); 
1012         sdstolower(argv
[0]); 
1014         /* Execute config directives */ 
1015         if (!strcasecmp(argv
[0],"timeout") && argc 
== 2) { 
1016             server
.maxidletime 
= atoi(argv
[1]); 
1017             if (server
.maxidletime 
< 0) { 
1018                 err 
= "Invalid timeout value"; goto loaderr
; 
1020         } else if (!strcasecmp(argv
[0],"port") && argc 
== 2) { 
1021             server
.port 
= atoi(argv
[1]); 
1022             if (server
.port 
< 1 || server
.port 
> 65535) { 
1023                 err 
= "Invalid port"; goto loaderr
; 
1025         } else if (!strcasecmp(argv
[0],"bind") && argc 
== 2) { 
1026             server
.bindaddr 
= zstrdup(argv
[1]); 
1027         } else if (!strcasecmp(argv
[0],"save") && argc 
== 3) { 
1028             int seconds 
= atoi(argv
[1]); 
1029             int changes 
= atoi(argv
[2]); 
1030             if (seconds 
< 1 || changes 
< 0) { 
1031                 err 
= "Invalid save parameters"; goto loaderr
; 
1033             appendServerSaveParams(seconds
,changes
); 
1034         } else if (!strcasecmp(argv
[0],"dir") && argc 
== 2) { 
1035             if (chdir(argv
[1]) == -1) { 
1036                 redisLog(REDIS_WARNING
,"Can't chdir to '%s': %s", 
1037                     argv
[1], strerror(errno
)); 
1040         } else if (!strcasecmp(argv
[0],"loglevel") && argc 
== 2) { 
1041             if (!strcasecmp(argv
[1],"debug")) server
.verbosity 
= REDIS_DEBUG
; 
1042             else if (!strcasecmp(argv
[1],"notice")) server
.verbosity 
= REDIS_NOTICE
; 
1043             else if (!strcasecmp(argv
[1],"warning")) server
.verbosity 
= REDIS_WARNING
; 
1045                 err 
= "Invalid log level. Must be one of debug, notice, warning"; 
1048         } else if (!strcasecmp(argv
[0],"logfile") && argc 
== 2) { 
1051             server
.logfile 
= zstrdup(argv
[1]); 
1052             if (!strcasecmp(server
.logfile
,"stdout")) { 
1053                 zfree(server
.logfile
); 
1054                 server
.logfile 
= NULL
; 
1056             if (server
.logfile
) { 
1057                 /* Test if we are able to open the file. The server will not 
1058                  * be able to abort just for this problem later... */ 
1059                 logfp 
= fopen(server
.logfile
,"a"); 
1060                 if (logfp 
== NULL
) { 
1061                     err 
= sdscatprintf(sdsempty(), 
1062                         "Can't open the log file: %s", strerror(errno
)); 
1067         } else if (!strcasecmp(argv
[0],"databases") && argc 
== 2) { 
1068             server
.dbnum 
= atoi(argv
[1]); 
1069             if (server
.dbnum 
< 1) { 
1070                 err 
= "Invalid number of databases"; goto loaderr
; 
1072         } else if (!strcasecmp(argv
[0],"maxclients") && argc 
== 2) { 
1073             server
.maxclients 
= atoi(argv
[1]); 
1074         } else if (!strcasecmp(argv
[0],"maxmemory") && argc 
== 2) { 
1075             server
.maxmemory 
= atoi(argv
[1]); 
1076         } else if (!strcasecmp(argv
[0],"slaveof") && argc 
== 3) { 
1077             server
.masterhost 
= sdsnew(argv
[1]); 
1078             server
.masterport 
= atoi(argv
[2]); 
1079             server
.replstate 
= REDIS_REPL_CONNECT
; 
1080         } else if (!strcasecmp(argv
[0],"glueoutputbuf") && argc 
== 2) { 
1081             if ((server
.glueoutputbuf 
= yesnotoi(argv
[1])) == -1) { 
1082                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1084         } else if (!strcasecmp(argv
[0],"shareobjects") && argc 
== 2) { 
1085             if ((server
.shareobjects 
= yesnotoi(argv
[1])) == -1) { 
1086                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1088         } else if (!strcasecmp(argv
[0],"shareobjectspoolsize") && argc 
== 2) { 
1089             server
.sharingpoolsize 
= atoi(argv
[1]); 
1090             if (server
.sharingpoolsize 
< 1) { 
1091                 err 
= "invalid object sharing pool size"; goto loaderr
; 
1093         } else if (!strcasecmp(argv
[0],"daemonize") && argc 
== 2) { 
1094             if ((server
.daemonize 
= yesnotoi(argv
[1])) == -1) { 
1095                 err 
= "argument must be 'yes' or 'no'"; goto loaderr
; 
1097         } else if (!strcasecmp(argv
[0],"requirepass") && argc 
== 2) { 
1098           server
.requirepass 
= zstrdup(argv
[1]); 
1099         } else if (!strcasecmp(argv
[0],"pidfile") && argc 
== 2) { 
1100           server
.pidfile 
= zstrdup(argv
[1]); 
1101         } else if (!strcasecmp(argv
[0],"dbfilename") && argc 
== 2) { 
1102           server
.dbfilename 
= zstrdup(argv
[1]); 
1104             err 
= "Bad directive or wrong number of arguments"; goto loaderr
; 
1106         for (j 
= 0; j 
< argc
; j
++) 
1111     if (fp 
!= stdin
) fclose(fp
); 
1115     fprintf(stderr
, "\n*** FATAL CONFIG FILE ERROR ***\n"); 
1116     fprintf(stderr
, "Reading the configuration file, at line %d\n", linenum
); 
1117     fprintf(stderr
, ">>> '%s'\n", line
); 
1118     fprintf(stderr
, "%s\n", err
); 
1122 static void freeClientArgv(redisClient 
*c
) { 
1125     for (j 
= 0; j 
< c
->argc
; j
++) 
1126         decrRefCount(c
->argv
[j
]); 
1130 static void freeClient(redisClient 
*c
) { 
1133     aeDeleteFileEvent(server
.el
,c
->fd
,AE_READABLE
); 
1134     aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
1135     sdsfree(c
->querybuf
); 
1136     listRelease(c
->reply
); 
1139     ln 
= listSearchKey(server
.clients
,c
); 
1141     listDelNode(server
.clients
,ln
); 
1142     if (c
->flags 
& REDIS_SLAVE
) { 
1143         if (c
->replstate 
== REDIS_REPL_SEND_BULK 
&& c
->repldbfd 
!= -1) 
1145         list 
*l 
= (c
->flags 
& REDIS_MONITOR
) ? server
.monitors 
: server
.slaves
; 
1146         ln 
= listSearchKey(l
,c
); 
1150     if (c
->flags 
& REDIS_MASTER
) { 
1151         server
.master 
= NULL
; 
1152         server
.replstate 
= REDIS_REPL_CONNECT
; 
1158 static void glueReplyBuffersIfNeeded(redisClient 
*c
) { 
1163     listRewind(c
->reply
); 
1164     while((ln 
= listYield(c
->reply
))) { 
1166         totlen 
+= sdslen(o
->ptr
); 
1167         /* This optimization makes more sense if we don't have to copy 
1169         if (totlen 
> 1024) return; 
1175         listRewind(c
->reply
); 
1176         while((ln 
= listYield(c
->reply
))) { 
1178             memcpy(buf
+copylen
,o
->ptr
,sdslen(o
->ptr
)); 
1179             copylen 
+= sdslen(o
->ptr
); 
1180             listDelNode(c
->reply
,ln
); 
1182         /* Now the output buffer is empty, add the new single element */ 
1183         o 
= createObject(REDIS_STRING
,sdsnewlen(buf
,totlen
)); 
1184         if (!listAddNodeTail(c
->reply
,o
)) oom("listAddNodeTail"); 
1188 static void sendReplyToClient(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1189     redisClient 
*c 
= privdata
; 
1190     int nwritten 
= 0, totwritten 
= 0, objlen
; 
1193     REDIS_NOTUSED(mask
); 
1195     if (server
.glueoutputbuf 
&& listLength(c
->reply
) > 1) 
1196         glueReplyBuffersIfNeeded(c
); 
1197     while(listLength(c
->reply
)) { 
1198         o 
= listNodeValue(listFirst(c
->reply
)); 
1199         objlen 
= sdslen(o
->ptr
); 
1202             listDelNode(c
->reply
,listFirst(c
->reply
)); 
1206         if (c
->flags 
& REDIS_MASTER
) { 
1207             /* Don't reply to a master */ 
1208             nwritten 
= objlen 
- c
->sentlen
; 
1210             nwritten 
= write(fd
, ((char*)o
->ptr
)+c
->sentlen
, objlen 
- c
->sentlen
); 
1211             if (nwritten 
<= 0) break; 
1213         c
->sentlen 
+= nwritten
; 
1214         totwritten 
+= nwritten
; 
1215         /* If we fully sent the object on head go to the next one */ 
1216         if (c
->sentlen 
== objlen
) { 
1217             listDelNode(c
->reply
,listFirst(c
->reply
)); 
1220         /* Note that we avoid to send more thank REDIS_MAX_WRITE_PER_EVENT 
1221          * bytes, in a single threaded server it's a good idea to server 
1222          * other clients as well, even if a very large request comes from 
1223          * super fast link that is always able to accept data (in real world 
1224          * terms think to 'KEYS *' against the loopback interfae) */ 
1225         if (totwritten 
> REDIS_MAX_WRITE_PER_EVENT
) break; 
1227     if (nwritten 
== -1) { 
1228         if (errno 
== EAGAIN
) { 
1231             redisLog(REDIS_DEBUG
, 
1232                 "Error writing to client: %s", strerror(errno
)); 
1237     if (totwritten 
> 0) c
->lastinteraction 
= time(NULL
); 
1238     if (listLength(c
->reply
) == 0) { 
1240         aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
1244 static struct redisCommand 
*lookupCommand(char *name
) { 
1246     while(cmdTable
[j
].name 
!= NULL
) { 
1247         if (!strcasecmp(name
,cmdTable
[j
].name
)) return &cmdTable
[j
]; 
1253 /* resetClient prepare the client to process the next command */ 
1254 static void resetClient(redisClient 
*c
) { 
1259 /* If this function gets called we already read a whole 
1260  * command, argments are in the client argv/argc fields. 
1261  * processCommand() execute the command or prepare the 
1262  * server for a bulk read from the client. 
1264  * If 1 is returned the client is still alive and valid and 
1265  * and other operations can be performed by the caller. Otherwise 
1266  * if 0 is returned the client was destroied (i.e. after QUIT). */ 
1267 static int processCommand(redisClient 
*c
) { 
1268     struct redisCommand 
*cmd
; 
1271     /* Free some memory if needed (maxmemory setting) */ 
1272     if (server
.maxmemory
) freeMemoryIfNeeded(); 
1274     /* The QUIT command is handled as a special case. Normal command 
1275      * procs are unable to close the client connection safely */ 
1276     if (!strcasecmp(c
->argv
[0]->ptr
,"quit")) { 
1280     cmd 
= lookupCommand(c
->argv
[0]->ptr
); 
1282         addReplySds(c
,sdsnew("-ERR unknown command\r\n")); 
1285     } else if ((cmd
->arity 
> 0 && cmd
->arity 
!= c
->argc
) || 
1286                (c
->argc 
< -cmd
->arity
)) { 
1287         addReplySds(c
,sdsnew("-ERR wrong number of arguments\r\n")); 
1290     } else if (server
.maxmemory 
&& cmd
->flags 
& REDIS_CMD_DENYOOM 
&& zmalloc_used_memory() > server
.maxmemory
) { 
1291         addReplySds(c
,sdsnew("-ERR command not allowed when used memory > 'maxmemory'\r\n")); 
1294     } else if (cmd
->flags 
& REDIS_CMD_BULK 
&& c
->bulklen 
== -1) { 
1295         int bulklen 
= atoi(c
->argv
[c
->argc
-1]->ptr
); 
1297         decrRefCount(c
->argv
[c
->argc
-1]); 
1298         if (bulklen 
< 0 || bulklen 
> 1024*1024*1024) { 
1300             addReplySds(c
,sdsnew("-ERR invalid bulk write count\r\n")); 
1305         c
->bulklen 
= bulklen
+2; /* add two bytes for CR+LF */ 
1306         /* It is possible that the bulk read is already in the 
1307          * buffer. Check this condition and handle it accordingly */ 
1308         if ((signed)sdslen(c
->querybuf
) >= c
->bulklen
) { 
1309             c
->argv
[c
->argc
] = createStringObject(c
->querybuf
,c
->bulklen
-2); 
1311             c
->querybuf 
= sdsrange(c
->querybuf
,c
->bulklen
,-1); 
1316     /* Let's try to share objects on the command arguments vector */ 
1317     if (server
.shareobjects
) { 
1319         for(j 
= 1; j 
< c
->argc
; j
++) 
1320             c
->argv
[j
] = tryObjectSharing(c
->argv
[j
]); 
1322     /* Check if the user is authenticated */ 
1323     if (server
.requirepass 
&& !c
->authenticated 
&& cmd
->proc 
!= authCommand
) { 
1324         addReplySds(c
,sdsnew("-ERR operation not permitted\r\n")); 
1329     /* Exec the command */ 
1330     dirty 
= server
.dirty
; 
1332     if (server
.dirty
-dirty 
!= 0 && listLength(server
.slaves
)) 
1333         replicationFeedSlaves(server
.slaves
,cmd
,c
->db
->id
,c
->argv
,c
->argc
); 
1334     if (listLength(server
.monitors
)) 
1335         replicationFeedSlaves(server
.monitors
,cmd
,c
->db
->id
,c
->argv
,c
->argc
); 
1336     server
.stat_numcommands
++; 
1338     /* Prepare the client for the next command */ 
1339     if (c
->flags 
& REDIS_CLOSE
) { 
1347 static void replicationFeedSlaves(list 
*slaves
, struct redisCommand 
*cmd
, int dictid
, robj 
**argv
, int argc
) { 
1351     /* (args*2)+1 is enough room for args, spaces, newlines */ 
1352     robj 
*static_outv
[REDIS_STATIC_ARGS
*2+1]; 
1354     if (argc 
<= REDIS_STATIC_ARGS
) { 
1357         outv 
= zmalloc(sizeof(robj
*)*(argc
*2+1)); 
1358         if (!outv
) oom("replicationFeedSlaves"); 
1361     for (j 
= 0; j 
< argc
; j
++) { 
1362         if (j 
!= 0) outv
[outc
++] = shared
.space
; 
1363         if ((cmd
->flags 
& REDIS_CMD_BULK
) && j 
== argc
-1) { 
1366             lenobj 
= createObject(REDIS_STRING
, 
1367                 sdscatprintf(sdsempty(),"%d\r\n",sdslen(argv
[j
]->ptr
))); 
1368             lenobj
->refcount 
= 0; 
1369             outv
[outc
++] = lenobj
; 
1371         outv
[outc
++] = argv
[j
]; 
1373     outv
[outc
++] = shared
.crlf
; 
1375     /* Increment all the refcounts at start and decrement at end in order to 
1376      * be sure to free objects if there is no slave in a replication state 
1377      * able to be feed with commands */ 
1378     for (j 
= 0; j 
< outc
; j
++) incrRefCount(outv
[j
]); 
1380     while((ln 
= listYield(slaves
))) { 
1381         redisClient 
*slave 
= ln
->value
; 
1383         /* Don't feed slaves that are still waiting for BGSAVE to start */ 
1384         if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) continue; 
1386         /* Feed all the other slaves, MONITORs and so on */ 
1387         if (slave
->slaveseldb 
!= dictid
) { 
1391             case 0: selectcmd 
= shared
.select0
; break; 
1392             case 1: selectcmd 
= shared
.select1
; break; 
1393             case 2: selectcmd 
= shared
.select2
; break; 
1394             case 3: selectcmd 
= shared
.select3
; break; 
1395             case 4: selectcmd 
= shared
.select4
; break; 
1396             case 5: selectcmd 
= shared
.select5
; break; 
1397             case 6: selectcmd 
= shared
.select6
; break; 
1398             case 7: selectcmd 
= shared
.select7
; break; 
1399             case 8: selectcmd 
= shared
.select8
; break; 
1400             case 9: selectcmd 
= shared
.select9
; break; 
1402                 selectcmd 
= createObject(REDIS_STRING
, 
1403                     sdscatprintf(sdsempty(),"select %d\r\n",dictid
)); 
1404                 selectcmd
->refcount 
= 0; 
1407             addReply(slave
,selectcmd
); 
1408             slave
->slaveseldb 
= dictid
; 
1410         for (j 
= 0; j 
< outc
; j
++) addReply(slave
,outv
[j
]); 
1412     for (j 
= 0; j 
< outc
; j
++) decrRefCount(outv
[j
]); 
1413     if (outv 
!= static_outv
) zfree(outv
); 
1416 static void readQueryFromClient(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1417     redisClient 
*c 
= (redisClient
*) privdata
; 
1418     char buf
[REDIS_IOBUF_LEN
]; 
1421     REDIS_NOTUSED(mask
); 
1423     nread 
= read(fd
, buf
, REDIS_IOBUF_LEN
); 
1425         if (errno 
== EAGAIN
) { 
1428             redisLog(REDIS_DEBUG
, "Reading from client: %s",strerror(errno
)); 
1432     } else if (nread 
== 0) { 
1433         redisLog(REDIS_DEBUG
, "Client closed connection"); 
1438         c
->querybuf 
= sdscatlen(c
->querybuf
, buf
, nread
); 
1439         c
->lastinteraction 
= time(NULL
); 
1445     if (c
->bulklen 
== -1) { 
1446         /* Read the first line of the query */ 
1447         char *p 
= strchr(c
->querybuf
,'\n'); 
1454             query 
= c
->querybuf
; 
1455             c
->querybuf 
= sdsempty(); 
1456             querylen 
= 1+(p
-(query
)); 
1457             if (sdslen(query
) > querylen
) { 
1458                 /* leave data after the first line of the query in the buffer */ 
1459                 c
->querybuf 
= sdscatlen(c
->querybuf
,query
+querylen
,sdslen(query
)-querylen
); 
1461             *p 
= '\0'; /* remove "\n" */ 
1462             if (*(p
-1) == '\r') *(p
-1) = '\0'; /* and "\r" if any */ 
1463             sdsupdatelen(query
); 
1465             /* Now we can split the query in arguments */ 
1466             if (sdslen(query
) == 0) { 
1467                 /* Ignore empty query */ 
1471             argv 
= sdssplitlen(query
,sdslen(query
)," ",1,&argc
); 
1472             if (argv 
== NULL
) oom("sdssplitlen"); 
1475             if (c
->argv
) zfree(c
->argv
); 
1476             c
->argv 
= zmalloc(sizeof(robj
*)*argc
); 
1477             if (c
->argv 
== NULL
) oom("allocating arguments list for client"); 
1479             for (j 
= 0; j 
< argc
; j
++) { 
1480                 if (sdslen(argv
[j
])) { 
1481                     c
->argv
[c
->argc
] = createObject(REDIS_STRING
,argv
[j
]); 
1488             /* Execute the command. If the client is still valid 
1489              * after processCommand() return and there is something 
1490              * on the query buffer try to process the next command. */ 
1491             if (processCommand(c
) && sdslen(c
->querybuf
)) goto again
; 
1493         } else if (sdslen(c
->querybuf
) >= REDIS_REQUEST_MAX_SIZE
) { 
1494             redisLog(REDIS_DEBUG
, "Client protocol error"); 
1499         /* Bulk read handling. Note that if we are at this point 
1500            the client already sent a command terminated with a newline, 
1501            we are reading the bulk data that is actually the last 
1502            argument of the command. */ 
1503         int qbl 
= sdslen(c
->querybuf
); 
1505         if (c
->bulklen 
<= qbl
) { 
1506             /* Copy everything but the final CRLF as final argument */ 
1507             c
->argv
[c
->argc
] = createStringObject(c
->querybuf
,c
->bulklen
-2); 
1509             c
->querybuf 
= sdsrange(c
->querybuf
,c
->bulklen
,-1); 
1516 static int selectDb(redisClient 
*c
, int id
) { 
1517     if (id 
< 0 || id 
>= server
.dbnum
) 
1519     c
->db 
= &server
.db
[id
]; 
1523 static void *dupClientReplyValue(void *o
) { 
1524     incrRefCount((robj
*)o
); 
1528 static redisClient 
*createClient(int fd
) { 
1529     redisClient 
*c 
= zmalloc(sizeof(*c
)); 
1531     anetNonBlock(NULL
,fd
); 
1532     anetTcpNoDelay(NULL
,fd
); 
1533     if (!c
) return NULL
; 
1536     c
->querybuf 
= sdsempty(); 
1542     c
->lastinteraction 
= time(NULL
); 
1543     c
->authenticated 
= 0; 
1544     c
->replstate 
= REDIS_REPL_NONE
; 
1545     if ((c
->reply 
= listCreate()) == NULL
) oom("listCreate"); 
1546     listSetFreeMethod(c
->reply
,decrRefCount
); 
1547     listSetDupMethod(c
->reply
,dupClientReplyValue
); 
1548     if (aeCreateFileEvent(server
.el
, c
->fd
, AE_READABLE
, 
1549         readQueryFromClient
, c
, NULL
) == AE_ERR
) { 
1553     if (!listAddNodeTail(server
.clients
,c
)) oom("listAddNodeTail"); 
1557 static void addReply(redisClient 
*c
, robj 
*obj
) { 
1558     if (listLength(c
->reply
) == 0 && 
1559         (c
->replstate 
== REDIS_REPL_NONE 
|| 
1560          c
->replstate 
== REDIS_REPL_ONLINE
) && 
1561         aeCreateFileEvent(server
.el
, c
->fd
, AE_WRITABLE
, 
1562         sendReplyToClient
, c
, NULL
) == AE_ERR
) return; 
1563     if (!listAddNodeTail(c
->reply
,obj
)) oom("listAddNodeTail"); 
1567 static void addReplySds(redisClient 
*c
, sds s
) { 
1568     robj 
*o 
= createObject(REDIS_STRING
,s
); 
1573 static void acceptHandler(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
1578     REDIS_NOTUSED(mask
); 
1579     REDIS_NOTUSED(privdata
); 
1581     cfd 
= anetAccept(server
.neterr
, fd
, cip
, &cport
); 
1582     if (cfd 
== AE_ERR
) { 
1583         redisLog(REDIS_DEBUG
,"Accepting client connection: %s", server
.neterr
); 
1586     redisLog(REDIS_DEBUG
,"Accepted %s:%d", cip
, cport
); 
1587     if ((c 
= createClient(cfd
)) == NULL
) { 
1588         redisLog(REDIS_WARNING
,"Error allocating resoures for the client"); 
1589         close(cfd
); /* May be already closed, just ingore errors */ 
1592     /* If maxclient directive is set and this is one client more... close the 
1593      * connection. Note that we create the client instead to check before 
1594      * for this condition, since now the socket is already set in nonblocking 
1595      * mode and we can send an error for free using the Kernel I/O */ 
1596     if (server
.maxclients 
&& listLength(server
.clients
) > server
.maxclients
) { 
1597         char *err 
= "-ERR max number of clients reached\r\n"; 
1599         /* That's a best effort error message, don't check write errors */ 
1600         (void) write(c
->fd
,err
,strlen(err
)); 
1604     server
.stat_numconnections
++; 
1607 /* ======================= Redis objects implementation ===================== */ 
1609 static robj 
*createObject(int type
, void *ptr
) { 
1612     if (listLength(server
.objfreelist
)) { 
1613         listNode 
*head 
= listFirst(server
.objfreelist
); 
1614         o 
= listNodeValue(head
); 
1615         listDelNode(server
.objfreelist
,head
); 
1617         o 
= zmalloc(sizeof(*o
)); 
1619     if (!o
) oom("createObject"); 
1626 static robj 
*createStringObject(char *ptr
, size_t len
) { 
1627     return createObject(REDIS_STRING
,sdsnewlen(ptr
,len
)); 
1630 static robj 
*createListObject(void) { 
1631     list 
*l 
= listCreate(); 
1633     if (!l
) oom("listCreate"); 
1634     listSetFreeMethod(l
,decrRefCount
); 
1635     return createObject(REDIS_LIST
,l
); 
1638 static robj 
*createSetObject(void) { 
1639     dict 
*d 
= dictCreate(&setDictType
,NULL
); 
1640     if (!d
) oom("dictCreate"); 
1641     return createObject(REDIS_SET
,d
); 
1644 static void freeStringObject(robj 
*o
) { 
1648 static void freeListObject(robj 
*o
) { 
1649     listRelease((list
*) o
->ptr
); 
1652 static void freeSetObject(robj 
*o
) { 
1653     dictRelease((dict
*) o
->ptr
); 
1656 static void freeHashObject(robj 
*o
) { 
1657     dictRelease((dict
*) o
->ptr
); 
1660 static void incrRefCount(robj 
*o
) { 
1662 #ifdef DEBUG_REFCOUNT 
1663     if (o
->type 
== REDIS_STRING
) 
1664         printf("Increment '%s'(%p), now is: %d\n",o
->ptr
,o
,o
->refcount
); 
1668 static void decrRefCount(void *obj
) { 
1671 #ifdef DEBUG_REFCOUNT 
1672     if (o
->type 
== REDIS_STRING
) 
1673         printf("Decrement '%s'(%p), now is: %d\n",o
->ptr
,o
,o
->refcount
-1); 
1675     if (--(o
->refcount
) == 0) { 
1677         case REDIS_STRING
: freeStringObject(o
); break; 
1678         case REDIS_LIST
: freeListObject(o
); break; 
1679         case REDIS_SET
: freeSetObject(o
); break; 
1680         case REDIS_HASH
: freeHashObject(o
); break; 
1681         default: assert(0 != 0); break; 
1683         if (listLength(server
.objfreelist
) > REDIS_OBJFREELIST_MAX 
|| 
1684             !listAddNodeHead(server
.objfreelist
,o
)) 
1689 /* Try to share an object against the shared objects pool */ 
1690 static robj 
*tryObjectSharing(robj 
*o
) { 
1691     struct dictEntry 
*de
; 
1694     if (o 
== NULL 
|| server
.shareobjects 
== 0) return o
; 
1696     assert(o
->type 
== REDIS_STRING
); 
1697     de 
= dictFind(server
.sharingpool
,o
); 
1699         robj 
*shared 
= dictGetEntryKey(de
); 
1701         c 
= ((unsigned long) dictGetEntryVal(de
))+1; 
1702         dictGetEntryVal(de
) = (void*) c
; 
1703         incrRefCount(shared
); 
1707         /* Here we are using a stream algorihtm: Every time an object is 
1708          * shared we increment its count, everytime there is a miss we 
1709          * recrement the counter of a random object. If this object reaches 
1710          * zero we remove the object and put the current object instead. */ 
1711         if (dictSize(server
.sharingpool
) >= 
1712                 server
.sharingpoolsize
) { 
1713             de 
= dictGetRandomKey(server
.sharingpool
); 
1715             c 
= ((unsigned long) dictGetEntryVal(de
))-1; 
1716             dictGetEntryVal(de
) = (void*) c
; 
1718                 dictDelete(server
.sharingpool
,de
->key
); 
1721             c 
= 0; /* If the pool is empty we want to add this object */ 
1726             retval 
= dictAdd(server
.sharingpool
,o
,(void*)1); 
1727             assert(retval 
== DICT_OK
); 
1734 static robj 
*lookupKey(redisDb 
*db
, robj 
*key
) { 
1735     dictEntry 
*de 
= dictFind(db
->dict
,key
); 
1736     return de 
? dictGetEntryVal(de
) : NULL
; 
1739 static robj 
*lookupKeyRead(redisDb 
*db
, robj 
*key
) { 
1740     expireIfNeeded(db
,key
); 
1741     return lookupKey(db
,key
); 
1744 static robj 
*lookupKeyWrite(redisDb 
*db
, robj 
*key
) { 
1745     deleteIfVolatile(db
,key
); 
1746     return lookupKey(db
,key
); 
1749 static int deleteKey(redisDb 
*db
, robj 
*key
) { 
1752     /* We need to protect key from destruction: after the first dictDelete() 
1753      * it may happen that 'key' is no longer valid if we don't increment 
1754      * it's count. This may happen when we get the object reference directly 
1755      * from the hash table with dictRandomKey() or dict iterators */ 
1757     if (dictSize(db
->expires
)) dictDelete(db
->expires
,key
); 
1758     retval 
= dictDelete(db
->dict
,key
); 
1761     return retval 
== DICT_OK
; 
1764 /*============================ DB saving/loading ============================ */ 
1766 static int rdbSaveType(FILE *fp
, unsigned char type
) { 
1767     if (fwrite(&type
,1,1,fp
) == 0) return -1; 
1771 static int rdbSaveTime(FILE *fp
, time_t t
) { 
1772     int32_t t32 
= (int32_t) t
; 
1773     if (fwrite(&t32
,4,1,fp
) == 0) return -1; 
1777 /* check rdbLoadLen() comments for more info */ 
1778 static int rdbSaveLen(FILE *fp
, uint32_t len
) { 
1779     unsigned char buf
[2]; 
1782         /* Save a 6 bit len */ 
1783         buf
[0] = (len
&0xFF)|(REDIS_RDB_6BITLEN
<<6); 
1784         if (fwrite(buf
,1,1,fp
) == 0) return -1; 
1785     } else if (len 
< (1<<14)) { 
1786         /* Save a 14 bit len */ 
1787         buf
[0] = ((len
>>8)&0xFF)|(REDIS_RDB_14BITLEN
<<6); 
1789         if (fwrite(buf
,2,1,fp
) == 0) return -1; 
1791         /* Save a 32 bit len */ 
1792         buf
[0] = (REDIS_RDB_32BITLEN
<<6); 
1793         if (fwrite(buf
,1,1,fp
) == 0) return -1; 
1795         if (fwrite(&len
,4,1,fp
) == 0) return -1; 
1800 /* String objects in the form "2391" "-100" without any space and with a 
1801  * range of values that can fit in an 8, 16 or 32 bit signed value can be 
1802  * encoded as integers to save space */ 
1803 static int rdbTryIntegerEncoding(sds s
, unsigned char *enc
) { 
1805     char *endptr
, buf
[32]; 
1807     /* Check if it's possible to encode this value as a number */ 
1808     value 
= strtoll(s
, &endptr
, 10); 
1809     if (endptr
[0] != '\0') return 0; 
1810     snprintf(buf
,32,"%lld",value
); 
1812     /* If the number converted back into a string is not identical 
1813      * then it's not possible to encode the string as integer */ 
1814     if (strlen(buf
) != sdslen(s
) || memcmp(buf
,s
,sdslen(s
))) return 0; 
1816     /* Finally check if it fits in our ranges */ 
1817     if (value 
>= -(1<<7) && value 
<= (1<<7)-1) { 
1818         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT8
; 
1819         enc
[1] = value
&0xFF; 
1821     } else if (value 
>= -(1<<15) && value 
<= (1<<15)-1) { 
1822         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT16
; 
1823         enc
[1] = value
&0xFF; 
1824         enc
[2] = (value
>>8)&0xFF; 
1826     } else if (value 
>= -((long long)1<<31) && value 
<= ((long long)1<<31)-1) { 
1827         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT32
; 
1828         enc
[1] = value
&0xFF; 
1829         enc
[2] = (value
>>8)&0xFF; 
1830         enc
[3] = (value
>>16)&0xFF; 
1831         enc
[4] = (value
>>24)&0xFF; 
1838 static int rdbSaveLzfStringObject(FILE *fp
, robj 
*obj
) { 
1839     unsigned int comprlen
, outlen
; 
1843     /* We require at least four bytes compression for this to be worth it */ 
1844     outlen 
= sdslen(obj
->ptr
)-4; 
1845     if (outlen 
<= 0) return 0; 
1846     if ((out 
= zmalloc(outlen
+1)) == NULL
) return 0; 
1847     comprlen 
= lzf_compress(obj
->ptr
, sdslen(obj
->ptr
), out
, outlen
); 
1848     if (comprlen 
== 0) { 
1852     /* Data compressed! Let's save it on disk */ 
1853     byte 
= (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_LZF
; 
1854     if (fwrite(&byte
,1,1,fp
) == 0) goto writeerr
; 
1855     if (rdbSaveLen(fp
,comprlen
) == -1) goto writeerr
; 
1856     if (rdbSaveLen(fp
,sdslen(obj
->ptr
)) == -1) goto writeerr
; 
1857     if (fwrite(out
,comprlen
,1,fp
) == 0) goto writeerr
; 
1866 /* Save a string objet as [len][data] on disk. If the object is a string 
1867  * representation of an integer value we try to safe it in a special form */ 
1868 static int rdbSaveStringObject(FILE *fp
, robj 
*obj
) { 
1869     size_t len 
= sdslen(obj
->ptr
); 
1872     /* Try integer encoding */ 
1874         unsigned char buf
[5]; 
1875         if ((enclen 
= rdbTryIntegerEncoding(obj
->ptr
,buf
)) > 0) { 
1876             if (fwrite(buf
,enclen
,1,fp
) == 0) return -1; 
1881     /* Try LZF compression - under 20 bytes it's unable to compress even 
1882      * aaaaaaaaaaaaaaaaaa so skip it */ 
1883     if (1 && len 
> 20) { 
1886         retval 
= rdbSaveLzfStringObject(fp
,obj
); 
1887         if (retval 
== -1) return -1; 
1888         if (retval 
> 0) return 0; 
1889         /* retval == 0 means data can't be compressed, save the old way */ 
1892     /* Store verbatim */ 
1893     if (rdbSaveLen(fp
,len
) == -1) return -1; 
1894     if (len 
&& fwrite(obj
->ptr
,len
,1,fp
) == 0) return -1; 
1898 /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */ 
1899 static int rdbSave(char *filename
) { 
1900     dictIterator 
*di 
= NULL
; 
1905     time_t now 
= time(NULL
); 
1907     snprintf(tmpfile
,256,"temp-%d.rdb", (int) getpid()); 
1908     fp 
= fopen(tmpfile
,"w"); 
1910         redisLog(REDIS_WARNING
, "Failed saving the DB: %s", strerror(errno
)); 
1913     if (fwrite("REDIS0001",9,1,fp
) == 0) goto werr
; 
1914     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
1915         redisDb 
*db 
= server
.db
+j
; 
1917         if (dictSize(d
) == 0) continue; 
1918         di 
= dictGetIterator(d
); 
1924         /* Write the SELECT DB opcode */ 
1925         if (rdbSaveType(fp
,REDIS_SELECTDB
) == -1) goto werr
; 
1926         if (rdbSaveLen(fp
,j
) == -1) goto werr
; 
1928         /* Iterate this DB writing every entry */ 
1929         while((de 
= dictNext(di
)) != NULL
) { 
1930             robj 
*key 
= dictGetEntryKey(de
); 
1931             robj 
*o 
= dictGetEntryVal(de
); 
1932             time_t expiretime 
= getExpire(db
,key
); 
1934             /* Save the expire time */ 
1935             if (expiretime 
!= -1) { 
1936                 /* If this key is already expired skip it */ 
1937                 if (expiretime 
< now
) continue; 
1938                 if (rdbSaveType(fp
,REDIS_EXPIRETIME
) == -1) goto werr
; 
1939                 if (rdbSaveTime(fp
,expiretime
) == -1) goto werr
; 
1941             /* Save the key and associated value */ 
1942             if (rdbSaveType(fp
,o
->type
) == -1) goto werr
; 
1943             if (rdbSaveStringObject(fp
,key
) == -1) goto werr
; 
1944             if (o
->type 
== REDIS_STRING
) { 
1945                 /* Save a string value */ 
1946                 if (rdbSaveStringObject(fp
,o
) == -1) goto werr
; 
1947             } else if (o
->type 
== REDIS_LIST
) { 
1948                 /* Save a list value */ 
1949                 list 
*list 
= o
->ptr
; 
1953                 if (rdbSaveLen(fp
,listLength(list
)) == -1) goto werr
; 
1954                 while((ln 
= listYield(list
))) { 
1955                     robj 
*eleobj 
= listNodeValue(ln
); 
1957                     if (rdbSaveStringObject(fp
,eleobj
) == -1) goto werr
; 
1959             } else if (o
->type 
== REDIS_SET
) { 
1960                 /* Save a set value */ 
1962                 dictIterator 
*di 
= dictGetIterator(set
); 
1965                 if (!set
) oom("dictGetIteraotr"); 
1966                 if (rdbSaveLen(fp
,dictSize(set
)) == -1) goto werr
; 
1967                 while((de 
= dictNext(di
)) != NULL
) { 
1968                     robj 
*eleobj 
= dictGetEntryKey(de
); 
1970                     if (rdbSaveStringObject(fp
,eleobj
) == -1) goto werr
; 
1972                 dictReleaseIterator(di
); 
1977         dictReleaseIterator(di
); 
1980     if (rdbSaveType(fp
,REDIS_EOF
) == -1) goto werr
; 
1982     /* Make sure data will not remain on the OS's output buffers */ 
1987     /* Use RENAME to make sure the DB file is changed atomically only 
1988      * if the generate DB file is ok. */ 
1989     if (rename(tmpfile
,filename
) == -1) { 
1990         redisLog(REDIS_WARNING
,"Error moving temp DB file on the final destionation: %s", strerror(errno
)); 
1994     redisLog(REDIS_NOTICE
,"DB saved on disk"); 
1996     server
.lastsave 
= time(NULL
); 
2002     redisLog(REDIS_WARNING
,"Write error saving DB on disk: %s", strerror(errno
)); 
2003     if (di
) dictReleaseIterator(di
); 
2007 static int rdbSaveBackground(char *filename
) { 
2010     if (server
.bgsaveinprogress
) return REDIS_ERR
; 
2011     if ((childpid 
= fork()) == 0) { 
2014         if (rdbSave(filename
) == REDIS_OK
) { 
2021         if (childpid 
== -1) { 
2022             redisLog(REDIS_WARNING
,"Can't save in background: fork: %s", 
2026         redisLog(REDIS_NOTICE
,"Background saving started by pid %d",childpid
); 
2027         server
.bgsaveinprogress 
= 1; 
2028         server
.bgsavechildpid 
= childpid
; 
2031     return REDIS_OK
; /* unreached */ 
2034 static void rdbRemoveTempFile(pid_t childpid
) { 
2037     snprintf(tmpfile
,256,"temp-%d.rdb", (int) childpid
); 
2041 static int rdbLoadType(FILE *fp
) { 
2043     if (fread(&type
,1,1,fp
) == 0) return -1; 
2047 static time_t rdbLoadTime(FILE *fp
) { 
2049     if (fread(&t32
,4,1,fp
) == 0) return -1; 
2050     return (time_t) t32
; 
2053 /* Load an encoded length from the DB, see the REDIS_RDB_* defines on the top 
2054  * of this file for a description of how this are stored on disk. 
2056  * isencoded is set to 1 if the readed length is not actually a length but 
2057  * an "encoding type", check the above comments for more info */ 
2058 static uint32_t rdbLoadLen(FILE *fp
, int rdbver
, int *isencoded
) { 
2059     unsigned char buf
[2]; 
2062     if (isencoded
) *isencoded 
= 0; 
2064         if (fread(&len
,4,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2069         if (fread(buf
,1,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2070         type 
= (buf
[0]&0xC0)>>6; 
2071         if (type 
== REDIS_RDB_6BITLEN
) { 
2072             /* Read a 6 bit len */ 
2074         } else if (type 
== REDIS_RDB_ENCVAL
) { 
2075             /* Read a 6 bit len encoding type */ 
2076             if (isencoded
) *isencoded 
= 1; 
2078         } else if (type 
== REDIS_RDB_14BITLEN
) { 
2079             /* Read a 14 bit len */ 
2080             if (fread(buf
+1,1,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2081             return ((buf
[0]&0x3F)<<8)|buf
[1]; 
2083             /* Read a 32 bit len */ 
2084             if (fread(&len
,4,1,fp
) == 0) return REDIS_RDB_LENERR
; 
2090 static robj 
*rdbLoadIntegerObject(FILE *fp
, int enctype
) { 
2091     unsigned char enc
[4]; 
2094     if (enctype 
== REDIS_RDB_ENC_INT8
) { 
2095         if (fread(enc
,1,1,fp
) == 0) return NULL
; 
2096         val 
= (signed char)enc
[0]; 
2097     } else if (enctype 
== REDIS_RDB_ENC_INT16
) { 
2099         if (fread(enc
,2,1,fp
) == 0) return NULL
; 
2100         v 
= enc
[0]|(enc
[1]<<8); 
2102     } else if (enctype 
== REDIS_RDB_ENC_INT32
) { 
2104         if (fread(enc
,4,1,fp
) == 0) return NULL
; 
2105         v 
= enc
[0]|(enc
[1]<<8)|(enc
[2]<<16)|(enc
[3]<<24); 
2108         val 
= 0; /* anti-warning */ 
2111     return createObject(REDIS_STRING
,sdscatprintf(sdsempty(),"%lld",val
)); 
2114 static robj 
*rdbLoadLzfStringObject(FILE*fp
, int rdbver
) { 
2115     unsigned int len
, clen
; 
2116     unsigned char *c 
= NULL
; 
2119     if ((clen 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
2120     if ((len 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
2121     if ((c 
= zmalloc(clen
)) == NULL
) goto err
; 
2122     if ((val 
= sdsnewlen(NULL
,len
)) == NULL
) goto err
; 
2123     if (fread(c
,clen
,1,fp
) == 0) goto err
; 
2124     if (lzf_decompress(c
,clen
,val
,len
) == 0) goto err
; 
2126     return createObject(REDIS_STRING
,val
); 
2133 static robj 
*rdbLoadStringObject(FILE*fp
, int rdbver
) { 
2138     len 
= rdbLoadLen(fp
,rdbver
,&isencoded
); 
2141         case REDIS_RDB_ENC_INT8
: 
2142         case REDIS_RDB_ENC_INT16
: 
2143         case REDIS_RDB_ENC_INT32
: 
2144             return tryObjectSharing(rdbLoadIntegerObject(fp
,len
)); 
2145         case REDIS_RDB_ENC_LZF
: 
2146             return tryObjectSharing(rdbLoadLzfStringObject(fp
,rdbver
)); 
2152     if (len 
== REDIS_RDB_LENERR
) return NULL
; 
2153     val 
= sdsnewlen(NULL
,len
); 
2154     if (len 
&& fread(val
,len
,1,fp
) == 0) { 
2158     return tryObjectSharing(createObject(REDIS_STRING
,val
)); 
2161 static int rdbLoad(char *filename
) { 
2163     robj 
*keyobj 
= NULL
; 
2165     int type
, retval
, rdbver
; 
2166     dict 
*d 
= server
.db
[0].dict
; 
2167     redisDb 
*db 
= server
.db
+0; 
2169     time_t expiretime 
= -1, now 
= time(NULL
); 
2171     fp 
= fopen(filename
,"r"); 
2172     if (!fp
) return REDIS_ERR
; 
2173     if (fread(buf
,9,1,fp
) == 0) goto eoferr
; 
2175     if (memcmp(buf
,"REDIS",5) != 0) { 
2177         redisLog(REDIS_WARNING
,"Wrong signature trying to load DB from file"); 
2180     rdbver 
= atoi(buf
+5); 
2183         redisLog(REDIS_WARNING
,"Can't handle RDB format version %d",rdbver
); 
2190         if ((type 
= rdbLoadType(fp
)) == -1) goto eoferr
; 
2191         if (type 
== REDIS_EXPIRETIME
) { 
2192             if ((expiretime 
= rdbLoadTime(fp
)) == -1) goto eoferr
; 
2193             /* We read the time so we need to read the object type again */ 
2194             if ((type 
= rdbLoadType(fp
)) == -1) goto eoferr
; 
2196         if (type 
== REDIS_EOF
) break; 
2197         /* Handle SELECT DB opcode as a special case */ 
2198         if (type 
== REDIS_SELECTDB
) { 
2199             if ((dbid 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) 
2201             if (dbid 
>= (unsigned)server
.dbnum
) { 
2202                 redisLog(REDIS_WARNING
,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server
.dbnum
); 
2205             db 
= server
.db
+dbid
; 
2210         if ((keyobj 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2212         if (type 
== REDIS_STRING
) { 
2213             /* Read string value */ 
2214             if ((o 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2215         } else if (type 
== REDIS_LIST 
|| type 
== REDIS_SET
) { 
2216             /* Read list/set value */ 
2219             if ((listlen 
= rdbLoadLen(fp
,rdbver
,NULL
)) == REDIS_RDB_LENERR
) 
2221             o 
= (type 
== REDIS_LIST
) ? createListObject() : createSetObject(); 
2222             /* Load every single element of the list/set */ 
2226                 if ((ele 
= rdbLoadStringObject(fp
,rdbver
)) == NULL
) goto eoferr
; 
2227                 if (type 
== REDIS_LIST
) { 
2228                     if (!listAddNodeTail((list
*)o
->ptr
,ele
)) 
2229                         oom("listAddNodeTail"); 
2231                     if (dictAdd((dict
*)o
->ptr
,ele
,NULL
) == DICT_ERR
) 
2238         /* Add the new object in the hash table */ 
2239         retval 
= dictAdd(d
,keyobj
,o
); 
2240         if (retval 
== DICT_ERR
) { 
2241             redisLog(REDIS_WARNING
,"Loading DB, duplicated key (%s) found! Unrecoverable error, exiting now.", keyobj
->ptr
); 
2244         /* Set the expire time if needed */ 
2245         if (expiretime 
!= -1) { 
2246             setExpire(db
,keyobj
,expiretime
); 
2247             /* Delete this key if already expired */ 
2248             if (expiretime 
< now
) deleteKey(db
,keyobj
); 
2256 eoferr
: /* unexpected end of file is handled here with a fatal exit */ 
2257     if (keyobj
) decrRefCount(keyobj
); 
2258     redisLog(REDIS_WARNING
,"Short read or OOM loading DB. Unrecoverable error, exiting now."); 
2260     return REDIS_ERR
; /* Just to avoid warning */ 
2263 /*================================== Commands =============================== */ 
2265 static void authCommand(redisClient 
*c
) { 
2266     if (!server
.requirepass 
|| !strcmp(c
->argv
[1]->ptr
, server
.requirepass
)) { 
2267       c
->authenticated 
= 1; 
2268       addReply(c
,shared
.ok
); 
2270       c
->authenticated 
= 0; 
2271       addReply(c
,shared
.err
); 
2275 static void pingCommand(redisClient 
*c
) { 
2276     addReply(c
,shared
.pong
); 
2279 static void echoCommand(redisClient 
*c
) { 
2280     addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n", 
2281         (int)sdslen(c
->argv
[1]->ptr
))); 
2282     addReply(c
,c
->argv
[1]); 
2283     addReply(c
,shared
.crlf
); 
2286 /*=================================== Strings =============================== */ 
2288 static void setGenericCommand(redisClient 
*c
, int nx
) { 
2291     retval 
= dictAdd(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2292     if (retval 
== DICT_ERR
) { 
2294             dictReplace(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2295             incrRefCount(c
->argv
[2]); 
2297             addReply(c
,shared
.czero
); 
2301         incrRefCount(c
->argv
[1]); 
2302         incrRefCount(c
->argv
[2]); 
2305     removeExpire(c
->db
,c
->argv
[1]); 
2306     addReply(c
, nx 
? shared
.cone 
: shared
.ok
); 
2309 static void setCommand(redisClient 
*c
) { 
2310     setGenericCommand(c
,0); 
2313 static void setnxCommand(redisClient 
*c
) { 
2314     setGenericCommand(c
,1); 
2317 static void getCommand(redisClient 
*c
) { 
2318     robj 
*o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
2321         addReply(c
,shared
.nullbulk
); 
2323         if (o
->type 
!= REDIS_STRING
) { 
2324             addReply(c
,shared
.wrongtypeerr
); 
2326             addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(o
->ptr
))); 
2328             addReply(c
,shared
.crlf
); 
2333 static void getSetCommand(redisClient 
*c
) { 
2335     if (dictAdd(c
->db
->dict
,c
->argv
[1],c
->argv
[2]) == DICT_ERR
) { 
2336         dictReplace(c
->db
->dict
,c
->argv
[1],c
->argv
[2]); 
2338         incrRefCount(c
->argv
[1]); 
2340     incrRefCount(c
->argv
[2]); 
2342     removeExpire(c
->db
,c
->argv
[1]); 
2345 static void mgetCommand(redisClient 
*c
) { 
2348     addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",c
->argc
-1)); 
2349     for (j 
= 1; j 
< c
->argc
; j
++) { 
2350         robj 
*o 
= lookupKeyRead(c
->db
,c
->argv
[j
]); 
2352             addReply(c
,shared
.nullbulk
); 
2354             if (o
->type 
!= REDIS_STRING
) { 
2355                 addReply(c
,shared
.nullbulk
); 
2357                 addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(o
->ptr
))); 
2359                 addReply(c
,shared
.crlf
); 
2365 static void incrDecrCommand(redisClient 
*c
, long long incr
) { 
2370     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2374         if (o
->type 
!= REDIS_STRING
) { 
2379             value 
= strtoll(o
->ptr
, &eptr
, 10); 
2384     o 
= createObject(REDIS_STRING
,sdscatprintf(sdsempty(),"%lld",value
)); 
2385     retval 
= dictAdd(c
->db
->dict
,c
->argv
[1],o
); 
2386     if (retval 
== DICT_ERR
) { 
2387         dictReplace(c
->db
->dict
,c
->argv
[1],o
); 
2388         removeExpire(c
->db
,c
->argv
[1]); 
2390         incrRefCount(c
->argv
[1]); 
2393     addReply(c
,shared
.colon
); 
2395     addReply(c
,shared
.crlf
); 
2398 static void incrCommand(redisClient 
*c
) { 
2399     incrDecrCommand(c
,1); 
2402 static void decrCommand(redisClient 
*c
) { 
2403     incrDecrCommand(c
,-1); 
2406 static void incrbyCommand(redisClient 
*c
) { 
2407     long long incr 
= strtoll(c
->argv
[2]->ptr
, NULL
, 10); 
2408     incrDecrCommand(c
,incr
); 
2411 static void decrbyCommand(redisClient 
*c
) { 
2412     long long incr 
= strtoll(c
->argv
[2]->ptr
, NULL
, 10); 
2413     incrDecrCommand(c
,-incr
); 
2416 /* ========================= Type agnostic commands ========================= */ 
2418 static void delCommand(redisClient 
*c
) { 
2421     for (j 
= 1; j 
< c
->argc
; j
++) { 
2422         if (deleteKey(c
->db
,c
->argv
[j
])) { 
2429         addReply(c
,shared
.czero
); 
2432         addReply(c
,shared
.cone
); 
2435         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",deleted
)); 
2440 static void existsCommand(redisClient 
*c
) { 
2441     addReply(c
,lookupKeyRead(c
->db
,c
->argv
[1]) ? shared
.cone 
: shared
.czero
); 
2444 static void selectCommand(redisClient 
*c
) { 
2445     int id 
= atoi(c
->argv
[1]->ptr
); 
2447     if (selectDb(c
,id
) == REDIS_ERR
) { 
2448         addReplySds(c
,sdsnew("-ERR invalid DB index\r\n")); 
2450         addReply(c
,shared
.ok
); 
2454 static void randomkeyCommand(redisClient 
*c
) { 
2458         de 
= dictGetRandomKey(c
->db
->dict
); 
2459         if (!de 
|| expireIfNeeded(c
->db
,dictGetEntryKey(de
)) == 0) break; 
2462         addReply(c
,shared
.plus
); 
2463         addReply(c
,shared
.crlf
); 
2465         addReply(c
,shared
.plus
); 
2466         addReply(c
,dictGetEntryKey(de
)); 
2467         addReply(c
,shared
.crlf
); 
2471 static void keysCommand(redisClient 
*c
) { 
2474     sds pattern 
= c
->argv
[1]->ptr
; 
2475     int plen 
= sdslen(pattern
); 
2476     int numkeys 
= 0, keyslen 
= 0; 
2477     robj 
*lenobj 
= createObject(REDIS_STRING
,NULL
); 
2479     di 
= dictGetIterator(c
->db
->dict
); 
2480     if (!di
) oom("dictGetIterator"); 
2482     decrRefCount(lenobj
); 
2483     while((de 
= dictNext(di
)) != NULL
) { 
2484         robj 
*keyobj 
= dictGetEntryKey(de
); 
2486         sds key 
= keyobj
->ptr
; 
2487         if ((pattern
[0] == '*' && pattern
[1] == '\0') || 
2488             stringmatchlen(pattern
,plen
,key
,sdslen(key
),0)) { 
2489             if (expireIfNeeded(c
->db
,keyobj
) == 0) { 
2491                     addReply(c
,shared
.space
); 
2494                 keyslen 
+= sdslen(key
); 
2498     dictReleaseIterator(di
); 
2499     lenobj
->ptr 
= sdscatprintf(sdsempty(),"$%lu\r\n",keyslen
+(numkeys 
? (numkeys
-1) : 0)); 
2500     addReply(c
,shared
.crlf
); 
2503 static void dbsizeCommand(redisClient 
*c
) { 
2505         sdscatprintf(sdsempty(),":%lu\r\n",dictSize(c
->db
->dict
))); 
2508 static void lastsaveCommand(redisClient 
*c
) { 
2510         sdscatprintf(sdsempty(),":%lu\r\n",server
.lastsave
)); 
2513 static void typeCommand(redisClient 
*c
) { 
2517     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
2522         case REDIS_STRING
: type 
= "+string"; break; 
2523         case REDIS_LIST
: type 
= "+list"; break; 
2524         case REDIS_SET
: type 
= "+set"; break; 
2525         default: type 
= "unknown"; break; 
2528     addReplySds(c
,sdsnew(type
)); 
2529     addReply(c
,shared
.crlf
); 
2532 static void saveCommand(redisClient 
*c
) { 
2533     if (server
.bgsaveinprogress
) { 
2534         addReplySds(c
,sdsnew("-ERR background save in progress\r\n")); 
2537     if (rdbSave(server
.dbfilename
) == REDIS_OK
) { 
2538         addReply(c
,shared
.ok
); 
2540         addReply(c
,shared
.err
); 
2544 static void bgsaveCommand(redisClient 
*c
) { 
2545     if (server
.bgsaveinprogress
) { 
2546         addReplySds(c
,sdsnew("-ERR background save already in progress\r\n")); 
2549     if (rdbSaveBackground(server
.dbfilename
) == REDIS_OK
) { 
2550         addReply(c
,shared
.ok
); 
2552         addReply(c
,shared
.err
); 
2556 static void shutdownCommand(redisClient 
*c
) { 
2557     redisLog(REDIS_WARNING
,"User requested shutdown, saving DB..."); 
2558     /* Kill the saving child if there is a background saving in progress. 
2559        We want to avoid race conditions, for instance our saving child may 
2560        overwrite the synchronous saving did by SHUTDOWN. */ 
2561     if (server
.bgsaveinprogress
) { 
2562         redisLog(REDIS_WARNING
,"There is a live saving child. Killing it!"); 
2563         kill(server
.bgsavechildpid
,SIGKILL
); 
2564         rdbRemoveTempFile(server
.bgsavechildpid
); 
2567     if (rdbSave(server
.dbfilename
) == REDIS_OK
) { 
2568         if (server
.daemonize
) 
2569             unlink(server
.pidfile
); 
2570         redisLog(REDIS_WARNING
,"%zu bytes used at exit",zmalloc_used_memory()); 
2571         redisLog(REDIS_WARNING
,"Server exit now, bye bye..."); 
2574         /* Ooops.. error saving! The best we can do is to continue operating. 
2575          * Note that if there was a background saving process, in the next 
2576          * cron() Redis will be notified that the background saving aborted, 
2577          * handling special stuff like slaves pending for synchronization... */ 
2578         redisLog(REDIS_WARNING
,"Error trying to save the DB, can't exit");  
2579         addReplySds(c
,sdsnew("-ERR can't quit, problems saving the DB\r\n")); 
2583 static void renameGenericCommand(redisClient 
*c
, int nx
) { 
2586     /* To use the same key as src and dst is probably an error */ 
2587     if (sdscmp(c
->argv
[1]->ptr
,c
->argv
[2]->ptr
) == 0) { 
2588         addReply(c
,shared
.sameobjecterr
); 
2592     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2594         addReply(c
,shared
.nokeyerr
); 
2598     deleteIfVolatile(c
->db
,c
->argv
[2]); 
2599     if (dictAdd(c
->db
->dict
,c
->argv
[2],o
) == DICT_ERR
) { 
2602             addReply(c
,shared
.czero
); 
2605         dictReplace(c
->db
->dict
,c
->argv
[2],o
); 
2607         incrRefCount(c
->argv
[2]); 
2609     deleteKey(c
->db
,c
->argv
[1]); 
2611     addReply(c
,nx 
? shared
.cone 
: shared
.ok
); 
2614 static void renameCommand(redisClient 
*c
) { 
2615     renameGenericCommand(c
,0); 
2618 static void renamenxCommand(redisClient 
*c
) { 
2619     renameGenericCommand(c
,1); 
2622 static void moveCommand(redisClient 
*c
) { 
2627     /* Obtain source and target DB pointers */ 
2630     if (selectDb(c
,atoi(c
->argv
[2]->ptr
)) == REDIS_ERR
) { 
2631         addReply(c
,shared
.outofrangeerr
); 
2635     selectDb(c
,srcid
); /* Back to the source DB */ 
2637     /* If the user is moving using as target the same 
2638      * DB as the source DB it is probably an error. */ 
2640         addReply(c
,shared
.sameobjecterr
); 
2644     /* Check if the element exists and get a reference */ 
2645     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2647         addReply(c
,shared
.czero
); 
2651     /* Try to add the element to the target DB */ 
2652     deleteIfVolatile(dst
,c
->argv
[1]); 
2653     if (dictAdd(dst
->dict
,c
->argv
[1],o
) == DICT_ERR
) { 
2654         addReply(c
,shared
.czero
); 
2657     incrRefCount(c
->argv
[1]); 
2660     /* OK! key moved, free the entry in the source DB */ 
2661     deleteKey(src
,c
->argv
[1]); 
2663     addReply(c
,shared
.cone
); 
2666 /* =================================== Lists ================================ */ 
2667 static void pushGenericCommand(redisClient 
*c
, int where
) { 
2671     lobj 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2673         lobj 
= createListObject(); 
2675         if (where 
== REDIS_HEAD
) { 
2676             if (!listAddNodeHead(list
,c
->argv
[2])) oom("listAddNodeHead"); 
2678             if (!listAddNodeTail(list
,c
->argv
[2])) oom("listAddNodeTail"); 
2680         dictAdd(c
->db
->dict
,c
->argv
[1],lobj
); 
2681         incrRefCount(c
->argv
[1]); 
2682         incrRefCount(c
->argv
[2]); 
2684         if (lobj
->type 
!= REDIS_LIST
) { 
2685             addReply(c
,shared
.wrongtypeerr
); 
2689         if (where 
== REDIS_HEAD
) { 
2690             if (!listAddNodeHead(list
,c
->argv
[2])) oom("listAddNodeHead"); 
2692             if (!listAddNodeTail(list
,c
->argv
[2])) oom("listAddNodeTail"); 
2694         incrRefCount(c
->argv
[2]); 
2697     addReply(c
,shared
.ok
); 
2700 static void lpushCommand(redisClient 
*c
) { 
2701     pushGenericCommand(c
,REDIS_HEAD
); 
2704 static void rpushCommand(redisClient 
*c
) { 
2705     pushGenericCommand(c
,REDIS_TAIL
); 
2708 static void llenCommand(redisClient 
*c
) { 
2712     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
2714         addReply(c
,shared
.czero
); 
2717         if (o
->type 
!= REDIS_LIST
) { 
2718             addReply(c
,shared
.wrongtypeerr
); 
2721             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",listLength(l
))); 
2726 static void lindexCommand(redisClient 
*c
) { 
2728     int index 
= atoi(c
->argv
[2]->ptr
); 
2730     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
2732         addReply(c
,shared
.nullbulk
); 
2734         if (o
->type 
!= REDIS_LIST
) { 
2735             addReply(c
,shared
.wrongtypeerr
); 
2737             list 
*list 
= o
->ptr
; 
2740             ln 
= listIndex(list
, index
); 
2742                 addReply(c
,shared
.nullbulk
); 
2744                 robj 
*ele 
= listNodeValue(ln
); 
2745                 addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(ele
->ptr
))); 
2747                 addReply(c
,shared
.crlf
); 
2753 static void lsetCommand(redisClient 
*c
) { 
2755     int index 
= atoi(c
->argv
[2]->ptr
); 
2757     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2759         addReply(c
,shared
.nokeyerr
); 
2761         if (o
->type 
!= REDIS_LIST
) { 
2762             addReply(c
,shared
.wrongtypeerr
); 
2764             list 
*list 
= o
->ptr
; 
2767             ln 
= listIndex(list
, index
); 
2769                 addReply(c
,shared
.outofrangeerr
); 
2771                 robj 
*ele 
= listNodeValue(ln
); 
2774                 listNodeValue(ln
) = c
->argv
[3]; 
2775                 incrRefCount(c
->argv
[3]); 
2776                 addReply(c
,shared
.ok
); 
2783 static void popGenericCommand(redisClient 
*c
, int where
) { 
2786     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2788         addReply(c
,shared
.nullbulk
); 
2790         if (o
->type 
!= REDIS_LIST
) { 
2791             addReply(c
,shared
.wrongtypeerr
); 
2793             list 
*list 
= o
->ptr
; 
2796             if (where 
== REDIS_HEAD
) 
2797                 ln 
= listFirst(list
); 
2799                 ln 
= listLast(list
); 
2802                 addReply(c
,shared
.nullbulk
); 
2804                 robj 
*ele 
= listNodeValue(ln
); 
2805                 addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(ele
->ptr
))); 
2807                 addReply(c
,shared
.crlf
); 
2808                 listDelNode(list
,ln
); 
2815 static void lpopCommand(redisClient 
*c
) { 
2816     popGenericCommand(c
,REDIS_HEAD
); 
2819 static void rpopCommand(redisClient 
*c
) { 
2820     popGenericCommand(c
,REDIS_TAIL
); 
2823 static void lrangeCommand(redisClient 
*c
) { 
2825     int start 
= atoi(c
->argv
[2]->ptr
); 
2826     int end 
= atoi(c
->argv
[3]->ptr
); 
2828     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
2830         addReply(c
,shared
.nullmultibulk
); 
2832         if (o
->type 
!= REDIS_LIST
) { 
2833             addReply(c
,shared
.wrongtypeerr
); 
2835             list 
*list 
= o
->ptr
; 
2837             int llen 
= listLength(list
); 
2841             /* convert negative indexes */ 
2842             if (start 
< 0) start 
= llen
+start
; 
2843             if (end 
< 0) end 
= llen
+end
; 
2844             if (start 
< 0) start 
= 0; 
2845             if (end 
< 0) end 
= 0; 
2847             /* indexes sanity checks */ 
2848             if (start 
> end 
|| start 
>= llen
) { 
2849                 /* Out of range start or start > end result in empty list */ 
2850                 addReply(c
,shared
.emptymultibulk
); 
2853             if (end 
>= llen
) end 
= llen
-1; 
2854             rangelen 
= (end
-start
)+1; 
2856             /* Return the result in form of a multi-bulk reply */ 
2857             ln 
= listIndex(list
, start
); 
2858             addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",rangelen
)); 
2859             for (j 
= 0; j 
< rangelen
; j
++) { 
2860                 ele 
= listNodeValue(ln
); 
2861                 addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(ele
->ptr
))); 
2863                 addReply(c
,shared
.crlf
); 
2870 static void ltrimCommand(redisClient 
*c
) { 
2872     int start 
= atoi(c
->argv
[2]->ptr
); 
2873     int end 
= atoi(c
->argv
[3]->ptr
); 
2875     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2877         addReply(c
,shared
.nokeyerr
); 
2879         if (o
->type 
!= REDIS_LIST
) { 
2880             addReply(c
,shared
.wrongtypeerr
); 
2882             list 
*list 
= o
->ptr
; 
2884             int llen 
= listLength(list
); 
2885             int j
, ltrim
, rtrim
; 
2887             /* convert negative indexes */ 
2888             if (start 
< 0) start 
= llen
+start
; 
2889             if (end 
< 0) end 
= llen
+end
; 
2890             if (start 
< 0) start 
= 0; 
2891             if (end 
< 0) end 
= 0; 
2893             /* indexes sanity checks */ 
2894             if (start 
> end 
|| start 
>= llen
) { 
2895                 /* Out of range start or start > end result in empty list */ 
2899                 if (end 
>= llen
) end 
= llen
-1; 
2904             /* Remove list elements to perform the trim */ 
2905             for (j 
= 0; j 
< ltrim
; j
++) { 
2906                 ln 
= listFirst(list
); 
2907                 listDelNode(list
,ln
); 
2909             for (j 
= 0; j 
< rtrim
; j
++) { 
2910                 ln 
= listLast(list
); 
2911                 listDelNode(list
,ln
); 
2914             addReply(c
,shared
.ok
); 
2919 static void lremCommand(redisClient 
*c
) { 
2922     o 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2924         addReply(c
,shared
.czero
); 
2926         if (o
->type 
!= REDIS_LIST
) { 
2927             addReply(c
,shared
.wrongtypeerr
); 
2929             list 
*list 
= o
->ptr
; 
2930             listNode 
*ln
, *next
; 
2931             int toremove 
= atoi(c
->argv
[2]->ptr
); 
2936                 toremove 
= -toremove
; 
2939             ln 
= fromtail 
? list
->tail 
: list
->head
; 
2941                 robj 
*ele 
= listNodeValue(ln
); 
2943                 next 
= fromtail 
? ln
->prev 
: ln
->next
; 
2944                 if (sdscmp(ele
->ptr
,c
->argv
[3]->ptr
) == 0) { 
2945                     listDelNode(list
,ln
); 
2948                     if (toremove 
&& removed 
== toremove
) break; 
2952             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",removed
)); 
2957 /* ==================================== Sets ================================ */ 
2959 static void saddCommand(redisClient 
*c
) { 
2962     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2964         set 
= createSetObject(); 
2965         dictAdd(c
->db
->dict
,c
->argv
[1],set
); 
2966         incrRefCount(c
->argv
[1]); 
2968         if (set
->type 
!= REDIS_SET
) { 
2969             addReply(c
,shared
.wrongtypeerr
); 
2973     if (dictAdd(set
->ptr
,c
->argv
[2],NULL
) == DICT_OK
) { 
2974         incrRefCount(c
->argv
[2]); 
2976         addReply(c
,shared
.cone
); 
2978         addReply(c
,shared
.czero
); 
2982 static void sremCommand(redisClient 
*c
) { 
2985     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
2987         addReply(c
,shared
.czero
); 
2989         if (set
->type 
!= REDIS_SET
) { 
2990             addReply(c
,shared
.wrongtypeerr
); 
2993         if (dictDelete(set
->ptr
,c
->argv
[2]) == DICT_OK
) { 
2995             if (htNeedsResize(set
->ptr
)) dictResize(set
->ptr
); 
2996             addReply(c
,shared
.cone
); 
2998             addReply(c
,shared
.czero
); 
3003 static void smoveCommand(redisClient 
*c
) { 
3004     robj 
*srcset
, *dstset
; 
3006     srcset 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3007     dstset 
= lookupKeyWrite(c
->db
,c
->argv
[2]); 
3009     /* If the source key does not exist return 0, if it's of the wrong type 
3011     if (srcset 
== NULL 
|| srcset
->type 
!= REDIS_SET
) { 
3012         addReply(c
, srcset 
? shared
.wrongtypeerr 
: shared
.czero
); 
3015     /* Error if the destination key is not a set as well */ 
3016     if (dstset 
&& dstset
->type 
!= REDIS_SET
) { 
3017         addReply(c
,shared
.wrongtypeerr
); 
3020     /* Remove the element from the source set */ 
3021     if (dictDelete(srcset
->ptr
,c
->argv
[3]) == DICT_ERR
) { 
3022         /* Key not found in the src set! return zero */ 
3023         addReply(c
,shared
.czero
); 
3027     /* Add the element to the destination set */ 
3029         dstset 
= createSetObject(); 
3030         dictAdd(c
->db
->dict
,c
->argv
[2],dstset
); 
3031         incrRefCount(c
->argv
[2]); 
3033     if (dictAdd(dstset
->ptr
,c
->argv
[3],NULL
) == DICT_OK
) 
3034         incrRefCount(c
->argv
[3]); 
3035     addReply(c
,shared
.cone
); 
3038 static void sismemberCommand(redisClient 
*c
) { 
3041     set 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3043         addReply(c
,shared
.czero
); 
3045         if (set
->type 
!= REDIS_SET
) { 
3046             addReply(c
,shared
.wrongtypeerr
); 
3049         if (dictFind(set
->ptr
,c
->argv
[2])) 
3050             addReply(c
,shared
.cone
); 
3052             addReply(c
,shared
.czero
); 
3056 static void scardCommand(redisClient 
*c
) { 
3060     o 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3062         addReply(c
,shared
.czero
); 
3065         if (o
->type 
!= REDIS_SET
) { 
3066             addReply(c
,shared
.wrongtypeerr
); 
3069             addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3075 static void spopCommand(redisClient 
*c
) { 
3079     set 
= lookupKeyWrite(c
->db
,c
->argv
[1]); 
3081         addReply(c
,shared
.nullbulk
); 
3083         if (set
->type 
!= REDIS_SET
) { 
3084             addReply(c
,shared
.wrongtypeerr
); 
3087         de 
= dictGetRandomKey(set
->ptr
); 
3089             addReply(c
,shared
.nullbulk
); 
3091             robj 
*ele 
= dictGetEntryKey(de
); 
3093             addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",sdslen(ele
->ptr
))); 
3095             addReply(c
,shared
.crlf
); 
3096             dictDelete(set
->ptr
,ele
); 
3097             if (htNeedsResize(set
->ptr
)) dictResize(set
->ptr
); 
3103 static int qsortCompareSetsByCardinality(const void *s1
, const void *s2
) { 
3104     dict 
**d1 
= (void*) s1
, **d2 
= (void*) s2
; 
3106     return dictSize(*d1
)-dictSize(*d2
); 
3109 static void sinterGenericCommand(redisClient 
*c
, robj 
**setskeys
, int setsnum
, robj 
*dstkey
) { 
3110     dict 
**dv 
= zmalloc(sizeof(dict
*)*setsnum
); 
3113     robj 
*lenobj 
= NULL
, *dstset 
= NULL
; 
3114     int j
, cardinality 
= 0; 
3116     if (!dv
) oom("sinterGenericCommand"); 
3117     for (j 
= 0; j 
< setsnum
; j
++) { 
3121                     lookupKeyWrite(c
->db
,setskeys
[j
]) : 
3122                     lookupKeyRead(c
->db
,setskeys
[j
]); 
3126                 deleteKey(c
->db
,dstkey
); 
3127                 addReply(c
,shared
.ok
); 
3129                 addReply(c
,shared
.nullmultibulk
); 
3133         if (setobj
->type 
!= REDIS_SET
) { 
3135             addReply(c
,shared
.wrongtypeerr
); 
3138         dv
[j
] = setobj
->ptr
; 
3140     /* Sort sets from the smallest to largest, this will improve our 
3141      * algorithm's performace */ 
3142     qsort(dv
,setsnum
,sizeof(dict
*),qsortCompareSetsByCardinality
); 
3144     /* The first thing we should output is the total number of elements... 
3145      * since this is a multi-bulk write, but at this stage we don't know 
3146      * the intersection set size, so we use a trick, append an empty object 
3147      * to the output list and save the pointer to later modify it with the 
3150         lenobj 
= createObject(REDIS_STRING
,NULL
); 
3152         decrRefCount(lenobj
); 
3154         /* If we have a target key where to store the resulting set 
3155          * create this key with an empty set inside */ 
3156         dstset 
= createSetObject(); 
3159     /* Iterate all the elements of the first (smallest) set, and test 
3160      * the element against all the other sets, if at least one set does 
3161      * not include the element it is discarded */ 
3162     di 
= dictGetIterator(dv
[0]); 
3163     if (!di
) oom("dictGetIterator"); 
3165     while((de 
= dictNext(di
)) != NULL
) { 
3168         for (j 
= 1; j 
< setsnum
; j
++) 
3169             if (dictFind(dv
[j
],dictGetEntryKey(de
)) == NULL
) break; 
3171             continue; /* at least one set does not contain the member */ 
3172         ele 
= dictGetEntryKey(de
); 
3174             addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",sdslen(ele
->ptr
))); 
3176             addReply(c
,shared
.crlf
); 
3179             dictAdd(dstset
->ptr
,ele
,NULL
); 
3183     dictReleaseIterator(di
); 
3186         /* Store the resulting set into the target */ 
3187         deleteKey(c
->db
,dstkey
); 
3188         dictAdd(c
->db
->dict
,dstkey
,dstset
); 
3189         incrRefCount(dstkey
); 
3193         lenobj
->ptr 
= sdscatprintf(sdsempty(),"*%d\r\n",cardinality
); 
3195         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3196             dictSize((dict
*)dstset
->ptr
))); 
3202 static void sinterCommand(redisClient 
*c
) { 
3203     sinterGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
); 
3206 static void sinterstoreCommand(redisClient 
*c
) { 
3207     sinterGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1]); 
3210 #define REDIS_OP_UNION 0 
3211 #define REDIS_OP_DIFF 1 
3213 static void sunionDiffGenericCommand(redisClient 
*c
, robj 
**setskeys
, int setsnum
, robj 
*dstkey
, int op
) { 
3214     dict 
**dv 
= zmalloc(sizeof(dict
*)*setsnum
); 
3217     robj 
*dstset 
= NULL
; 
3218     int j
, cardinality 
= 0; 
3220     if (!dv
) oom("sunionDiffGenericCommand"); 
3221     for (j 
= 0; j 
< setsnum
; j
++) { 
3225                     lookupKeyWrite(c
->db
,setskeys
[j
]) : 
3226                     lookupKeyRead(c
->db
,setskeys
[j
]); 
3231         if (setobj
->type 
!= REDIS_SET
) { 
3233             addReply(c
,shared
.wrongtypeerr
); 
3236         dv
[j
] = setobj
->ptr
; 
3239     /* We need a temp set object to store our union. If the dstkey 
3240      * is not NULL (that is, we are inside an SUNIONSTORE operation) then 
3241      * this set object will be the resulting object to set into the target key*/ 
3242     dstset 
= createSetObject(); 
3244     /* Iterate all the elements of all the sets, add every element a single 
3245      * time to the result set */ 
3246     for (j 
= 0; j 
< setsnum
; j
++) { 
3247         if (op 
== REDIS_OP_DIFF 
&& j 
== 0 && !dv
[j
]) break; /* result set is empty */ 
3248         if (!dv
[j
]) continue; /* non existing keys are like empty sets */ 
3250         di 
= dictGetIterator(dv
[j
]); 
3251         if (!di
) oom("dictGetIterator"); 
3253         while((de 
= dictNext(di
)) != NULL
) { 
3256             /* dictAdd will not add the same element multiple times */ 
3257             ele 
= dictGetEntryKey(de
); 
3258             if (op 
== REDIS_OP_UNION 
|| j 
== 0) { 
3259                 if (dictAdd(dstset
->ptr
,ele
,NULL
) == DICT_OK
) { 
3263             } else if (op 
== REDIS_OP_DIFF
) { 
3264                 if (dictDelete(dstset
->ptr
,ele
) == DICT_OK
) { 
3269         dictReleaseIterator(di
); 
3271         if (op 
== REDIS_OP_DIFF 
&& cardinality 
== 0) break; /* result set is empty */ 
3274     /* Output the content of the resulting set, if not in STORE mode */ 
3276         addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",cardinality
)); 
3277         di 
= dictGetIterator(dstset
->ptr
); 
3278         if (!di
) oom("dictGetIterator"); 
3279         while((de 
= dictNext(di
)) != NULL
) { 
3282             ele 
= dictGetEntryKey(de
); 
3283             addReplySds(c
,sdscatprintf(sdsempty(), 
3284                     "$%d\r\n",sdslen(ele
->ptr
))); 
3286             addReply(c
,shared
.crlf
); 
3288         dictReleaseIterator(di
); 
3290         /* If we have a target key where to store the resulting set 
3291          * create this key with the result set inside */ 
3292         deleteKey(c
->db
,dstkey
); 
3293         dictAdd(c
->db
->dict
,dstkey
,dstset
); 
3294         incrRefCount(dstkey
); 
3299         decrRefCount(dstset
); 
3301         addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n", 
3302             dictSize((dict
*)dstset
->ptr
))); 
3308 static void sunionCommand(redisClient 
*c
) { 
3309     sunionDiffGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
,REDIS_OP_UNION
); 
3312 static void sunionstoreCommand(redisClient 
*c
) { 
3313     sunionDiffGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1],REDIS_OP_UNION
); 
3316 static void sdiffCommand(redisClient 
*c
) { 
3317     sunionDiffGenericCommand(c
,c
->argv
+1,c
->argc
-1,NULL
,REDIS_OP_DIFF
); 
3320 static void sdiffstoreCommand(redisClient 
*c
) { 
3321     sunionDiffGenericCommand(c
,c
->argv
+2,c
->argc
-2,c
->argv
[1],REDIS_OP_DIFF
); 
3324 static void flushdbCommand(redisClient 
*c
) { 
3325     server
.dirty 
+= dictSize(c
->db
->dict
); 
3326     dictEmpty(c
->db
->dict
); 
3327     dictEmpty(c
->db
->expires
); 
3328     addReply(c
,shared
.ok
); 
3331 static void flushallCommand(redisClient 
*c
) { 
3332     server
.dirty 
+= emptyDb(); 
3333     addReply(c
,shared
.ok
); 
3334     rdbSave(server
.dbfilename
); 
3338 static redisSortOperation 
*createSortOperation(int type
, robj 
*pattern
) { 
3339     redisSortOperation 
*so 
= zmalloc(sizeof(*so
)); 
3340     if (!so
) oom("createSortOperation"); 
3342     so
->pattern 
= pattern
; 
3346 /* Return the value associated to the key with a name obtained 
3347  * substituting the first occurence of '*' in 'pattern' with 'subst' */ 
3348 static robj 
*lookupKeyByPattern(redisDb 
*db
, robj 
*pattern
, robj 
*subst
) { 
3352     int prefixlen
, sublen
, postfixlen
; 
3353     /* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */ 
3357         char buf
[REDIS_SORTKEY_MAX
+1]; 
3360     spat 
= pattern
->ptr
; 
3362     if (sdslen(spat
)+sdslen(ssub
)-1 > REDIS_SORTKEY_MAX
) return NULL
; 
3363     p 
= strchr(spat
,'*'); 
3364     if (!p
) return NULL
; 
3367     sublen 
= sdslen(ssub
); 
3368     postfixlen 
= sdslen(spat
)-(prefixlen
+1); 
3369     memcpy(keyname
.buf
,spat
,prefixlen
); 
3370     memcpy(keyname
.buf
+prefixlen
,ssub
,sublen
); 
3371     memcpy(keyname
.buf
+prefixlen
+sublen
,p
+1,postfixlen
); 
3372     keyname
.buf
[prefixlen
+sublen
+postfixlen
] = '\0'; 
3373     keyname
.len 
= prefixlen
+sublen
+postfixlen
; 
3375     keyobj
.refcount 
= 1; 
3376     keyobj
.type 
= REDIS_STRING
; 
3377     keyobj
.ptr 
= ((char*)&keyname
)+(sizeof(long)*2); 
3379     /* printf("lookup '%s' => %p\n", keyname.buf,de); */ 
3380     return lookupKeyRead(db
,&keyobj
); 
3383 /* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with 
3384  * the additional parameter is not standard but a BSD-specific we have to 
3385  * pass sorting parameters via the global 'server' structure */ 
3386 static int sortCompare(const void *s1
, const void *s2
) { 
3387     const redisSortObject 
*so1 
= s1
, *so2 
= s2
; 
3390     if (!server
.sort_alpha
) { 
3391         /* Numeric sorting. Here it's trivial as we precomputed scores */ 
3392         if (so1
->u
.score 
> so2
->u
.score
) { 
3394         } else if (so1
->u
.score 
< so2
->u
.score
) { 
3400         /* Alphanumeric sorting */ 
3401         if (server
.sort_bypattern
) { 
3402             if (!so1
->u
.cmpobj 
|| !so2
->u
.cmpobj
) { 
3403                 /* At least one compare object is NULL */ 
3404                 if (so1
->u
.cmpobj 
== so2
->u
.cmpobj
) 
3406                 else if (so1
->u
.cmpobj 
== NULL
) 
3411                 /* We have both the objects, use strcoll */ 
3412                 cmp 
= strcoll(so1
->u
.cmpobj
->ptr
,so2
->u
.cmpobj
->ptr
); 
3415             /* Compare elements directly */ 
3416             cmp 
= strcoll(so1
->obj
->ptr
,so2
->obj
->ptr
); 
3419     return server
.sort_desc 
? -cmp 
: cmp
; 
3422 /* The SORT command is the most complex command in Redis. Warning: this code 
3423  * is optimized for speed and a bit less for readability */ 
3424 static void sortCommand(redisClient 
*c
) { 
3427     int desc 
= 0, alpha 
= 0; 
3428     int limit_start 
= 0, limit_count 
= -1, start
, end
; 
3429     int j
, dontsort 
= 0, vectorlen
; 
3430     int getop 
= 0; /* GET operation counter */ 
3431     robj 
*sortval
, *sortby 
= NULL
; 
3432     redisSortObject 
*vector
; /* Resulting vector to sort */ 
3434     /* Lookup the key to sort. It must be of the right types */ 
3435     sortval 
= lookupKeyRead(c
->db
,c
->argv
[1]); 
3436     if (sortval 
== NULL
) { 
3437         addReply(c
,shared
.nokeyerr
); 
3440     if (sortval
->type 
!= REDIS_SET 
&& sortval
->type 
!= REDIS_LIST
) { 
3441         addReply(c
,shared
.wrongtypeerr
); 
3445     /* Create a list of operations to perform for every sorted element. 
3446      * Operations can be GET/DEL/INCR/DECR */ 
3447     operations 
= listCreate(); 
3448     listSetFreeMethod(operations
,zfree
); 
3451     /* Now we need to protect sortval incrementing its count, in the future 
3452      * SORT may have options able to overwrite/delete keys during the sorting 
3453      * and the sorted key itself may get destroied */ 
3454     incrRefCount(sortval
); 
3456     /* The SORT command has an SQL-alike syntax, parse it */ 
3457     while(j 
< c
->argc
) { 
3458         int leftargs 
= c
->argc
-j
-1; 
3459         if (!strcasecmp(c
->argv
[j
]->ptr
,"asc")) { 
3461         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"desc")) { 
3463         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"alpha")) { 
3465         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"limit") && leftargs 
>= 2) { 
3466             limit_start 
= atoi(c
->argv
[j
+1]->ptr
); 
3467             limit_count 
= atoi(c
->argv
[j
+2]->ptr
); 
3469         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"by") && leftargs 
>= 1) { 
3470             sortby 
= c
->argv
[j
+1]; 
3471             /* If the BY pattern does not contain '*', i.e. it is constant, 
3472              * we don't need to sort nor to lookup the weight keys. */ 
3473             if (strchr(c
->argv
[j
+1]->ptr
,'*') == NULL
) dontsort 
= 1; 
3475         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"get") && leftargs 
>= 1) { 
3476             listAddNodeTail(operations
,createSortOperation( 
3477                 REDIS_SORT_GET
,c
->argv
[j
+1])); 
3480         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"del") && leftargs 
>= 1) { 
3481             listAddNodeTail(operations
,createSortOperation( 
3482                 REDIS_SORT_DEL
,c
->argv
[j
+1])); 
3484         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"incr") && leftargs 
>= 1) { 
3485             listAddNodeTail(operations
,createSortOperation( 
3486                 REDIS_SORT_INCR
,c
->argv
[j
+1])); 
3488         } else if (!strcasecmp(c
->argv
[j
]->ptr
,"get") && leftargs 
>= 1) { 
3489             listAddNodeTail(operations
,createSortOperation( 
3490                 REDIS_SORT_DECR
,c
->argv
[j
+1])); 
3493             decrRefCount(sortval
); 
3494             listRelease(operations
); 
3495             addReply(c
,shared
.syntaxerr
); 
3501     /* Load the sorting vector with all the objects to sort */ 
3502     vectorlen 
= (sortval
->type 
== REDIS_LIST
) ? 
3503         listLength((list
*)sortval
->ptr
) : 
3504         dictSize((dict
*)sortval
->ptr
); 
3505     vector 
= zmalloc(sizeof(redisSortObject
)*vectorlen
); 
3506     if (!vector
) oom("allocating objects vector for SORT"); 
3508     if (sortval
->type 
== REDIS_LIST
) { 
3509         list 
*list 
= sortval
->ptr
; 
3513         while((ln 
= listYield(list
))) { 
3514             robj 
*ele 
= ln
->value
; 
3515             vector
[j
].obj 
= ele
; 
3516             vector
[j
].u
.score 
= 0; 
3517             vector
[j
].u
.cmpobj 
= NULL
; 
3521         dict 
*set 
= sortval
->ptr
; 
3525         di 
= dictGetIterator(set
); 
3526         if (!di
) oom("dictGetIterator"); 
3527         while((setele 
= dictNext(di
)) != NULL
) { 
3528             vector
[j
].obj 
= dictGetEntryKey(setele
); 
3529             vector
[j
].u
.score 
= 0; 
3530             vector
[j
].u
.cmpobj 
= NULL
; 
3533         dictReleaseIterator(di
); 
3535     assert(j 
== vectorlen
); 
3537     /* Now it's time to load the right scores in the sorting vector */ 
3538     if (dontsort 
== 0) { 
3539         for (j 
= 0; j 
< vectorlen
; j
++) { 
3543                 byval 
= lookupKeyByPattern(c
->db
,sortby
,vector
[j
].obj
); 
3544                 if (!byval 
|| byval
->type 
!= REDIS_STRING
) continue; 
3546                     vector
[j
].u
.cmpobj 
= byval
; 
3547                     incrRefCount(byval
); 
3549                     vector
[j
].u
.score 
= strtod(byval
->ptr
,NULL
); 
3552                 if (!alpha
) vector
[j
].u
.score 
= strtod(vector
[j
].obj
->ptr
,NULL
); 
3557     /* We are ready to sort the vector... perform a bit of sanity check 
3558      * on the LIMIT option too. We'll use a partial version of quicksort. */ 
3559     start 
= (limit_start 
< 0) ? 0 : limit_start
; 
3560     end 
= (limit_count 
< 0) ? vectorlen
-1 : start
+limit_count
-1; 
3561     if (start 
>= vectorlen
) { 
3562         start 
= vectorlen
-1; 
3565     if (end 
>= vectorlen
) end 
= vectorlen
-1; 
3567     if (dontsort 
== 0) { 
3568         server
.sort_desc 
= desc
; 
3569         server
.sort_alpha 
= alpha
; 
3570         server
.sort_bypattern 
= sortby 
? 1 : 0; 
3571         if (sortby 
&& (start 
!= 0 || end 
!= vectorlen
-1)) 
3572             pqsort(vector
,vectorlen
,sizeof(redisSortObject
),sortCompare
, start
,end
); 
3574             qsort(vector
,vectorlen
,sizeof(redisSortObject
),sortCompare
); 
3577     /* Send command output to the output buffer, performing the specified 
3578      * GET/DEL/INCR/DECR operations if any. */ 
3579     outputlen 
= getop 
? getop
*(end
-start
+1) : end
-start
+1; 
3580     addReplySds(c
,sdscatprintf(sdsempty(),"*%d\r\n",outputlen
)); 
3581     for (j 
= start
; j 
<= end
; j
++) { 
3584             addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n", 
3585                 sdslen(vector
[j
].obj
->ptr
))); 
3586             addReply(c
,vector
[j
].obj
); 
3587             addReply(c
,shared
.crlf
); 
3589         listRewind(operations
); 
3590         while((ln 
= listYield(operations
))) { 
3591             redisSortOperation 
*sop 
= ln
->value
; 
3592             robj 
*val 
= lookupKeyByPattern(c
->db
,sop
->pattern
, 
3595             if (sop
->type 
== REDIS_SORT_GET
) { 
3596                 if (!val 
|| val
->type 
!= REDIS_STRING
) { 
3597                     addReply(c
,shared
.nullbulk
); 
3599                     addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n", 
3602                     addReply(c
,shared
.crlf
); 
3604             } else if (sop
->type 
== REDIS_SORT_DEL
) { 
3611     decrRefCount(sortval
); 
3612     listRelease(operations
); 
3613     for (j 
= 0; j 
< vectorlen
; j
++) { 
3614         if (sortby 
&& alpha 
&& vector
[j
].u
.cmpobj
) 
3615             decrRefCount(vector
[j
].u
.cmpobj
); 
3620 static void infoCommand(redisClient 
*c
) { 
3622     time_t uptime 
= time(NULL
)-server
.stat_starttime
; 
3625     info 
= sdscatprintf(sdsempty(), 
3626         "redis_version:%s\r\n" 
3627         "uptime_in_seconds:%d\r\n" 
3628         "uptime_in_days:%d\r\n" 
3629         "connected_clients:%d\r\n" 
3630         "connected_slaves:%d\r\n" 
3631         "used_memory:%zu\r\n" 
3632         "changes_since_last_save:%lld\r\n" 
3633         "bgsave_in_progress:%d\r\n" 
3634         "last_save_time:%d\r\n" 
3635         "total_connections_received:%lld\r\n" 
3636         "total_commands_processed:%lld\r\n" 
3641         listLength(server
.clients
)-listLength(server
.slaves
), 
3642         listLength(server
.slaves
), 
3645         server
.bgsaveinprogress
, 
3647         server
.stat_numconnections
, 
3648         server
.stat_numcommands
, 
3649         server
.masterhost 
== NULL 
? "master" : "slave" 
3651     if (server
.masterhost
) { 
3652         info 
= sdscatprintf(info
, 
3653             "master_host:%s\r\n" 
3654             "master_port:%d\r\n" 
3655             "master_link_status:%s\r\n" 
3656             "master_last_io_seconds_ago:%d\r\n" 
3659             (server
.replstate 
== REDIS_REPL_CONNECTED
) ? 
3661             (int)(time(NULL
)-server
.master
->lastinteraction
) 
3664     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
3665         long long keys
, vkeys
; 
3667         keys 
= dictSize(server
.db
[j
].dict
); 
3668         vkeys 
= dictSize(server
.db
[j
].expires
); 
3669         if (keys 
|| vkeys
) { 
3670             info 
= sdscatprintf(info
, "db%d: keys=%lld,expires=%lld\r\n", 
3674     addReplySds(c
,sdscatprintf(sdsempty(),"$%d\r\n",sdslen(info
))); 
3675     addReplySds(c
,info
); 
3676     addReply(c
,shared
.crlf
); 
3679 static void monitorCommand(redisClient 
*c
) { 
3680     /* ignore MONITOR if aleady slave or in monitor mode */ 
3681     if (c
->flags 
& REDIS_SLAVE
) return; 
3683     c
->flags 
|= (REDIS_SLAVE
|REDIS_MONITOR
); 
3685     if (!listAddNodeTail(server
.monitors
,c
)) oom("listAddNodeTail"); 
3686     addReply(c
,shared
.ok
); 
3689 /* ================================= Expire ================================= */ 
3690 static int removeExpire(redisDb 
*db
, robj 
*key
) { 
3691     if (dictDelete(db
->expires
,key
) == DICT_OK
) { 
3698 static int setExpire(redisDb 
*db
, robj 
*key
, time_t when
) { 
3699     if (dictAdd(db
->expires
,key
,(void*)when
) == DICT_ERR
) { 
3707 /* Return the expire time of the specified key, or -1 if no expire 
3708  * is associated with this key (i.e. the key is non volatile) */ 
3709 static time_t getExpire(redisDb 
*db
, robj 
*key
) { 
3712     /* No expire? return ASAP */ 
3713     if (dictSize(db
->expires
) == 0 || 
3714        (de 
= dictFind(db
->expires
,key
)) == NULL
) return -1; 
3716     return (time_t) dictGetEntryVal(de
); 
3719 static int expireIfNeeded(redisDb 
*db
, robj 
*key
) { 
3723     /* No expire? return ASAP */ 
3724     if (dictSize(db
->expires
) == 0 || 
3725        (de 
= dictFind(db
->expires
,key
)) == NULL
) return 0; 
3727     /* Lookup the expire */ 
3728     when 
= (time_t) dictGetEntryVal(de
); 
3729     if (time(NULL
) <= when
) return 0; 
3731     /* Delete the key */ 
3732     dictDelete(db
->expires
,key
); 
3733     return dictDelete(db
->dict
,key
) == DICT_OK
; 
3736 static int deleteIfVolatile(redisDb 
*db
, robj 
*key
) { 
3739     /* No expire? return ASAP */ 
3740     if (dictSize(db
->expires
) == 0 || 
3741        (de 
= dictFind(db
->expires
,key
)) == NULL
) return 0; 
3743     /* Delete the key */ 
3745     dictDelete(db
->expires
,key
); 
3746     return dictDelete(db
->dict
,key
) == DICT_OK
; 
3749 static void expireCommand(redisClient 
*c
) { 
3751     int seconds 
= atoi(c
->argv
[2]->ptr
); 
3753     de 
= dictFind(c
->db
->dict
,c
->argv
[1]); 
3755         addReply(c
,shared
.czero
); 
3759         addReply(c
, shared
.czero
); 
3762         time_t when 
= time(NULL
)+seconds
; 
3763         if (setExpire(c
->db
,c
->argv
[1],when
)) { 
3764             addReply(c
,shared
.cone
); 
3767             addReply(c
,shared
.czero
); 
3773 static void ttlCommand(redisClient 
*c
) { 
3777     expire 
= getExpire(c
->db
,c
->argv
[1]); 
3779         ttl 
= (int) (expire
-time(NULL
)); 
3780         if (ttl 
< 0) ttl 
= -1; 
3782     addReplySds(c
,sdscatprintf(sdsempty(),":%d\r\n",ttl
)); 
3785 /* =============================== Replication  ============================= */ 
3787 static int syncWrite(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
3788     ssize_t nwritten
, ret 
= size
; 
3789     time_t start 
= time(NULL
); 
3793         if (aeWait(fd
,AE_WRITABLE
,1000) & AE_WRITABLE
) { 
3794             nwritten 
= write(fd
,ptr
,size
); 
3795             if (nwritten 
== -1) return -1; 
3799         if ((time(NULL
)-start
) > timeout
) { 
3807 static int syncRead(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
3808     ssize_t nread
, totread 
= 0; 
3809     time_t start 
= time(NULL
); 
3813         if (aeWait(fd
,AE_READABLE
,1000) & AE_READABLE
) { 
3814             nread 
= read(fd
,ptr
,size
); 
3815             if (nread 
== -1) return -1; 
3820         if ((time(NULL
)-start
) > timeout
) { 
3828 static int syncReadLine(int fd
, char *ptr
, ssize_t size
, int timeout
) { 
3835         if (syncRead(fd
,&c
,1,timeout
) == -1) return -1; 
3838             if (nread 
&& *(ptr
-1) == '\r') *(ptr
-1) = '\0'; 
3849 static void syncCommand(redisClient 
*c
) { 
3850     /* ignore SYNC if aleady slave or in monitor mode */ 
3851     if (c
->flags 
& REDIS_SLAVE
) return; 
3853     /* SYNC can't be issued when the server has pending data to send to 
3854      * the client about already issued commands. We need a fresh reply 
3855      * buffer registering the differences between the BGSAVE and the current 
3856      * dataset, so that we can copy to other slaves if needed. */ 
3857     if (listLength(c
->reply
) != 0) { 
3858         addReplySds(c
,sdsnew("-ERR SYNC is invalid with pending input\r\n")); 
3862     redisLog(REDIS_NOTICE
,"Slave ask for synchronization"); 
3863     /* Here we need to check if there is a background saving operation 
3864      * in progress, or if it is required to start one */ 
3865     if (server
.bgsaveinprogress
) { 
3866         /* Ok a background save is in progress. Let's check if it is a good 
3867          * one for replication, i.e. if there is another slave that is 
3868          * registering differences since the server forked to save */ 
3872         listRewind(server
.slaves
); 
3873         while((ln 
= listYield(server
.slaves
))) { 
3875             if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_END
) break; 
3878             /* Perfect, the server is already registering differences for 
3879              * another slave. Set the right state, and copy the buffer. */ 
3880             listRelease(c
->reply
); 
3881             c
->reply 
= listDup(slave
->reply
); 
3882             if (!c
->reply
) oom("listDup copying slave reply list"); 
3883             c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
3884             redisLog(REDIS_NOTICE
,"Waiting for end of BGSAVE for SYNC"); 
3886             /* No way, we need to wait for the next BGSAVE in order to 
3887              * register differences */ 
3888             c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_START
; 
3889             redisLog(REDIS_NOTICE
,"Waiting for next BGSAVE for SYNC"); 
3892         /* Ok we don't have a BGSAVE in progress, let's start one */ 
3893         redisLog(REDIS_NOTICE
,"Starting BGSAVE for SYNC"); 
3894         if (rdbSaveBackground(server
.dbfilename
) != REDIS_OK
) { 
3895             redisLog(REDIS_NOTICE
,"Replication failed, can't BGSAVE"); 
3896             addReplySds(c
,sdsnew("-ERR Unalbe to perform background save\r\n")); 
3899         c
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
3902     c
->flags 
|= REDIS_SLAVE
; 
3904     if (!listAddNodeTail(server
.slaves
,c
)) oom("listAddNodeTail"); 
3908 static void sendBulkToSlave(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
3909     redisClient 
*slave 
= privdata
; 
3911     REDIS_NOTUSED(mask
); 
3912     char buf
[REDIS_IOBUF_LEN
]; 
3913     ssize_t nwritten
, buflen
; 
3915     if (slave
->repldboff 
== 0) { 
3916         /* Write the bulk write count before to transfer the DB. In theory here 
3917          * we don't know how much room there is in the output buffer of the 
3918          * socket, but in pratice SO_SNDLOWAT (the minimum count for output 
3919          * operations) will never be smaller than the few bytes we need. */ 
3922         bulkcount 
= sdscatprintf(sdsempty(),"$%lld\r\n",(unsigned long long) 
3924         if (write(fd
,bulkcount
,sdslen(bulkcount
)) != (signed)sdslen(bulkcount
)) 
3932     lseek(slave
->repldbfd
,slave
->repldboff
,SEEK_SET
); 
3933     buflen 
= read(slave
->repldbfd
,buf
,REDIS_IOBUF_LEN
); 
3935         redisLog(REDIS_WARNING
,"Read error sending DB to slave: %s", 
3936             (buflen 
== 0) ? "premature EOF" : strerror(errno
)); 
3940     if ((nwritten 
= write(fd
,buf
,buflen
)) == -1) { 
3941         redisLog(REDIS_DEBUG
,"Write error sending DB to slave: %s", 
3946     slave
->repldboff 
+= nwritten
; 
3947     if (slave
->repldboff 
== slave
->repldbsize
) { 
3948         close(slave
->repldbfd
); 
3949         slave
->repldbfd 
= -1; 
3950         aeDeleteFileEvent(server
.el
,slave
->fd
,AE_WRITABLE
); 
3951         slave
->replstate 
= REDIS_REPL_ONLINE
; 
3952         if (aeCreateFileEvent(server
.el
, slave
->fd
, AE_WRITABLE
, 
3953             sendReplyToClient
, slave
, NULL
) == AE_ERR
) { 
3957         addReplySds(slave
,sdsempty()); 
3958         redisLog(REDIS_NOTICE
,"Synchronization with slave succeeded"); 
3962 /* This function is called at the end of every backgrond saving. 
3963  * The argument bgsaveerr is REDIS_OK if the background saving succeeded 
3964  * otherwise REDIS_ERR is passed to the function. 
3966  * The goal of this function is to handle slaves waiting for a successful 
3967  * background saving in order to perform non-blocking synchronization. */ 
3968 static void updateSlavesWaitingBgsave(int bgsaveerr
) { 
3970     int startbgsave 
= 0; 
3972     listRewind(server
.slaves
); 
3973     while((ln 
= listYield(server
.slaves
))) { 
3974         redisClient 
*slave 
= ln
->value
; 
3976         if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) { 
3978             slave
->replstate 
= REDIS_REPL_WAIT_BGSAVE_END
; 
3979         } else if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_END
) { 
3980             struct redis_stat buf
; 
3982             if (bgsaveerr 
!= REDIS_OK
) { 
3984                 redisLog(REDIS_WARNING
,"SYNC failed. BGSAVE child returned an error"); 
3987             if ((slave
->repldbfd 
= open(server
.dbfilename
,O_RDONLY
)) == -1 || 
3988                 redis_fstat(slave
->repldbfd
,&buf
) == -1) { 
3990                 redisLog(REDIS_WARNING
,"SYNC failed. Can't open/stat DB after BGSAVE: %s", strerror(errno
)); 
3993             slave
->repldboff 
= 0; 
3994             slave
->repldbsize 
= buf
.st_size
; 
3995             slave
->replstate 
= REDIS_REPL_SEND_BULK
; 
3996             aeDeleteFileEvent(server
.el
,slave
->fd
,AE_WRITABLE
); 
3997             if (aeCreateFileEvent(server
.el
, slave
->fd
, AE_WRITABLE
, sendBulkToSlave
, slave
, NULL
) == AE_ERR
) { 
4004         if (rdbSaveBackground(server
.dbfilename
) != REDIS_OK
) { 
4005             listRewind(server
.slaves
); 
4006             redisLog(REDIS_WARNING
,"SYNC failed. BGSAVE failed"); 
4007             while((ln 
= listYield(server
.slaves
))) { 
4008                 redisClient 
*slave 
= ln
->value
; 
4010                 if (slave
->replstate 
== REDIS_REPL_WAIT_BGSAVE_START
) 
4017 static int syncWithMaster(void) { 
4018     char buf
[1024], tmpfile
[256]; 
4020     int fd 
= anetTcpConnect(NULL
,server
.masterhost
,server
.masterport
); 
4024         redisLog(REDIS_WARNING
,"Unable to connect to MASTER: %s", 
4028     /* Issue the SYNC command */ 
4029     if (syncWrite(fd
,"SYNC \r\n",7,5) == -1) { 
4031         redisLog(REDIS_WARNING
,"I/O error writing to MASTER: %s", 
4035     /* Read the bulk write count */ 
4036     if (syncReadLine(fd
,buf
,1024,3600) == -1) { 
4038         redisLog(REDIS_WARNING
,"I/O error reading bulk count from MASTER: %s", 
4042     dumpsize 
= atoi(buf
+1); 
4043     redisLog(REDIS_NOTICE
,"Receiving %d bytes data dump from MASTER",dumpsize
); 
4044     /* Read the bulk write data on a temp file */ 
4045     snprintf(tmpfile
,256,"temp-%d.%ld.rdb",(int)time(NULL
),(long int)random()); 
4046     dfd 
= open(tmpfile
,O_CREAT
|O_WRONLY
,0644); 
4049         redisLog(REDIS_WARNING
,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno
)); 
4053         int nread
, nwritten
; 
4055         nread 
= read(fd
,buf
,(dumpsize 
< 1024)?dumpsize
:1024); 
4057             redisLog(REDIS_WARNING
,"I/O error trying to sync with MASTER: %s", 
4063         nwritten 
= write(dfd
,buf
,nread
); 
4064         if (nwritten 
== -1) { 
4065             redisLog(REDIS_WARNING
,"Write error writing to the DB dump file needed for MASTER <-> SLAVE synchrnonization: %s", strerror(errno
)); 
4073     if (rename(tmpfile
,server
.dbfilename
) == -1) { 
4074         redisLog(REDIS_WARNING
,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", strerror(errno
)); 
4080     if (rdbLoad(server
.dbfilename
) != REDIS_OK
) { 
4081         redisLog(REDIS_WARNING
,"Failed trying to load the MASTER synchronization DB from disk"); 
4085     server
.master 
= createClient(fd
); 
4086     server
.master
->flags 
|= REDIS_MASTER
; 
4087     server
.replstate 
= REDIS_REPL_CONNECTED
; 
4091 static void slaveofCommand(redisClient 
*c
) { 
4092     if (!strcasecmp(c
->argv
[1]->ptr
,"no") && 
4093         !strcasecmp(c
->argv
[2]->ptr
,"one")) { 
4094         if (server
.masterhost
) { 
4095             sdsfree(server
.masterhost
); 
4096             server
.masterhost 
= NULL
; 
4097             if (server
.master
) freeClient(server
.master
); 
4098             server
.replstate 
= REDIS_REPL_NONE
; 
4099             redisLog(REDIS_NOTICE
,"MASTER MODE enabled (user request)"); 
4102         sdsfree(server
.masterhost
); 
4103         server
.masterhost 
= sdsdup(c
->argv
[1]->ptr
); 
4104         server
.masterport 
= atoi(c
->argv
[2]->ptr
); 
4105         if (server
.master
) freeClient(server
.master
); 
4106         server
.replstate 
= REDIS_REPL_CONNECT
; 
4107         redisLog(REDIS_NOTICE
,"SLAVE OF %s:%d enabled (user request)", 
4108             server
.masterhost
, server
.masterport
); 
4110     addReply(c
,shared
.ok
); 
4113 /* ============================ Maxmemory directive  ======================== */ 
4115 /* This function gets called when 'maxmemory' is set on the config file to limit 
4116  * the max memory used by the server, and we are out of memory. 
4117  * This function will try to, in order: 
4119  * - Free objects from the free list 
4120  * - Try to remove keys with an EXPIRE set 
4122  * It is not possible to free enough memory to reach used-memory < maxmemory 
4123  * the server will start refusing commands that will enlarge even more the 
4126 static void freeMemoryIfNeeded(void) { 
4127     while (server
.maxmemory 
&& zmalloc_used_memory() > server
.maxmemory
) { 
4128         if (listLength(server
.objfreelist
)) { 
4131             listNode 
*head 
= listFirst(server
.objfreelist
); 
4132             o 
= listNodeValue(head
); 
4133             listDelNode(server
.objfreelist
,head
); 
4136             int j
, k
, freed 
= 0; 
4138             for (j 
= 0; j 
< server
.dbnum
; j
++) { 
4140                 robj 
*minkey 
= NULL
; 
4141                 struct dictEntry 
*de
; 
4143                 if (dictSize(server
.db
[j
].expires
)) { 
4145                     /* From a sample of three keys drop the one nearest to 
4146                      * the natural expire */ 
4147                     for (k 
= 0; k 
< 3; k
++) { 
4150                         de 
= dictGetRandomKey(server
.db
[j
].expires
); 
4151                         t 
= (time_t) dictGetEntryVal(de
); 
4152                         if (minttl 
== -1 || t 
< minttl
) { 
4153                             minkey 
= dictGetEntryKey(de
); 
4157                     deleteKey(server
.db
+j
,minkey
); 
4160             if (!freed
) return; /* nothing to free... */ 
4165 /* ================================= Debugging ============================== */ 
4167 static void debugCommand(redisClient 
*c
) { 
4168     if (!strcasecmp(c
->argv
[1]->ptr
,"segfault")) { 
4170     } else if (!strcasecmp(c
->argv
[1]->ptr
,"object") && c
->argc 
== 3) { 
4171         dictEntry 
*de 
= dictFind(c
->db
->dict
,c
->argv
[2]); 
4175             addReply(c
,shared
.nokeyerr
); 
4178         key 
= dictGetEntryKey(de
); 
4179         val 
= dictGetEntryVal(de
); 
4180         addReplySds(c
,sdscatprintf(sdsempty(), 
4181             "+Key at:%p refcount:%d, value at:%p refcount:%d\r\n", 
4182                 key
, key
->refcount
, val
, val
->refcount
)); 
4184         addReplySds(c
,sdsnew( 
4185             "-ERR Syntax error, try DEBUG [SEGFAULT|OBJECT <key>]\r\n")); 
4189 #ifdef HAVE_BACKTRACE 
4190 static struct redisFunctionSym symsTable
[] = { 
4191 {"freeStringObject", (unsigned long)freeStringObject
}, 
4192 {"freeListObject", (unsigned long)freeListObject
}, 
4193 {"freeSetObject", (unsigned long)freeSetObject
}, 
4194 {"decrRefCount", (unsigned long)decrRefCount
}, 
4195 {"createObject", (unsigned long)createObject
}, 
4196 {"freeClient", (unsigned long)freeClient
}, 
4197 {"rdbLoad", (unsigned long)rdbLoad
}, 
4198 {"addReply", (unsigned long)addReply
}, 
4199 {"addReplySds", (unsigned long)addReplySds
}, 
4200 {"incrRefCount", (unsigned long)incrRefCount
}, 
4201 {"rdbSaveBackground", (unsigned long)rdbSaveBackground
}, 
4202 {"createStringObject", (unsigned long)createStringObject
}, 
4203 {"replicationFeedSlaves", (unsigned long)replicationFeedSlaves
}, 
4204 {"syncWithMaster", (unsigned long)syncWithMaster
}, 
4205 {"tryObjectSharing", (unsigned long)tryObjectSharing
}, 
4206 {"removeExpire", (unsigned long)removeExpire
}, 
4207 {"expireIfNeeded", (unsigned long)expireIfNeeded
}, 
4208 {"deleteIfVolatile", (unsigned long)deleteIfVolatile
}, 
4209 {"deleteKey", (unsigned long)deleteKey
}, 
4210 {"getExpire", (unsigned long)getExpire
}, 
4211 {"setExpire", (unsigned long)setExpire
}, 
4212 {"updateSlavesWaitingBgsave", (unsigned long)updateSlavesWaitingBgsave
}, 
4213 {"freeMemoryIfNeeded", (unsigned long)freeMemoryIfNeeded
}, 
4214 {"authCommand", (unsigned long)authCommand
}, 
4215 {"pingCommand", (unsigned long)pingCommand
}, 
4216 {"echoCommand", (unsigned long)echoCommand
}, 
4217 {"setCommand", (unsigned long)setCommand
}, 
4218 {"setnxCommand", (unsigned long)setnxCommand
}, 
4219 {"getCommand", (unsigned long)getCommand
}, 
4220 {"delCommand", (unsigned long)delCommand
}, 
4221 {"existsCommand", (unsigned long)existsCommand
}, 
4222 {"incrCommand", (unsigned long)incrCommand
}, 
4223 {"decrCommand", (unsigned long)decrCommand
}, 
4224 {"incrbyCommand", (unsigned long)incrbyCommand
}, 
4225 {"decrbyCommand", (unsigned long)decrbyCommand
}, 
4226 {"selectCommand", (unsigned long)selectCommand
}, 
4227 {"randomkeyCommand", (unsigned long)randomkeyCommand
}, 
4228 {"keysCommand", (unsigned long)keysCommand
}, 
4229 {"dbsizeCommand", (unsigned long)dbsizeCommand
}, 
4230 {"lastsaveCommand", (unsigned long)lastsaveCommand
}, 
4231 {"saveCommand", (unsigned long)saveCommand
}, 
4232 {"bgsaveCommand", (unsigned long)bgsaveCommand
}, 
4233 {"shutdownCommand", (unsigned long)shutdownCommand
}, 
4234 {"moveCommand", (unsigned long)moveCommand
}, 
4235 {"renameCommand", (unsigned long)renameCommand
}, 
4236 {"renamenxCommand", (unsigned long)renamenxCommand
}, 
4237 {"lpushCommand", (unsigned long)lpushCommand
}, 
4238 {"rpushCommand", (unsigned long)rpushCommand
}, 
4239 {"lpopCommand", (unsigned long)lpopCommand
}, 
4240 {"rpopCommand", (unsigned long)rpopCommand
}, 
4241 {"llenCommand", (unsigned long)llenCommand
}, 
4242 {"lindexCommand", (unsigned long)lindexCommand
}, 
4243 {"lrangeCommand", (unsigned long)lrangeCommand
}, 
4244 {"ltrimCommand", (unsigned long)ltrimCommand
}, 
4245 {"typeCommand", (unsigned long)typeCommand
}, 
4246 {"lsetCommand", (unsigned long)lsetCommand
}, 
4247 {"saddCommand", (unsigned long)saddCommand
}, 
4248 {"sremCommand", (unsigned long)sremCommand
}, 
4249 {"smoveCommand", (unsigned long)smoveCommand
}, 
4250 {"sismemberCommand", (unsigned long)sismemberCommand
}, 
4251 {"scardCommand", (unsigned long)scardCommand
}, 
4252 {"spopCommand", (unsigned long)spopCommand
}, 
4253 {"sinterCommand", (unsigned long)sinterCommand
}, 
4254 {"sinterstoreCommand", (unsigned long)sinterstoreCommand
}, 
4255 {"sunionCommand", (unsigned long)sunionCommand
}, 
4256 {"sunionstoreCommand", (unsigned long)sunionstoreCommand
}, 
4257 {"sdiffCommand", (unsigned long)sdiffCommand
}, 
4258 {"sdiffstoreCommand", (unsigned long)sdiffstoreCommand
}, 
4259 {"syncCommand", (unsigned long)syncCommand
}, 
4260 {"flushdbCommand", (unsigned long)flushdbCommand
}, 
4261 {"flushallCommand", (unsigned long)flushallCommand
}, 
4262 {"sortCommand", (unsigned long)sortCommand
}, 
4263 {"lremCommand", (unsigned long)lremCommand
}, 
4264 {"infoCommand", (unsigned long)infoCommand
}, 
4265 {"mgetCommand", (unsigned long)mgetCommand
}, 
4266 {"monitorCommand", (unsigned long)monitorCommand
}, 
4267 {"expireCommand", (unsigned long)expireCommand
}, 
4268 {"getSetCommand", (unsigned long)getSetCommand
}, 
4269 {"ttlCommand", (unsigned long)ttlCommand
}, 
4270 {"slaveofCommand", (unsigned long)slaveofCommand
}, 
4271 {"debugCommand", (unsigned long)debugCommand
}, 
4272 {"processCommand", (unsigned long)processCommand
}, 
4273 {"setupSigSegvAction", (unsigned long)setupSigSegvAction
}, 
4274 {"readQueryFromClient", (unsigned long)readQueryFromClient
}, 
4275 {"rdbRemoveTempFile", (unsigned long)rdbRemoveTempFile
}, 
4279 /* This function try to convert a pointer into a function name. It's used in 
4280  * oreder to provide a backtrace under segmentation fault that's able to 
4281  * display functions declared as static (otherwise the backtrace is useless). */ 
4282 static char *findFuncName(void *pointer
, unsigned long *offset
){ 
4284     unsigned long off
, minoff 
= 0; 
4286     /* Try to match against the Symbol with the smallest offset */ 
4287     for (i
=0; symsTable
[i
].pointer
; i
++) { 
4288         unsigned long lp 
= (unsigned long) pointer
; 
4290         if (lp 
!= (unsigned long)-1 && lp 
>= symsTable
[i
].pointer
) { 
4291             off
=lp
-symsTable
[i
].pointer
; 
4292             if (ret 
< 0 || off 
< minoff
) { 
4298     if (ret 
== -1) return NULL
; 
4300     return symsTable
[ret
].name
; 
4303 static void *getMcontextEip(ucontext_t 
*uc
) { 
4304 #if defined(__FreeBSD__) 
4305     return (void*) uc
->uc_mcontext
.mc_eip
; 
4306 #elif defined(__dietlibc__) 
4307     return (void*) uc
->uc_mcontext
.eip
; 
4308 #elif defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6) 
4309     return (void*) uc
->uc_mcontext
->__ss
.__eip
; 
4310 #elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6) 
4311   #ifdef _STRUCT_X86_THREAD_STATE64 
4312     return (void*) uc
->uc_mcontext
->__ss
.__rip
; 
4314     return (void*) uc
->uc_mcontext
->__ss
.__eip
; 
4316 #elif defined(__i386__) || defined(__X86_64__) /* Linux x86 */ 
4317     return (void*) uc
->uc_mcontext
.gregs
[REG_EIP
]; 
4318 #elif defined(__ia64__) /* Linux IA64 */ 
4319     return (void*) uc
->uc_mcontext
.sc_ip
; 
4325 static void segvHandler(int sig
, siginfo_t 
*info
, void *secret
) { 
4327     char **messages 
= NULL
; 
4328     int i
, trace_size 
= 0; 
4329     unsigned long offset
=0; 
4330     time_t uptime 
= time(NULL
)-server
.stat_starttime
; 
4331     ucontext_t 
*uc 
= (ucontext_t
*) secret
; 
4332     REDIS_NOTUSED(info
); 
4334     redisLog(REDIS_WARNING
, 
4335         "======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION
, sig
); 
4336     redisLog(REDIS_WARNING
, "%s", sdscatprintf(sdsempty(), 
4337         "redis_version:%s; " 
4338         "uptime_in_seconds:%d; " 
4339         "connected_clients:%d; " 
4340         "connected_slaves:%d; " 
4342         "changes_since_last_save:%lld; " 
4343         "bgsave_in_progress:%d; " 
4344         "last_save_time:%d; " 
4345         "total_connections_received:%lld; " 
4346         "total_commands_processed:%lld; " 
4350         listLength(server
.clients
)-listLength(server
.slaves
), 
4351         listLength(server
.slaves
), 
4354         server
.bgsaveinprogress
, 
4356         server
.stat_numconnections
, 
4357         server
.stat_numcommands
, 
4358         server
.masterhost 
== NULL 
? "master" : "slave" 
4361     trace_size 
= backtrace(trace
, 100); 
4362     /* overwrite sigaction with caller's address */ 
4363     if (getMcontextEip(uc
) != NULL
) { 
4364         trace
[1] = getMcontextEip(uc
); 
4366     messages 
= backtrace_symbols(trace
, trace_size
); 
4368     for (i
=1; i
<trace_size
; ++i
) { 
4369         char *fn 
= findFuncName(trace
[i
], &offset
), *p
; 
4371         p 
= strchr(messages
[i
],'+'); 
4372         if (!fn 
|| (p 
&& ((unsigned long)strtol(p
+1,NULL
,10)) < offset
)) { 
4373             redisLog(REDIS_WARNING
,"%s", messages
[i
]); 
4375             redisLog(REDIS_WARNING
,"%d redis-server %p %s + %d", i
, trace
[i
], fn
, (unsigned int)offset
); 
4382 static void setupSigSegvAction(void) { 
4383     struct sigaction act
; 
4385     sigemptyset (&act
.sa_mask
); 
4386     /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction 
4387      * is used. Otherwise, sa_handler is used */ 
4388     act
.sa_flags 
= SA_NODEFER 
| SA_ONSTACK 
| SA_RESETHAND 
| SA_SIGINFO
; 
4389     act
.sa_sigaction 
= segvHandler
; 
4390     sigaction (SIGSEGV
, &act
, NULL
); 
4391     sigaction (SIGBUS
, &act
, NULL
); 
4392     sigaction (SIGFPE
, &act
, NULL
); 
4393     sigaction (SIGILL
, &act
, NULL
); 
4394     sigaction (SIGBUS
, &act
, NULL
); 
4397 #else /* HAVE_BACKTRACE */ 
4398 static void setupSigSegvAction(void) { 
4400 #endif /* HAVE_BACKTRACE */ 
4402 /* =================================== Main! ================================ */ 
4405 int linuxOvercommitMemoryValue(void) { 
4406     FILE *fp 
= fopen("/proc/sys/vm/overcommit_memory","r"); 
4410     if (fgets(buf
,64,fp
) == NULL
) { 
4419 void linuxOvercommitMemoryWarning(void) { 
4420     if (linuxOvercommitMemoryValue() == 0) { 
4421         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."); 
4424 #endif /* __linux__ */ 
4426 static void daemonize(void) { 
4430     if (fork() != 0) exit(0); /* parent exits */ 
4431     setsid(); /* create a new session */ 
4433     /* Every output goes to /dev/null. If Redis is daemonized but 
4434      * the 'logfile' is set to 'stdout' in the configuration file 
4435      * it will not log at all. */ 
4436     if ((fd 
= open("/dev/null", O_RDWR
, 0)) != -1) { 
4437         dup2(fd
, STDIN_FILENO
); 
4438         dup2(fd
, STDOUT_FILENO
); 
4439         dup2(fd
, STDERR_FILENO
); 
4440         if (fd 
> STDERR_FILENO
) close(fd
); 
4442     /* Try to write the pid file */ 
4443     fp 
= fopen(server
.pidfile
,"w"); 
4445         fprintf(fp
,"%d\n",getpid()); 
4450 int main(int argc
, char **argv
) { 
4453         ResetServerSaveParams(); 
4454         loadServerConfig(argv
[1]); 
4455     } else if (argc 
> 2) { 
4456         fprintf(stderr
,"Usage: ./redis-server [/path/to/redis.conf]\n"); 
4459         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'"); 
4462     if (server
.daemonize
) daemonize(); 
4463     redisLog(REDIS_NOTICE
,"Server started, Redis version " REDIS_VERSION
); 
4465     linuxOvercommitMemoryWarning(); 
4467     if (rdbLoad(server
.dbfilename
) == REDIS_OK
) 
4468         redisLog(REDIS_NOTICE
,"DB loaded from disk"); 
4469     if (aeCreateFileEvent(server
.el
, server
.fd
, AE_READABLE
, 
4470         acceptHandler
, NULL
, NULL
) == AE_ERR
) oom("creating file event"); 
4471     redisLog(REDIS_NOTICE
,"The server is now ready to accept connections on port %d", server
.port
); 
4473     aeDeleteEventLoop(server
.el
);