]> git.saurik.com Git - redis.git/blame - src/redis.c
Fixed issue #516 (ZINTERSTORE mixing sets and zsets).
[redis.git] / src / redis.c
CommitLineData
e2641e09 1/*
2 * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
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.
16 *
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.
28 */
29
30#include "redis.h"
daa70b17 31#include "slowlog.h"
8f61a72f 32#include "bio.h"
e2641e09 33
e2641e09 34#include <time.h>
35#include <signal.h>
36#include <sys/wait.h>
37#include <errno.h>
38#include <assert.h>
39#include <ctype.h>
40#include <stdarg.h>
e2641e09 41#include <arpa/inet.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <sys/time.h>
45#include <sys/resource.h>
46#include <sys/uio.h>
47#include <limits.h>
48#include <float.h>
49#include <math.h>
2b00385d 50#include <sys/resource.h>
5ad1faa0 51#include <sys/utsname.h>
e2641e09 52
53/* Our shared "common" objects */
54
55struct sharedObjectsStruct shared;
56
c74b7c77 57/* Global vars that are actually used as constants. The following double
e2641e09 58 * values are used for double on-disk serialization, and are initialized
59 * at runtime to avoid strange compiler optimizations. */
60
61double R_Zero, R_PosInf, R_NegInf, R_Nan;
62
63/*================================= Globals ================================= */
64
65/* Global vars */
66struct redisServer server; /* server global state */
67struct redisCommand *commandTable;
5d02b00f 68
7501c66f 69/* Our command table.
70 *
71 * Every entry is composed of the following fields:
72 *
73 * name: a string representing the command name.
74 * function: pointer to the C function implementing the command.
75 * arity: number of arguments, it is possible to use -N to say >= N
76 * sflags: command flags as string. See below for a table of flags.
77 * flags: flags as bitmask. Computed by Redis using the 'sflags' field.
78 * get_keys_proc: an optional function to get key arguments from a command.
79 * This is only used when the following three fields are not
80 * enough to specify what arguments are keys.
81 * first_key_index: first argument that is a key
82 * last_key_index: last argument that is a key
83 * key_step: step to get all the keys from first to last argument. For instance
84 * in MSET the step is two since arguments are key,val,key,val,...
85 * microseconds: microseconds of total execution time for this command.
86 * calls: total number of calls of this command.
87 *
88 * The flags, microseconds and calls fields are computed by Redis and should
89 * always be set to zero.
90 *
91 * Command flags are expressed using strings where every character represents
92 * a flag. Later the populateCommandTable() function will take care of
93 * populating the real 'flags' field using this characters.
5d02b00f 94 *
95 * This is the meaning of the flags:
96 *
97 * w: write command (may modify the key space).
98 * r: read command (will never modify the key space).
99 * m: may increase memory usage once called. Don't allow if out of memory.
100 * a: admin command, like SAVE or SHUTDOWN.
101 * p: Pub/Sub related command.
b60ed6e8 102 * f: force replication of this command, regarless of server.dirty.
103 * s: command not allowed in scripts.
7e14a208 104 * R: random command. Command is not deterministic, that is, the same command
b60ed6e8 105 * with the same arguments, with the same key space, may have different
548efd91 106 * results. For instance SPOP and RANDOMKEY are two random commands.
107 * S: Sort command output array if called from script, so that the output
108 * is deterministic.
109 */
d7ed7fd2 110struct redisCommand redisCommandTable[] = {
5d02b00f 111 {"get",getCommand,2,"r",0,NULL,1,1,1,0,0},
112 {"set",setCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
113 {"setnx",setnxCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
39da5d1f 114 {"setex",setexCommand,4,"wm",0,noPreloadGetKeys,1,1,1,0,0},
115 {"psetex",psetexCommand,4,"wm",0,noPreloadGetKeys,1,1,1,0,0},
5d02b00f 116 {"append",appendCommand,3,"wm",0,NULL,1,1,1,0,0},
117 {"strlen",strlenCommand,2,"r",0,NULL,1,1,1,0,0},
118 {"del",delCommand,-2,"w",0,noPreloadGetKeys,1,-1,1,0,0},
119 {"exists",existsCommand,2,"r",0,NULL,1,1,1,0,0},
120 {"setbit",setbitCommand,4,"wm",0,NULL,1,1,1,0,0},
121 {"getbit",getbitCommand,3,"r",0,NULL,1,1,1,0,0},
122 {"setrange",setrangeCommand,4,"wm",0,NULL,1,1,1,0,0},
123 {"getrange",getrangeCommand,4,"r",0,NULL,1,1,1,0,0},
124 {"substr",getrangeCommand,4,"r",0,NULL,1,1,1,0,0},
125 {"incr",incrCommand,2,"wm",0,NULL,1,1,1,0,0},
126 {"decr",decrCommand,2,"wm",0,NULL,1,1,1,0,0},
127 {"mget",mgetCommand,-2,"r",0,NULL,1,-1,1,0,0},
128 {"rpush",rpushCommand,-3,"wm",0,NULL,1,1,1,0,0},
129 {"lpush",lpushCommand,-3,"wm",0,NULL,1,1,1,0,0},
130 {"rpushx",rpushxCommand,3,"wm",0,NULL,1,1,1,0,0},
131 {"lpushx",lpushxCommand,3,"wm",0,NULL,1,1,1,0,0},
132 {"linsert",linsertCommand,5,"wm",0,NULL,1,1,1,0,0},
133 {"rpop",rpopCommand,2,"w",0,NULL,1,1,1,0,0},
134 {"lpop",lpopCommand,2,"w",0,NULL,1,1,1,0,0},
e41677b4 135 {"brpop",brpopCommand,-3,"ws",0,NULL,1,1,1,0,0},
136 {"brpoplpush",brpoplpushCommand,4,"wms",0,NULL,1,2,1,0,0},
137 {"blpop",blpopCommand,-3,"ws",0,NULL,1,-2,1,0,0},
5d02b00f 138 {"llen",llenCommand,2,"r",0,NULL,1,1,1,0,0},
139 {"lindex",lindexCommand,3,"r",0,NULL,1,1,1,0,0},
140 {"lset",lsetCommand,4,"wm",0,NULL,1,1,1,0,0},
141 {"lrange",lrangeCommand,4,"r",0,NULL,1,1,1,0,0},
142 {"ltrim",ltrimCommand,4,"w",0,NULL,1,1,1,0,0},
143 {"lrem",lremCommand,4,"w",0,NULL,1,1,1,0,0},
144 {"rpoplpush",rpoplpushCommand,3,"wm",0,NULL,1,2,1,0,0},
145 {"sadd",saddCommand,-3,"wm",0,NULL,1,1,1,0,0},
146 {"srem",sremCommand,-3,"w",0,NULL,1,1,1,0,0},
147 {"smove",smoveCommand,4,"w",0,NULL,1,2,1,0,0},
148 {"sismember",sismemberCommand,3,"r",0,NULL,1,1,1,0,0},
149 {"scard",scardCommand,2,"r",0,NULL,1,1,1,0,0},
15ef6053 150 {"spop",spopCommand,2,"wRs",0,NULL,1,1,1,0,0},
b60ed6e8 151 {"srandmember",srandmemberCommand,2,"rR",0,NULL,1,1,1,0,0},
548efd91 152 {"sinter",sinterCommand,-2,"rS",0,NULL,1,-1,1,0,0},
1bcfa0f6 153 {"sinterstore",sinterstoreCommand,-3,"wm",0,NULL,1,-1,1,0,0},
548efd91 154 {"sunion",sunionCommand,-2,"rS",0,NULL,1,-1,1,0,0},
1bcfa0f6 155 {"sunionstore",sunionstoreCommand,-3,"wm",0,NULL,1,-1,1,0,0},
548efd91 156 {"sdiff",sdiffCommand,-2,"rS",0,NULL,1,-1,1,0,0},
1bcfa0f6 157 {"sdiffstore",sdiffstoreCommand,-3,"wm",0,NULL,1,-1,1,0,0},
548efd91 158 {"smembers",sinterCommand,2,"rS",0,NULL,1,1,1,0,0},
5d02b00f 159 {"zadd",zaddCommand,-4,"wm",0,NULL,1,1,1,0,0},
160 {"zincrby",zincrbyCommand,4,"wm",0,NULL,1,1,1,0,0},
161 {"zrem",zremCommand,-3,"w",0,NULL,1,1,1,0,0},
162 {"zremrangebyscore",zremrangebyscoreCommand,4,"w",0,NULL,1,1,1,0,0},
163 {"zremrangebyrank",zremrangebyrankCommand,4,"w",0,NULL,1,1,1,0,0},
164 {"zunionstore",zunionstoreCommand,-4,"wm",0,zunionInterGetKeys,0,0,0,0,0},
165 {"zinterstore",zinterstoreCommand,-4,"wm",0,zunionInterGetKeys,0,0,0,0,0},
166 {"zrange",zrangeCommand,-4,"r",0,NULL,1,1,1,0,0},
167 {"zrangebyscore",zrangebyscoreCommand,-4,"r",0,NULL,1,1,1,0,0},
168 {"zrevrangebyscore",zrevrangebyscoreCommand,-4,"r",0,NULL,1,1,1,0,0},
169 {"zcount",zcountCommand,4,"r",0,NULL,1,1,1,0,0},
170 {"zrevrange",zrevrangeCommand,-4,"r",0,NULL,1,1,1,0,0},
171 {"zcard",zcardCommand,2,"r",0,NULL,1,1,1,0,0},
172 {"zscore",zscoreCommand,3,"r",0,NULL,1,1,1,0,0},
173 {"zrank",zrankCommand,3,"r",0,NULL,1,1,1,0,0},
174 {"zrevrank",zrevrankCommand,3,"r",0,NULL,1,1,1,0,0},
175 {"hset",hsetCommand,4,"wm",0,NULL,1,1,1,0,0},
176 {"hsetnx",hsetnxCommand,4,"wm",0,NULL,1,1,1,0,0},
177 {"hget",hgetCommand,3,"r",0,NULL,1,1,1,0,0},
178 {"hmset",hmsetCommand,-4,"wm",0,NULL,1,1,1,0,0},
179 {"hmget",hmgetCommand,-3,"r",0,NULL,1,1,1,0,0},
180 {"hincrby",hincrbyCommand,4,"wm",0,NULL,1,1,1,0,0},
68bfe993 181 {"hincrbyfloat",hincrbyfloatCommand,4,"wm",0,NULL,1,1,1,0,0},
5d02b00f 182 {"hdel",hdelCommand,-3,"w",0,NULL,1,1,1,0,0},
183 {"hlen",hlenCommand,2,"r",0,NULL,1,1,1,0,0},
548efd91 184 {"hkeys",hkeysCommand,2,"rS",0,NULL,1,1,1,0,0},
185 {"hvals",hvalsCommand,2,"rS",0,NULL,1,1,1,0,0},
5d02b00f 186 {"hgetall",hgetallCommand,2,"r",0,NULL,1,1,1,0,0},
187 {"hexists",hexistsCommand,3,"r",0,NULL,1,1,1,0,0},
188 {"incrby",incrbyCommand,3,"wm",0,NULL,1,1,1,0,0},
189 {"decrby",decrbyCommand,3,"wm",0,NULL,1,1,1,0,0},
5574b53e 190 {"incrbyfloat",incrbyfloatCommand,3,"wm",0,NULL,1,1,1,0,0},
5d02b00f 191 {"getset",getsetCommand,3,"wm",0,NULL,1,1,1,0,0},
192 {"mset",msetCommand,-3,"wm",0,NULL,1,-1,2,0,0},
193 {"msetnx",msetnxCommand,-3,"wm",0,NULL,1,-1,2,0,0},
b60ed6e8 194 {"randomkey",randomkeyCommand,1,"rR",0,NULL,0,0,0,0,0},
5d02b00f 195 {"select",selectCommand,2,"r",0,NULL,0,0,0,0,0},
196 {"move",moveCommand,3,"w",0,NULL,1,1,1,0,0},
197 {"rename",renameCommand,3,"w",0,renameGetKeys,1,2,1,0,0},
198 {"renamenx",renamenxCommand,3,"w",0,renameGetKeys,1,2,1,0,0},
12d293ca 199 {"expire",expireCommand,3,"w",0,NULL,1,1,1,0,0},
200 {"expireat",expireatCommand,3,"w",0,NULL,1,1,1,0,0},
201 {"pexpire",pexpireCommand,3,"w",0,NULL,1,1,1,0,0},
202 {"pexpireat",pexpireatCommand,3,"w",0,NULL,1,1,1,0,0},
548efd91 203 {"keys",keysCommand,2,"rS",0,NULL,0,0,0,0,0},
5d02b00f 204 {"dbsize",dbsizeCommand,1,"r",0,NULL,0,0,0,0,0},
e41677b4 205 {"auth",authCommand,2,"rs",0,NULL,0,0,0,0,0},
5d02b00f 206 {"ping",pingCommand,1,"r",0,NULL,0,0,0,0,0},
207 {"echo",echoCommand,2,"r",0,NULL,0,0,0,0,0},
e41677b4 208 {"save",saveCommand,1,"ars",0,NULL,0,0,0,0,0},
5d02b00f 209 {"bgsave",bgsaveCommand,1,"ar",0,NULL,0,0,0,0,0},
210 {"bgrewriteaof",bgrewriteaofCommand,1,"ar",0,NULL,0,0,0,0,0},
4ab8695d 211 {"shutdown",shutdownCommand,-1,"ar",0,NULL,0,0,0,0,0},
5d02b00f 212 {"lastsave",lastsaveCommand,1,"r",0,NULL,0,0,0,0,0},
213 {"type",typeCommand,2,"r",0,NULL,1,1,1,0,0},
b60ed6e8 214 {"multi",multiCommand,1,"rs",0,NULL,0,0,0,0,0},
f3fd419f 215 {"exec",execCommand,1,"s",0,NULL,0,0,0,0,0},
b60ed6e8 216 {"discard",discardCommand,1,"rs",0,NULL,0,0,0,0,0},
217 {"sync",syncCommand,1,"ars",0,NULL,0,0,0,0,0},
5d02b00f 218 {"flushdb",flushdbCommand,1,"w",0,NULL,0,0,0,0,0},
219 {"flushall",flushallCommand,1,"w",0,NULL,0,0,0,0,0},
2c861050 220 {"sort",sortCommand,-2,"wmS",0,NULL,1,1,1,0,0},
5d02b00f 221 {"info",infoCommand,-1,"r",0,NULL,0,0,0,0,0},
b60ed6e8 222 {"monitor",monitorCommand,1,"ars",0,NULL,0,0,0,0,0},
12d293ca 223 {"ttl",ttlCommand,2,"r",0,NULL,1,1,1,0,0},
224 {"pttl",pttlCommand,2,"r",0,NULL,1,1,1,0,0},
5d02b00f 225 {"persist",persistCommand,2,"w",0,NULL,1,1,1,0,0},
bb0fbc84 226 {"slaveof",slaveofCommand,3,"as",0,NULL,0,0,0,0,0},
7dcdd281 227 {"debug",debugCommand,-2,"as",0,NULL,0,0,0,0,0},
5d02b00f 228 {"config",configCommand,-2,"ar",0,NULL,0,0,0,0,0},
b60ed6e8 229 {"subscribe",subscribeCommand,-2,"rps",0,NULL,0,0,0,0,0},
230 {"unsubscribe",unsubscribeCommand,-1,"rps",0,NULL,0,0,0,0,0},
231 {"psubscribe",psubscribeCommand,-2,"rps",0,NULL,0,0,0,0,0},
232 {"punsubscribe",punsubscribeCommand,-1,"rps",0,NULL,0,0,0,0,0},
bb0aadbe 233 {"publish",publishCommand,3,"pf",0,NULL,0,0,0,0,0},
b60ed6e8 234 {"watch",watchCommand,-2,"rs",0,noPreloadGetKeys,1,-1,1,0,0},
235 {"unwatch",unwatchCommand,1,"rs",0,NULL,0,0,0,0,0},
5d02b00f 236 {"cluster",clusterCommand,-2,"ar",0,NULL,0,0,0,0,0},
7afc3a96 237 {"restore",restoreCommand,4,"awm",0,NULL,1,1,1,0,0},
5d02b00f 238 {"migrate",migrateCommand,6,"aw",0,NULL,0,0,0,0,0},
6856c7b4 239 {"asking",askingCommand,1,"r",0,NULL,0,0,0,0,0},
1bcfa0f6 240 {"dump",dumpCommand,2,"ar",0,NULL,1,1,1,0,0},
241 {"object",objectCommand,-2,"r",0,NULL,2,2,2,0,0},
5d02b00f 242 {"client",clientCommand,-2,"ar",0,NULL,0,0,0,0,0},
f3fd419f 243 {"eval",evalCommand,-3,"s",0,zunionInterGetKeys,0,0,0,0,0},
244 {"evalsha",evalShaCommand,-3,"s",0,zunionInterGetKeys,0,0,0,0,0},
070e3945 245 {"slowlog",slowlogCommand,-2,"r",0,NULL,0,0,0,0,0},
9494f1f1 246 {"script",scriptCommand,-2,"ras",0,NULL,0,0,0,0,0},
247 {"time",timeCommand,1,"rR",0,NULL,0,0,0,0,0}
e2641e09 248};
249
250/*============================ Utility functions ============================ */
251
9c104c68 252/* Low level logging. To use only for very big messages, otherwise
253 * redisLog() is to prefer. */
254void redisLogRaw(int level, const char *msg) {
e1a586ee
JH
255 const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING };
256 const char *c = ".-*#";
e2641e09 257 FILE *fp;
23072961 258 char buf[64];
996d503d 259 int rawmode = (level & REDIS_LOG_RAW);
23072961 260
996d503d 261 level &= 0xff; /* clear flags */
23072961 262 if (level < server.verbosity) return;
e2641e09 263
264 fp = (server.logfile == NULL) ? stdout : fopen(server.logfile,"a");
265 if (!fp) return;
266
996d503d 267 if (rawmode) {
268 fprintf(fp,"%s",msg);
269 } else {
9a322ab7 270 int off;
271 struct timeval tv;
272
273 gettimeofday(&tv,NULL);
274 off = strftime(buf,sizeof(buf),"%d %b %H:%M:%S.",localtime(&tv.tv_sec));
275 snprintf(buf+off,sizeof(buf)-off,"%03d",(int)tv.tv_usec/1000);
996d503d 276 fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg);
277 }
e1a586ee
JH
278 fflush(fp);
279
e2641e09 280 if (server.logfile) fclose(fp);
e1a586ee
JH
281
282 if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg);
e2641e09 283}
284
9c104c68 285/* Like redisLogRaw() but with printf-alike support. This is the funciton that
286 * is used across the code. The raw version is only used in order to dump
287 * the INFO output on crash. */
288void redisLog(int level, const char *fmt, ...) {
289 va_list ap;
290 char msg[REDIS_MAX_LOGMSG_LEN];
291
996d503d 292 if ((level&0xff) < server.verbosity) return;
9c104c68 293
294 va_start(ap, fmt);
295 vsnprintf(msg, sizeof(msg), fmt, ap);
296 va_end(ap);
297
298 redisLogRaw(level,msg);
299}
300
a7d12cba 301/* Log a fixed message without printf-alike capabilities, in a way that is
302 * safe to call from a signal handler.
303 *
304 * We actually use this only for signals that are not fatal from the point
305 * of view of Redis. Signals that are going to kill the server anyway and
306 * where we need printf-alike features are served by redisLog(). */
307void redisLogFromHandler(int level, const char *msg) {
308 int fd;
309 char buf[64];
310
311 if ((level&0xff) < server.verbosity ||
312 (server.logfile == NULL && server.daemonize)) return;
313 fd = server.logfile ?
314 open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644) :
5471b8ba 315 STDOUT_FILENO;
a7d12cba 316 if (fd == -1) return;
317 ll2string(buf,sizeof(buf),getpid());
0b913c65 318 if (write(fd,"[",1) == -1) goto err;
319 if (write(fd,buf,strlen(buf)) == -1) goto err;
320 if (write(fd," | signal handler] (",20) == -1) goto err;
a7d12cba 321 ll2string(buf,sizeof(buf),time(NULL));
0b913c65 322 if (write(fd,buf,strlen(buf)) == -1) goto err;
323 if (write(fd,") ",2) == -1) goto err;
324 if (write(fd,msg,strlen(msg)) == -1) goto err;
325 if (write(fd,"\n",1) == -1) goto err;
326err:
5471b8ba 327 if (server.logfile) close(fd);
a7d12cba 328}
329
e2641e09 330/* Redis generally does not try to recover from out of memory conditions
331 * when allocating objects or strings, it is not clear if it will be possible
332 * to report this condition to the client since the networking layer itself
333 * is based on heap allocation for send buffers, so we simply abort.
334 * At least the code will be simpler to read... */
335void oom(const char *msg) {
336 redisLog(REDIS_WARNING, "%s: Out of memory\n",msg);
337 sleep(1);
338 abort();
339}
340
d9cb288c 341/* Return the UNIX time in microseconds */
342long long ustime(void) {
343 struct timeval tv;
344 long long ust;
345
346 gettimeofday(&tv, NULL);
347 ust = ((long long)tv.tv_sec)*1000000;
348 ust += tv.tv_usec;
349 return ust;
350}
351
2c2b2085 352/* Return the UNIX time in milliseconds */
353long long mstime(void) {
354 return ustime()/1000;
355}
356
2cbdab90 357/* After an RDB dump or AOF rewrite we exit from children using _exit() instead of
358 * exit(), because the latter may interact with the same file objects used by
359 * the parent process. However if we are testing the coverage normal exit() is
360 * used in order to obtain the right coverage information. */
361void exitFromChild(int retcode) {
362#ifdef COVERAGE_TEST
363 exit(retcode);
364#else
365 _exit(retcode);
366#endif
367}
368
e2641e09 369/*====================== Hash table type implementation ==================== */
370
371/* This is an hash table type that uses the SDS dynamic strings libary as
372 * keys and radis objects as values (objects can hold SDS strings,
373 * lists, sets). */
374
375void dictVanillaFree(void *privdata, void *val)
376{
377 DICT_NOTUSED(privdata);
378 zfree(val);
379}
380
381void dictListDestructor(void *privdata, void *val)
382{
383 DICT_NOTUSED(privdata);
384 listRelease((list*)val);
385}
386
387int dictSdsKeyCompare(void *privdata, const void *key1,
388 const void *key2)
389{
390 int l1,l2;
391 DICT_NOTUSED(privdata);
392
393 l1 = sdslen((sds)key1);
394 l2 = sdslen((sds)key2);
395 if (l1 != l2) return 0;
396 return memcmp(key1, key2, l1) == 0;
397}
398
1b1f47c9 399/* A case insensitive version used for the command lookup table. */
400int dictSdsKeyCaseCompare(void *privdata, const void *key1,
401 const void *key2)
402{
403 DICT_NOTUSED(privdata);
404
405 return strcasecmp(key1, key2) == 0;
406}
407
e2641e09 408void dictRedisObjectDestructor(void *privdata, void *val)
409{
410 DICT_NOTUSED(privdata);
411
412 if (val == NULL) return; /* Values of swapped out keys as set to NULL */
413 decrRefCount(val);
414}
415
416void dictSdsDestructor(void *privdata, void *val)
417{
418 DICT_NOTUSED(privdata);
419
420 sdsfree(val);
421}
422
423int dictObjKeyCompare(void *privdata, const void *key1,
424 const void *key2)
425{
426 const robj *o1 = key1, *o2 = key2;
427 return dictSdsKeyCompare(privdata,o1->ptr,o2->ptr);
428}
429
430unsigned int dictObjHash(const void *key) {
431 const robj *o = key;
432 return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));
433}
434
435unsigned int dictSdsHash(const void *key) {
436 return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));
437}
438
1b1f47c9 439unsigned int dictSdsCaseHash(const void *key) {
440 return dictGenCaseHashFunction((unsigned char*)key, sdslen((char*)key));
441}
442
e2641e09 443int dictEncObjKeyCompare(void *privdata, const void *key1,
444 const void *key2)
445{
446 robj *o1 = (robj*) key1, *o2 = (robj*) key2;
447 int cmp;
448
449 if (o1->encoding == REDIS_ENCODING_INT &&
450 o2->encoding == REDIS_ENCODING_INT)
451 return o1->ptr == o2->ptr;
452
453 o1 = getDecodedObject(o1);
454 o2 = getDecodedObject(o2);
455 cmp = dictSdsKeyCompare(privdata,o1->ptr,o2->ptr);
456 decrRefCount(o1);
457 decrRefCount(o2);
458 return cmp;
459}
460
461unsigned int dictEncObjHash(const void *key) {
462 robj *o = (robj*) key;
463
464 if (o->encoding == REDIS_ENCODING_RAW) {
465 return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));
466 } else {
467 if (o->encoding == REDIS_ENCODING_INT) {
468 char buf[32];
469 int len;
470
471 len = ll2string(buf,32,(long)o->ptr);
472 return dictGenHashFunction((unsigned char*)buf, len);
473 } else {
474 unsigned int hash;
475
476 o = getDecodedObject(o);
477 hash = dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));
478 decrRefCount(o);
479 return hash;
480 }
481 }
482}
483
4dd444bb 484/* Sets type hash table */
e2641e09 485dictType setDictType = {
486 dictEncObjHash, /* hash function */
487 NULL, /* key dup */
488 NULL, /* val dup */
489 dictEncObjKeyCompare, /* key compare */
490 dictRedisObjectDestructor, /* key destructor */
491 NULL /* val destructor */
492};
493
494/* Sorted sets hash (note: a skiplist is used in addition to the hash table) */
495dictType zsetDictType = {
496 dictEncObjHash, /* hash function */
497 NULL, /* key dup */
498 NULL, /* val dup */
499 dictEncObjKeyCompare, /* key compare */
500 dictRedisObjectDestructor, /* key destructor */
69ef89f2 501 NULL /* val destructor */
e2641e09 502};
503
504/* Db->dict, keys are sds strings, vals are Redis objects. */
505dictType dbDictType = {
506 dictSdsHash, /* hash function */
507 NULL, /* key dup */
508 NULL, /* val dup */
509 dictSdsKeyCompare, /* key compare */
510 dictSdsDestructor, /* key destructor */
511 dictRedisObjectDestructor /* val destructor */
512};
513
514/* Db->expires */
515dictType keyptrDictType = {
516 dictSdsHash, /* hash function */
517 NULL, /* key dup */
518 NULL, /* val dup */
519 dictSdsKeyCompare, /* key compare */
520 NULL, /* key destructor */
521 NULL /* val destructor */
522};
523
1b1f47c9 524/* Command table. sds string -> command struct pointer. */
525dictType commandTableDictType = {
526 dictSdsCaseHash, /* hash function */
527 NULL, /* key dup */
528 NULL, /* val dup */
529 dictSdsKeyCaseCompare, /* key compare */
530 dictSdsDestructor, /* key destructor */
531 NULL /* val destructor */
532};
533
e2641e09 534/* Hash type hash table (note that small hashes are represented with zimpaps) */
535dictType hashDictType = {
536 dictEncObjHash, /* hash function */
537 NULL, /* key dup */
538 NULL, /* val dup */
539 dictEncObjKeyCompare, /* key compare */
540 dictRedisObjectDestructor, /* key destructor */
541 dictRedisObjectDestructor /* val destructor */
542};
543
544/* Keylist hash table type has unencoded redis objects as keys and
545 * lists as values. It's used for blocking operations (BLPOP) and to
546 * map swapped keys to a list of clients waiting for this keys to be loaded. */
547dictType keylistDictType = {
548 dictObjHash, /* hash function */
549 NULL, /* key dup */
550 NULL, /* val dup */
551 dictObjKeyCompare, /* key compare */
552 dictRedisObjectDestructor, /* key destructor */
553 dictListDestructor /* val destructor */
554};
555
ecc91094 556/* Cluster nodes hash table, mapping nodes addresses 1.2.3.4:6379 to
557 * clusterNode structures. */
558dictType clusterNodesDictType = {
559 dictSdsHash, /* hash function */
560 NULL, /* key dup */
561 NULL, /* val dup */
562 dictSdsKeyCompare, /* key compare */
563 dictSdsDestructor, /* key destructor */
564 NULL /* val destructor */
565};
566
e2641e09 567int htNeedsResize(dict *dict) {
568 long long size, used;
569
570 size = dictSlots(dict);
571 used = dictSize(dict);
572 return (size && used && size > DICT_HT_INITIAL_SIZE &&
573 (used*100/size < REDIS_HT_MINFILL));
574}
575
576/* If the percentage of used slots in the HT reaches REDIS_HT_MINFILL
577 * we resize the hash table to save memory */
578void tryResizeHashTables(void) {
579 int j;
580
581 for (j = 0; j < server.dbnum; j++) {
582 if (htNeedsResize(server.db[j].dict))
583 dictResize(server.db[j].dict);
584 if (htNeedsResize(server.db[j].expires))
585 dictResize(server.db[j].expires);
586 }
587}
588
589/* Our hash table implementation performs rehashing incrementally while
590 * we write/read from the hash table. Still if the server is idle, the hash
591 * table will use two tables for a long time. So we try to use 1 millisecond
592 * of CPU time at every serverCron() loop in order to rehash some key. */
593void incrementallyRehash(void) {
594 int j;
595
596 for (j = 0; j < server.dbnum; j++) {
61daf891 597 /* Keys dictionary */
e2641e09 598 if (dictIsRehashing(server.db[j].dict)) {
599 dictRehashMilliseconds(server.db[j].dict,1);
600 break; /* already used our millisecond for this loop... */
601 }
61daf891 602 /* Expires */
603 if (dictIsRehashing(server.db[j].expires)) {
604 dictRehashMilliseconds(server.db[j].expires,1);
605 break; /* already used our millisecond for this loop... */
606 }
e2641e09 607 }
608}
609
610/* This function is called once a background process of some kind terminates,
611 * as we want to avoid resizing the hash tables when there is a child in order
612 * to play well with copy-on-write (otherwise when a resize happens lots of
613 * memory pages are copied). The goal of this function is to update the ability
614 * for dict.c to resize the hash tables accordingly to the fact we have o not
615 * running childs. */
616void updateDictResizePolicy(void) {
f48cd4b9 617 if (server.rdb_child_pid == -1 && server.aof_child_pid == -1)
e2641e09 618 dictEnableResize();
619 else
620 dictDisableResize();
621}
622
623/* ======================= Cron: called every 100 ms ======================== */
624
bcf2995c 625/* Try to expire a few timed out keys. The algorithm used is adaptive and
626 * will use few CPU cycles if there are few expiring keys, otherwise
627 * it will get more aggressive to avoid that too much memory is used by
628 * keys that can be removed from the keyspace. */
629void activeExpireCycle(void) {
b3624f5a 630 int j, iteration = 0;
61daf891 631 long long start = ustime(), timelimit;
94343492 632
633 /* We can use at max REDIS_EXPIRELOOKUPS_TIME_PERC percentage of CPU time
634 * per iteration. Since this function gets called with a frequency of
635 * REDIS_HZ times per second, the following is the max amount of
61daf891 636 * microseconds we can spend in this function. */
637 timelimit = 1000000*REDIS_EXPIRELOOKUPS_TIME_PERC/REDIS_HZ/100;
94343492 638 if (timelimit <= 0) timelimit = 1;
bcf2995c 639
640 for (j = 0; j < server.dbnum; j++) {
b3624f5a 641 int expired;
bcf2995c 642 redisDb *db = server.db+j;
643
644 /* Continue to expire if at the end of the cycle more than 25%
645 * of the keys were expired. */
646 do {
61daf891 647 unsigned long num = dictSize(db->expires);
648 unsigned long slots = dictSlots(db->expires);
4be855e7 649 long long now = mstime();
bcf2995c 650
61daf891 651 /* When there are less than 1% filled slots getting random
652 * keys is expensive, so stop here waiting for better times...
653 * The dictionary will be resized asap. */
654 if (num && slots > DICT_HT_INITIAL_SIZE &&
655 (num*100/slots < 1)) break;
656
b3624f5a 657 /* The main collection cycle. Sample random keys among keys
658 * with an expire set, checking for expired ones. */
bcf2995c 659 expired = 0;
660 if (num > REDIS_EXPIRELOOKUPS_PER_CRON)
661 num = REDIS_EXPIRELOOKUPS_PER_CRON;
662 while (num--) {
663 dictEntry *de;
4be855e7 664 long long t;
bcf2995c 665
666 if ((de = dictGetRandomKey(db->expires)) == NULL) break;
4be855e7 667 t = dictGetSignedIntegerVal(de);
bcf2995c 668 if (now > t) {
c0ba9ebe 669 sds key = dictGetKey(de);
bcf2995c 670 robj *keyobj = createStringObject(key,sdslen(key));
671
672 propagateExpire(db,keyobj);
673 dbDelete(db,keyobj);
674 decrRefCount(keyobj);
675 expired++;
676 server.stat_expiredkeys++;
677 }
678 }
1dcc95d0 679 /* We can't block forever here even if there are many keys to
680 * expire. So after a given amount of milliseconds return to the
681 * caller waiting for the other active expire cycle. */
682 iteration++;
b3624f5a 683 if ((iteration & 0xf) == 0 && /* check once every 16 cycles. */
61daf891 684 (ustime()-start) > timelimit) return;
bcf2995c 685 } while (expired > REDIS_EXPIRELOOKUPS_PER_CRON/4);
686 }
687}
688
165346ca 689void updateLRUClock(void) {
d1949054 690 server.lruclock = (server.unixtime/REDIS_LRU_CLOCK_RESOLUTION) &
165346ca 691 REDIS_LRU_CLOCK_MAX;
692}
bcf2995c 693
250e7f69 694
695/* Add a sample to the operations per second array of samples. */
696void trackOperationsPerSecond(void) {
697 long long t = mstime() - server.ops_sec_last_sample_time;
698 long long ops = server.stat_numcommands - server.ops_sec_last_sample_ops;
699 long long ops_sec;
700
701 ops_sec = t > 0 ? (ops*1000/t) : 0;
702
703 server.ops_sec_samples[server.ops_sec_idx] = ops_sec;
704 server.ops_sec_idx = (server.ops_sec_idx+1) % REDIS_OPS_SEC_SAMPLES;
705 server.ops_sec_last_sample_time = mstime();
706 server.ops_sec_last_sample_ops = server.stat_numcommands;
707}
708
709/* Return the mean of all the samples. */
710long long getOperationsPerSecond(void) {
711 int j;
712 long long sum = 0;
713
714 for (j = 0; j < REDIS_OPS_SEC_SAMPLES; j++)
715 sum += server.ops_sec_samples[j];
716 return sum / REDIS_OPS_SEC_SAMPLES;
717}
718
c9d3dda2 719/* Check for timeouts. Returns non-zero if the client was terminated */
720int clientsCronHandleTimeout(redisClient *c) {
ae22bf1e 721 time_t now = server.unixtime;
d19015be 722
723 if (server.maxidletime &&
724 !(c->flags & REDIS_SLAVE) && /* no timeout for slaves */
725 !(c->flags & REDIS_MASTER) && /* no timeout for masters */
726 !(c->flags & REDIS_BLOCKED) && /* no timeout for BLPOP */
727 dictSize(c->pubsub_channels) == 0 && /* no timeout for pubsub */
728 listLength(c->pubsub_patterns) == 0 &&
729 (now - c->lastinteraction > server.maxidletime))
730 {
731 redisLog(REDIS_VERBOSE,"Closing idle client");
732 freeClient(c);
c9d3dda2 733 return 1;
d19015be 734 } else if (c->flags & REDIS_BLOCKED) {
735 if (c->bpop.timeout != 0 && c->bpop.timeout < now) {
736 addReply(c,shared.nullmultibulk);
737 unblockClientWaitingData(c);
738 }
739 }
c9d3dda2 740 return 0;
d19015be 741}
742
ae22bf1e 743/* The client query buffer is an sds.c string that can end with a lot of
c9d3dda2 744 * free space not used, this function reclaims space if needed.
745 *
746 * The funciton always returns 0 as it never terminates the client. */
747int clientsCronResizeQueryBuffer(redisClient *c) {
ae22bf1e 748 size_t querybuf_size = sdsAllocSize(c->querybuf);
749 time_t idletime = server.unixtime - c->lastinteraction;
750
751 /* There are two conditions to resize the query buffer:
752 * 1) Query buffer is > BIG_ARG and too big for latest peak.
753 * 2) Client is inactive and the buffer is bigger than 1k. */
754 if (((querybuf_size > REDIS_MBULK_BIG_ARG) &&
755 (querybuf_size/(c->querybuf_peak+1)) > 2) ||
756 (querybuf_size > 1024 && idletime > 2))
757 {
758 /* Only resize the query buffer if it is actually wasting space. */
759 if (sdsavail(c->querybuf) > 1024) {
760 c->querybuf = sdsRemoveFreeSpace(c->querybuf);
761 }
762 }
763 /* Reset the peak again to capture the peak memory usage in the next
764 * cycle. */
765 c->querybuf_peak = 0;
c9d3dda2 766 return 0;
ae22bf1e 767}
768
d19015be 769void clientsCron(void) {
94343492 770 /* Make sure to process at least 1/(REDIS_HZ*10) of clients per call.
771 * Since this function is called REDIS_HZ times per second we are sure that
d19015be 772 * in the worst case we process all the clients in 10 seconds.
773 * In normal conditions (a reasonable number of clients) we process
774 * all the clients in a shorter time. */
ae22bf1e 775 int numclients = listLength(server.clients);
94343492 776 int iterations = numclients/(REDIS_HZ*10);
d19015be 777
ae22bf1e 778 if (iterations < 50)
779 iterations = (numclients < 50) ? numclients : 50;
d19015be 780 while(listLength(server.clients) && iterations--) {
781 redisClient *c;
782 listNode *head;
783
784 /* Rotate the list, take the current head, process.
785 * This way if the client must be removed from the list it's the
786 * first element and we don't incur into O(N) computation. */
787 listRotate(server.clients);
788 head = listFirst(server.clients);
789 c = listNodeValue(head);
c9d3dda2 790 /* The following functions do different service checks on the client.
791 * The protocol is that they return non-zero if the client was
792 * terminated. */
793 if (clientsCronHandleTimeout(c)) continue;
794 if (clientsCronResizeQueryBuffer(c)) continue;
d19015be 795 }
796}
797
94343492 798/* This is our timer interrupt, called REDIS_HZ times per second.
799 * Here is where we do a number of things that need to be done asynchronously.
800 * For instance:
801 *
802 * - Active expired keys collection (it is also performed in a lazy way on
803 * lookup).
804 * - Software watchdong.
805 * - Update some statistic.
806 * - Incremental rehashing of the DBs hash tables.
807 * - Triggering BGSAVE / AOF rewrite, and handling of terminated children.
808 * - Clients timeout of differnet kinds.
809 * - Replication reconnection.
810 * - Many more...
811 *
812 * Everything directly called here will be called REDIS_HZ times per second,
813 * so in order to throttle execution of things we want to do less frequently
814 * a macro is used: run_with_period(milliseconds) { .... }
815 */
816
817/* Using the following macro you can run code inside serverCron() with the
818 * specified period, specified in milliseconds.
819 * The actual resolution depends on REDIS_HZ. */
820#define run_with_period(_ms_) if (!(loops % ((_ms_)/(1000/REDIS_HZ))))
821
e2641e09 822int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
89a1433e 823 int j, loops = server.cronloops;
e2641e09 824 REDIS_NOTUSED(eventLoop);
825 REDIS_NOTUSED(id);
826 REDIS_NOTUSED(clientData);
827
39bd025c 828 /* Software watchdog: deliver the SIGALRM that will reach the signal
829 * handler if we don't return here fast enough. */
830 if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period);
831
e2641e09 832 /* We take a cached value of the unix time in the global state because
833 * with virtual memory and aging there is to store the current time
834 * in objects at every object access, and accuracy is not needed.
835 * To access a global var is faster than calling time(NULL) */
836 server.unixtime = time(NULL);
4f06867a 837
94343492 838 run_with_period(100) trackOperationsPerSecond();
250e7f69 839
ef59a8bc 840 /* We have just 22 bits per object for LRU information.
165346ca 841 * So we use an (eventually wrapping) LRU clock with 10 seconds resolution.
842 * 2^22 bits with 10 seconds resoluton is more or less 1.5 years.
e2641e09 843 *
165346ca 844 * Note that even if this will wrap after 1.5 years it's not a problem,
ef59a8bc 845 * everything will still work but just some object will appear younger
165346ca 846 * to Redis. But for this to happen a given object should never be touched
847 * for 1.5 years.
848 *
849 * Note that you can change the resolution altering the
850 * REDIS_LRU_CLOCK_RESOLUTION define.
e2641e09 851 */
165346ca 852 updateLRUClock();
e2641e09 853
17b24ff3 854 /* Record the max memory used since the server was started. */
855 if (zmalloc_used_memory() > server.stat_peak_memory)
856 server.stat_peak_memory = zmalloc_used_memory();
857
e2641e09 858 /* We received a SIGTERM, shutting down here in a safe way, as it is
859 * not ok doing so inside the signal handler. */
860 if (server.shutdown_asap) {
4ab8695d 861 if (prepareForShutdown(0) == REDIS_OK) exit(0);
e2641e09 862 redisLog(REDIS_WARNING,"SIGTERM received but errors trying to shut down the server, check the logs for more information");
863 }
864
865 /* Show some info about non-empty databases */
94343492 866 run_with_period(5000) {
867 for (j = 0; j < server.dbnum; j++) {
868 long long size, used, vkeys;
869
870 size = dictSlots(server.db[j].dict);
871 used = dictSize(server.db[j].dict);
872 vkeys = dictSize(server.db[j].expires);
873 if (used || vkeys) {
874 redisLog(REDIS_VERBOSE,"DB %d: %lld keys (%lld volatile) in %lld slots HT.",j,used,vkeys,size);
875 /* dictPrintStats(server.dict); */
876 }
e2641e09 877 }
878 }
879
880 /* We don't want to resize the hash tables while a bacground saving
881 * is in progress: the saving child is created using fork() that is
882 * implemented with a copy-on-write semantic in most modern systems, so
883 * if we resize the HT while there is the saving child at work actually
884 * a lot of memory movements in the parent will cause a lot of pages
885 * copied. */
f48cd4b9 886 if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
61daf891 887 tryResizeHashTables();
e2641e09 888 if (server.activerehashing) incrementallyRehash();
889 }
890
891 /* Show information about connected clients */
94343492 892 run_with_period(5000) {
e2641e09 893 redisLog(REDIS_VERBOSE,"%d clients connected (%d slaves), %zu bytes in use",
894 listLength(server.clients)-listLength(server.slaves),
895 listLength(server.slaves),
ca734d17 896 zmalloc_used_memory());
e2641e09 897 }
898
d19015be 899 /* We need to do a few operations on clients asynchronously. */
900 clientsCron();
e2641e09 901
b333e239 902 /* Start a scheduled AOF rewrite if this was requested by the user while
903 * a BGSAVE was in progress. */
f48cd4b9 904 if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 &&
2c915bcf 905 server.aof_rewrite_scheduled)
b333e239 906 {
907 rewriteAppendOnlyFileBackground();
908 }
909
f03fe802 910 /* Check if a background saving or AOF rewrite in progress terminated. */
f48cd4b9 911 if (server.rdb_child_pid != -1 || server.aof_child_pid != -1) {
e2641e09 912 int statloc;
913 pid_t pid;
914
915 if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {
36c17a53 916 int exitcode = WEXITSTATUS(statloc);
917 int bysignal = 0;
918
919 if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);
920
f48cd4b9 921 if (pid == server.rdb_child_pid) {
36c17a53 922 backgroundSaveDoneHandler(exitcode,bysignal);
e2641e09 923 } else {
36c17a53 924 backgroundRewriteDoneHandler(exitcode,bysignal);
e2641e09 925 }
926 updateDictResizePolicy();
927 }
c9d0c362 928 } else {
b333e239 929 /* If there is not a background saving/rewrite in progress check if
930 * we have to save/rewrite now */
e2641e09 931 for (j = 0; j < server.saveparamslen; j++) {
932 struct saveparam *sp = server.saveparams+j;
933
934 if (server.dirty >= sp->changes &&
d1949054 935 server.unixtime-server.lastsave > sp->seconds) {
e2641e09 936 redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...",
937 sp->changes, sp->seconds);
f48cd4b9 938 rdbSaveBackground(server.rdb_filename);
e2641e09 939 break;
940 }
941 }
b333e239 942
943 /* Trigger an AOF rewrite if needed */
f48cd4b9 944 if (server.rdb_child_pid == -1 &&
ff2145ad 945 server.aof_child_pid == -1 &&
2c915bcf 946 server.aof_rewrite_perc &&
947 server.aof_current_size > server.aof_rewrite_min_size)
b333e239 948 {
2c915bcf 949 long long base = server.aof_rewrite_base_size ?
950 server.aof_rewrite_base_size : 1;
951 long long growth = (server.aof_current_size*100/base) - 100;
952 if (growth >= server.aof_rewrite_perc) {
19b46c9a 953 redisLog(REDIS_NOTICE,"Starting automatic rewriting of AOF on %lld%% growth",growth);
b333e239 954 rewriteAppendOnlyFileBackground();
955 }
956 }
e2641e09 957 }
958
db3c2a4f 959
960 /* If we postponed an AOF buffer flush, let's try to do it every time the
961 * cron function is called. */
962 if (server.aof_flush_postponed_start) flushAppendOnlyFile(0);
963
bcf2995c 964 /* Expire a few keys per cycle, only if this is a master.
965 * On slaves we wait for DEL operations synthesized by the master
966 * in order to guarantee a strict consistency. */
967 if (server.masterhost == NULL) activeExpireCycle();
e2641e09 968
8c43e663 969 /* Close clients that need to be closed asynchronous */
970 freeClientsInAsyncFreeQueue();
971
f4aa600b 972 /* Replication cron function -- used to reconnect to master and
973 * to detect transfer failures. */
94343492 974 run_with_period(1000) replicationCron();
f4aa600b 975
ecc91094 976 /* Run other sub-systems specific cron jobs */
94343492 977 run_with_period(1000) {
978 if (server.cluster_enabled) clusterCron();
979 }
ecc91094 980
89a1433e 981 server.cronloops++;
94343492 982 return 1000/REDIS_HZ;
e2641e09 983}
984
985/* This function gets called every time Redis is entering the
986 * main loop of the event driven library, that is, before to sleep
987 * for ready file descriptors. */
988void beforeSleep(struct aeEventLoop *eventLoop) {
989 REDIS_NOTUSED(eventLoop);
a4ce7581
PN
990 listNode *ln;
991 redisClient *c;
e2641e09 992
a4ce7581
PN
993 /* Try to process pending commands for clients that were just unblocked. */
994 while (listLength(server.unblocked_clients)) {
995 ln = listFirst(server.unblocked_clients);
996 redisAssert(ln != NULL);
997 c = ln->value;
998 listDelNode(server.unblocked_clients,ln);
3bcffcbe 999 c->flags &= ~REDIS_UNBLOCKED;
a4ce7581
PN
1000
1001 /* Process remaining data in the input buffer. */
00010fa9 1002 if (c->querybuf && sdslen(c->querybuf) > 0) {
1003 server.current_client = c;
a4ce7581 1004 processInputBuffer(c);
00010fa9 1005 server.current_client = NULL;
1006 }
a4ce7581
PN
1007 }
1008
e2641e09 1009 /* Write the AOF buffer on disk */
db3c2a4f 1010 flushAppendOnlyFile(0);
e2641e09 1011}
1012
1013/* =========================== Server initialization ======================== */
1014
1015void createSharedObjects(void) {
1016 int j;
1017
1018 shared.crlf = createObject(REDIS_STRING,sdsnew("\r\n"));
1019 shared.ok = createObject(REDIS_STRING,sdsnew("+OK\r\n"));
1020 shared.err = createObject(REDIS_STRING,sdsnew("-ERR\r\n"));
1021 shared.emptybulk = createObject(REDIS_STRING,sdsnew("$0\r\n\r\n"));
1022 shared.czero = createObject(REDIS_STRING,sdsnew(":0\r\n"));
1023 shared.cone = createObject(REDIS_STRING,sdsnew(":1\r\n"));
1024 shared.cnegone = createObject(REDIS_STRING,sdsnew(":-1\r\n"));
1025 shared.nullbulk = createObject(REDIS_STRING,sdsnew("$-1\r\n"));
1026 shared.nullmultibulk = createObject(REDIS_STRING,sdsnew("*-1\r\n"));
1027 shared.emptymultibulk = createObject(REDIS_STRING,sdsnew("*0\r\n"));
1028 shared.pong = createObject(REDIS_STRING,sdsnew("+PONG\r\n"));
1029 shared.queued = createObject(REDIS_STRING,sdsnew("+QUEUED\r\n"));
1030 shared.wrongtypeerr = createObject(REDIS_STRING,sdsnew(
1031 "-ERR Operation against a key holding the wrong kind of value\r\n"));
1032 shared.nokeyerr = createObject(REDIS_STRING,sdsnew(
1033 "-ERR no such key\r\n"));
1034 shared.syntaxerr = createObject(REDIS_STRING,sdsnew(
1035 "-ERR syntax error\r\n"));
1036 shared.sameobjecterr = createObject(REDIS_STRING,sdsnew(
1037 "-ERR source and destination objects are the same\r\n"));
1038 shared.outofrangeerr = createObject(REDIS_STRING,sdsnew(
1039 "-ERR index out of range\r\n"));
7229d60d 1040 shared.noscripterr = createObject(REDIS_STRING,sdsnew(
1041 "-NOSCRIPT No matching script. Please use EVAL.\r\n"));
97e7f8ae 1042 shared.loadingerr = createObject(REDIS_STRING,sdsnew(
1043 "-LOADING Redis is loading the dataset in memory\r\n"));
115e3ff3 1044 shared.slowscripterr = createObject(REDIS_STRING,sdsnew(
4ab8695d 1045 "-BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.\r\n"));
ae62d29d 1046 shared.masterdownerr = createObject(REDIS_STRING,sdsnew(
1047 "-MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to 'no'.\r\n"));
c25e7eaf 1048 shared.bgsaveerr = createObject(REDIS_STRING,sdsnew(
f3fd419f 1049 "-MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.\r\n"));
1050 shared.roslaveerr = createObject(REDIS_STRING,sdsnew(
1051 "-READONLY You can't write against a read only slave.\r\n"));
b22eab8f 1052 shared.oomerr = createObject(REDIS_STRING,sdsnew(
1053 "-OOM command not allowed when used memory > 'maxmemory'.\r\n"));
e2641e09 1054 shared.space = createObject(REDIS_STRING,sdsnew(" "));
1055 shared.colon = createObject(REDIS_STRING,sdsnew(":"));
1056 shared.plus = createObject(REDIS_STRING,sdsnew("+"));
f892797e
JJ
1057
1058 for (j = 0; j < REDIS_SHARED_SELECT_CMDS; j++) {
1059 shared.select[j] = createObject(REDIS_STRING,
1060 sdscatprintf(sdsempty(),"select %d\r\n", j));
1061 }
e2641e09 1062 shared.messagebulk = createStringObject("$7\r\nmessage\r\n",13);
1063 shared.pmessagebulk = createStringObject("$8\r\npmessage\r\n",14);
1064 shared.subscribebulk = createStringObject("$9\r\nsubscribe\r\n",15);
1065 shared.unsubscribebulk = createStringObject("$11\r\nunsubscribe\r\n",18);
1066 shared.psubscribebulk = createStringObject("$10\r\npsubscribe\r\n",17);
1067 shared.punsubscribebulk = createStringObject("$12\r\npunsubscribe\r\n",19);
355f8591 1068 shared.del = createStringObject("DEL",3);
c1db214e 1069 shared.rpop = createStringObject("RPOP",4);
1070 shared.lpop = createStringObject("LPOP",4);
e2641e09 1071 for (j = 0; j < REDIS_SHARED_INTEGERS; j++) {
1072 shared.integers[j] = createObject(REDIS_STRING,(void*)(long)j);
1073 shared.integers[j]->encoding = REDIS_ENCODING_INT;
1074 }
355f8591 1075 for (j = 0; j < REDIS_SHARED_BULKHDR_LEN; j++) {
1076 shared.mbulkhdr[j] = createObject(REDIS_STRING,
1077 sdscatprintf(sdsempty(),"*%d\r\n",j));
1078 shared.bulkhdr[j] = createObject(REDIS_STRING,
1079 sdscatprintf(sdsempty(),"$%d\r\n",j));
1080 }
e2641e09 1081}
1082
1083void initServerConfig() {
91d664d6 1084 getRandomHexChars(server.runid,REDIS_RUN_ID_SIZE);
1085 server.runid[REDIS_RUN_ID_SIZE] = '\0';
75eaac5c 1086 server.arch_bits = (sizeof(long) == 8) ? 64 : 32;
e2641e09 1087 server.port = REDIS_SERVERPORT;
a5639e7d 1088 server.bindaddr = NULL;
5d10923f 1089 server.unixsocket = NULL;
85238765 1090 server.unixsocketperm = 0;
a5639e7d
PN
1091 server.ipfd = -1;
1092 server.sofd = -1;
1093 server.dbnum = REDIS_DEFAULT_DBNUM;
c6f9ee88 1094 server.verbosity = REDIS_NOTICE;
e2641e09 1095 server.maxidletime = REDIS_MAXIDLETIME;
becf5fdb 1096 server.client_max_querybuf_len = REDIS_MAX_QUERYBUF_LEN;
e2641e09 1097 server.saveparams = NULL;
97e7f8ae 1098 server.loading = 0;
e2641e09 1099 server.logfile = NULL; /* NULL = log on standard output */
e1a586ee
JH
1100 server.syslog_enabled = 0;
1101 server.syslog_ident = zstrdup("redis");
1102 server.syslog_facility = LOG_LOCAL0;
e2641e09 1103 server.daemonize = 0;
e394114d 1104 server.aof_state = REDIS_AOF_OFF;
2c915bcf 1105 server.aof_fsync = AOF_FSYNC_EVERYSEC;
1106 server.aof_no_fsync_on_rewrite = 0;
1107 server.aof_rewrite_perc = REDIS_AOF_REWRITE_PERC;
1108 server.aof_rewrite_min_size = REDIS_AOF_REWRITE_MIN_SIZE;
1109 server.aof_rewrite_base_size = 0;
1110 server.aof_rewrite_scheduled = 0;
ff2145ad 1111 server.aof_last_fsync = time(NULL);
c1d01b3c 1112 server.aof_delayed_fsync = 0;
ff2145ad 1113 server.aof_fd = -1;
1114 server.aof_selected_db = -1; /* Make sure the first time will not match */
db3c2a4f 1115 server.aof_flush_postponed_start = 0;
e2641e09 1116 server.pidfile = zstrdup("/var/run/redis.pid");
f48cd4b9 1117 server.rdb_filename = zstrdup("dump.rdb");
2c915bcf 1118 server.aof_filename = zstrdup("appendonly.aof");
e2641e09 1119 server.requirepass = NULL;
f48cd4b9 1120 server.rdb_compression = 1;
84bcd3aa 1121 server.rdb_checksum = 1;
e2641e09 1122 server.activerehashing = 1;
58732c23 1123 server.maxclients = REDIS_MAX_CLIENTS;
5fa95ad7 1124 server.bpop_blocked_clients = 0;
e2641e09 1125 server.maxmemory = 0;
165346ca 1126 server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU;
1127 server.maxmemory_samples = 3;
ebd85e9a
PN
1128 server.hash_max_ziplist_entries = REDIS_HASH_MAX_ZIPLIST_ENTRIES;
1129 server.hash_max_ziplist_value = REDIS_HASH_MAX_ZIPLIST_VALUE;
e2641e09 1130 server.list_max_ziplist_entries = REDIS_LIST_MAX_ZIPLIST_ENTRIES;
1131 server.list_max_ziplist_value = REDIS_LIST_MAX_ZIPLIST_VALUE;
96ffb2fe 1132 server.set_max_intset_entries = REDIS_SET_MAX_INTSET_ENTRIES;
3ea204e1
PN
1133 server.zset_max_ziplist_entries = REDIS_ZSET_MAX_ZIPLIST_ENTRIES;
1134 server.zset_max_ziplist_value = REDIS_ZSET_MAX_ZIPLIST_VALUE;
e2641e09 1135 server.shutdown_asap = 0;
aeecbdfa 1136 server.repl_ping_slave_period = REDIS_REPL_PING_SLAVE_PERIOD;
1137 server.repl_timeout = REDIS_REPL_TIMEOUT;
ecc91094 1138 server.cluster_enabled = 0;
ef21ab96 1139 server.cluster.configfile = zstrdup("nodes.conf");
4ab8695d 1140 server.lua_caller = NULL;
eeffcf38 1141 server.lua_time_limit = REDIS_LUA_TIME_LIMIT;
070e3945 1142 server.lua_client = NULL;
115e3ff3 1143 server.lua_timedout = 0;
e2641e09 1144
95506e46 1145 updateLRUClock();
e2641e09 1146 resetServerSaveParams();
1147
1148 appendServerSaveParams(60*60,1); /* save after 1 hour and 1 change */
1149 appendServerSaveParams(300,100); /* save after 5 minutes and 100 changes */
1150 appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */
1151 /* Replication related */
e2641e09 1152 server.masterauth = NULL;
1153 server.masterhost = NULL;
1154 server.masterport = 6379;
1155 server.master = NULL;
1844f990 1156 server.repl_state = REDIS_REPL_NONE;
890a2ed9 1157 server.repl_syncio_timeout = REDIS_REPL_SYNCIO_TIMEOUT;
4ebfc455 1158 server.repl_serve_stale_data = 1;
f3fd419f 1159 server.repl_slave_ro = 1;
4b8c9661 1160 server.repl_down_since = time(NULL);
e2641e09 1161
7eac2a75 1162 /* Client output buffer limits */
1163 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_NORMAL].hard_limit_bytes = 0;
1164 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_NORMAL].soft_limit_bytes = 0;
1165 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_NORMAL].soft_limit_seconds = 0;
c8a607f2 1166 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_SLAVE].hard_limit_bytes = 1024*1024*256;
1167 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_SLAVE].soft_limit_bytes = 1024*1024*64;
7eac2a75 1168 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_SLAVE].soft_limit_seconds = 60;
c8a607f2 1169 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_PUBSUB].hard_limit_bytes = 1024*1024*32;
1170 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_PUBSUB].soft_limit_bytes = 1024*1024*8;
7eac2a75 1171 server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_PUBSUB].soft_limit_seconds = 60;
1172
e2641e09 1173 /* Double constants initialization */
1174 R_Zero = 0.0;
1175 R_PosInf = 1.0/R_Zero;
1176 R_NegInf = -1.0/R_Zero;
1177 R_Nan = R_Zero/R_Zero;
8d3e063a 1178
1179 /* Command table -- we intiialize it here as it is part of the
1180 * initial configuration, since command names may be changed via
1181 * redis.conf using the rename-command directive. */
1182 server.commands = dictCreate(&commandTableDictType,NULL);
1183 populateCommandTable();
1184 server.delCommand = lookupCommandByCString("del");
1185 server.multiCommand = lookupCommandByCString("multi");
eeb34eff 1186 server.lpushCommand = lookupCommandByCString("lpush");
daa70b17 1187
1188 /* Slow log */
1189 server.slowlog_log_slower_than = REDIS_SLOWLOG_LOG_SLOWER_THAN;
1190 server.slowlog_max_len = REDIS_SLOWLOG_MAX_LEN;
fa5af017 1191
39bd025c 1192 /* Debugging */
fa5af017 1193 server.assert_failed = "<no assertion failed>";
1194 server.assert_file = "<no file>";
1195 server.assert_line = 0;
1196 server.bug_report_start = 0;
39bd025c 1197 server.watchdog_period = 0;
e2641e09 1198}
1199
e074416b 1200/* This function will try to raise the max number of open files accordingly to
1201 * the configured max number of clients. It will also account for 32 additional
1202 * file descriptors as we need a few more for persistence, listening
1203 * sockets, log files and so forth.
1204 *
1205 * If it will not be possible to set the limit accordingly to the configured
1206 * max number of clients, the function will do the reverse setting
1207 * server.maxclients to the value that we can actually handle. */
1208void adjustOpenFilesLimit(void) {
1209 rlim_t maxfiles = server.maxclients+32;
1210 struct rlimit limit;
1211
e074416b 1212 if (getrlimit(RLIMIT_NOFILE,&limit) == -1) {
1213 redisLog(REDIS_WARNING,"Unable to obtain the current NOFILE limit (%s), assuming 1024 and setting the max clients configuration accordingly.",
1214 strerror(errno));
1215 server.maxclients = 1024-32;
1216 } else {
1217 rlim_t oldlimit = limit.rlim_cur;
1218
1219 /* Set the max number of files if the current limit is not enough
1220 * for our needs. */
1221 if (oldlimit < maxfiles) {
e7957ca6 1222 rlim_t f;
1223
1224 f = maxfiles;
1225 while(f > oldlimit) {
1226 limit.rlim_cur = f;
1227 limit.rlim_max = f;
1228 if (setrlimit(RLIMIT_NOFILE,&limit) != -1) break;
1229 f -= 128;
1230 }
1231 if (f < oldlimit) f = oldlimit;
1232 if (f != maxfiles) {
1233 server.maxclients = f-32;
e074416b 1234 redisLog(REDIS_WARNING,"Unable to set the max number of files limit to %d (%s), setting the max clients configuration to %d.",
1235 (int) maxfiles, strerror(errno), (int) server.maxclients);
1236 } else {
1237 redisLog(REDIS_NOTICE,"Max number of open files set to %d",
1238 (int) maxfiles);
1239 }
1240 }
1241 }
1242}
1243
e2641e09 1244void initServer() {
1245 int j;
1246
1247 signal(SIGHUP, SIG_IGN);
1248 signal(SIGPIPE, SIG_IGN);
633a9410 1249 setupSignalHandlers();
e2641e09 1250
e1a586ee
JH
1251 if (server.syslog_enabled) {
1252 openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,
1253 server.syslog_facility);
1254 }
1255
00010fa9 1256 server.current_client = NULL;
e2641e09 1257 server.clients = listCreate();
7eac2a75 1258 server.clients_to_close = listCreate();
e2641e09 1259 server.slaves = listCreate();
1260 server.monitors = listCreate();
a4ce7581 1261 server.unblocked_clients = listCreate();
cea8c5cd 1262
e2641e09 1263 createSharedObjects();
e074416b 1264 adjustOpenFilesLimit();
1265 server.el = aeCreateEventLoop(server.maxclients+1024);
e2641e09 1266 server.db = zmalloc(sizeof(redisDb)*server.dbnum);
68d6345d 1267
a53b4c24 1268 if (server.port != 0) {
68d6345d 1269 server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr);
a53b4c24 1270 if (server.ipfd == ANET_ERR) {
eef17490 1271 redisLog(REDIS_WARNING, "Opening port %d: %s",
1272 server.port, server.neterr);
a53b4c24 1273 exit(1);
1274 }
a5639e7d 1275 }
5d10923f
PN
1276 if (server.unixsocket != NULL) {
1277 unlink(server.unixsocket); /* don't care if this fails */
85238765 1278 server.sofd = anetUnixServer(server.neterr,server.unixsocket,server.unixsocketperm);
a5639e7d
PN
1279 if (server.sofd == ANET_ERR) {
1280 redisLog(REDIS_WARNING, "Opening socket: %s", server.neterr);
1281 exit(1);
1282 }
c61e6925 1283 }
a5639e7d
PN
1284 if (server.ipfd < 0 && server.sofd < 0) {
1285 redisLog(REDIS_WARNING, "Configured to not listen anywhere, exiting.");
e2641e09 1286 exit(1);
1287 }
1288 for (j = 0; j < server.dbnum; j++) {
1289 server.db[j].dict = dictCreate(&dbDictType,NULL);
1290 server.db[j].expires = dictCreate(&keyptrDictType,NULL);
1291 server.db[j].blocking_keys = dictCreate(&keylistDictType,NULL);
1292 server.db[j].watched_keys = dictCreate(&keylistDictType,NULL);
e2641e09 1293 server.db[j].id = j;
1294 }
1295 server.pubsub_channels = dictCreate(&keylistDictType,NULL);
1296 server.pubsub_patterns = listCreate();
1297 listSetFreeMethod(server.pubsub_patterns,freePubsubPattern);
1298 listSetMatchMethod(server.pubsub_patterns,listMatchPubsubPattern);
1299 server.cronloops = 0;
f48cd4b9 1300 server.rdb_child_pid = -1;
ff2145ad 1301 server.aof_child_pid = -1;
1302 server.aof_rewrite_buf = sdsempty();
1303 server.aof_buf = sdsempty();
e2641e09 1304 server.lastsave = time(NULL);
1305 server.dirty = 0;
1306 server.stat_numcommands = 0;
1307 server.stat_numconnections = 0;
1308 server.stat_expiredkeys = 0;
f21779ff 1309 server.stat_evictedkeys = 0;
e2641e09 1310 server.stat_starttime = time(NULL);
53eeeaff 1311 server.stat_keyspace_misses = 0;
1312 server.stat_keyspace_hits = 0;
17b24ff3 1313 server.stat_peak_memory = 0;
615e414c 1314 server.stat_fork_time = 0;
3c95e721 1315 server.stat_rejected_conn = 0;
250e7f69 1316 memset(server.ops_sec_samples,0,sizeof(server.ops_sec_samples));
1317 server.ops_sec_idx = 0;
1318 server.ops_sec_last_sample_time = mstime();
1319 server.ops_sec_last_sample_ops = 0;
e2641e09 1320 server.unixtime = time(NULL);
c25e7eaf 1321 server.lastbgsave_status = REDIS_OK;
4d3bbf35 1322 server.stop_writes_on_bgsave_err = 1;
e2641e09 1323 aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL);
a5639e7d 1324 if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE,
ab17b909 1325 acceptTcpHandler,NULL) == AE_ERR) oom("creating file event");
a5639e7d 1326 if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,
ab17b909 1327 acceptUnixHandler,NULL) == AE_ERR) oom("creating file event");
e2641e09 1328
e394114d 1329 if (server.aof_state == REDIS_AOF_ON) {
ff2145ad 1330 server.aof_fd = open(server.aof_filename,
e394114d 1331 O_WRONLY|O_APPEND|O_CREAT,0644);
ff2145ad 1332 if (server.aof_fd == -1) {
e2641e09 1333 redisLog(REDIS_WARNING, "Can't open the append-only file: %s",
1334 strerror(errno));
1335 exit(1);
1336 }
1337 }
1338
d876678b 1339 /* 32 bit instances are limited to 4GB of address space, so if there is
1340 * no explicit limit in the user provided configuration we set a limit
1341 * at 3.5GB using maxmemory with 'noeviction' policy'. This saves
1342 * useless crashes of the Redis instance. */
1343 if (server.arch_bits == 32 && server.maxmemory == 0) {
1344 redisLog(REDIS_WARNING,"Warning: 32 bit instance detected but no memory limit set. Setting 3.5 GB maxmemory limit with 'noeviction' policy now.");
1345 server.maxmemory = 3584LL*(1024*1024); /* 3584 MB = 3.5 GB */
1346 server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;
1347 }
1348
ecc91094 1349 if (server.cluster_enabled) clusterInit();
7585836e 1350 scriptingInit();
daa70b17 1351 slowlogInit();
8f61a72f 1352 bioInit();
e2641e09 1353}
1354
1b1f47c9 1355/* Populates the Redis Command Table starting from the hard coded list
1356 * we have on top of redis.c file. */
1357void populateCommandTable(void) {
1358 int j;
d7ed7fd2 1359 int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);
1b1f47c9 1360
1361 for (j = 0; j < numcommands; j++) {
d7ed7fd2 1362 struct redisCommand *c = redisCommandTable+j;
5d02b00f 1363 char *f = c->sflags;
1b1f47c9 1364 int retval;
e2641e09 1365
5d02b00f 1366 while(*f != '\0') {
1367 switch(*f) {
1368 case 'w': c->flags |= REDIS_CMD_WRITE; break;
1369 case 'r': c->flags |= REDIS_CMD_READONLY; break;
1370 case 'm': c->flags |= REDIS_CMD_DENYOOM; break;
1371 case 'a': c->flags |= REDIS_CMD_ADMIN; break;
1372 case 'p': c->flags |= REDIS_CMD_PUBSUB; break;
1373 case 'f': c->flags |= REDIS_CMD_FORCE_REPLICATION; break;
b60ed6e8 1374 case 's': c->flags |= REDIS_CMD_NOSCRIPT; break;
1375 case 'R': c->flags |= REDIS_CMD_RANDOM; break;
548efd91 1376 case 'S': c->flags |= REDIS_CMD_SORT_FOR_SCRIPT; break;
5d02b00f 1377 default: redisPanic("Unsupported command flag"); break;
1378 }
1379 f++;
1380 }
1381
1b1f47c9 1382 retval = dictAdd(server.commands, sdsnew(c->name), c);
1383 assert(retval == DICT_OK);
1384 }
e2641e09 1385}
1386
d7ed7fd2 1387void resetCommandTableStats(void) {
1388 int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);
1389 int j;
1390
1391 for (j = 0; j < numcommands; j++) {
1392 struct redisCommand *c = redisCommandTable+j;
1393
1394 c->microseconds = 0;
1395 c->calls = 0;
1396 }
1397}
1398
78d6a22d 1399/* ========================== Redis OP Array API ============================ */
1400
1401void redisOpArrayInit(redisOpArray *oa) {
1402 oa->ops = NULL;
1403 oa->numops = 0;
1404}
1405
1406int redisOpArrayAppend(redisOpArray *oa, struct redisCommand *cmd, int dbid,
1407 robj **argv, int argc, int target)
1408{
1409 redisOp *op;
1410
1411 oa->ops = zrealloc(oa->ops,sizeof(redisOp)*(oa->numops+1));
1412 op = oa->ops+oa->numops;
1413 op->cmd = cmd;
1414 op->dbid = dbid;
1415 op->argv = argv;
1416 op->argc = argc;
1417 op->target = target;
1418 oa->numops++;
1419 return oa->numops;
1420}
1421
1422void redisOpArrayFree(redisOpArray *oa) {
1423 while(oa->numops) {
1424 int j;
1425 redisOp *op;
1426
1427 oa->numops--;
1428 op = oa->ops+oa->numops;
1429 for (j = 0; j < op->argc; j++)
1430 decrRefCount(op->argv[j]);
1431 zfree(op->argv);
1432 }
1433 zfree(oa->ops);
1434}
1435
e2641e09 1436/* ====================== Commands lookup and execution ===================== */
1437
1b1f47c9 1438struct redisCommand *lookupCommand(sds name) {
1439 return dictFetchValue(server.commands, name);
1440}
1441
1442struct redisCommand *lookupCommandByCString(char *s) {
1443 struct redisCommand *cmd;
1444 sds name = sdsnew(s);
1445
1446 cmd = dictFetchValue(server.commands, name);
1447 sdsfree(name);
1448 return cmd;
e2641e09 1449}
1450
ad08d059 1451/* Propagate the specified command (in the context of the specified database id)
1452 * to AOF, Slaves and Monitors.
1453 *
1454 * flags are an xor between:
1455 * + REDIS_PROPAGATE_NONE (no propagation of command at all)
1456 * + REDIS_PROPAGATE_AOF (propagate into the AOF file if is enabled)
1457 * + REDIS_PROPAGATE_REPL (propagate into the replication link)
1458 */
1459void propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,
1460 int flags)
1461{
1462 if (server.aof_state != REDIS_AOF_OFF && flags & REDIS_PROPAGATE_AOF)
1463 feedAppendOnlyFile(cmd,dbid,argv,argc);
1464 if (flags & REDIS_PROPAGATE_REPL && listLength(server.slaves))
1465 replicationFeedSlaves(server.slaves,dbid,argv,argc);
1466}
1467
78d6a22d 1468/* Used inside commands to schedule the propagation of additional commands
1469 * after the current command is propagated to AOF / Replication. */
eeb34eff 1470void alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,
1471 int target)
1472{
78d6a22d 1473 redisOpArrayAppend(&server.also_propagate,cmd,dbid,argv,argc,target);
eeb34eff 1474}
1475
e2641e09 1476/* Call() is the core of Redis execution of a command */
ce8b772b 1477void call(redisClient *c, int flags) {
daa70b17 1478 long long dirty, start = ustime(), duration;
e2641e09 1479
ad08d059 1480 /* Sent the command to clients in MONITOR mode, only if the commands are
1481 * not geneated from reading an AOF. */
1482 if (listLength(server.monitors) && !server.loading)
e31b615e 1483 replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);
ad08d059 1484
1485 /* Call the command. */
78d6a22d 1486 redisOpArrayInit(&server.also_propagate);
e2641e09 1487 dirty = server.dirty;
09e2d9ee 1488 c->cmd->proc(c);
e2641e09 1489 dirty = server.dirty-dirty;
daa70b17 1490 duration = ustime()-start;
ce8b772b 1491
1492 /* When EVAL is called loading the AOF we don't want commands called
1493 * from Lua to go into the slowlog or to populate statistics. */
1494 if (server.loading && c->flags & REDIS_LUA_CLIENT)
1495 flags &= ~(REDIS_CALL_SLOWLOG | REDIS_CALL_STATS);
1496
ad08d059 1497 /* Log the command into the Slow log if needed, and populate the
1498 * per-command statistics that we show in INFO commandstats. */
ce8b772b 1499 if (flags & REDIS_CALL_SLOWLOG)
1500 slowlogPushEntryIfNeeded(c->argv,c->argc,duration);
1501 if (flags & REDIS_CALL_STATS) {
1502 c->cmd->microseconds += duration;
1503 c->cmd->calls++;
1504 }
ad08d059 1505
1506 /* Propagate the command into the AOF and replication link */
ce8b772b 1507 if (flags & REDIS_CALL_PROPAGATE) {
ad08d059 1508 int flags = REDIS_PROPAGATE_NONE;
1509
1510 if (c->cmd->flags & REDIS_CMD_FORCE_REPLICATION)
1511 flags |= REDIS_PROPAGATE_REPL;
1512 if (dirty)
1513 flags |= (REDIS_PROPAGATE_REPL | REDIS_PROPAGATE_AOF);
1514 if (flags != REDIS_PROPAGATE_NONE)
1515 propagate(c->cmd,c->db->id,c->argv,c->argc,flags);
ce8b772b 1516 }
eeb34eff 1517 /* Commands such as LPUSH or BRPOPLPUSH may propagate an additional
1518 * PUSH command. */
78d6a22d 1519 if (server.also_propagate.numops) {
eeb34eff 1520 int j;
78d6a22d 1521 redisOp *rop;
eeb34eff 1522
78d6a22d 1523 for (j = 0; j < server.also_propagate.numops; j++) {
1524 rop = &server.also_propagate.ops[j];
1525 propagate(rop->cmd, rop->dbid, rop->argv, rop->argc, rop->target);
1526 }
1527 redisOpArrayFree(&server.also_propagate);
eeb34eff 1528 }
e2641e09 1529 server.stat_numcommands++;
1530}
1531
1532/* If this function gets called we already read a whole
1533 * command, argments are in the client argv/argc fields.
1534 * processCommand() execute the command or prepare the
1535 * server for a bulk read from the client.
1536 *
1537 * If 1 is returned the client is still alive and valid and
1538 * and other operations can be performed by the caller. Otherwise
1539 * if 0 is returned the client was destroied (i.e. after QUIT). */
1540int processCommand(redisClient *c) {
941c9fa2
PN
1541 /* The QUIT command is handled separately. Normal command procs will
1542 * go through checking for replication and QUIT will cause trouble
1543 * when FORCE_REPLICATION is enabled and would be implemented in
1544 * a regular command proc. */
e2641e09 1545 if (!strcasecmp(c->argv[0]->ptr,"quit")) {
941c9fa2 1546 addReply(c,shared.ok);
5e78edb3 1547 c->flags |= REDIS_CLOSE_AFTER_REPLY;
cd8788f2 1548 return REDIS_ERR;
e2641e09 1549 }
1550
1551 /* Now lookup the command and check ASAP about trivial error conditions
09e2d9ee 1552 * such as wrong arity, bad command name and so forth. */
2c74a9f9 1553 c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr);
09e2d9ee 1554 if (!c->cmd) {
3ab20376
PN
1555 addReplyErrorFormat(c,"unknown command '%s'",
1556 (char*)c->argv[0]->ptr);
cd8788f2 1557 return REDIS_OK;
09e2d9ee 1558 } else if ((c->cmd->arity > 0 && c->cmd->arity != c->argc) ||
1559 (c->argc < -c->cmd->arity)) {
3ab20376 1560 addReplyErrorFormat(c,"wrong number of arguments for '%s' command",
09e2d9ee 1561 c->cmd->name);
cd8788f2 1562 return REDIS_OK;
e2641e09 1563 }
e2641e09 1564
1565 /* Check if the user is authenticated */
09e2d9ee 1566 if (server.requirepass && !c->authenticated && c->cmd->proc != authCommand)
1567 {
3ab20376 1568 addReplyError(c,"operation not permitted");
cd8788f2 1569 return REDIS_OK;
e2641e09 1570 }
1571
ecc91094 1572 /* If cluster is enabled, redirect here */
1573 if (server.cluster_enabled &&
09e2d9ee 1574 !(c->cmd->getkeys_proc == NULL && c->cmd->firstkey == 0)) {
ecc91094 1575 int hashslot;
1576
1577 if (server.cluster.state != REDIS_CLUSTER_OK) {
1578 addReplyError(c,"The cluster is down. Check with CLUSTER INFO for more information");
1579 return REDIS_OK;
1580 } else {
eda827f8 1581 int ask;
09e2d9ee 1582 clusterNode *n = getNodeByQuery(c,c->cmd,c->argv,c->argc,&hashslot,&ask);
ecc91094 1583 if (n == NULL) {
eda827f8 1584 addReplyError(c,"Multi keys request invalid in cluster");
ecc91094 1585 return REDIS_OK;
1586 } else if (n != server.cluster.myself) {
1587 addReplySds(c,sdscatprintf(sdsempty(),
eda827f8 1588 "-%s %d %s:%d\r\n", ask ? "ASK" : "MOVED",
1589 hashslot,n->ip,n->port));
ecc91094 1590 return REDIS_OK;
1591 }
1592 }
1593 }
1594
1dd10ca2 1595 /* Handle the maxmemory directive.
1596 *
1597 * First we try to free some memory if possible (if there are volatile
1598 * keys in the dataset). If there are not the only thing we can do
1599 * is returning an error. */
f6b32c14 1600 if (server.maxmemory) {
1601 int retval = freeMemoryIfNeeded();
1602 if ((c->cmd->flags & REDIS_CMD_DENYOOM) && retval == REDIS_ERR) {
f3fd419f 1603 addReply(c, shared.oomerr);
f6b32c14 1604 return REDIS_OK;
1605 }
e2641e09 1606 }
1607
c25e7eaf 1608 /* Don't accept write commands if there are problems persisting on disk. */
4d3bbf35 1609 if (server.stop_writes_on_bgsave_err &&
1610 server.saveparamslen > 0
1611 && server.lastbgsave_status == REDIS_ERR &&
c25e7eaf 1612 c->cmd->flags & REDIS_CMD_WRITE)
1613 {
1614 addReply(c, shared.bgsaveerr);
1615 return REDIS_OK;
1616 }
1617
f3fd419f 1618 /* Don't accept wirte commands if this is a read only slave. But
1619 * accept write commands if this is our master. */
1620 if (server.masterhost && server.repl_slave_ro &&
1621 !(c->flags & REDIS_MASTER) &&
1622 c->cmd->flags & REDIS_CMD_WRITE)
1623 {
1624 addReply(c, shared.roslaveerr);
1625 return REDIS_OK;
1626 }
1627
e2641e09 1628 /* Only allow SUBSCRIBE and UNSUBSCRIBE in the context of Pub/Sub */
1629 if ((dictSize(c->pubsub_channels) > 0 || listLength(c->pubsub_patterns) > 0)
1630 &&
09e2d9ee 1631 c->cmd->proc != subscribeCommand &&
1632 c->cmd->proc != unsubscribeCommand &&
1633 c->cmd->proc != psubscribeCommand &&
1634 c->cmd->proc != punsubscribeCommand) {
3ab20376 1635 addReplyError(c,"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context");
cd8788f2 1636 return REDIS_OK;
e2641e09 1637 }
1638
4ebfc455 1639 /* Only allow INFO and SLAVEOF when slave-serve-stale-data is no and
1640 * we are a slave with a broken link with master. */
1844f990 1641 if (server.masterhost && server.repl_state != REDIS_REPL_CONNECTED &&
4ebfc455 1642 server.repl_serve_stale_data == 0 &&
09e2d9ee 1643 c->cmd->proc != infoCommand && c->cmd->proc != slaveofCommand)
4ebfc455 1644 {
ae62d29d 1645 addReply(c, shared.masterdownerr);
4ebfc455 1646 return REDIS_OK;
1647 }
1648
97e7f8ae 1649 /* Loading DB? Return an error if the command is not INFO */
09e2d9ee 1650 if (server.loading && c->cmd->proc != infoCommand) {
97e7f8ae 1651 addReply(c, shared.loadingerr);
1652 return REDIS_OK;
1653 }
1654
4ab8695d 1655 /* Lua script too slow? Only allow SHUTDOWN NOSAVE and SCRIPT KILL. */
1656 if (server.lua_timedout &&
e3923a35 1657 !(c->cmd->proc == shutdownCommand &&
4ab8695d 1658 c->argc == 2 &&
1659 tolower(((char*)c->argv[1]->ptr)[0]) == 'n') &&
1660 !(c->cmd->proc == scriptCommand &&
1661 c->argc == 2 &&
1662 tolower(((char*)c->argv[1]->ptr)[0]) == 'k'))
1663 {
115e3ff3 1664 addReply(c, shared.slowscripterr);
1665 return REDIS_OK;
1666 }
1667
e2641e09 1668 /* Exec the command */
1669 if (c->flags & REDIS_MULTI &&
09e2d9ee 1670 c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&
1671 c->cmd->proc != multiCommand && c->cmd->proc != watchCommand)
e2641e09 1672 {
09e2d9ee 1673 queueMultiCommand(c);
e2641e09 1674 addReply(c,shared.queued);
1675 } else {
ce8b772b 1676 call(c,REDIS_CALL_FULL);
e2641e09 1677 }
cd8788f2 1678 return REDIS_OK;
e2641e09 1679}
1680
1681/*================================== Shutdown =============================== */
1682
4ab8695d 1683int prepareForShutdown(int flags) {
1684 int save = flags & REDIS_SHUTDOWN_SAVE;
1685 int nosave = flags & REDIS_SHUTDOWN_NOSAVE;
1686
adae85cd 1687 redisLog(REDIS_WARNING,"User requested shutdown...");
e2641e09 1688 /* Kill the saving child if there is a background saving in progress.
1689 We want to avoid race conditions, for instance our saving child may
1690 overwrite the synchronous saving did by SHUTDOWN. */
f48cd4b9 1691 if (server.rdb_child_pid != -1) {
adae85cd 1692 redisLog(REDIS_WARNING,"There is a child saving an .rdb. Killing it!");
f48cd4b9 1693 kill(server.rdb_child_pid,SIGKILL);
1694 rdbRemoveTempFile(server.rdb_child_pid);
e2641e09 1695 }
e394114d 1696 if (server.aof_state != REDIS_AOF_OFF) {
adae85cd 1697 /* Kill the AOF saving child as the AOF we already have may be longer
1698 * but contains the full dataset anyway. */
ff2145ad 1699 if (server.aof_child_pid != -1) {
adae85cd 1700 redisLog(REDIS_WARNING,
1701 "There is a child rewriting the AOF. Killing it!");
ff2145ad 1702 kill(server.aof_child_pid,SIGKILL);
adae85cd 1703 }
e2641e09 1704 /* Append only file: fsync() the AOF and exit */
adae85cd 1705 redisLog(REDIS_NOTICE,"Calling fsync() on the AOF file.");
ff2145ad 1706 aof_fsync(server.aof_fd);
adae85cd 1707 }
4ab8695d 1708 if ((server.saveparamslen > 0 && !nosave) || save) {
adae85cd 1709 redisLog(REDIS_NOTICE,"Saving the final RDB snapshot before exiting.");
e2641e09 1710 /* Snapshotting. Perform a SYNC SAVE and exit */
f48cd4b9 1711 if (rdbSave(server.rdb_filename) != REDIS_OK) {
e2641e09 1712 /* Ooops.. error saving! The best we can do is to continue
1713 * operating. Note that if there was a background saving process,
1714 * in the next cron() Redis will be notified that the background
1715 * saving aborted, handling special stuff like slaves pending for
1716 * synchronization... */
adae85cd 1717 redisLog(REDIS_WARNING,"Error trying to save the DB, can't exit.");
e2641e09 1718 return REDIS_ERR;
1719 }
1720 }
adae85cd 1721 if (server.daemonize) {
1722 redisLog(REDIS_NOTICE,"Removing the pid file.");
1723 unlink(server.pidfile);
1724 }
80e87a46 1725 /* Close the listening sockets. Apparently this allows faster restarts. */
1726 if (server.ipfd != -1) close(server.ipfd);
1727 if (server.sofd != -1) close(server.sofd);
56209f72
NF
1728 if (server.unixsocket) {
1729 redisLog(REDIS_NOTICE,"Removing the unix socket file.");
1730 unlink(server.unixsocket); /* don't care if this fails */
1731 }
80e87a46 1732
adae85cd 1733 redisLog(REDIS_WARNING,"Redis is now ready to exit, bye bye...");
e2641e09 1734 return REDIS_OK;
1735}
1736
1737/*================================== Commands =============================== */
1738
1739void authCommand(redisClient *c) {
ab52d1f4 1740 if (!server.requirepass) {
1741 addReplyError(c,"Client sent AUTH, but no password is set");
1742 } else if (!strcmp(c->argv[1]->ptr, server.requirepass)) {
e2641e09 1743 c->authenticated = 1;
1744 addReply(c,shared.ok);
1745 } else {
1746 c->authenticated = 0;
3ab20376 1747 addReplyError(c,"invalid password");
e2641e09 1748 }
1749}
1750
1751void pingCommand(redisClient *c) {
1752 addReply(c,shared.pong);
1753}
1754
1755void echoCommand(redisClient *c) {
1756 addReplyBulk(c,c->argv[1]);
1757}
1758
9494f1f1 1759void timeCommand(redisClient *c) {
1760 struct timeval tv;
1761
1762 /* gettimeofday() can only fail if &tv is a bad addresss so we
1763 * don't check for errors. */
1764 gettimeofday(&tv,NULL);
1765 addReplyMultiBulkLen(c,2);
1766 addReplyBulkLongLong(c,tv.tv_sec);
1767 addReplyBulkLongLong(c,tv.tv_usec);
1768}
1769
e2641e09 1770/* Convert an amount of bytes into a human readable string in the form
1771 * of 100B, 2G, 100M, 4K, and so forth. */
1772void bytesToHuman(char *s, unsigned long long n) {
1773 double d;
1774
1775 if (n < 1024) {
1776 /* Bytes */
1777 sprintf(s,"%lluB",n);
1778 return;
1779 } else if (n < (1024*1024)) {
1780 d = (double)n/(1024);
1781 sprintf(s,"%.2fK",d);
1782 } else if (n < (1024LL*1024*1024)) {
1783 d = (double)n/(1024*1024);
1784 sprintf(s,"%.2fM",d);
1785 } else if (n < (1024LL*1024*1024*1024)) {
1786 d = (double)n/(1024LL*1024*1024);
1787 sprintf(s,"%.2fG",d);
1788 }
1789}
1790
1791/* Create the string returned by the INFO command. This is decoupled
1792 * by the INFO command itself as we need to report the same information
1793 * on memory corruption problems. */
1b085c9f 1794sds genRedisInfoString(char *section) {
1795 sds info = sdsempty();
d1949054 1796 time_t uptime = server.unixtime-server.stat_starttime;
d9cb288c 1797 int j, numcommands;
2b00385d 1798 struct rusage self_ru, c_ru;
7a1fd61e 1799 unsigned long lol, bib;
1b085c9f 1800 int allsections = 0, defsections = 0;
1801 int sections = 0;
1802
1803 if (section) {
1804 allsections = strcasecmp(section,"all") == 0;
0d808ef2 1805 defsections = strcasecmp(section,"default") == 0;
1b085c9f 1806 }
2b00385d 1807
1808 getrusage(RUSAGE_SELF, &self_ru);
1809 getrusage(RUSAGE_CHILDREN, &c_ru);
7a1fd61e 1810 getClientsMaxBuffers(&lol,&bib);
1b085c9f 1811
1812 /* Server */
1813 if (allsections || defsections || !strcasecmp(section,"server")) {
5ad1faa0 1814 struct utsname name;
1815
1b085c9f 1816 if (sections++) info = sdscat(info,"\r\n");
5ad1faa0 1817 uname(&name);
e2641e09 1818 info = sdscatprintf(info,
1b085c9f 1819 "# Server\r\n"
1820 "redis_version:%s\r\n"
1821 "redis_git_sha1:%s\r\n"
1822 "redis_git_dirty:%d\r\n"
5ad1faa0 1823 "os:%s %s %s\r\n"
75eaac5c 1824 "arch_bits:%d\r\n"
1b085c9f 1825 "multiplexing_api:%s\r\n"
5db904bd 1826 "gcc_version:%d.%d.%d\r\n"
1b085c9f 1827 "process_id:%ld\r\n"
91d664d6 1828 "run_id:%s\r\n"
1b085c9f 1829 "tcp_port:%d\r\n"
1830 "uptime_in_seconds:%ld\r\n"
1831 "uptime_in_days:%ld\r\n"
1832 "lru_clock:%ld\r\n",
1833 REDIS_VERSION,
1834 redisGitSHA1(),
1835 strtol(redisGitDirty(),NULL,10) > 0,
5ad1faa0 1836 name.sysname, name.release, name.machine,
75eaac5c 1837 server.arch_bits,
1b085c9f 1838 aeGetApiName(),
5db904bd 1839#ifdef __GNUC__
1840 __GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__,
1841#else
1842 0,0,0,
1843#endif
1b085c9f 1844 (long) getpid(),
91d664d6 1845 server.runid,
1b085c9f 1846 server.port,
1847 uptime,
1848 uptime/(3600*24),
1849 (unsigned long) server.lruclock);
1850 }
1851
1852 /* Clients */
1853 if (allsections || defsections || !strcasecmp(section,"clients")) {
1854 if (sections++) info = sdscat(info,"\r\n");
1855 info = sdscatprintf(info,
1856 "# Clients\r\n"
3c08fdae 1857 "connected_clients:%lu\r\n"
1b085c9f 1858 "client_longest_output_list:%lu\r\n"
1859 "client_biggest_input_buf:%lu\r\n"
1860 "blocked_clients:%d\r\n",
1861 listLength(server.clients)-listLength(server.slaves),
1862 lol, bib,
1863 server.bpop_blocked_clients);
1864 }
1865
1866 /* Memory */
1867 if (allsections || defsections || !strcasecmp(section,"memory")) {
17b24ff3 1868 char hmem[64];
1869 char peak_hmem[64];
1870
1871 bytesToHuman(hmem,zmalloc_used_memory());
1872 bytesToHuman(peak_hmem,server.stat_peak_memory);
1b085c9f 1873 if (sections++) info = sdscat(info,"\r\n");
1874 info = sdscatprintf(info,
1875 "# Memory\r\n"
1876 "used_memory:%zu\r\n"
1877 "used_memory_human:%s\r\n"
1878 "used_memory_rss:%zu\r\n"
17b24ff3 1879 "used_memory_peak:%zu\r\n"
1880 "used_memory_peak_human:%s\r\n"
8c3402df 1881 "used_memory_lua:%lld\r\n"
1b085c9f 1882 "mem_fragmentation_ratio:%.2f\r\n"
32f99c51 1883 "mem_allocator:%s\r\n",
1b085c9f 1884 zmalloc_used_memory(),
1885 hmem,
1886 zmalloc_get_rss(),
17b24ff3 1887 server.stat_peak_memory,
1888 peak_hmem,
8c3402df 1889 ((long long)lua_gc(server.lua,LUA_GCCOUNT,0))*1024LL,
1b085c9f 1890 zmalloc_get_fragmentation_ratio(),
fec5a664 1891 ZMALLOC_LIB
12ebe2ac 1892 );
0d808ef2 1893 }
1894
1b085c9f 1895 /* Persistence */
1896 if (allsections || defsections || !strcasecmp(section,"persistence")) {
1897 if (sections++) info = sdscat(info,"\r\n");
e2641e09 1898 info = sdscatprintf(info,
1b085c9f 1899 "# Persistence\r\n"
1900 "loading:%d\r\n"
1901 "aof_enabled:%d\r\n"
1902 "changes_since_last_save:%lld\r\n"
1903 "bgsave_in_progress:%d\r\n"
1904 "last_save_time:%ld\r\n"
c25e7eaf 1905 "last_bgsave_status:%s\r\n"
618a9229 1906 "bgrewriteaof_in_progress:%d\r\n"
1907 "bgrewriteaof_scheduled:%d\r\n",
1b085c9f 1908 server.loading,
e394114d 1909 server.aof_state != REDIS_AOF_OFF,
1b085c9f 1910 server.dirty,
f48cd4b9 1911 server.rdb_child_pid != -1,
1b085c9f 1912 server.lastsave,
c25e7eaf 1913 server.lastbgsave_status == REDIS_OK ? "ok" : "err",
618a9229 1914 server.aof_child_pid != -1,
1915 server.aof_rewrite_scheduled);
1b085c9f 1916
e394114d 1917 if (server.aof_state != REDIS_AOF_OFF) {
d630abcd 1918 info = sdscatprintf(info,
1919 "aof_current_size:%lld\r\n"
1920 "aof_base_size:%lld\r\n"
e7ef418c 1921 "aof_pending_rewrite:%d\r\n"
1922 "aof_buffer_length:%zu\r\n"
c1d01b3c 1923 "aof_pending_bio_fsync:%llu\r\n"
1924 "aof_delayed_fsync:%lu\r\n",
2c915bcf 1925 (long long) server.aof_current_size,
1926 (long long) server.aof_rewrite_base_size,
1927 server.aof_rewrite_scheduled,
ff2145ad 1928 sdslen(server.aof_buf),
c1d01b3c 1929 bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC),
1930 server.aof_delayed_fsync);
d630abcd 1931 }
1932
1b085c9f 1933 if (server.loading) {
1934 double perc;
1935 time_t eta, elapsed;
1936 off_t remaining_bytes = server.loading_total_bytes-
1937 server.loading_loaded_bytes;
1938
1939 perc = ((double)server.loading_loaded_bytes /
1940 server.loading_total_bytes) * 100;
1941
d1949054 1942 elapsed = server.unixtime-server.loading_start_time;
1b085c9f 1943 if (elapsed == 0) {
1944 eta = 1; /* A fake 1 second figure if we don't have
1945 enough info */
1946 } else {
1947 eta = (elapsed*remaining_bytes)/server.loading_loaded_bytes;
1948 }
1949
1950 info = sdscatprintf(info,
1951 "loading_start_time:%ld\r\n"
1952 "loading_total_bytes:%llu\r\n"
1953 "loading_loaded_bytes:%llu\r\n"
1954 "loading_loaded_perc:%.2f\r\n"
1955 "loading_eta_seconds:%ld\r\n"
1956 ,(unsigned long) server.loading_start_time,
1957 (unsigned long long) server.loading_total_bytes,
1958 (unsigned long long) server.loading_loaded_bytes,
1959 perc,
1960 eta
1961 );
1962 }
e2641e09 1963 }
1b085c9f 1964
1b085c9f 1965 /* Stats */
1966 if (allsections || defsections || !strcasecmp(section,"stats")) {
1967 if (sections++) info = sdscat(info,"\r\n");
97e7f8ae 1968 info = sdscatprintf(info,
1b085c9f 1969 "# Stats\r\n"
1970 "total_connections_received:%lld\r\n"
1971 "total_commands_processed:%lld\r\n"
250e7f69 1972 "instantaneous_ops_per_sec:%lld\r\n"
3c95e721 1973 "rejected_connections:%lld\r\n"
1b085c9f 1974 "expired_keys:%lld\r\n"
1975 "evicted_keys:%lld\r\n"
1976 "keyspace_hits:%lld\r\n"
1977 "keyspace_misses:%lld\r\n"
1978 "pubsub_channels:%ld\r\n"
3c08fdae 1979 "pubsub_patterns:%lu\r\n"
615e414c 1980 "latest_fork_usec:%lld\r\n",
1b085c9f 1981 server.stat_numconnections,
1982 server.stat_numcommands,
250e7f69 1983 getOperationsPerSecond(),
3c95e721 1984 server.stat_rejected_conn,
1b085c9f 1985 server.stat_expiredkeys,
1986 server.stat_evictedkeys,
1987 server.stat_keyspace_hits,
1988 server.stat_keyspace_misses,
1989 dictSize(server.pubsub_channels),
615e414c 1990 listLength(server.pubsub_patterns),
1991 server.stat_fork_time);
97e7f8ae 1992 }
67a1810b 1993
1b085c9f 1994 /* Replication */
1995 if (allsections || defsections || !strcasecmp(section,"replication")) {
1996 if (sections++) info = sdscat(info,"\r\n");
1997 info = sdscatprintf(info,
1998 "# Replication\r\n"
1999 "role:%s\r\n",
2000 server.masterhost == NULL ? "master" : "slave");
2001 if (server.masterhost) {
2002 info = sdscatprintf(info,
2003 "master_host:%s\r\n"
2004 "master_port:%d\r\n"
2005 "master_link_status:%s\r\n"
2006 "master_last_io_seconds_ago:%d\r\n"
2007 "master_sync_in_progress:%d\r\n"
2008 ,server.masterhost,
2009 server.masterport,
1844f990 2010 (server.repl_state == REDIS_REPL_CONNECTED) ?
1b085c9f 2011 "up" : "down",
2012 server.master ?
d1949054 2013 ((int)(server.unixtime-server.master->lastinteraction)) : -1,
1844f990 2014 server.repl_state == REDIS_REPL_TRANSFER
1b085c9f 2015 );
2016
1844f990 2017 if (server.repl_state == REDIS_REPL_TRANSFER) {
1b085c9f 2018 info = sdscatprintf(info,
2019 "master_sync_left_bytes:%ld\r\n"
2020 "master_sync_last_io_seconds_ago:%d\r\n"
2021 ,(long)server.repl_transfer_left,
d1949054 2022 (int)(server.unixtime-server.repl_transfer_lastio)
1b085c9f 2023 );
2024 }
07486df6 2025
1844f990 2026 if (server.repl_state != REDIS_REPL_CONNECTED) {
07486df6 2027 info = sdscatprintf(info,
2028 "master_link_down_since_seconds:%ld\r\n",
d1949054 2029 (long)server.unixtime-server.repl_down_since);
07486df6 2030 }
67a1810b 2031 }
1b085c9f 2032 info = sdscatprintf(info,
3c08fdae 2033 "connected_slaves:%lu\r\n",
1b085c9f 2034 listLength(server.slaves));
503d87a8 2035 if (listLength(server.slaves)) {
2036 int slaveid = 0;
2037 listNode *ln;
2038 listIter li;
2039
2040 listRewind(server.slaves,&li);
2041 while((ln = listNext(&li))) {
2042 redisClient *slave = listNodeValue(ln);
2043 char *state = NULL;
2044 char ip[32];
2045 int port;
2046
2047 if (anetPeerToString(slave->fd,ip,&port) == -1) continue;
2048 switch(slave->replstate) {
2049 case REDIS_REPL_WAIT_BGSAVE_START:
2050 case REDIS_REPL_WAIT_BGSAVE_END:
2051 state = "wait_bgsave";
2052 break;
2053 case REDIS_REPL_SEND_BULK:
2054 state = "send_bulk";
2055 break;
2056 case REDIS_REPL_ONLINE:
2057 state = "online";
2058 break;
2059 }
2060 if (state == NULL) continue;
2061 info = sdscatprintf(info,"slave%d:%s,%d,%s\r\n",
2062 slaveid,ip,port,state);
2063 slaveid++;
2064 }
2065 }
67a1810b 2066 }
67a1810b 2067
0d808ef2 2068 /* CPU */
2069 if (allsections || defsections || !strcasecmp(section,"cpu")) {
1b085c9f 2070 if (sections++) info = sdscat(info,"\r\n");
2071 info = sdscatprintf(info,
0d808ef2 2072 "# CPU\r\n"
1b085c9f 2073 "used_cpu_sys:%.2f\r\n"
2074 "used_cpu_user:%.2f\r\n"
5a9dd97c 2075 "used_cpu_sys_children:%.2f\r\n"
2076 "used_cpu_user_children:%.2f\r\n",
1b085c9f 2077 (float)self_ru.ru_stime.tv_sec+(float)self_ru.ru_stime.tv_usec/1000000,
d83eda48 2078 (float)self_ru.ru_utime.tv_sec+(float)self_ru.ru_utime.tv_usec/1000000,
2079 (float)c_ru.ru_stime.tv_sec+(float)c_ru.ru_stime.tv_usec/1000000,
2080 (float)c_ru.ru_utime.tv_sec+(float)c_ru.ru_utime.tv_usec/1000000);
0d808ef2 2081 }
1b085c9f 2082
0d808ef2 2083 /* cmdtime */
2084 if (allsections || !strcasecmp(section,"commandstats")) {
2085 if (sections++) info = sdscat(info,"\r\n");
2086 info = sdscatprintf(info, "# Commandstats\r\n");
d7ed7fd2 2087 numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);
1b085c9f 2088 for (j = 0; j < numcommands; j++) {
d7ed7fd2 2089 struct redisCommand *c = redisCommandTable+j;
0d808ef2 2090
d7ed7fd2 2091 if (!c->calls) continue;
2092 info = sdscatprintf(info,
2093 "cmdstat_%s:calls=%lld,usec=%lld,usec_per_call=%.2f\r\n",
2094 c->name, c->calls, c->microseconds,
2095 (c->calls == 0) ? 0 : ((float)c->microseconds/c->calls));
1b085c9f 2096 }
d9cb288c 2097 }
2098
f2f2ba1b 2099 /* Cluster */
1c708b25
SS
2100 if (allsections || defsections || !strcasecmp(section,"cluster")) {
2101 if (sections++) info = sdscat(info,"\r\n");
2102 info = sdscatprintf(info,
2103 "# Cluster\r\n"
2104 "cluster_enabled:%d\r\n",
2105 server.cluster_enabled);
2106 }
2107
1b085c9f 2108 /* Key space */
2109 if (allsections || defsections || !strcasecmp(section,"keyspace")) {
2110 if (sections++) info = sdscat(info,"\r\n");
2111 info = sdscatprintf(info, "# Keyspace\r\n");
2112 for (j = 0; j < server.dbnum; j++) {
2113 long long keys, vkeys;
e2641e09 2114
1b085c9f 2115 keys = dictSize(server.db[j].dict);
2116 vkeys = dictSize(server.db[j].expires);
2117 if (keys || vkeys) {
2118 info = sdscatprintf(info, "db%d:keys=%lld,expires=%lld\r\n",
2119 j, keys, vkeys);
2120 }
e2641e09 2121 }
2122 }
2123 return info;
2124}
2125
2126void infoCommand(redisClient *c) {
1b085c9f 2127 char *section = c->argc == 2 ? c->argv[1]->ptr : "default";
2128
2129 if (c->argc > 2) {
2130 addReply(c,shared.syntaxerr);
2131 return;
2132 }
2133 sds info = genRedisInfoString(section);
e2641e09 2134 addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n",
2135 (unsigned long)sdslen(info)));
2136 addReplySds(c,info);
2137 addReply(c,shared.crlf);
2138}
2139
2140void monitorCommand(redisClient *c) {
2141 /* ignore MONITOR if aleady slave or in monitor mode */
2142 if (c->flags & REDIS_SLAVE) return;
2143
2144 c->flags |= (REDIS_SLAVE|REDIS_MONITOR);
2145 c->slaveseldb = 0;
2146 listAddNodeTail(server.monitors,c);
2147 addReply(c,shared.ok);
2148}
2149
2150/* ============================ Maxmemory directive ======================== */
2151
e2641e09 2152/* This function gets called when 'maxmemory' is set on the config file to limit
f6b32c14 2153 * the max memory used by the server, before processing a command.
e2641e09 2154 *
f6b32c14 2155 * The goal of the function is to free enough memory to keep Redis under the
2156 * configured memory limit.
e2641e09 2157 *
f6b32c14 2158 * The function starts calculating how many bytes should be freed to keep
2159 * Redis under the limit, and enters a loop selecting the best keys to
2160 * evict accordingly to the configured policy.
2161 *
2162 * If all the bytes needed to return back under the limit were freed the
2163 * function returns REDIS_OK, otherwise REDIS_ERR is returned, and the caller
2164 * should block the execution of commands that will result in more memory
2165 * used by the server.
e2641e09 2166 */
f6b32c14 2167int freeMemoryIfNeeded(void) {
2168 size_t mem_used, mem_tofree, mem_freed;
2169 int slaves = listLength(server.slaves);
2170
c1ef6ffe 2171 /* Remove the size of slaves output buffers and AOF buffer from the
2172 * count of used memory. */
f6b32c14 2173 mem_used = zmalloc_used_memory();
2174 if (slaves) {
2175 listIter li;
2176 listNode *ln;
2177
2178 listRewind(server.slaves,&li);
2179 while((ln = listNext(&li))) {
2180 redisClient *slave = listNodeValue(ln);
2181 unsigned long obuf_bytes = getClientOutputBufferMemoryUsage(slave);
2182 if (obuf_bytes > mem_used)
2183 mem_used = 0;
2184 else
2185 mem_used -= obuf_bytes;
2186 }
2187 }
c1ef6ffe 2188 if (server.aof_state != REDIS_AOF_OFF) {
2189 mem_used -= sdslen(server.aof_buf);
2190 mem_used -= sdslen(server.aof_rewrite_buf);
2191 }
5402c426 2192
f6b32c14 2193 /* Check if we are over the memory limit. */
2194 if (mem_used <= server.maxmemory) return REDIS_OK;
2195
2196 if (server.maxmemory_policy == REDIS_MAXMEMORY_NO_EVICTION)
2197 return REDIS_ERR; /* We need to free memory, but policy forbids. */
2198
2199 /* Compute how much memory we need to free. */
2200 mem_tofree = mem_used - server.maxmemory;
f6b32c14 2201 mem_freed = 0;
2202 while (mem_freed < mem_tofree) {
2203 int j, k, keys_freed = 0;
e2641e09 2204
165346ca 2205 for (j = 0; j < server.dbnum; j++) {
10c12171 2206 long bestval = 0; /* just to prevent warning */
165346ca 2207 sds bestkey = NULL;
2208 struct dictEntry *de;
2209 redisDb *db = server.db+j;
2210 dict *dict;
2211
2212 if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_LRU ||
2213 server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_RANDOM)
2214 {
2215 dict = server.db[j].dict;
2216 } else {
2217 dict = server.db[j].expires;
2218 }
2219 if (dictSize(dict) == 0) continue;
2220
2221 /* volatile-random and allkeys-random policy */
2222 if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_RANDOM ||
2223 server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_RANDOM)
2224 {
2225 de = dictGetRandomKey(dict);
c0ba9ebe 2226 bestkey = dictGetKey(de);
165346ca 2227 }
2228
2229 /* volatile-lru and allkeys-lru policy */
2230 else if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_LRU ||
2231 server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_LRU)
2232 {
2233 for (k = 0; k < server.maxmemory_samples; k++) {
2234 sds thiskey;
2235 long thisval;
2236 robj *o;
2237
2238 de = dictGetRandomKey(dict);
c0ba9ebe 2239 thiskey = dictGetKey(de);
0c2f75c6 2240 /* When policy is volatile-lru we need an additonal lookup
2241 * to locate the real key, as dict is set to db->expires. */
2242 if (server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_LRU)
2243 de = dictFind(db->dict, thiskey);
c0ba9ebe 2244 o = dictGetVal(de);
165346ca 2245 thisval = estimateObjectIdleTime(o);
2246
2247 /* Higher idle time is better candidate for deletion */
2248 if (bestkey == NULL || thisval > bestval) {
2249 bestkey = thiskey;
2250 bestval = thisval;
2251 }
2252 }
2253 }
2254
2255 /* volatile-ttl */
2256 else if (server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_TTL) {
2257 for (k = 0; k < server.maxmemory_samples; k++) {
2258 sds thiskey;
2259 long thisval;
2260
2261 de = dictGetRandomKey(dict);
c0ba9ebe 2262 thiskey = dictGetKey(de);
2263 thisval = (long) dictGetVal(de);
165346ca 2264
2265 /* Expire sooner (minor expire unix timestamp) is better
2266 * candidate for deletion */
2267 if (bestkey == NULL || thisval < bestval) {
2268 bestkey = thiskey;
2269 bestval = thisval;
2270 }
2271 }
2272 }
2273
2274 /* Finally remove the selected key. */
2275 if (bestkey) {
f6b32c14 2276 long long delta;
2277
165346ca 2278 robj *keyobj = createStringObject(bestkey,sdslen(bestkey));
452229b6 2279 propagateExpire(db,keyobj);
f6b32c14 2280 /* We compute the amount of memory freed by dbDelete() alone.
2281 * It is possible that actually the memory needed to propagate
2282 * the DEL in AOF and replication link is greater than the one
2283 * we are freeing removing the key, but we can't account for
2284 * that otherwise we would never exit the loop.
2285 *
2286 * AOF and Output buffer memory will be freed eventually so
2287 * we only care about memory used by the key space. */
2288 delta = (long long) zmalloc_used_memory();
165346ca 2289 dbDelete(db,keyobj);
f6b32c14 2290 delta -= (long long) zmalloc_used_memory();
f6b32c14 2291 mem_freed += delta;
f21779ff 2292 server.stat_evictedkeys++;
165346ca 2293 decrRefCount(keyobj);
f6b32c14 2294 keys_freed++;
2295
2296 /* When the memory to free starts to be big enough, we may
2297 * start spending so much time here that is impossible to
2298 * deliver data to the slaves fast enough, so we force the
2299 * transmission here inside the loop. */
8b7c3455 2300 if (slaves) flushSlavesOutputBuffers();
165346ca 2301 }
2302 }
b129c6df 2303 if (!keys_freed) return REDIS_ERR; /* nothing to free... */
165346ca 2304 }
f6b32c14 2305 return REDIS_OK;
e2641e09 2306}
2307
2308/* =================================== Main! ================================ */
2309
2310#ifdef __linux__
2311int linuxOvercommitMemoryValue(void) {
2312 FILE *fp = fopen("/proc/sys/vm/overcommit_memory","r");
2313 char buf[64];
2314
2315 if (!fp) return -1;
2316 if (fgets(buf,64,fp) == NULL) {
2317 fclose(fp);
2318 return -1;
2319 }
2320 fclose(fp);
2321
2322 return atoi(buf);
2323}
2324
2325void linuxOvercommitMemoryWarning(void) {
2326 if (linuxOvercommitMemoryValue() == 0) {
2327 redisLog(REDIS_WARNING,"WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. 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.");
2328 }
2329}
2330#endif /* __linux__ */
2331
695fe874 2332void createPidFile(void) {
2333 /* Try to write the pid file in a best-effort way. */
2334 FILE *fp = fopen(server.pidfile,"w");
2335 if (fp) {
8ce39260 2336 fprintf(fp,"%d\n",(int)getpid());
695fe874 2337 fclose(fp);
2338 }
2339}
2340
e2641e09 2341void daemonize(void) {
2342 int fd;
e2641e09 2343
2344 if (fork() != 0) exit(0); /* parent exits */
2345 setsid(); /* create a new session */
2346
2347 /* Every output goes to /dev/null. If Redis is daemonized but
2348 * the 'logfile' is set to 'stdout' in the configuration file
2349 * it will not log at all. */
2350 if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
2351 dup2(fd, STDIN_FILENO);
2352 dup2(fd, STDOUT_FILENO);
2353 dup2(fd, STDERR_FILENO);
2354 if (fd > STDERR_FILENO) close(fd);
2355 }
e2641e09 2356}
2357
2358void version() {
6e05f333 2359 printf("Redis server v=%s sha=%s:%d malloc=%s bits=%d\n",
2360 REDIS_VERSION,
2361 redisGitSHA1(),
2362 atoi(redisGitDirty()) > 0,
2363 ZMALLOC_LIB,
2364 sizeof(long) == 4 ? 32 : 64);
e2641e09 2365 exit(0);
2366}
2367
2368void usage() {
9268a5b5 2369 fprintf(stderr,"Usage: ./redis-server [/path/to/redis.conf] [options]\n");
e2641e09 2370 fprintf(stderr," ./redis-server - (read config from stdin)\n");
9268a5b5 2371 fprintf(stderr," ./redis-server -v or --version\n");
c5166e3f 2372 fprintf(stderr," ./redis-server -h or --help\n");
2373 fprintf(stderr," ./redis-server --test-memory <megabytes>\n\n");
9268a5b5 2374 fprintf(stderr,"Examples:\n");
2375 fprintf(stderr," ./redis-server (run the server with default conf)\n");
2376 fprintf(stderr," ./redis-server /etc/redis/6379.conf\n");
2377 fprintf(stderr," ./redis-server --port 7777\n");
2378 fprintf(stderr," ./redis-server --port 7777 --slaveof 127.0.0.1 8888\n");
2379 fprintf(stderr," ./redis-server /etc/myredis.conf --loglevel verbose\n");
e2641e09 2380 exit(1);
2381}
2382
996d503d 2383void redisAsciiArt(void) {
2384#include "asciilogo.h"
2385 char *buf = zmalloc(1024*16);
2386
2387 snprintf(buf,1024*16,ascii_logo,
2388 REDIS_VERSION,
2389 redisGitSHA1(),
2390 strtol(redisGitDirty(),NULL,10) > 0,
2391 (sizeof(long) == 8) ? "64" : "32",
2392 server.cluster_enabled ? "cluster" : "stand alone",
2393 server.port,
2394 (long) getpid()
2395 );
2396 redisLogRaw(REDIS_NOTICE|REDIS_LOG_RAW,buf);
2397 zfree(buf);
2398}
2399
633a9410 2400static void sigtermHandler(int sig) {
e2641e09 2401 REDIS_NOTUSED(sig);
2402
a7d12cba 2403 redisLogFromHandler(REDIS_WARNING,"Received SIGTERM, scheduling shutdown...");
e2641e09 2404 server.shutdown_asap = 1;
2405}
2406
633a9410 2407void setupSignalHandlers(void) {
e2641e09 2408 struct sigaction act;
2409
633a9410
PN
2410 /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction is used.
2411 * Otherwise, sa_handler is used. */
2412 sigemptyset(&act.sa_mask);
c5757662 2413 act.sa_flags = 0;
e2641e09 2414 act.sa_handler = sigtermHandler;
633a9410 2415 sigaction(SIGTERM, &act, NULL);
e2641e09 2416
633a9410
PN
2417#ifdef HAVE_BACKTRACE
2418 sigemptyset(&act.sa_mask);
3ada43e7 2419 act.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
633a9410
PN
2420 act.sa_sigaction = sigsegvHandler;
2421 sigaction(SIGSEGV, &act, NULL);
2422 sigaction(SIGBUS, &act, NULL);
2423 sigaction(SIGFPE, &act, NULL);
2424 sigaction(SIGILL, &act, NULL);
2425#endif
2426 return;
e2641e09 2427}
e2641e09 2428
c5166e3f 2429void memtest(size_t megabytes, int passes);
2430
39ca1713 2431int main(int argc, char **argv) {
2432 long long start;
a48c8d87 2433 struct timeval tv;
39ca1713 2434
06c5523a 2435 /* We need to initialize our libraries, and the server configuration. */
39ca1713 2436 zmalloc_enable_thread_safeness();
a48c8d87 2437 srand(time(NULL)^getpid());
2438 gettimeofday(&tv,NULL);
2439 dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());
39ca1713 2440 initServerConfig();
a48c8d87 2441
67c6f0f6 2442 if (argc >= 2) {
2443 int j = 1; /* First option to parse in argv[] */
2444 sds options = sdsempty();
2445 char *configfile = NULL;
2446
2447 /* Handle special options --help and --version */
39ca1713 2448 if (strcmp(argv[1], "-v") == 0 ||
2449 strcmp(argv[1], "--version") == 0) version();
4c8bd905 2450 if (strcmp(argv[1], "--help") == 0 ||
2451 strcmp(argv[1], "-h") == 0) usage();
c5166e3f 2452 if (strcmp(argv[1], "--test-memory") == 0) {
2453 if (argc == 3) {
d033ccb0 2454 memtest(atoi(argv[2]),50);
c5166e3f 2455 exit(0);
2456 } else {
2457 fprintf(stderr,"Please specify the amount of memory to test in megabytes.\n");
2458 fprintf(stderr,"Example: ./redis-server --test-memory 4096\n\n");
2459 exit(1);
2460 }
2461 }
2462
67c6f0f6 2463 /* First argument is the config file name? */
2464 if (argv[j][0] != '-' || argv[j][1] != '-')
2465 configfile = argv[j++];
2466 /* All the other options are parsed and conceptually appended to the
2467 * configuration file. For instance --port 6380 will generate the
2468 * string "port 6380\n" to be parsed after the actual file name
2469 * is parsed, if any. */
2470 while(j != argc) {
2471 if (argv[j][0] == '-' && argv[j][1] == '-') {
2472 /* Option name */
2473 if (sdslen(options)) options = sdscat(options,"\n");
2474 options = sdscat(options,argv[j]+2);
2475 options = sdscat(options," ");
2476 } else {
2477 /* Option argument */
2478 options = sdscatrepr(options,argv[j],strlen(argv[j]));
2479 options = sdscat(options," ");
2480 }
2481 j++;
2482 }
39ca1713 2483 resetServerSaveParams();
67c6f0f6 2484 loadServerConfig(configfile,options);
2485 sdsfree(options);
39ca1713 2486 } else {
2487 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'");
2488 }
2489 if (server.daemonize) daemonize();
2490 initServer();
2491 if (server.daemonize) createPidFile();
2492 redisAsciiArt();
27ccb94a 2493 redisLog(REDIS_WARNING,"Server started, Redis version " REDIS_VERSION);
39ca1713 2494#ifdef __linux__
2495 linuxOvercommitMemoryWarning();
2496#endif
2497 start = ustime();
e394114d 2498 if (server.aof_state == REDIS_AOF_ON) {
2c915bcf 2499 if (loadAppendOnlyFile(server.aof_filename) == REDIS_OK)
39ca1713 2500 redisLog(REDIS_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000);
2501 } else {
f48cd4b9 2502 if (rdbLoad(server.rdb_filename) == REDIS_OK) {
39ca1713 2503 redisLog(REDIS_NOTICE,"DB loaded from disk: %.3f seconds",
2504 (float)(ustime()-start)/1000000);
2505 } else if (errno != ENOENT) {
2506 redisLog(REDIS_WARNING,"Fatal error loading the DB. Exiting.");
2507 exit(1);
2508 }
2509 }
2510 if (server.ipfd > 0)
2511 redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
2512 if (server.sofd > 0)
2513 redisLog(REDIS_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket);
2514 aeSetBeforeSleepProc(server.el,beforeSleep);
2515 aeMain(server.el);
2516 aeDeleteEventLoop(server.el);
2517 return 0;
2518}
2519
e2641e09 2520/* The End */