redis源码笔记-config

redis配置文件的头文件,有一些和平台有关的配置,在这里边进行设置。

config.h

 1 #ifndef __CONFIG_H
 2 #define __CONFIG_H
 3 
 4 #ifdef __APPLE__
 5 #include <AvailabilityMacros.h>
 6 #endif
 7 
 8 /* Define redis_fstat to fstat or fstat64() */
 9 #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)
10 #define redis_fstat fstat64
11 #define redis_stat stat64
12 #else
13 #define redis_fstat fstat
14 #define redis_stat stat
15 #endif
16 
17 /* Test for proc filesystem */
18 //proc filesystem是进程文件系统的意思,包含一个伪文件系统(启动时动态生成的文件系统),用于通过内核访问进程信息。这个文件系统通常挂载在/proc目录下,/proc不是真正的文件系统,仅占用内存空间
19 //redis在获取rss信息(zmalloc.c的zmalloc_get_rss函数)时,需要判断是否有proc filesystem。rss是Resident Set Size的缩写,表示进程占用被hold在内存的那一部分。
20 #ifdef __linux__
21 #define HAVE_PROCFS 1
22 #endif         
23 
24 /* Test for task_info() */
25 #if defined(__APPLE__)
26 #define HAVE_TASKINFO 1
27 #endif
28 
29 //backtrace是指“A backtrace is a list of the function calls that are currently active in a thread. The usual way to inspect a backtrace of a program is to use an external debugger such as gdb. However, sometimes it is useful to obtain a backtrace programmatically from within a program, e.g., for the purposes of logging or diagnostics.”或者说,我们通常说的栈祯。在debug.c和redis.c中均有应用,具体到相关调用处再说明。
30 /* Test for backtrace() */
31 #if defined(__APPLE__) || defined(__linux__) || defined(__sun)
32 #define HAVE_BACKTRACE 1
33 #endif
34 
35 //linux下使用epoll构建事件框架
36 /* Test for polling API */
37 #ifdef __linux__
38 #define HAVE_EPOLL 1
39 #endif
40 
41 #if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__)
42 #define HAVE_KQUEUE 1
43 #endif
44 
45 //linux下使用fdatasync来flush硬盘。apue上讲过,fsync和fdatasync的区别是,fsync同时刷新文件的元数据(精确描述大家自己翻书吧)。redis使用fsync是为了将内存中的业务数据保存下来,具体rdb文件的元数据是否得到及时更新,并不是很重要,因此,如果在fdatasync可用的时候,使用更快的就是一个更明智的选择。
46 /* Define aof_fsync to fdatasync() in Linux and fsync() for all the rest */
47 #ifdef __linux__
48 #define aof_fsync fdatasync
49 #else
50 #define aof_fsync fsync
51 #endif
52 
53 #endif

