2012-11-08 12:25:23 -05:00
/* Configuration file parsing and CONFIG GET/SET commands implementation.
*
* Copyright ( c ) 2009 - 2012 , Salvatore Sanfilippo < antirez at gmail dot com >
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
*
* * Redistributions of source code must retain the above copyright notice ,
* this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
* CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*/
2010-06-21 18:07:48 -04:00
# include "redis.h"
/*-----------------------------------------------------------------------------
* Config file parsing
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int yesnotoi ( char * s ) {
if ( ! strcasecmp ( s , " yes " ) ) return 1 ;
else if ( ! strcasecmp ( s , " no " ) ) return 0 ;
else return - 1 ;
}
void appendServerSaveParams ( time_t seconds , int changes ) {
server . saveparams = zrealloc ( server . saveparams , sizeof ( struct saveparam ) * ( server . saveparamslen + 1 ) ) ;
server . saveparams [ server . saveparamslen ] . seconds = seconds ;
server . saveparams [ server . saveparamslen ] . changes = changes ;
server . saveparamslen + + ;
}
void resetServerSaveParams ( ) {
zfree ( server . saveparams ) ;
server . saveparams = NULL ;
server . saveparamslen = 0 ;
}
2011-12-01 07:44:53 -05:00
void loadServerConfigFromString ( char * config ) {
char * err = NULL ;
int linenum = 0 , totlines , i ;
sds * lines ;
2010-06-21 18:07:48 -04:00
2011-12-01 07:44:53 -05:00
lines = sdssplitlen ( config , strlen ( config ) , " \n " , 1 , & totlines ) ;
2010-06-21 18:07:48 -04:00
2011-12-01 07:44:53 -05:00
for ( i = 0 ; i < totlines ; i + + ) {
2010-06-21 18:07:48 -04:00
sds * argv ;
2011-12-01 07:44:53 -05:00
int argc ;
2010-06-21 18:07:48 -04:00
2011-12-01 07:44:53 -05:00
linenum = i + 1 ;
lines [ i ] = sdstrim ( lines [ i ] , " \t \r \n " ) ;
2010-06-21 18:07:48 -04:00
/* Skip comments and blank lines*/
2011-12-01 07:44:53 -05:00
if ( lines [ i ] [ 0 ] = = ' # ' | | lines [ i ] [ 0 ] = = ' \0 ' ) continue ;
2010-06-21 18:07:48 -04:00
/* Split into arguments */
2011-12-01 07:44:53 -05:00
argv = sdssplitargs ( lines [ i ] , & argc ) ;
2010-06-21 18:07:48 -04:00
sdstolower ( argv [ 0 ] ) ;
/* Execute config directives */
if ( ! strcasecmp ( argv [ 0 ] , " timeout " ) & & argc = = 2 ) {
server . maxidletime = atoi ( argv [ 1 ] ) ;
if ( server . maxidletime < 0 ) {
err = " Invalid timeout value " ; goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " port " ) & & argc = = 2 ) {
server . port = atoi ( argv [ 1 ] ) ;
2011-02-22 05:49:17 -05:00
if ( server . port < 0 | | server . port > 65535 ) {
2010-06-21 18:07:48 -04:00
err = " Invalid port " ; goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " bind " ) & & argc = = 2 ) {
server . bindaddr = zstrdup ( argv [ 1 ] ) ;
2010-10-13 11:17:56 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " unixsocket " ) & & argc = = 2 ) {
server . unixsocket = zstrdup ( argv [ 1 ] ) ;
2011-10-10 14:21:15 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " unixsocketperm " ) & & argc = = 2 ) {
2011-10-20 21:20:58 -04:00
errno = 0 ;
2011-10-10 14:21:15 -04:00
server . unixsocketperm = ( mode_t ) strtol ( argv [ 1 ] , NULL , 8 ) ;
if ( errno | | server . unixsocketperm > 0777 ) {
err = " Invalid socket file permissions " ; goto loaderr ;
}
2012-01-16 10:50:24 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " save " ) ) {
if ( argc = = 3 ) {
int seconds = atoi ( argv [ 1 ] ) ;
int changes = atoi ( argv [ 2 ] ) ;
if ( seconds < 1 | | changes < 0 ) {
err = " Invalid save parameters " ; goto loaderr ;
}
appendServerSaveParams ( seconds , changes ) ;
} else if ( argc = = 2 & & ! strcasecmp ( argv [ 1 ] , " " ) ) {
resetServerSaveParams ( ) ;
2010-06-21 18:07:48 -04:00
}
} else if ( ! strcasecmp ( argv [ 0 ] , " dir " ) & & argc = = 2 ) {
if ( chdir ( argv [ 1 ] ) = = - 1 ) {
redisLog ( REDIS_WARNING , " Can't chdir to '%s': %s " ,
argv [ 1 ] , strerror ( errno ) ) ;
exit ( 1 ) ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " loglevel " ) & & argc = = 2 ) {
if ( ! strcasecmp ( argv [ 1 ] , " debug " ) ) server . verbosity = REDIS_DEBUG ;
else if ( ! strcasecmp ( argv [ 1 ] , " verbose " ) ) server . verbosity = REDIS_VERBOSE ;
else if ( ! strcasecmp ( argv [ 1 ] , " notice " ) ) server . verbosity = REDIS_NOTICE ;
else if ( ! strcasecmp ( argv [ 1 ] , " warning " ) ) server . verbosity = REDIS_WARNING ;
else {
err = " Invalid log level. Must be one of debug, notice, warning " ;
goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " logfile " ) & & argc = = 2 ) {
FILE * logfp ;
server . logfile = zstrdup ( argv [ 1 ] ) ;
if ( ! strcasecmp ( server . logfile , " stdout " ) ) {
zfree ( server . logfile ) ;
server . logfile = NULL ;
}
if ( server . logfile ) {
/* Test if we are able to open the file. The server will not
* be able to abort just for this problem later . . . */
logfp = fopen ( server . logfile , " a " ) ;
if ( logfp = = NULL ) {
err = sdscatprintf ( sdsempty ( ) ,
" Can't open the log file: %s " , strerror ( errno ) ) ;
goto loaderr ;
}
fclose ( logfp ) ;
}
2010-12-09 11:10:21 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " syslog-enabled " ) & & argc = = 2 ) {
if ( ( server . syslog_enabled = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " syslog-ident " ) & & argc = = 2 ) {
if ( server . syslog_ident ) zfree ( server . syslog_ident ) ;
server . syslog_ident = zstrdup ( argv [ 1 ] ) ;
} else if ( ! strcasecmp ( argv [ 0 ] , " syslog-facility " ) & & argc = = 2 ) {
struct {
const char * name ;
const int value ;
} validSyslogFacilities [ ] = {
{ " user " , LOG_USER } ,
{ " local0 " , LOG_LOCAL0 } ,
{ " local1 " , LOG_LOCAL1 } ,
{ " local2 " , LOG_LOCAL2 } ,
{ " local3 " , LOG_LOCAL3 } ,
{ " local4 " , LOG_LOCAL4 } ,
{ " local5 " , LOG_LOCAL5 } ,
{ " local6 " , LOG_LOCAL6 } ,
{ " local7 " , LOG_LOCAL7 } ,
{ NULL , 0 }
} ;
int i ;
for ( i = 0 ; validSyslogFacilities [ i ] . name ; i + + ) {
if ( ! strcasecmp ( validSyslogFacilities [ i ] . name , argv [ 1 ] ) ) {
server . syslog_facility = validSyslogFacilities [ i ] . value ;
break ;
}
}
if ( ! validSyslogFacilities [ i ] . name ) {
err = " Invalid log facility. Must be one of USER or between LOCAL0-LOCAL7 " ;
goto loaderr ;
}
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " databases " ) & & argc = = 2 ) {
server . dbnum = atoi ( argv [ 1 ] ) ;
if ( server . dbnum < 1 ) {
err = " Invalid number of databases " ; goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " include " ) & & argc = = 2 ) {
2011-12-01 07:44:53 -05:00
loadServerConfig ( argv [ 1 ] , NULL ) ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " maxclients " ) & & argc = = 2 ) {
server . maxclients = atoi ( argv [ 1 ] ) ;
2012-04-18 05:31:24 -04:00
if ( server . maxclients < 1 ) {
err = " Invalid max clients limit " ; goto loaderr ;
}
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " maxmemory " ) & & argc = = 2 ) {
server . maxmemory = memtoll ( argv [ 1 ] , NULL ) ;
2010-10-14 15:22:21 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " maxmemory-policy " ) & & argc = = 2 ) {
if ( ! strcasecmp ( argv [ 1 ] , " volatile-lru " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU ;
} else if ( ! strcasecmp ( argv [ 1 ] , " volatile-random " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_RANDOM ;
} else if ( ! strcasecmp ( argv [ 1 ] , " volatile-ttl " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_TTL ;
} else if ( ! strcasecmp ( argv [ 1 ] , " allkeys-lru " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_LRU ;
} else if ( ! strcasecmp ( argv [ 1 ] , " allkeys-random " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_RANDOM ;
2010-11-08 10:12:16 -05:00
} else if ( ! strcasecmp ( argv [ 1 ] , " noeviction " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION ;
2010-10-14 15:22:21 -04:00
} else {
err = " Invalid maxmemory policy " ;
goto loaderr ;
}
2010-10-15 05:57:38 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " maxmemory-samples " ) & & argc = = 2 ) {
server . maxmemory_samples = atoi ( argv [ 1 ] ) ;
if ( server . maxmemory_samples < = 0 ) {
err = " maxmemory-samples must be 1 or greater " ;
goto loaderr ;
}
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " slaveof " ) & & argc = = 3 ) {
server . masterhost = sdsnew ( argv [ 1 ] ) ;
server . masterport = atoi ( argv [ 2 ] ) ;
2011-12-21 06:23:18 -05:00
server . repl_state = REDIS_REPL_CONNECT ;
2011-10-31 06:13:28 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " repl-ping-slave-period " ) & & argc = = 2 ) {
server . repl_ping_slave_period = atoi ( argv [ 1 ] ) ;
if ( server . repl_ping_slave_period < = 0 ) {
err = " repl-ping-slave-period must be 1 or greater " ;
goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " repl-timeout " ) & & argc = = 2 ) {
server . repl_timeout = atoi ( argv [ 1 ] ) ;
if ( server . repl_timeout < = 0 ) {
err = " repl-timeout must be 1 or greater " ;
goto loaderr ;
}
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " masterauth " ) & & argc = = 2 ) {
server . masterauth = zstrdup ( argv [ 1 ] ) ;
2010-11-04 14:59:21 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " slave-serve-stale-data " ) & & argc = = 2 ) {
if ( ( server . repl_serve_stale_data = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
2012-03-20 12:32:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " slave-read-only " ) & & argc = = 2 ) {
if ( ( server . repl_slave_ro = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " rdbcompression " ) & & argc = = 2 ) {
2011-12-21 06:22:13 -05:00
if ( ( server . rdb_compression = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
2010-06-21 18:07:48 -04:00
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
2012-04-10 09:47:10 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " rdbchecksum " ) & & argc = = 2 ) {
if ( ( server . rdb_checksum = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " activerehashing " ) & & argc = = 2 ) {
if ( ( server . activerehashing = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " daemonize " ) & & argc = = 2 ) {
if ( ( server . daemonize = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
2012-12-14 11:10:40 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " hz " ) & & argc = = 2 ) {
server . hz = atoi ( argv [ 1 ] ) ;
if ( server . hz < REDIS_MIN_HZ ) server . hz = REDIS_MIN_HZ ;
if ( server . hz > REDIS_MAX_HZ ) server . hz = REDIS_MAX_HZ ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " appendonly " ) & & argc = = 2 ) {
2011-12-21 04:31:34 -05:00
int yes ;
if ( ( yes = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
2010-06-21 18:07:48 -04:00
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
2011-12-21 04:31:34 -05:00
server . aof_state = yes ? REDIS_AOF_ON : REDIS_AOF_OFF ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " appendfilename " ) & & argc = = 2 ) {
2011-12-21 05:58:42 -05:00
zfree ( server . aof_filename ) ;
server . aof_filename = zstrdup ( argv [ 1 ] ) ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " no-appendfsync-on-rewrite " )
& & argc = = 2 ) {
2011-12-21 05:58:42 -05:00
if ( ( server . aof_no_fsync_on_rewrite = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
2010-06-21 18:07:48 -04:00
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " appendfsync " ) & & argc = = 2 ) {
if ( ! strcasecmp ( argv [ 1 ] , " no " ) ) {
2011-12-21 05:58:42 -05:00
server . aof_fsync = AOF_FSYNC_NO ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 1 ] , " always " ) ) {
2011-12-21 05:58:42 -05:00
server . aof_fsync = AOF_FSYNC_ALWAYS ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 1 ] , " everysec " ) ) {
2011-12-21 05:58:42 -05:00
server . aof_fsync = AOF_FSYNC_EVERYSEC ;
2010-06-21 18:07:48 -04:00
} else {
err = " argument must be 'no', 'always' or 'everysec' " ;
goto loaderr ;
}
2011-06-10 06:39:23 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " auto-aof-rewrite-percentage " ) & &
argc = = 2 )
{
2011-12-21 05:58:42 -05:00
server . aof_rewrite_perc = atoi ( argv [ 1 ] ) ;
if ( server . aof_rewrite_perc < 0 ) {
2011-06-10 06:39:23 -04:00
err = " Invalid negative percentage for AOF auto rewrite " ;
goto loaderr ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " auto-aof-rewrite-min-size " ) & &
argc = = 2 )
{
2011-12-21 05:58:42 -05:00
server . aof_rewrite_min_size = memtoll ( argv [ 1 ] , NULL ) ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " requirepass " ) & & argc = = 2 ) {
2012-06-21 05:50:01 -04:00
if ( strlen ( argv [ 1 ] ) > REDIS_AUTHPASS_MAX_LEN ) {
err = " Password is longer than REDIS_AUTHPASS_MAX_LEN " ;
goto loaderr ;
}
2010-06-21 18:07:48 -04:00
server . requirepass = zstrdup ( argv [ 1 ] ) ;
} else if ( ! strcasecmp ( argv [ 0 ] , " pidfile " ) & & argc = = 2 ) {
zfree ( server . pidfile ) ;
server . pidfile = zstrdup ( argv [ 1 ] ) ;
} else if ( ! strcasecmp ( argv [ 0 ] , " dbfilename " ) & & argc = = 2 ) {
2011-12-21 06:22:13 -05:00
zfree ( server . rdb_filename ) ;
server . rdb_filename = zstrdup ( argv [ 1 ] ) ;
2012-01-03 01:14:10 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " hash-max-ziplist-entries " ) & & argc = = 2 ) {
server . hash_max_ziplist_entries = memtoll ( argv [ 1 ] , NULL ) ;
} else if ( ! strcasecmp ( argv [ 0 ] , " hash-max-ziplist-value " ) & & argc = = 2 ) {
server . hash_max_ziplist_value = memtoll ( argv [ 1 ] , NULL ) ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " list-max-ziplist-entries " ) & & argc = = 2 ) {
server . list_max_ziplist_entries = memtoll ( argv [ 1 ] , NULL ) ;
2010-11-03 07:14:36 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " list-max-ziplist-value " ) & & argc = = 2 ) {
2010-06-21 18:07:48 -04:00
server . list_max_ziplist_value = memtoll ( argv [ 1 ] , NULL ) ;
2010-11-03 07:14:36 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " set-max-intset-entries " ) & & argc = = 2 ) {
2010-07-02 13:57:12 -04:00
server . set_max_intset_entries = memtoll ( argv [ 1 ] , NULL ) ;
2011-03-09 08:01:57 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " zset-max-ziplist-entries " ) & & argc = = 2 ) {
server . zset_max_ziplist_entries = memtoll ( argv [ 1 ] , NULL ) ;
} else if ( ! strcasecmp ( argv [ 0 ] , " zset-max-ziplist-value " ) & & argc = = 2 ) {
server . zset_max_ziplist_value = memtoll ( argv [ 1 ] , NULL ) ;
2010-11-03 07:14:36 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " rename-command " ) & & argc = = 3 ) {
struct redisCommand * cmd = lookupCommand ( argv [ 1 ] ) ;
int retval ;
if ( ! cmd ) {
err = " No such command in rename-command " ;
goto loaderr ;
}
2013-01-16 12:00:20 -05:00
/* If the target command name is the empty string we just
2010-11-03 07:14:36 -04:00
* remove it from the command table . */
retval = dictDelete ( server . commands , argv [ 1 ] ) ;
redisAssert ( retval = = DICT_OK ) ;
/* Otherwise we re-add the command under a different name. */
if ( sdslen ( argv [ 2 ] ) ! = 0 ) {
sds copy = sdsdup ( argv [ 2 ] ) ;
retval = dictAdd ( server . commands , copy , cmd ) ;
if ( retval ! = DICT_OK ) {
sdsfree ( copy ) ;
err = " Target command name already exists " ; goto loaderr ;
}
}
2011-03-29 11:51:15 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " cluster-enabled " ) & & argc = = 2 ) {
if ( ( server . cluster_enabled = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
2011-04-07 15:34:41 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " cluster-config-file " ) & & argc = = 2 ) {
zfree ( server . cluster . configfile ) ;
server . cluster . configfile = zstrdup ( argv [ 1 ] ) ;
2011-05-06 11:21:27 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " lua-time-limit " ) & & argc = = 2 ) {
server . lua_time_limit = strtoll ( argv [ 1 ] , NULL , 10 ) ;
2011-06-30 09:47:15 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " slowlog-log-slower-than " ) & &
argc = = 2 )
{
server . slowlog_log_slower_than = strtoll ( argv [ 1 ] , NULL , 10 ) ;
} else if ( ! strcasecmp ( argv [ 0 ] , " slowlog-max-len " ) & & argc = = 2 ) {
server . slowlog_max_len = strtoll ( argv [ 1 ] , NULL , 10 ) ;
2012-01-24 04:43:30 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " client-output-buffer-limit " ) & &
argc = = 5 )
{
int class = getClientLimitClassByName ( argv [ 1 ] ) ;
unsigned long long hard , soft ;
int soft_seconds ;
if ( class = = - 1 ) {
err = " Unrecognized client limit class " ;
goto loaderr ;
}
hard = memtoll ( argv [ 2 ] , NULL ) ;
soft = memtoll ( argv [ 3 ] , NULL ) ;
soft_seconds = atoi ( argv [ 4 ] ) ;
if ( soft_seconds < 0 ) {
2013-01-16 12:00:20 -05:00
err = " Negative number of seconds in soft limit is invalid " ;
2012-01-24 04:43:30 -05:00
goto loaderr ;
}
server . client_obuf_limits [ class ] . hard_limit_bytes = hard ;
server . client_obuf_limits [ class ] . soft_limit_bytes = soft ;
server . client_obuf_limits [ class ] . soft_limit_seconds = soft_seconds ;
2012-03-07 12:02:26 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " stop-writes-on-bgsave-error " ) & &
argc = = 2 ) {
if ( ( server . stop_writes_on_bgsave_err = yesnotoi ( argv [ 1 ] ) ) = = - 1 ) {
err = " argument must be 'yes' or 'no' " ; goto loaderr ;
}
2012-08-28 11:20:26 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " slave-priority " ) & & argc = = 2 ) {
server . slave_priority = atoi ( argv [ 1 ] ) ;
2013-01-23 10:23:33 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " notify-keyspace-events " ) & & argc = = 2 ) {
2013-01-25 07:19:08 -05:00
int flags = keyspaceEventsStringToFlags ( argv [ 1 ] ) ;
if ( flags = = - 1 ) {
err = " Invalid event class character. Use 'g$lshzxeA'. " ;
goto loaderr ;
2013-01-23 10:23:33 -05:00
}
2013-01-25 07:19:08 -05:00
server . notify_keyspace_events = flags ;
2012-07-23 06:54:52 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " sentinel " ) ) {
/* argc == 1 is handled by main() as we need to enter the sentinel
* mode ASAP . */
if ( argc ! = 1 ) {
if ( ! server . sentinel_mode ) {
err = " sentinel directive while not in sentinel mode " ;
goto loaderr ;
}
err = sentinelHandleConfiguration ( argv + 1 , argc - 1 ) ;
if ( err ) goto loaderr ;
}
2010-06-21 18:07:48 -04:00
} else {
err = " Bad directive or wrong number of arguments " ; goto loaderr ;
}
2011-12-01 07:44:53 -05:00
sdsfreesplitres ( argv , argc ) ;
2010-06-21 18:07:48 -04:00
}
2011-12-01 07:44:53 -05:00
sdsfreesplitres ( lines , totlines ) ;
2010-06-21 18:07:48 -04:00
return ;
loaderr :
fprintf ( stderr , " \n *** FATAL CONFIG FILE ERROR *** \n " ) ;
fprintf ( stderr , " Reading the configuration file, at line %d \n " , linenum ) ;
2011-12-01 07:44:53 -05:00
fprintf ( stderr , " >>> '%s' \n " , lines [ i ] ) ;
2010-06-21 18:07:48 -04:00
fprintf ( stderr , " %s \n " , err ) ;
exit ( 1 ) ;
}
2011-12-01 07:44:53 -05:00
/* Load the server configuration from the specified filename.
* The function appends the additional configuration directives stored
* in the ' options ' string to the config file before loading .
*
* Both filename and options can be NULL , in such a case are considered
2013-01-16 12:00:20 -05:00
* empty . This way loadServerConfig can be used to just load a file or
2011-12-01 07:44:53 -05:00
* just load a string . */
void loadServerConfig ( char * filename , char * options ) {
sds config = sdsempty ( ) ;
char buf [ REDIS_CONFIGLINE_MAX + 1 ] ;
/* Load the file content */
if ( filename ) {
FILE * fp ;
if ( filename [ 0 ] = = ' - ' & & filename [ 1 ] = = ' \0 ' ) {
fp = stdin ;
} else {
if ( ( fp = fopen ( filename , " r " ) ) = = NULL ) {
redisLog ( REDIS_WARNING ,
" Fatal error, can't open config file '%s' " , filename ) ;
exit ( 1 ) ;
}
}
while ( fgets ( buf , REDIS_CONFIGLINE_MAX + 1 , fp ) ! = NULL )
config = sdscat ( config , buf ) ;
if ( fp ! = stdin ) fclose ( fp ) ;
}
/* Append the additional options */
if ( options ) {
config = sdscat ( config , " \n " ) ;
config = sdscat ( config , options ) ;
}
loadServerConfigFromString ( config ) ;
sdsfree ( config ) ;
}
2010-06-21 18:07:48 -04:00
/*-----------------------------------------------------------------------------
* CONFIG command for remote configuration
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void configSetCommand ( redisClient * c ) {
2010-10-17 12:09:23 -04:00
robj * o ;
2010-06-21 18:07:48 -04:00
long long ll ;
2011-10-04 12:43:03 -04:00
redisAssertWithInfo ( c , c - > argv [ 2 ] , c - > argv [ 2 ] - > encoding = = REDIS_ENCODING_RAW ) ;
redisAssertWithInfo ( c , c - > argv [ 2 ] , c - > argv [ 3 ] - > encoding = = REDIS_ENCODING_RAW ) ;
2010-10-17 12:09:23 -04:00
o = c - > argv [ 3 ] ;
2010-06-21 18:07:48 -04:00
if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " dbfilename " ) ) {
2011-12-21 06:22:13 -05:00
zfree ( server . rdb_filename ) ;
server . rdb_filename = zstrdup ( o - > ptr ) ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " requirepass " ) ) {
2012-06-21 05:50:01 -04:00
if ( sdslen ( o - > ptr ) > REDIS_AUTHPASS_MAX_LEN ) goto badfmt ;
2010-06-21 18:07:48 -04:00
zfree ( server . requirepass ) ;
2011-10-31 04:57:06 -04:00
server . requirepass = ( ( char * ) o - > ptr ) [ 0 ] ? zstrdup ( o - > ptr ) : NULL ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " masterauth " ) ) {
zfree ( server . masterauth ) ;
server . masterauth = zstrdup ( o - > ptr ) ;
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " maxmemory " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | |
ll < 0 ) goto badfmt ;
server . maxmemory = ll ;
2012-10-05 04:48:49 -04:00
if ( server . maxmemory ) {
if ( server . maxmemory < zmalloc_used_memory ( ) ) {
redisLog ( REDIS_WARNING , " WARNING: the new maxmemory value set via CONFIG SET is smaller than the current memory usage. This will result in keys eviction and/or inability to accept new write commands depending on the maxmemory-policy. " ) ;
}
freeMemoryIfNeeded ( ) ;
}
2012-12-14 11:10:40 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " hz " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | |
ll < 0 ) goto badfmt ;
server . hz = ( int ) ll ;
if ( server . hz < REDIS_MIN_HZ ) server . hz = REDIS_MIN_HZ ;
if ( server . hz > REDIS_MAX_HZ ) server . hz = REDIS_MAX_HZ ;
2010-10-14 15:22:21 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " maxmemory-policy " ) ) {
if ( ! strcasecmp ( o - > ptr , " volatile-lru " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU ;
} else if ( ! strcasecmp ( o - > ptr , " volatile-random " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_RANDOM ;
} else if ( ! strcasecmp ( o - > ptr , " volatile-ttl " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_TTL ;
} else if ( ! strcasecmp ( o - > ptr , " allkeys-lru " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_LRU ;
} else if ( ! strcasecmp ( o - > ptr , " allkeys-random " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_RANDOM ;
2010-11-08 10:12:16 -05:00
} else if ( ! strcasecmp ( o - > ptr , " noeviction " ) ) {
server . maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION ;
2010-10-14 15:22:21 -04:00
} else {
goto badfmt ;
}
2010-10-15 05:57:38 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " maxmemory-samples " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | |
ll < = 0 ) goto badfmt ;
server . maxmemory_samples = ll ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " timeout " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | |
ll < 0 | | ll > LONG_MAX ) goto badfmt ;
server . maxidletime = ll ;
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " appendfsync " ) ) {
if ( ! strcasecmp ( o - > ptr , " no " ) ) {
2011-12-21 05:58:42 -05:00
server . aof_fsync = AOF_FSYNC_NO ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( o - > ptr , " everysec " ) ) {
2011-12-21 05:58:42 -05:00
server . aof_fsync = AOF_FSYNC_EVERYSEC ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( o - > ptr , " always " ) ) {
2011-12-21 05:58:42 -05:00
server . aof_fsync = AOF_FSYNC_ALWAYS ;
2010-06-21 18:07:48 -04:00
} else {
goto badfmt ;
}
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " no-appendfsync-on-rewrite " ) ) {
int yn = yesnotoi ( o - > ptr ) ;
if ( yn = = - 1 ) goto badfmt ;
2011-12-21 05:58:42 -05:00
server . aof_no_fsync_on_rewrite = yn ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " appendonly " ) ) {
2011-12-21 04:31:34 -05:00
int enable = yesnotoi ( o - > ptr ) ;
if ( enable = = - 1 ) goto badfmt ;
if ( enable = = 0 & & server . aof_state ! = REDIS_AOF_OFF ) {
stopAppendOnly ( ) ;
} else if ( enable & & server . aof_state = = REDIS_AOF_OFF ) {
if ( startAppendOnly ( ) = = REDIS_ERR ) {
addReplyError ( c ,
" Unable to turn on AOF. Check server logs. " ) ;
return ;
2010-06-21 18:07:48 -04:00
}
}
2011-06-10 09:14:10 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " auto-aof-rewrite-percentage " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
2011-12-21 05:58:42 -05:00
server . aof_rewrite_perc = ll ;
2011-06-10 09:14:10 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " auto-aof-rewrite-min-size " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
2011-12-21 05:58:42 -05:00
server . aof_rewrite_min_size = ll ;
2010-06-21 18:07:48 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " save " ) ) {
int vlen , j ;
sds * v = sdssplitlen ( o - > ptr , sdslen ( o - > ptr ) , " " , 1 , & vlen ) ;
/* Perform sanity check before setting the new config:
* - Even number of args
* - Seconds > = 1 , changes > = 0 */
if ( vlen & 1 ) {
sdsfreesplitres ( v , vlen ) ;
goto badfmt ;
}
for ( j = 0 ; j < vlen ; j + + ) {
char * eptr ;
long val ;
val = strtoll ( v [ j ] , & eptr , 10 ) ;
if ( eptr [ 0 ] ! = ' \0 ' | |
( ( j & 1 ) = = 0 & & val < 1 ) | |
( ( j & 1 ) = = 1 & & val < 0 ) ) {
sdsfreesplitres ( v , vlen ) ;
goto badfmt ;
}
}
/* Finally set the new config */
resetServerSaveParams ( ) ;
for ( j = 0 ; j < vlen ; j + = 2 ) {
time_t seconds ;
int changes ;
seconds = strtoll ( v [ j ] , NULL , 10 ) ;
changes = strtoll ( v [ j + 1 ] , NULL , 10 ) ;
appendServerSaveParams ( seconds , changes ) ;
}
sdsfreesplitres ( v , vlen ) ;
2010-11-04 14:59:21 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " slave-serve-stale-data " ) ) {
int yn = yesnotoi ( o - > ptr ) ;
if ( yn = = - 1 ) goto badfmt ;
server . repl_serve_stale_data = yn ;
2012-03-20 12:32:48 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " slave-read-only " ) ) {
int yn = yesnotoi ( o - > ptr ) ;
if ( yn = = - 1 ) goto badfmt ;
server . repl_slave_ro = yn ;
2011-02-13 20:51:27 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " dir " ) ) {
if ( chdir ( ( char * ) o - > ptr ) = = - 1 ) {
addReplyErrorFormat ( c , " Changing directory: %s " , strerror ( errno ) ) ;
return ;
}
2012-01-03 01:14:10 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " hash-max-ziplist-entries " ) ) {
2011-02-17 06:20:59 -05:00
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
2012-01-03 01:14:10 -05:00
server . hash_max_ziplist_entries = ll ;
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " hash-max-ziplist-value " ) ) {
2011-02-17 06:20:59 -05:00
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
2012-01-03 01:14:10 -05:00
server . hash_max_ziplist_value = ll ;
2011-02-17 06:20:59 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " list-max-ziplist-entries " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
server . list_max_ziplist_entries = ll ;
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " list-max-ziplist-value " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
server . list_max_ziplist_value = ll ;
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " set-max-intset-entries " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
server . set_max_intset_entries = ll ;
2011-03-09 08:01:57 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " zset-max-ziplist-entries " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
server . zset_max_ziplist_entries = ll ;
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " zset-max-ziplist-value " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
server . zset_max_ziplist_value = ll ;
2011-05-06 11:21:27 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " lua-time-limit " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
server . lua_time_limit = ll ;
2011-06-30 09:47:15 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " slowlog-log-slower-than " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR ) goto badfmt ;
server . slowlog_log_slower_than = ll ;
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " slowlog-max-len " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
server . slowlog_max_len = ( unsigned ) ll ;
2011-10-05 10:08:35 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " loglevel " ) ) {
if ( ! strcasecmp ( o - > ptr , " warning " ) ) {
server . verbosity = REDIS_WARNING ;
} else if ( ! strcasecmp ( o - > ptr , " notice " ) ) {
server . verbosity = REDIS_NOTICE ;
} else if ( ! strcasecmp ( o - > ptr , " verbose " ) ) {
server . verbosity = REDIS_VERBOSE ;
} else if ( ! strcasecmp ( o - > ptr , " debug " ) ) {
server . verbosity = REDIS_DEBUG ;
} else {
goto badfmt ;
}
2012-01-24 04:43:30 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " client-output-buffer-limit " ) ) {
int vlen , j ;
sds * v = sdssplitlen ( o - > ptr , sdslen ( o - > ptr ) , " " , 1 , & vlen ) ;
/* We need a multiple of 4: <class> <hard> <soft> <soft_seconds> */
if ( vlen % 4 ) {
sdsfreesplitres ( v , vlen ) ;
goto badfmt ;
}
/* Sanity check of single arguments, so that we either refuse the
* whole configuration string or accept it all , even if a single
* error in a single client class is present . */
for ( j = 0 ; j < vlen ; j + + ) {
char * eptr ;
long val ;
if ( ( j % 4 ) = = 0 ) {
if ( getClientLimitClassByName ( v [ j ] ) = = - 1 ) {
sdsfreesplitres ( v , vlen ) ;
goto badfmt ;
}
} else {
val = strtoll ( v [ j ] , & eptr , 10 ) ;
if ( eptr [ 0 ] ! = ' \0 ' | | val < 0 ) {
sdsfreesplitres ( v , vlen ) ;
goto badfmt ;
}
}
}
/* Finally set the new config */
for ( j = 0 ; j < vlen ; j + = 4 ) {
int class ;
unsigned long long hard , soft ;
int soft_seconds ;
class = getClientLimitClassByName ( v [ j ] ) ;
hard = strtoll ( v [ j + 1 ] , NULL , 10 ) ;
soft = strtoll ( v [ j + 2 ] , NULL , 10 ) ;
soft_seconds = strtoll ( v [ j + 3 ] , NULL , 10 ) ;
server . client_obuf_limits [ class ] . hard_limit_bytes = hard ;
server . client_obuf_limits [ class ] . soft_limit_bytes = soft ;
server . client_obuf_limits [ class ] . soft_limit_seconds = soft_seconds ;
}
sdsfreesplitres ( v , vlen ) ;
2012-03-07 12:02:26 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " stop-writes-on-bgsave-error " ) ) {
int yn = yesnotoi ( o - > ptr ) ;
2012-01-24 04:43:30 -05:00
2012-03-07 12:02:26 -05:00
if ( yn = = - 1 ) goto badfmt ;
server . stop_writes_on_bgsave_err = yn ;
2012-03-08 06:14:23 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " repl-ping-slave-period " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < = 0 ) goto badfmt ;
server . repl_ping_slave_period = ll ;
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " repl-timeout " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < = 0 ) goto badfmt ;
server . repl_timeout = ll ;
2012-03-27 05:47:51 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " watchdog-period " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | | ll < 0 ) goto badfmt ;
if ( ll )
enableWatchdog ( ll ) ;
else
disableWatchdog ( ) ;
2012-04-10 09:47:10 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " rdbcompression " ) ) {
int yn = yesnotoi ( o - > ptr ) ;
if ( yn = = - 1 ) goto badfmt ;
server . rdb_compression = yn ;
2013-01-23 10:23:33 -05:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " notify-keyspace-events " ) ) {
2013-01-25 07:19:08 -05:00
int flags = keyspaceEventsStringToFlags ( o - > ptr ) ;
2012-04-10 09:47:10 -04:00
2013-01-25 07:19:08 -05:00
if ( flags = = - 1 ) goto badfmt ;
server . notify_keyspace_events = flags ;
2012-08-28 11:20:26 -04:00
} else if ( ! strcasecmp ( c - > argv [ 2 ] - > ptr , " slave-priority " ) ) {
if ( getLongLongFromObject ( o , & ll ) = = REDIS_ERR | |
ll < = 0 ) goto badfmt ;
server . slave_priority = ll ;
2010-06-21 18:07:48 -04:00
} else {
2010-09-02 13:52:24 -04:00
addReplyErrorFormat ( c , " Unsupported CONFIG parameter: %s " ,
( char * ) c - > argv [ 2 ] - > ptr ) ;
2010-06-21 18:07:48 -04:00
return ;
}
addReply ( c , shared . ok ) ;
return ;
badfmt : /* Bad format errors */
2010-09-02 13:52:24 -04:00
addReplyErrorFormat ( c , " Invalid argument '%s' for CONFIG SET '%s' " ,
2010-06-21 18:07:48 -04:00
( char * ) o - > ptr ,
2010-09-02 13:52:24 -04:00
( char * ) c - > argv [ 2 ] - > ptr ) ;
2010-06-21 18:07:48 -04:00
}
2012-03-08 06:14:23 -05:00
# define config_get_string_field(_name,_var) do { \
if ( stringmatch ( pattern , _name , 0 ) ) { \
addReplyBulkCString ( c , _name ) ; \
addReplyBulkCString ( c , _var ? _var : " " ) ; \
matches + + ; \
} \
} while ( 0 ) ;
# define config_get_bool_field(_name,_var) do { \
if ( stringmatch ( pattern , _name , 0 ) ) { \
addReplyBulkCString ( c , _name ) ; \
addReplyBulkCString ( c , _var ? " yes " : " no " ) ; \
matches + + ; \
} \
} while ( 0 ) ;
# define config_get_numerical_field(_name,_var) do { \
if ( stringmatch ( pattern , _name , 0 ) ) { \
ll2string ( buf , sizeof ( buf ) , _var ) ; \
addReplyBulkCString ( c , _name ) ; \
addReplyBulkCString ( c , buf ) ; \
matches + + ; \
} \
} while ( 0 ) ;
2010-06-21 18:07:48 -04:00
void configGetCommand ( redisClient * c ) {
2010-10-17 12:09:23 -04:00
robj * o = c - > argv [ 2 ] ;
2010-08-30 10:02:06 -04:00
void * replylen = addDeferredMultiBulkLength ( c ) ;
2010-06-21 18:07:48 -04:00
char * pattern = o - > ptr ;
2010-10-15 05:57:38 -04:00
char buf [ 128 ] ;
2010-06-21 18:07:48 -04:00
int matches = 0 ;
2011-10-04 12:43:03 -04:00
redisAssertWithInfo ( c , o , o - > encoding = = REDIS_ENCODING_RAW ) ;
2010-06-21 18:07:48 -04:00
2012-03-08 06:14:23 -05:00
/* String values */
config_get_string_field ( " dbfilename " , server . rdb_filename ) ;
config_get_string_field ( " requirepass " , server . requirepass ) ;
config_get_string_field ( " masterauth " , server . requirepass ) ;
config_get_string_field ( " bind " , server . bindaddr ) ;
config_get_string_field ( " unixsocket " , server . unixsocket ) ;
config_get_string_field ( " logfile " , server . logfile ) ;
config_get_string_field ( " pidfile " , server . pidfile ) ;
/* Numerical values */
config_get_numerical_field ( " maxmemory " , server . maxmemory ) ;
config_get_numerical_field ( " maxmemory-samples " , server . maxmemory_samples ) ;
config_get_numerical_field ( " timeout " , server . maxidletime ) ;
config_get_numerical_field ( " auto-aof-rewrite-percentage " ,
server . aof_rewrite_perc ) ;
config_get_numerical_field ( " auto-aof-rewrite-min-size " ,
server . aof_rewrite_min_size ) ;
2012-03-09 16:07:45 -05:00
config_get_numerical_field ( " hash-max-ziplist-entries " ,
server . hash_max_ziplist_entries ) ;
config_get_numerical_field ( " hash-max-ziplist-value " ,
server . hash_max_ziplist_value ) ;
2012-03-08 06:14:23 -05:00
config_get_numerical_field ( " list-max-ziplist-entries " ,
server . list_max_ziplist_entries ) ;
config_get_numerical_field ( " list-max-ziplist-value " ,
server . list_max_ziplist_value ) ;
config_get_numerical_field ( " set-max-intset-entries " ,
server . set_max_intset_entries ) ;
config_get_numerical_field ( " zset-max-ziplist-entries " ,
server . zset_max_ziplist_entries ) ;
config_get_numerical_field ( " zset-max-ziplist-value " ,
server . zset_max_ziplist_value ) ;
config_get_numerical_field ( " lua-time-limit " , server . lua_time_limit ) ;
config_get_numerical_field ( " slowlog-log-slower-than " ,
server . slowlog_log_slower_than ) ;
config_get_numerical_field ( " slowlog-max-len " ,
server . slowlog_max_len ) ;
config_get_numerical_field ( " port " , server . port ) ;
config_get_numerical_field ( " databases " , server . dbnum ) ;
config_get_numerical_field ( " repl-ping-slave-period " , server . repl_ping_slave_period ) ;
config_get_numerical_field ( " repl-timeout " , server . repl_timeout ) ;
config_get_numerical_field ( " maxclients " , server . maxclients ) ;
2012-03-27 05:47:51 -04:00
config_get_numerical_field ( " watchdog-period " , server . watchdog_period ) ;
2012-08-28 11:20:26 -04:00
config_get_numerical_field ( " slave-priority " , server . slave_priority ) ;
2012-12-14 11:10:40 -05:00
config_get_numerical_field ( " hz " , server . hz ) ;
2012-03-08 06:14:23 -05:00
/* Bool (yes/no) values */
config_get_bool_field ( " no-appendfsync-on-rewrite " ,
server . aof_no_fsync_on_rewrite ) ;
config_get_bool_field ( " slave-serve-stale-data " ,
server . repl_serve_stale_data ) ;
2012-03-20 12:32:48 -04:00
config_get_bool_field ( " slave-read-only " ,
server . repl_slave_ro ) ;
2012-03-08 06:14:23 -05:00
config_get_bool_field ( " stop-writes-on-bgsave-error " ,
server . stop_writes_on_bgsave_err ) ;
config_get_bool_field ( " daemonize " , server . daemonize ) ;
config_get_bool_field ( " rdbcompression " , server . rdb_compression ) ;
2012-04-10 09:47:10 -04:00
config_get_bool_field ( " rdbchecksum " , server . rdb_checksum ) ;
2012-03-08 06:14:23 -05:00
config_get_bool_field ( " activerehashing " , server . activerehashing ) ;
/* Everything we can't handle with macros follows. */
if ( stringmatch ( pattern , " appendonly " , 0 ) ) {
addReplyBulkCString ( c , " appendonly " ) ;
addReplyBulkCString ( c , server . aof_state = = REDIS_AOF_OFF ? " no " : " yes " ) ;
matches + + ;
}
2011-02-13 20:51:27 -05:00
if ( stringmatch ( pattern , " dir " , 0 ) ) {
char buf [ 1024 ] ;
2011-07-27 09:03:48 -04:00
if ( getcwd ( buf , sizeof ( buf ) ) = = NULL )
2011-02-21 11:41:25 -05:00
buf [ 0 ] = ' \0 ' ;
2011-07-27 09:03:48 -04:00
addReplyBulkCString ( c , " dir " ) ;
addReplyBulkCString ( c , buf ) ;
2011-02-13 20:51:27 -05:00
matches + + ;
}
2010-10-14 15:22:21 -04:00
if ( stringmatch ( pattern , " maxmemory-policy " , 0 ) ) {
char * s ;
switch ( server . maxmemory_policy ) {
case REDIS_MAXMEMORY_VOLATILE_LRU : s = " volatile-lru " ; break ;
case REDIS_MAXMEMORY_VOLATILE_TTL : s = " volatile-ttl " ; break ;
case REDIS_MAXMEMORY_VOLATILE_RANDOM : s = " volatile-random " ; break ;
case REDIS_MAXMEMORY_ALLKEYS_LRU : s = " allkeys-lru " ; break ;
case REDIS_MAXMEMORY_ALLKEYS_RANDOM : s = " allkeys-random " ; break ;
2010-11-08 10:12:16 -05:00
case REDIS_MAXMEMORY_NO_EVICTION : s = " noeviction " ; break ;
2010-10-14 15:22:21 -04:00
default : s = " unknown " ; break ; /* too harmless to panic */
}
addReplyBulkCString ( c , " maxmemory-policy " ) ;
addReplyBulkCString ( c , s ) ;
matches + + ;
}
2010-06-21 18:07:48 -04:00
if ( stringmatch ( pattern , " appendfsync " , 0 ) ) {
char * policy ;
2011-12-21 05:58:42 -05:00
switch ( server . aof_fsync ) {
case AOF_FSYNC_NO : policy = " no " ; break ;
case AOF_FSYNC_EVERYSEC : policy = " everysec " ; break ;
case AOF_FSYNC_ALWAYS : policy = " always " ; break ;
2010-06-21 18:07:48 -04:00
default : policy = " unknown " ; break ; /* too harmless to panic */
}
addReplyBulkCString ( c , " appendfsync " ) ;
addReplyBulkCString ( c , policy ) ;
matches + + ;
}
if ( stringmatch ( pattern , " save " , 0 ) ) {
sds buf = sdsempty ( ) ;
int j ;
for ( j = 0 ; j < server . saveparamslen ; j + + ) {
buf = sdscatprintf ( buf , " %ld %d " ,
server . saveparams [ j ] . seconds ,
server . saveparams [ j ] . changes ) ;
if ( j ! = server . saveparamslen - 1 )
buf = sdscatlen ( buf , " " , 1 ) ;
}
addReplyBulkCString ( c , " save " ) ;
addReplyBulkCString ( c , buf ) ;
sdsfree ( buf ) ;
matches + + ;
}
2011-10-05 10:08:35 -04:00
if ( stringmatch ( pattern , " loglevel " , 0 ) ) {
char * s ;
switch ( server . verbosity ) {
case REDIS_WARNING : s = " warning " ; break ;
case REDIS_VERBOSE : s = " verbose " ; break ;
case REDIS_NOTICE : s = " notice " ; break ;
case REDIS_DEBUG : s = " debug " ; break ;
default : s = " unknown " ; break ; /* too harmless to panic */
}
addReplyBulkCString ( c , " loglevel " ) ;
addReplyBulkCString ( c , s ) ;
matches + + ;
}
2012-01-24 04:43:30 -05:00
if ( stringmatch ( pattern , " client-output-buffer-limit " , 0 ) ) {
sds buf = sdsempty ( ) ;
int j ;
for ( j = 0 ; j < REDIS_CLIENT_LIMIT_NUM_CLASSES ; j + + ) {
buf = sdscatprintf ( buf , " %s %llu %llu %ld " ,
getClientLimitClassName ( j ) ,
server . client_obuf_limits [ j ] . hard_limit_bytes ,
server . client_obuf_limits [ j ] . soft_limit_bytes ,
( long ) server . client_obuf_limits [ j ] . soft_limit_seconds ) ;
if ( j ! = REDIS_CLIENT_LIMIT_NUM_CLASSES - 1 )
buf = sdscatlen ( buf , " " , 1 ) ;
}
addReplyBulkCString ( c , " client-output-buffer-limit " ) ;
addReplyBulkCString ( c , buf ) ;
sdsfree ( buf ) ;
matches + + ;
}
2012-03-08 06:14:23 -05:00
if ( stringmatch ( pattern , " unixsocketperm " , 0 ) ) {
char buf [ 32 ] ;
snprintf ( buf , sizeof ( buf ) , " %o " , server . unixsocketperm ) ;
addReplyBulkCString ( c , " unixsocketperm " ) ;
addReplyBulkCString ( c , buf ) ;
matches + + ;
}
if ( stringmatch ( pattern , " slaveof " , 0 ) ) {
char buf [ 256 ] ;
addReplyBulkCString ( c , " slaveof " ) ;
if ( server . masterhost )
snprintf ( buf , sizeof ( buf ) , " %s %d " ,
server . masterhost , server . masterport ) ;
else
buf [ 0 ] = ' \0 ' ;
addReplyBulkCString ( c , buf ) ;
2012-03-07 12:02:26 -05:00
matches + + ;
}
2013-01-25 07:19:08 -05:00
if ( stringmatch ( pattern , " notify-keyspace-events " , 0 ) ) {
robj * flagsobj = createObject ( REDIS_STRING ,
keyspaceEventsFlagsToString ( server . notify_keyspace_events ) ) ;
addReplyBulkCString ( c , " notify-keyspace-events " ) ;
addReplyBulk ( c , flagsobj ) ;
decrRefCount ( flagsobj ) ;
matches + + ;
}
2010-08-30 10:02:06 -04:00
setDeferredMultiBulkLength ( c , replylen , matches * 2 ) ;
2010-06-21 18:07:48 -04:00
}
void configCommand ( redisClient * c ) {
if ( ! strcasecmp ( c - > argv [ 1 ] - > ptr , " set " ) ) {
if ( c - > argc ! = 4 ) goto badarity ;
configSetCommand ( c ) ;
} else if ( ! strcasecmp ( c - > argv [ 1 ] - > ptr , " get " ) ) {
if ( c - > argc ! = 3 ) goto badarity ;
configGetCommand ( c ) ;
} else if ( ! strcasecmp ( c - > argv [ 1 ] - > ptr , " resetstat " ) ) {
if ( c - > argc ! = 2 ) goto badarity ;
2010-10-15 06:29:05 -04:00
server . stat_keyspace_hits = 0 ;
server . stat_keyspace_misses = 0 ;
2010-06-21 18:07:48 -04:00
server . stat_numcommands = 0 ;
server . stat_numconnections = 0 ;
server . stat_expiredkeys = 0 ;
2012-03-25 05:43:19 -04:00
server . stat_rejected_conn = 0 ;
server . stat_fork_time = 0 ;
2012-03-25 05:27:35 -04:00
server . aof_delayed_fsync = 0 ;
2011-01-24 04:56:06 -05:00
resetCommandTableStats ( ) ;
2010-06-21 18:07:48 -04:00
addReply ( c , shared . ok ) ;
} else {
2010-09-02 13:52:24 -04:00
addReplyError ( c ,
" CONFIG subcommand must be one of GET, SET, RESETSTAT " ) ;
2010-06-21 18:07:48 -04:00
}
return ;
badarity :
2010-09-02 13:52:24 -04:00
addReplyErrorFormat ( c , " Wrong number of arguments for CONFIG %s " ,
( char * ) c - > argv [ 1 ] - > ptr ) ;
2010-06-21 18:07:48 -04:00
}