config.c   读取配置文件,以及和配置文件有关的client命令的执行函数,可谓又臭又长,看看就好。

  1 #include "redis.h"
  2 
  3 /*-----------------------------------------------------------------------------
  4  * Config file parsing
  5  *----------------------------------------------------------------------------*/
  6 
  7 int yesnotoi(char *s) {
  8     if (!strcasecmp(s,"yes")) return 1;
  9     else if (!strcasecmp(s,"no")) return 0;
 10     else return -1;
 11 }
 12 
 13 void appendServerSaveParams(time_t seconds, int changes) {
 14     server.saveparams = zrealloc(server.saveparams,sizeof(struct saveparam)*(server.saveparamslen+1));
 15     server.saveparams[server.saveparamslen].seconds = seconds;
 16     server.saveparams[server.saveparamslen].changes = changes;
 17     server.saveparamslen++;
 18 }
 19 
 20 void resetServerSaveParams() {
 21     zfree(server.saveparams);
 22     server.saveparams = NULL;
 23     server.saveparamslen = 0;
 24 }
 25 
 26 /* I agree, this is a very rudimental way to load a configuration...
 27    will improve later if the config gets more complex */
 28 void loadServerConfig(char *filename) {
 29     FILE *fp;
 30     char buf[REDIS_CONFIGLINE_MAX+1], *err = NULL;
 31     int linenum = 0;
 32     sds line = NULL;
 33     int really_use_vm = 0;
 34 
 35     if (filename[0] == '-' && filename[1] == '\0')
 36         fp = stdin;
 37     else {
 38         if ((fp = fopen(filename,"r")) == NULL) {
 39             redisLog(REDIS_WARNING, "Fatal error, can't open config file '%s'", filename);
 40             exit(1);
 41         }
 42     }
 43 
 44     while(fgets(buf,REDIS_CONFIGLINE_MAX+1,fp) != NULL) {
 45         sds *argv;
 46         int argc, j;
 47 
 48         linenum++;
 49         line = sdsnew(buf);
 50         line = sdstrim(line," \t\r\n");
 51 
 52         /* Skip comments and blank lines*/
 53         if (line[0] == '#' || line[0] == '\0') {
 54             sdsfree(line);
 55             continue;
 56         }
 57 
 58         /* Split into arguments */
 59         argv = sdssplitargs(line,&argc);
 60         sdstolower(argv[0]);
 61 
 62         /* Execute config directives */
 63         if (!strcasecmp(argv[0],"timeout") && argc == 2) {
 64             server.maxidletime = atoi(argv[1]);
 65             if (server.maxidletime < 0) {
 66                 err = "Invalid timeout value"; goto loaderr;
 67             }
 68         } else if (!strcasecmp(argv[0],"port") && argc == 2) {
 69             server.port = atoi(argv[1]);
 70             if (server.port < 0 || server.port > 65535) {
 71                 err = "Invalid port"; goto loaderr;
 72             }
 73         } else if (!strcasecmp(argv[0],"bind") && argc == 2) {
 74             server.bindaddr = zstrdup(argv[1]);
 75         } else if (!strcasecmp(argv[0],"unixsocket") && argc == 2) {
 76             server.unixsocket = zstrdup(argv[1]);
 77         } else if (!strcasecmp(argv[0],"unixsocketperm") && argc == 2) {
 78             errno = 0;
 79             server.unixsocketperm = (mode_t)strtol(argv[1], NULL, 8);
 80             if (errno || server.unixsocketperm > 0777) {
 81                 err = "Invalid socket file permissions"; goto loaderr;
 82             }
 83         } else if (!strcasecmp(argv[0],"save") && argc == 3) {
 84             int seconds = atoi(argv[1]);
 85             int changes = atoi(argv[2]);
 86             if (seconds < 1 || changes < 0) {
 87                 err = "Invalid save parameters"; goto loaderr;
 88             }
 89             appendServerSaveParams(seconds,changes);
 90         } else if (!strcasecmp(argv[0],"dir") && argc == 2) {
 91             if (chdir(argv[1]) == -1) {
 92                 redisLog(REDIS_WARNING,"Can't chdir to '%s': %s",
 93                     argv[1], strerror(errno));
 94                 exit(1);
 95             }
 96         } else if (!strcasecmp(argv[0],"loglevel") && argc == 2) {
 97             if (!strcasecmp(argv[1],"debug")) server.verbosity = REDIS_DEBUG;
 98             else if (!strcasecmp(argv[1],"verbose")) server.verbosity = REDIS_VERBOSE;
 99             else if (!strcasecmp(argv[1],"notice")) server.verbosity = REDIS_NOTICE;
100             else if (!strcasecmp(argv[1],"warning")) server.verbosity = REDIS_WARNING;
101             else {
102                 err = "Invalid log level. Must be one of debug, notice, warning";
103                 goto loaderr;
104             }
105         } else if (!strcasecmp(argv[0],"logfile") && argc == 2) {
106             FILE *logfp;
107 
108             server.logfile = zstrdup(argv[1]);
109             if (!strcasecmp(server.logfile,"stdout")) {
110                 zfree(server.logfile);
111                 server.logfile = NULL;
112             }
113             if (server.logfile) {
114                 /* Test if we are able to open the file. The server will not
115                  * be able to abort just for this problem later... */
116                 logfp = fopen(server.logfile,"a");
117                 if (logfp == NULL) {
118                     err = sdscatprintf(sdsempty(),
119                         "Can't open the log file: %s", strerror(errno));
120                     goto loaderr;
121                 }
122                 fclose(logfp);
123             }
124         } else if (!strcasecmp(argv[0],"syslog-enabled") && argc == 2) {
125             if ((server.syslog_enabled = yesnotoi(argv[1])) == -1) {
126                 err = "argument must be 'yes' or 'no'"; goto loaderr;
127             }
128         } else if (!strcasecmp(argv[0],"syslog-ident") && argc == 2) {
129             if (server.syslog_ident) zfree(server.syslog_ident);
130             server.syslog_ident = zstrdup(argv[1]);
131         } else if (!strcasecmp(argv[0],"syslog-facility") && argc == 2) {
132             struct {
133                 const char     *name;
134                 const int       value;
135             } validSyslogFacilities[] = {
136                 {"user",    LOG_USER},
137                 {"local0",  LOG_LOCAL0},
138                 {"local1",  LOG_LOCAL1},
139                 {"local2",  LOG_LOCAL2},
140                 {"local3",  LOG_LOCAL3},
141                 {"local4",  LOG_LOCAL4},
142                 {"local5",  LOG_LOCAL5},
143                 {"local6",  LOG_LOCAL6},
144                 {"local7",  LOG_LOCAL7},
145                 {NULL, 0}
146             };
147             int i;
148 
149             for (i = 0; validSyslogFacilities[i].name; i++) {
150                 if (!strcasecmp(validSyslogFacilities[i].name, argv[1])) {
151                     server.syslog_facility = validSyslogFacilities[i].value;
152                     break;
153                 }
154             }
155 
156             if (!validSyslogFacilities[i].name) {
157                 err = "Invalid log facility. Must be one of USER or between LOCAL0-LOCAL7";
158                 goto loaderr;
159             }
160         } else if (!strcasecmp(argv[0],"databases") && argc == 2) {
161             server.dbnum = atoi(argv[1]);
162             if (server.dbnum < 1) {
163                 err = "Invalid number of databases"; goto loaderr;
164             }
165         } else if (!strcasecmp(argv[0],"include") && argc == 2) {
166             loadServerConfig(argv[1]);
167         } else if (!strcasecmp(argv[0],"maxclients") && argc == 2) {
168             server.maxclients = atoi(argv[1]);
169         } else if (!strcasecmp(argv[0],"maxmemory") && argc == 2) {
170             server.maxmemory = memtoll(argv[1],NULL);
171         } else if (!strcasecmp(argv[0],"maxmemory-policy") && argc == 2) {
172             if (!strcasecmp(argv[1],"volatile-lru")) {
173                 server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU;
174             } else if (!strcasecmp(argv[1],"volatile-random")) {
175                 server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_RANDOM;
176             } else if (!strcasecmp(argv[1],"volatile-ttl")) {
177                 server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_TTL;
178             } else if (!strcasecmp(argv[1],"allkeys-lru")) {
179                 server.maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_LRU;
180             } else if (!strcasecmp(argv[1],"allkeys-random")) {
181                 server.maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_RANDOM;
182             } else if (!strcasecmp(argv[1],"noeviction")) {
183                 server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;
184             } else {
185                 err = "Invalid maxmemory policy";
186                 goto loaderr;
187             }
188         } else if (!strcasecmp(argv[0],"maxmemory-samples") && argc == 2) {
189             server.maxmemory_samples = atoi(argv[1]);
190             if (server.maxmemory_samples <= 0) {
191                 err = "maxmemory-samples must be 1 or greater";
192                 goto loaderr;
193             }
194         } else if (!strcasecmp(argv[0],"slaveof") && argc == 3) {
195             server.masterhost = sdsnew(argv[1]);
196             server.masterport = atoi(argv[2]);
197             server.replstate = REDIS_REPL_CONNECT;
198         } else if (!strcasecmp(argv[0],"repl-ping-slave-period") && argc == 2) {
199             server.repl_ping_slave_period = atoi(argv[1]);
200             if (server.repl_ping_slave_period <= 0) {
201                 err = "repl-ping-slave-period must be 1 or greater";
202                 goto loaderr;
203             }
204         } else if (!strcasecmp(argv[0],"repl-timeout") && argc == 2) {
205             server.repl_timeout = atoi(argv[1]);
206             if (server.repl_timeout <= 0) {
207                 err = "repl-timeout must be 1 or greater";
208                 goto loaderr;
209             }
210         } else if (!strcasecmp(argv[0],"masterauth") && argc == 2) {
211             server.masterauth = zstrdup(argv[1]);
212         } else if (!strcasecmp(argv[0],"slave-serve-stale-data") && argc == 2) {
213             if ((server.repl_serve_stale_data = yesnotoi(argv[1])) == -1) {
214                 err = "argument must be 'yes' or 'no'"; goto loaderr;
215             }
216         } else if (!strcasecmp(argv[0],"glueoutputbuf")) {
217             redisLog(REDIS_WARNING, "Deprecated configuration directive: \"%s\"", argv[0]);
218         } else if (!strcasecmp(argv[0],"rdbcompression") && argc == 2) {
219             if ((server.rdbcompression = yesnotoi(argv[1])) == -1) {
220                 err = "argument must be 'yes' or 'no'"; goto loaderr;
221             }
222         } else if (!strcasecmp(argv[0],"activerehashing") && argc == 2) {
223             if ((server.activerehashing = yesnotoi(argv[1])) == -1) {
224                 err = "argument must be 'yes' or 'no'"; goto loaderr;
225             }
226         } else if (!strcasecmp(argv[0],"daemonize") && argc == 2) {
227             if ((server.daemonize = yesnotoi(argv[1])) == -1) {
228                 err = "argument must be 'yes' or 'no'"; goto loaderr;
229             }
230         } else if (!strcasecmp(argv[0],"appendonly") && argc == 2) {
231             if ((server.appendonly = yesnotoi(argv[1])) == -1) {
232                 err = "argument must be 'yes' or 'no'"; goto loaderr;
233             }
234         } else if (!strcasecmp(argv[0],"appendfilename") && argc == 2) {
235             zfree(server.appendfilename);
236             server.appendfilename = zstrdup(argv[1]);
237         } else if (!strcasecmp(argv[0],"no-appendfsync-on-rewrite")
238                    && argc == 2) {
239             if ((server.no_appendfsync_on_rewrite= yesnotoi(argv[1])) == -1) {
240                 err = "argument must be 'yes' or 'no'"; goto loaderr;
241             }
242         } else if (!strcasecmp(argv[0],"appendfsync") && argc == 2) {
243             if (!strcasecmp(argv[1],"no")) {
244                 server.appendfsync = APPENDFSYNC_NO;
245             } else if (!strcasecmp(argv[1],"always")) {
246                 server.appendfsync = APPENDFSYNC_ALWAYS;
247             } else if (!strcasecmp(argv[1],"everysec")) {
248                 server.appendfsync = APPENDFSYNC_EVERYSEC;
249             } else {
250                 err = "argument must be 'no', 'always' or 'everysec'";
251                 goto loaderr;
252             }
253         } else if (!strcasecmp(argv[0],"auto-aof-rewrite-percentage") &&
254                    argc == 2)
255         {
256             server.auto_aofrewrite_perc = atoi(argv[1]);
257             if (server.auto_aofrewrite_perc < 0) {
258                 err = "Invalid negative percentage for AOF auto rewrite";
259                 goto loaderr;
260             }
261         } else if (!strcasecmp(argv[0],"auto-aof-rewrite-min-size") &&
262                    argc == 2)
263         {
264             server.auto_aofrewrite_min_size = memtoll(argv[1],NULL);
265         } else if (!strcasecmp(argv[0],"requirepass") && argc == 2) {
266             server.requirepass = zstrdup(argv[1]);
267         } else if (!strcasecmp(argv[0],"pidfile") && argc == 2) {
268             zfree(server.pidfile);
269             server.pidfile = zstrdup(argv[1]);
270         } else if (!strcasecmp(argv[0],"dbfilename") && argc == 2) {
271             zfree(server.dbfilename);
272             server.dbfilename = zstrdup(argv[1]);
273         } else if (!strcasecmp(argv[0],"vm-enabled") && argc == 2) {
274             if ((server.vm_enabled = yesnotoi(argv[1])) == -1) {
275                 err = "argument must be 'yes' or 'no'"; goto loaderr;
276             }
277         } else if (!strcasecmp(argv[0],"really-use-vm") && argc == 2) {
278             if ((really_use_vm = yesnotoi(argv[1])) == -1) {
279                 err = "argument must be 'yes' or 'no'"; goto loaderr;
280             }
281         } else if (!strcasecmp(argv[0],"vm-swap-file") && argc == 2) {
282             zfree(server.vm_swap_file);
283             server.vm_swap_file = zstrdup(argv[1]);
284         } else if (!strcasecmp(argv[0],"vm-max-memory") && argc == 2) {
285             server.vm_max_memory = memtoll(argv[1],NULL);
286         } else if (!strcasecmp(argv[0],"vm-page-size") && argc == 2) {
287             server.vm_page_size = memtoll(argv[1], NULL);
288         } else if (!strcasecmp(argv[0],"vm-pages") && argc == 2) {
289             server.vm_pages = memtoll(argv[1], NULL);
290         } else if (!strcasecmp(argv[0],"vm-max-threads") && argc == 2) {
291             server.vm_max_threads = strtoll(argv[1], NULL, 10);
292         } else if (!strcasecmp(argv[0],"hash-max-zipmap-entries") && argc == 2) {
293             server.hash_max_zipmap_entries = memtoll(argv[1], NULL);
294         } else if (!strcasecmp(argv[0],"hash-max-zipmap-value") && argc == 2) {
295             server.hash_max_zipmap_value = memtoll(argv[1], NULL);
296         } else if (!strcasecmp(argv[0],"list-max-ziplist-entries") && argc == 2){
297             server.list_max_ziplist_entries = memtoll(argv[1], NULL);
298         } else if (!strcasecmp(argv[0],"list-max-ziplist-value") && argc == 2) {
299             server.list_max_ziplist_value = memtoll(argv[1], NULL);
300         } else if (!strcasecmp(argv[0],"set-max-intset-entries") && argc == 2) {
301             server.set_max_intset_entries = memtoll(argv[1], NULL);
302         } else if (!strcasecmp(argv[0],"zset-max-ziplist-entries") && argc == 2) {
303             server.zset_max_ziplist_entries = memtoll(argv[1], NULL);
304         } else if (!strcasecmp(argv[0],"zset-max-ziplist-value") && argc == 2) {
305             server.zset_max_ziplist_value = memtoll(argv[1], NULL);
306         } else if (!strcasecmp(argv[0],"rename-command") && argc == 3) {
307             struct redisCommand *cmd = lookupCommand(argv[1]);
308             int retval;
309 
310             if (!cmd) {
311                 err = "No such command in rename-command";
312                 goto loaderr;
313             }
314 
315             /* If the target command name is the emtpy string we just
316              * remove it from the command table. */
317             retval = dictDelete(server.commands, argv[1]);
318             redisAssert(retval == DICT_OK);
319 
320             /* Otherwise we re-add the command under a different name. */
321             if (sdslen(argv[2]) != 0) {
322                 sds copy = sdsdup(argv[2]);
323 
324                 retval = dictAdd(server.commands, copy, cmd);
325                 if (retval != DICT_OK) {
326                     sdsfree(copy);
327                     err = "Target command name already exists"; goto loaderr;
328                 }
329             }
330         } else if (!strcasecmp(argv[0],"slowlog-log-slower-than") &&
331                    argc == 2)
332         {
333             server.slowlog_log_slower_than = strtoll(argv[1],NULL,10);
334         } else if (!strcasecmp(argv[0],"slowlog-max-len") && argc == 2) {
335             server.slowlog_max_len = strtoll(argv[1],NULL,10);
336         } else {
337             err = "Bad directive or wrong number of arguments"; goto loaderr;
338         }
339         for (j = 0; j < argc; j++)
340             sdsfree(argv[j]);
341         zfree(argv);
342         sdsfree(line);
343     }
344     if (fp != stdin) fclose(fp);
345     if (server.vm_enabled && !really_use_vm) goto vm_warning;
346     return;
347 
348 loaderr:
349     fprintf(stderr, "\n*** FATAL CONFIG FILE ERROR ***\n");
350     fprintf(stderr, "Reading the configuration file, at line %d\n", linenum);
351     fprintf(stderr, ">>> '%s'\n", line);
352     fprintf(stderr, "%s\n", err);
353     exit(1);
354 
355 vm_warning:
356     fprintf(stderr, "\nARE YOU SURE YOU WANT TO USE VM?\n\n");
357     fprintf(stderr, "Redis Virtual Memory is going to be deprecated soon,\n");
358     fprintf(stderr, "we think you should NOT use it, but use Redis only if\n");
359     fprintf(stderr, "your data is suitable for an in-memory database.\n");
360     fprintf(stderr, "If you *really* want VM add this in the config file:\n");
361     fprintf(stderr, "\n    really-use-vm yes\n\n");
362     exit(1);
363 }
364 
365 /*-----------------------------------------------------------------------------
366  * CONFIG command for remote configuration
367  *----------------------------------------------------------------------------*/
368 
369 void configSetCommand(redisClient *c) {
370     robj *o;
371     long long ll;
372     redisAssert(c->argv[2]->encoding == REDIS_ENCODING_RAW);
373     redisAssert(c->argv[3]->encoding == REDIS_ENCODING_RAW);
374     o = c->argv[3];
375 
376     if (!strcasecmp(c->argv[2]->ptr,"dbfilename")) {
377         zfree(server.dbfilename);
378         server.dbfilename = zstrdup(o->ptr);
379     } else if (!strcasecmp(c->argv[2]->ptr,"requirepass")) {
380         zfree(server.requirepass);
381         server.requirepass = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;
382     } else if (!strcasecmp(c->argv[2]->ptr,"masterauth")) {
383         zfree(server.masterauth);
384         server.masterauth = zstrdup(o->ptr);
385     } else if (!strcasecmp(c->argv[2]->ptr,"maxmemory")) {
386         if (getLongLongFromObject(o,&ll) == REDIS_ERR ||
387             ll < 0) goto badfmt;
388         server.maxmemory = ll;
389         if (server.maxmemory) freeMemoryIfNeeded();
390     } else if (!strcasecmp(c->argv[2]->ptr,"maxmemory-policy")) {
391         if (!strcasecmp(o->ptr,"volatile-lru")) {
392             server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU;
393         } else if (!strcasecmp(o->ptr,"volatile-random")) {
394             server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_RANDOM;
395         } else if (!strcasecmp(o->ptr,"volatile-ttl")) {
396             server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_TTL;
397         } else if (!strcasecmp(o->ptr,"allkeys-lru")) {
398             server.maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_LRU;
399         } else if (!strcasecmp(o->ptr,"allkeys-random")) {
400             server.maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_RANDOM;
401         } else if (!strcasecmp(o->ptr,"noeviction")) {
402             server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;
403         } else {
404             goto badfmt;
405         }
406     } else if (!strcasecmp(c->argv[2]->ptr,"maxmemory-samples")) {
407         if (getLongLongFromObject(o,&ll) == REDIS_ERR ||
408             ll <= 0) goto badfmt;
409         server.maxmemory_samples = ll;
410     } else if (!strcasecmp(c->argv[2]->ptr,"timeout")) {
411         if (getLongLongFromObject(o,&ll) == REDIS_ERR ||
412             ll < 0 || ll > LONG_MAX) goto badfmt;
413         server.maxidletime = ll;
414     } else if (!strcasecmp(c->argv[2]->ptr,"appendfsync")) {
415         if (!strcasecmp(o->ptr,"no")) {
416             server.appendfsync = APPENDFSYNC_NO;
417         } else if (!strcasecmp(o->ptr,"everysec")) {
418             server.appendfsync = APPENDFSYNC_EVERYSEC;
419         } else if (!strcasecmp(o->ptr,"always")) {
420             server.appendfsync = APPENDFSYNC_ALWAYS;
421         } else {
422             goto badfmt;
423         }
424     } else if (!strcasecmp(c->argv[2]->ptr,"no-appendfsync-on-rewrite")) {
425         int yn = yesnotoi(o->ptr);
426 
427         if (yn == -1) goto badfmt;
428         server.no_appendfsync_on_rewrite = yn;
429     } else if (!strcasecmp(c->argv[2]->ptr,"appendonly")) {
430         int old = server.appendonly;
431         int new = yesnotoi(o->ptr);
432 
433         if (new == -1) goto badfmt;
434         if (old != new) {
435             if (new == 0) {
436                 stopAppendOnly();
437             } else {
438                 if (startAppendOnly() == REDIS_ERR) {
439                     addReplyError(c,
440                         "Unable to turn on AOF. Check server logs.");
441                     return;
442                 }
443             }
444         }
445     } else if (!strcasecmp(c->argv[2]->ptr,"auto-aof-rewrite-percentage")) {
446         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
447         server.auto_aofrewrite_perc = ll;
448     } else if (!strcasecmp(c->argv[2]->ptr,"auto-aof-rewrite-min-size")) {
449         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
450         server.auto_aofrewrite_min_size = ll;
451     } else if (!strcasecmp(c->argv[2]->ptr,"save")) {
452         int vlen, j;
453         sds *v = sdssplitlen(o->ptr,sdslen(o->ptr)," ",1,&vlen);
454 
455         /* Perform sanity check before setting the new config:
456          * - Even number of args
457          * - Seconds >= 1, changes >= 0 */
458         if (vlen & 1) {
459             sdsfreesplitres(v,vlen);
460             goto badfmt;
461         }
462         for (j = 0; j < vlen; j++) {
463             char *eptr;
464             long val;
465 
466             val = strtoll(v[j], &eptr, 10);
467             if (eptr[0] != '\0' ||
468                 ((j & 1) == 0 && val < 1) ||
469                 ((j & 1) == 1 && val < 0)) {
470                 sdsfreesplitres(v,vlen);
471                 goto badfmt;
472             }
473         }
474         /* Finally set the new config */
475         resetServerSaveParams();
476         for (j = 0; j < vlen; j += 2) {
477             time_t seconds;
478             int changes;
479 
480             seconds = strtoll(v[j],NULL,10);
481             changes = strtoll(v[j+1],NULL,10);
482             appendServerSaveParams(seconds, changes);
483         }
484         sdsfreesplitres(v,vlen);
485     } else if (!strcasecmp(c->argv[2]->ptr,"slave-serve-stale-data")) {
486         int yn = yesnotoi(o->ptr);
487 
488         if (yn == -1) goto badfmt;
489         server.repl_serve_stale_data = yn;
490     } else if (!strcasecmp(c->argv[2]->ptr,"dir")) {
491         if (chdir((char*)o->ptr) == -1) {
492             addReplyErrorFormat(c,"Changing directory: %s", strerror(errno));
493             return;
494         }
495     } else if (!strcasecmp(c->argv[2]->ptr,"hash-max-zipmap-entries")) {
496         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
497         server.hash_max_zipmap_entries = ll;
498     } else if (!strcasecmp(c->argv[2]->ptr,"hash-max-zipmap-value")) {
499         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
500         server.hash_max_zipmap_value = ll;
501     } else if (!strcasecmp(c->argv[2]->ptr,"list-max-ziplist-entries")) {
502         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
503         server.list_max_ziplist_entries = ll;
504     } else if (!strcasecmp(c->argv[2]->ptr,"list-max-ziplist-value")) {
505         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
506         server.list_max_ziplist_value = ll;
507     } else if (!strcasecmp(c->argv[2]->ptr,"set-max-intset-entries")) {
508         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
509         server.set_max_intset_entries = ll;
510     } else if (!strcasecmp(c->argv[2]->ptr,"zset-max-ziplist-entries")) {
511         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
512         server.zset_max_ziplist_entries = ll;
513     } else if (!strcasecmp(c->argv[2]->ptr,"zset-max-ziplist-value")) {
514         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
515         server.zset_max_ziplist_value = ll;
516     } else if (!strcasecmp(c->argv[2]->ptr,"slowlog-log-slower-than")) {
517         if (getLongLongFromObject(o,&ll) == REDIS_ERR) goto badfmt;
518         server.slowlog_log_slower_than = ll;
519     } else if (!strcasecmp(c->argv[2]->ptr,"slowlog-max-len")) {
520         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
521         server.slowlog_max_len = (unsigned)ll;
522     } else if (!strcasecmp(c->argv[2]->ptr,"loglevel")) {
523         if (!strcasecmp(o->ptr,"warning")) {
524             server.verbosity = REDIS_WARNING;
525         } else if (!strcasecmp(o->ptr,"notice")) {
526             server.verbosity = REDIS_NOTICE;
527         } else if (!strcasecmp(o->ptr,"verbose")) {
528             server.verbosity = REDIS_VERBOSE;
529         } else if (!strcasecmp(o->ptr,"debug")) {
530             server.verbosity = REDIS_DEBUG;
531         } else {
532             goto badfmt;
533         }
534     } else {
535         addReplyErrorFormat(c,"Unsupported CONFIG parameter: %s",
536             (char*)c->argv[2]->ptr);
537         return;
538     }
539     addReply(c,shared.ok);
540     return;
541 
542 badfmt: /* Bad format errors */
543     addReplyErrorFormat(c,"Invalid argument '%s' for CONFIG SET '%s'",
544             (char*)o->ptr,
545             (char*)c->argv[2]->ptr);
546 }
547 
548 void configGetCommand(redisClient *c) {
549     robj *o = c->argv[2];
550     void *replylen = addDeferredMultiBulkLength(c);
551     char *pattern = o->ptr;
552     char buf[128];
553     int matches = 0;
554     redisAssert(o->encoding == REDIS_ENCODING_RAW);
555 
556     if (stringmatch(pattern,"dir",0)) {
557         char buf[1024];
558 
559         if (getcwd(buf,sizeof(buf)) == NULL)
560             buf[0] = '\0';
561 
562         addReplyBulkCString(c,"dir");
563         addReplyBulkCString(c,buf);
564         matches++;
565     }
566     if (stringmatch(pattern,"dbfilename",0)) {
567         addReplyBulkCString(c,"dbfilename");
568         addReplyBulkCString(c,server.dbfilename);
569         matches++;
570     }
571     if (stringmatch(pattern,"requirepass",0)) {
572         addReplyBulkCString(c,"requirepass");
573         addReplyBulkCString(c,server.requirepass);
574         matches++;
575     }
576     if (stringmatch(pattern,"masterauth",0)) {
577         addReplyBulkCString(c,"masterauth");
578         addReplyBulkCString(c,server.masterauth);
579         matches++;
580     }
581     if (stringmatch(pattern,"maxmemory",0)) {
582         ll2string(buf,sizeof(buf),server.maxmemory);
583         addReplyBulkCString(c,"maxmemory");
584         addReplyBulkCString(c,buf);
585         matches++;
586     }
587     if (stringmatch(pattern,"maxmemory-policy",0)) {
588         char *s;
589 
590         switch(server.maxmemory_policy) {
591         case REDIS_MAXMEMORY_VOLATILE_LRU: s = "volatile-lru"; break;
592         case REDIS_MAXMEMORY_VOLATILE_TTL: s = "volatile-ttl"; break;
593         case REDIS_MAXMEMORY_VOLATILE_RANDOM: s = "volatile-random"; break;
594         case REDIS_MAXMEMORY_ALLKEYS_LRU: s = "allkeys-lru"; break;
595         case REDIS_MAXMEMORY_ALLKEYS_RANDOM: s = "allkeys-random"; break;
596         case REDIS_MAXMEMORY_NO_EVICTION: s = "noeviction"; break;
597         default: s = "unknown"; break; /* too harmless to panic */
598         }
599         addReplyBulkCString(c,"maxmemory-policy");
600         addReplyBulkCString(c,s);
601         matches++;
602     }
603     if (stringmatch(pattern,"maxmemory-samples",0)) {
604         ll2string(buf,sizeof(buf),server.maxmemory_samples);
605         addReplyBulkCString(c,"maxmemory-samples");
606         addReplyBulkCString(c,buf);
607         matches++;
608     }
609     if (stringmatch(pattern,"timeout",0)) {
610         ll2string(buf,sizeof(buf),server.maxidletime);
611         addReplyBulkCString(c,"timeout");
612         addReplyBulkCString(c,buf);
613         matches++;
614     }
615     if (stringmatch(pattern,"appendonly",0)) {
616         addReplyBulkCString(c,"appendonly");
617         addReplyBulkCString(c,server.appendonly ? "yes" : "no");
618         matches++;
619     }
620     if (stringmatch(pattern,"no-appendfsync-on-rewrite",0)) {
621         addReplyBulkCString(c,"no-appendfsync-on-rewrite");
622         addReplyBulkCString(c,server.no_appendfsync_on_rewrite ? "yes" : "no");
623         matches++;
624     }
625     if (stringmatch(pattern,"appendfsync",0)) {
626         char *policy;
627 
628         switch(server.appendfsync) {
629         case APPENDFSYNC_NO: policy = "no"; break;
630         case APPENDFSYNC_EVERYSEC: policy = "everysec"; break;
631         case APPENDFSYNC_ALWAYS: policy = "always"; break;
632         default: policy = "unknown"; break; /* too harmless to panic */
633         }
634         addReplyBulkCString(c,"appendfsync");
635         addReplyBulkCString(c,policy);
636         matches++;
637     }
638     if (stringmatch(pattern,"save",0)) {
639         sds buf = sdsempty();
640         int j;
641 
642         for (j = 0; j < server.saveparamslen; j++) {
643             buf = sdscatprintf(buf,"%ld %d",
644                     server.saveparams[j].seconds,
645                     server.saveparams[j].changes);
646             if (j != server.saveparamslen-1)
647                 buf = sdscatlen(buf," ",1);
648         }
649         addReplyBulkCString(c,"save");
650         addReplyBulkCString(c,buf);
651         sdsfree(buf);
652         matches++;
653     }
654     if (stringmatch(pattern,"auto-aof-rewrite-percentage",0)) {
655         addReplyBulkCString(c,"auto-aof-rewrite-percentage");
656         addReplyBulkLongLong(c,server.auto_aofrewrite_perc);
657         matches++;
658     }
659     if (stringmatch(pattern,"auto-aof-rewrite-min-size",0)) {
660         addReplyBulkCString(c,"auto-aof-rewrite-min-size");
661         addReplyBulkLongLong(c,server.auto_aofrewrite_min_size);
662         matches++;
663     }
664     if (stringmatch(pattern,"slave-serve-stale-data",0)) {
665         addReplyBulkCString(c,"slave-serve-stale-data");
666         addReplyBulkCString(c,server.repl_serve_stale_data ? "yes" : "no");
667         matches++;
668     }
669     if (stringmatch(pattern,"hash-max-zipmap-entries",0)) {
670         addReplyBulkCString(c,"hash-max-zipmap-entries");
671         addReplyBulkLongLong(c,server.hash_max_zipmap_entries);
672         matches++;
673     }
674     if (stringmatch(pattern,"hash-max-zipmap-value",0)) {
675         addReplyBulkCString(c,"hash-max-zipmap-value");
676         addReplyBulkLongLong(c,server.hash_max_zipmap_value);
677         matches++;
678     }
679     if (stringmatch(pattern,"list-max-ziplist-entries",0)) {
680         addReplyBulkCString(c,"list-max-ziplist-entries");
681         addReplyBulkLongLong(c,server.list_max_ziplist_entries);
682         matches++;
683     }
684     if (stringmatch(pattern,"list-max-ziplist-value",0)) {
685         addReplyBulkCString(c,"list-max-ziplist-value");
686         addReplyBulkLongLong(c,server.list_max_ziplist_value);
687         matches++;
688     }
689     if (stringmatch(pattern,"set-max-intset-entries",0)) {
690         addReplyBulkCString(c,"set-max-intset-entries");
691         addReplyBulkLongLong(c,server.set_max_intset_entries);
692         matches++;
693     }
694     if (stringmatch(pattern,"zset-max-ziplist-entries",0)) {
695         addReplyBulkCString(c,"zset-max-ziplist-entries");
696         addReplyBulkLongLong(c,server.zset_max_ziplist_entries);
697         matches++;
698     }
699     if (stringmatch(pattern,"zset-max-ziplist-value",0)) {
700         addReplyBulkCString(c,"zset-max-ziplist-value");
701         addReplyBulkLongLong(c,server.zset_max_ziplist_value);
702         matches++;
703     }
704     if (stringmatch(pattern,"slowlog-log-slower-than",0)) {
705         addReplyBulkCString(c,"slowlog-log-slower-than");
706         addReplyBulkLongLong(c,server.slowlog_log_slower_than);
707         matches++;
708     }
709     if (stringmatch(pattern,"slowlog-max-len",0)) {
710         addReplyBulkCString(c,"slowlog-max-len");
711         addReplyBulkLongLong(c,server.slowlog_max_len);
712         matches++;
713     }
714     if (stringmatch(pattern,"loglevel",0)) {
715         char *s;
716 
717         switch(server.verbosity) {
718         case REDIS_WARNING: s = "warning"; break;
719         case REDIS_VERBOSE: s = "verbose"; break;
720         case REDIS_NOTICE: s = "notice"; break;
721         case REDIS_DEBUG: s = "debug"; break;
722         default: s = "unknown"; break; /* too harmless to panic */
723         }
724         addReplyBulkCString(c,"loglevel");
725         addReplyBulkCString(c,s);
726         matches++;
727     }
728     setDeferredMultiBulkLength(c,replylen,matches*2);
729 }
730 
731 void configCommand(redisClient *c) {
732     if (!strcasecmp(c->argv[1]->ptr,"set")) {
733         if (c->argc != 4) goto badarity;
734         configSetCommand(c);
735     } else if (!strcasecmp(c->argv[1]->ptr,"get")) {
736         if (c->argc != 3) goto badarity;
737         configGetCommand(c);
738     } else if (!strcasecmp(c->argv[1]->ptr,"resetstat")) {
739         if (c->argc != 2) goto badarity;
740         server.stat_keyspace_hits = 0;
741         server.stat_keyspace_misses = 0;
742         server.stat_numcommands = 0;
743         server.stat_numconnections = 0;
744         server.stat_expiredkeys = 0;
745         addReply(c,shared.ok);
746     } else {
747         addReplyError(c,
748             "CONFIG subcommand must be one of GET, SET, RESETSTAT");
749     }
750     return;
751 
752 badarity:
753     addReplyErrorFormat(c,"Wrong number of arguments for CONFIG %s",
754         (char*) c->argv[1]->ptr);
755 }

 
posted @ 2012-05-13 09:54  刘浩de技术博客  阅读(12098)  评论(0编辑  收藏  举报