diff --git a/redis.conf b/redis.conf index 4587ee2b..d74ff98a 100644 --- a/redis.conf +++ b/redis.conf @@ -35,6 +35,14 @@ # include /path/to/local.conf # include /path/to/other.conf +################################## MODULES ##################################### + +# Load modules at startup. If the server is not able to load modules +# it will abort. It is possible to use multiple loadmodule directives. +# +# loadmodule /path/to/my_module.so +# loadmodule /path/to/other_module.so + ################################## NETWORK ##################################### # By default, if no "bind" configuration directive is specified, Redis listens @@ -51,7 +59,7 @@ # internet, binding to all the interfaces is dangerous and will expose the # instance to everybody on the internet. So by default we uncomment the # following bind directive, that will force Redis to listen only into -# the IPv4 lookback interface address (this means Redis will be able to +# the IPv4 loopback interface address (this means Redis will be able to # accept connections only from clients running into the same computer it # is running). # @@ -177,6 +185,14 @@ logfile "" # dbid is a number between 0 and 'databases'-1 databases 16 +# By default Redis shows an ASCII art logo only when started to log to the +# standard output and if the standard output is a TTY. Basically this means +# that normally a logo is displayed only in interactive sessions. +# +# However it is possible to force the pre-4.0 behavior and always show a +# ASCII art logo in startup logs by setting the following option to yes. +always-show-logo yes + ################################ SNAPSHOTTING ################################ # # Save the DB on disk: @@ -248,57 +264,64 @@ dir ./ ################################# REPLICATION ################################# -# Master-Slave replication. Use slaveof to make a Redis instance a copy of +# Master-Replica replication. Use replicaof to make a Redis instance a copy of # another Redis server. A few things to understand ASAP about Redis replication. # +# +------------------+ +---------------+ +# | Master | ---> | Replica | +# | (receive writes) | | (exact copy) | +# +------------------+ +---------------+ +# # 1) Redis replication is asynchronous, but you can configure a master to # stop accepting writes if it appears to be not connected with at least -# a given number of slaves. -# 2) Redis slaves are able to perform a partial resynchronization with the +# a given number of replicas. +# 2) Redis replicas are able to perform a partial resynchronization with the # master if the replication link is lost for a relatively small amount of # time. You may want to configure the replication backlog size (see the next # sections of this file) with a sensible value depending on your needs. # 3) Replication is automatic and does not need user intervention. After a -# network partition slaves automatically try to reconnect to masters +# network partition replicas automatically try to reconnect to masters # and resynchronize with them. # -# slaveof +# replicaof # If the master is password protected (using the "requirepass" configuration -# directive below) it is possible to tell the slave to authenticate before +# directive below) it is possible to tell the replica to authenticate before # starting the replication synchronization process, otherwise the master will -# refuse the slave request. +# refuse the replica request. # # masterauth -# When a slave loses its connection with the master, or when the replication -# is still in progress, the slave can act in two different ways: +# When a replica loses its connection with the master, or when the replication +# is still in progress, the replica can act in two different ways: # -# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will +# 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will # still reply to client requests, possibly with out of date data, or the # data set may just be empty if this is the first synchronization. # -# 2) if slave-serve-stale-data is set to 'no' the slave will reply with +# 2) if replica-serve-stale-data is set to 'no' the replica will reply with # an error "SYNC with master in progress" to all the kind of commands -# but to INFO and SLAVEOF. +# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG, +# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, +# COMMAND, POST, HOST: and LATENCY. # -slave-serve-stale-data yes +replica-serve-stale-data yes -# You can configure a slave instance to accept writes or not. Writing against -# a slave instance may be useful to store some ephemeral data (because data -# written on a slave will be easily deleted after resync with the master) but +# You can configure a replica instance to accept writes or not. Writing against +# a replica instance may be useful to store some ephemeral data (because data +# written on a replica will be easily deleted after resync with the master) but # may also cause problems if clients are writing to it because of a # misconfiguration. # -# Since Redis 2.6 by default slaves are read-only. +# Since Redis 2.6 by default replicas are read-only. # -# Note: read only slaves are not designed to be exposed to untrusted clients +# Note: read only replicas are not designed to be exposed to untrusted clients # on the internet. It's just a protection layer against misuse of the instance. -# Still a read only slave exports by default all the administrative commands +# Still a read only replica exports by default all the administrative commands # such as CONFIG, DEBUG, and so forth. To a limited extent you can improve -# security of read only slaves using 'rename-command' to shadow all the +# security of read only replicas using 'rename-command' to shadow all the # administrative / dangerous commands. -slave-read-only yes +replica-read-only yes # Replication SYNC strategy: disk or socket. # @@ -306,25 +329,25 @@ slave-read-only yes # WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY # ------------------------------------------------------- # -# New slaves and reconnecting slaves that are not able to continue the replication +# New replicas and reconnecting replicas that are not able to continue the replication # process just receiving differences, need to do what is called a "full -# synchronization". An RDB file is transmitted from the master to the slaves. +# synchronization". An RDB file is transmitted from the master to the replicas. # The transmission can happen in two different ways: # # 1) Disk-backed: The Redis master creates a new process that writes the RDB # file on disk. Later the file is transferred by the parent -# process to the slaves incrementally. +# process to the replicas incrementally. # 2) Diskless: The Redis master creates a new process that directly writes the -# RDB file to slave sockets, without touching the disk at all. +# RDB file to replica sockets, without touching the disk at all. # -# With disk-backed replication, while the RDB file is generated, more slaves +# With disk-backed replication, while the RDB file is generated, more replicas # can be queued and served with the RDB file as soon as the current child producing # the RDB file finishes its work. With diskless replication instead once -# the transfer starts, new slaves arriving will be queued and a new transfer +# the transfer starts, new replicas arriving will be queued and a new transfer # will start when the current one terminates. # # When diskless replication is used, the master waits a configurable amount of -# time (in seconds) before starting the transfer in the hope that multiple slaves +# time (in seconds) before starting the transfer in the hope that multiple replicas # will arrive and the transfer can be parallelized. # # With slow disks and fast (large bandwidth) networks, diskless replication @@ -333,107 +356,140 @@ repl-diskless-sync no # When diskless replication is enabled, it is possible to configure the delay # the server waits in order to spawn the child that transfers the RDB via socket -# to the slaves. +# to the replicas. # # This is important since once the transfer starts, it is not possible to serve -# new slaves arriving, that will be queued for the next RDB transfer, so the server -# waits a delay in order to let more slaves arrive. +# new replicas arriving, that will be queued for the next RDB transfer, so the server +# waits a delay in order to let more replicas arrive. # # The delay is specified in seconds, and by default is 5 seconds. To disable # it entirely just set it to 0 seconds and the transfer will start ASAP. repl-diskless-sync-delay 5 -# Slaves send PINGs to server in a predefined interval. It's possible to change -# this interval with the repl_ping_slave_period option. The default value is 10 +# Replicas send PINGs to server in a predefined interval. It's possible to change +# this interval with the repl_ping_replica_period option. The default value is 10 # seconds. # -# repl-ping-slave-period 10 +# repl-ping-replica-period 10 # The following option sets the replication timeout for: # -# 1) Bulk transfer I/O during SYNC, from the point of view of slave. -# 2) Master timeout from the point of view of slaves (data, pings). -# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings). +# 1) Bulk transfer I/O during SYNC, from the point of view of replica. +# 2) Master timeout from the point of view of replicas (data, pings). +# 3) Replica timeout from the point of view of masters (REPLCONF ACK pings). # # It is important to make sure that this value is greater than the value -# specified for repl-ping-slave-period otherwise a timeout will be detected -# every time there is low traffic between the master and the slave. +# specified for repl-ping-replica-period otherwise a timeout will be detected +# every time there is low traffic between the master and the replica. # # repl-timeout 60 -# Disable TCP_NODELAY on the slave socket after SYNC? +# Disable TCP_NODELAY on the replica socket after SYNC? # # If you select "yes" Redis will use a smaller number of TCP packets and -# less bandwidth to send data to slaves. But this can add a delay for -# the data to appear on the slave side, up to 40 milliseconds with +# less bandwidth to send data to replicas. But this can add a delay for +# the data to appear on the replica side, up to 40 milliseconds with # Linux kernels using a default configuration. # -# If you select "no" the delay for data to appear on the slave side will +# If you select "no" the delay for data to appear on the replica side will # be reduced but more bandwidth will be used for replication. # # By default we optimize for low latency, but in very high traffic conditions -# or when the master and slaves are many hops away, turning this to "yes" may +# or when the master and replicas are many hops away, turning this to "yes" may # be a good idea. repl-disable-tcp-nodelay no # Set the replication backlog size. The backlog is a buffer that accumulates -# slave data when slaves are disconnected for some time, so that when a slave +# replica data when replicas are disconnected for some time, so that when a replica # wants to reconnect again, often a full resync is not needed, but a partial -# resync is enough, just passing the portion of data the slave missed while +# resync is enough, just passing the portion of data the replica missed while # disconnected. # -# The bigger the replication backlog, the longer the time the slave can be +# The bigger the replication backlog, the longer the time the replica can be # disconnected and later be able to perform a partial resynchronization. # -# The backlog is only allocated once there is at least a slave connected. +# The backlog is only allocated once there is at least a replica connected. # # repl-backlog-size 1mb -# After a master has no longer connected slaves for some time, the backlog +# After a master has no longer connected replicas for some time, the backlog # will be freed. The following option configures the amount of seconds that -# need to elapse, starting from the time the last slave disconnected, for +# need to elapse, starting from the time the last replica disconnected, for # the backlog buffer to be freed. # +# Note that replicas never free the backlog for timeout, since they may be +# promoted to masters later, and should be able to correctly "partially +# resynchronize" with the replicas: hence they should always accumulate backlog. +# # A value of 0 means to never release the backlog. # # repl-backlog-ttl 3600 -# The slave priority is an integer number published by Redis in the INFO output. -# It is used by Redis Sentinel in order to select a slave to promote into a +# The replica priority is an integer number published by Redis in the INFO output. +# It is used by Redis Sentinel in order to select a replica to promote into a # master if the master is no longer working correctly. # -# A slave with a low priority number is considered better for promotion, so -# for instance if there are three slaves with priority 10, 100, 25 Sentinel will +# A replica with a low priority number is considered better for promotion, so +# for instance if there are three replicas with priority 10, 100, 25 Sentinel will # pick the one with priority 10, that is the lowest. # -# However a special priority of 0 marks the slave as not able to perform the -# role of master, so a slave with priority of 0 will never be selected by +# However a special priority of 0 marks the replica as not able to perform the +# role of master, so a replica with priority of 0 will never be selected by # Redis Sentinel for promotion. # # By default the priority is 100. -slave-priority 100 +replica-priority 100 # It is possible for a master to stop accepting writes if there are less than -# N slaves connected, having a lag less or equal than M seconds. +# N replicas connected, having a lag less or equal than M seconds. # -# The N slaves need to be in "online" state. +# The N replicas need to be in "online" state. # # The lag in seconds, that must be <= the specified value, is calculated from -# the last ping received from the slave, that is usually sent every second. +# the last ping received from the replica, that is usually sent every second. # # This option does not GUARANTEE that N replicas will accept the write, but -# will limit the window of exposure for lost writes in case not enough slaves +# will limit the window of exposure for lost writes in case not enough replicas # are available, to the specified number of seconds. # -# For example to require at least 3 slaves with a lag <= 10 seconds use: +# For example to require at least 3 replicas with a lag <= 10 seconds use: # -# min-slaves-to-write 3 -# min-slaves-max-lag 10 +# min-replicas-to-write 3 +# min-replicas-max-lag 10 # # Setting one or the other to 0 disables the feature. # -# By default min-slaves-to-write is set to 0 (feature disabled) and -# min-slaves-max-lag is set to 10. +# By default min-replicas-to-write is set to 0 (feature disabled) and +# min-replicas-max-lag is set to 10. + +# A Redis master is able to list the address and port of the attached +# replicas in different ways. For example the "INFO replication" section +# offers this information, which is used, among other tools, by +# Redis Sentinel in order to discover replica instances. +# Another place where this info is available is in the output of the +# "ROLE" command of a master. +# +# The listed IP and address normally reported by a replica is obtained +# in the following way: +# +# IP: The address is auto detected by checking the peer address +# of the socket used by the replica to connect with the master. +# +# Port: The port is communicated by the replica during the replication +# handshake, and is normally the port that the replica is using to +# listen for connections. +# +# However when port forwarding or Network Address Translation (NAT) is +# used, the replica may be actually reachable via different IP and port +# pairs. The following two options can be used by a replica in order to +# report to its master a specific set of IP and port, so that both INFO +# and ROLE will report those values. +# +# There is no need to use both the options if you need to override just +# the port or the IP address. +# +# replica-announce-ip 5.5.5.5 +# replica-announce-port 1234 ################################## SECURITY ################################### @@ -467,9 +523,9 @@ slave-priority 100 # rename-command CONFIG "" # # Please note that changing the name of commands that are logged into the -# AOF file or transmitted to slaves may cause problems. +# AOF file or transmitted to replicas may cause problems. -################################### LIMITS #################################### +################################### CLIENTS #################################### # Set the max number of connected clients at the same time. By default # this limit is set to 10000 clients, however if the Redis server is not @@ -482,7 +538,9 @@ slave-priority 100 # # maxclients 10000 -# Don't use more memory than the specified amount of bytes. +############################## MEMORY MANAGEMENT ################################ + +# Set a memory usage limit to the specified amount of bytes. # When the memory limit is reached Redis will try to remove keys # according to the eviction policy selected (see maxmemory-policy). # @@ -491,18 +549,18 @@ slave-priority 100 # that would use more memory, like SET, LPUSH, and so on, and will continue # to reply to read-only commands like GET. # -# This option is usually useful when using Redis as an LRU cache, or to set -# a hard memory limit for an instance (using the 'noeviction' policy). +# This option is usually useful when using Redis as an LRU or LFU cache, or to +# set a hard memory limit for an instance (using the 'noeviction' policy). # -# WARNING: If you have slaves attached to an instance with maxmemory on, -# the size of the output buffers needed to feed the slaves are subtracted +# WARNING: If you have replicas attached to an instance with maxmemory on, +# the size of the output buffers needed to feed the replicas are subtracted # from the used memory count, so that network problems / resyncs will # not trigger a loop where keys are evicted, and in turn the output -# buffer of slaves is full with DELs of keys evicted triggering the deletion +# buffer of replicas is full with DELs of keys evicted triggering the deletion # of more keys, and so forth until the database is completely emptied. # -# In short... if you have slaves attached it is suggested that you set a lower -# limit for maxmemory so that there is some free RAM on the system for slave +# In short... if you have replicas attached it is suggested that you set a lower +# limit for maxmemory so that there is some free RAM on the system for replica # output buffers (but this is not needed if the policy is 'noeviction'). # # maxmemory @@ -510,12 +568,20 @@ slave-priority 100 # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory # is reached. You can select among five behaviors: # -# volatile-lru -> remove the key with an expire set using an LRU algorithm -# allkeys-lru -> remove any key according to the LRU algorithm -# volatile-random -> remove a random key with an expire set -# allkeys-random -> remove a random key, any key -# volatile-ttl -> remove the key with the nearest expire time (minor TTL) -# noeviction -> don't expire at all, just return an error on write operations +# volatile-lru -> Evict using approximated LRU among the keys with an expire set. +# allkeys-lru -> Evict any key using approximated LRU. +# volatile-lfu -> Evict using approximated LFU among the keys with an expire set. +# allkeys-lfu -> Evict any key using approximated LFU. +# volatile-random -> Remove a random key among the ones with an expire set. +# allkeys-random -> Remove a random key, any key. +# volatile-ttl -> Remove the key with the nearest expire time (minor TTL) +# noeviction -> Don't evict anything, just return an error on write operations. +# +# LRU means Least Recently Used +# LFU means Least Frequently Used +# +# Both LRU, LFU and volatile-ttl are implemented using approximated +# randomized algorithms. # # Note: with any of the above policies, Redis will return an error on write # operations, when there are no suitable keys for eviction. @@ -530,17 +596,86 @@ slave-priority 100 # # maxmemory-policy noeviction -# LRU and minimal TTL algorithms are not precise algorithms but approximated +# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated # algorithms (in order to save memory), so you can tune it for speed or # accuracy. For default Redis will check five keys and pick the one that was # used less recently, you can change the sample size using the following # configuration directive. # # The default of 5 produces good enough results. 10 Approximates very closely -# true LRU but costs a bit more CPU. 3 is very fast but not very accurate. +# true LRU but costs more CPU. 3 is faster but not very accurate. # # maxmemory-samples 5 +# Starting from Redis 5, by default a replica will ignore its maxmemory setting +# (unless it is promoted to master after a failover or manually). It means +# that the eviction of keys will be just handled by the master, sending the +# DEL commands to the replica as keys evict in the master side. +# +# This behavior ensures that masters and replicas stay consistent, and is usually +# what you want, however if your replica is writable, or you want the replica to have +# a different memory setting, and you are sure all the writes performed to the +# replica are idempotent, then you may change this default (but be sure to understand +# what you are doing). +# +# Note that since the replica by default does not evict, it may end using more +# memory than the one set via maxmemory (there are certain buffers that may +# be larger on the replica, or data structures may sometimes take more memory and so +# forth). So make sure you monitor your replicas and make sure they have enough +# memory to never hit a real out-of-memory condition before the master hits +# the configured maxmemory setting. +# +# replica-ignore-maxmemory yes + +############################# LAZY FREEING #################################### + +# Redis has two primitives to delete keys. One is called DEL and is a blocking +# deletion of the object. It means that the server stops processing new commands +# in order to reclaim all the memory associated with an object in a synchronous +# way. If the key deleted is associated with a small object, the time needed +# in order to execute the DEL command is very small and comparable to most other +# O(1) or O(log_N) commands in Redis. However if the key is associated with an +# aggregated value containing millions of elements, the server can block for +# a long time (even seconds) in order to complete the operation. +# +# For the above reasons Redis also offers non blocking deletion primitives +# such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and +# FLUSHDB commands, in order to reclaim memory in background. Those commands +# are executed in constant time. Another thread will incrementally free the +# object in the background as fast as possible. +# +# DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled. +# It's up to the design of the application to understand when it is a good +# idea to use one or the other. However the Redis server sometimes has to +# delete keys or flush the whole database as a side effect of other operations. +# Specifically Redis deletes objects independently of a user call in the +# following scenarios: +# +# 1) On eviction, because of the maxmemory and maxmemory policy configurations, +# in order to make room for new data, without going over the specified +# memory limit. +# 2) Because of expire: when a key with an associated time to live (see the +# EXPIRE command) must be deleted from memory. +# 3) Because of a side effect of a command that stores data on a key that may +# already exist. For example the RENAME command may delete the old key +# content when it is replaced with another one. Similarly SUNIONSTORE +# or SORT with STORE option may delete existing keys. The SET command +# itself removes any old content of the specified key in order to replace +# it with the specified string. +# 4) During replication, when a replica performs a full resynchronization with +# its master, the content of the whole database is removed in order to +# load the RDB file just transferred. +# +# In all the above cases the default is to delete objects in a blocking way, +# like if DEL was called. However you can configure each case specifically +# in order to instead release memory in a non-blocking way like if UNLINK +# was called, using the following configuration directives: + +lazyfree-lazy-eviction no +lazyfree-lazy-expire no +lazyfree-lazy-server-del no +replica-lazy-flush no + ############################## APPEND ONLY MODE ############################### # By default Redis asynchronously dumps the dataset on disk. This mode is @@ -659,6 +794,17 @@ auto-aof-rewrite-min-size 64mb # will be found. aof-load-truncated yes +# When rewriting the AOF file, Redis is able to use an RDB preamble in the +# AOF file for faster rewrites and recoveries. When this option is turned +# on the rewritten AOF file is composed of two different stanzas: +# +# [RDB file][AOF tail] +# +# When loading Redis recognizes that the AOF file starts with the "REDIS" +# string and loads the prefixed RDB file, and continues loading the AOF +# tail. +aof-use-rdb-preamble yes + ################################ LUA SCRIPTING ############################### # Max execution time of a Lua script in milliseconds. @@ -678,13 +824,7 @@ aof-load-truncated yes lua-time-limit 5000 ################################ REDIS CLUSTER ############################### -# -# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however -# in order to mark it as "mature" we need to wait for a non trivial percentage -# of users to deploy it in production. -# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -# + # Normal Redis instances can't be part of a Redis Cluster; only nodes that are # started as cluster nodes can. In order to start a Redis instance as a # cluster node enable the cluster support uncommenting the following: @@ -705,42 +845,42 @@ lua-time-limit 5000 # # cluster-node-timeout 15000 -# A slave of a failing master will avoid to start a failover if its data +# A replica of a failing master will avoid to start a failover if its data # looks too old. # -# There is no simple way for a slave to actually have a exact measure of +# There is no simple way for a replica to actually have an exact measure of # its "data age", so the following two checks are performed: # -# 1) If there are multiple slaves able to failover, they exchange messages -# in order to try to give an advantage to the slave with the best +# 1) If there are multiple replicas able to failover, they exchange messages +# in order to try to give an advantage to the replica with the best # replication offset (more data from the master processed). -# Slaves will try to get their rank by offset, and apply to the start +# Replicas will try to get their rank by offset, and apply to the start # of the failover a delay proportional to their rank. # -# 2) Every single slave computes the time of the last interaction with +# 2) Every single replica computes the time of the last interaction with # its master. This can be the last ping or command received (if the master # is still in the "connected" state), or the time that elapsed since the # disconnection with the master (if the replication link is currently down). -# If the last interaction is too old, the slave will not try to failover +# If the last interaction is too old, the replica will not try to failover # at all. # -# The point "2" can be tuned by user. Specifically a slave will not perform +# The point "2" can be tuned by user. Specifically a replica will not perform # the failover if, since the last interaction with the master, the time # elapsed is greater than: # -# (node-timeout * slave-validity-factor) + repl-ping-slave-period +# (node-timeout * replica-validity-factor) + repl-ping-replica-period # -# So for example if node-timeout is 30 seconds, and the slave-validity-factor -# is 10, and assuming a default repl-ping-slave-period of 10 seconds, the -# slave will not try to failover if it was not able to talk with the master +# So for example if node-timeout is 30 seconds, and the replica-validity-factor +# is 10, and assuming a default repl-ping-replica-period of 10 seconds, the +# replica will not try to failover if it was not able to talk with the master # for longer than 310 seconds. # -# A large slave-validity-factor may allow slaves with too old data to failover +# A large replica-validity-factor may allow replicas with too old data to failover # a master, while a too small value may prevent the cluster from being able to -# elect a slave at all. +# elect a replica at all. # -# For maximum availability, it is possible to set the slave-validity-factor -# to a value of 0, which means, that slaves will always try to failover the +# For maximum availability, it is possible to set the replica-validity-factor +# to a value of 0, which means, that replicas will always try to failover the # master regardless of the last time they interacted with the master. # (However they'll always try to apply a delay proportional to their # offset rank). @@ -748,22 +888,22 @@ lua-time-limit 5000 # Zero is the only value able to guarantee that when all the partitions heal # the cluster will always be able to continue. # -# cluster-slave-validity-factor 10 +# cluster-replica-validity-factor 10 -# Cluster slaves are able to migrate to orphaned masters, that are masters -# that are left without working slaves. This improves the cluster ability +# Cluster replicas are able to migrate to orphaned masters, that are masters +# that are left without working replicas. This improves the cluster ability # to resist to failures as otherwise an orphaned master can't be failed over -# in case of failure if it has no working slaves. +# in case of failure if it has no working replicas. # -# Slaves migrate to orphaned masters only if there are still at least a -# given number of other working slaves for their old master. This number -# is the "migration barrier". A migration barrier of 1 means that a slave -# will migrate only if there is at least 1 other working slave for its master -# and so forth. It usually reflects the number of slaves you want for every +# Replicas migrate to orphaned masters only if there are still at least a +# given number of other working replicas for their old master. This number +# is the "migration barrier". A migration barrier of 1 means that a replica +# will migrate only if there is at least 1 other working replica for its master +# and so forth. It usually reflects the number of replicas you want for every # master in your cluster. # -# Default is 1 (slaves migrate only if their masters remain with at least -# one slave). To disable migration just set it to a very large value. +# Default is 1 (replicas migrate only if their masters remain with at least +# one replica). To disable migration just set it to a very large value. # A value of 0 can be set but is useful only for debugging and dangerous # in production. # @@ -782,9 +922,52 @@ lua-time-limit 5000 # # cluster-require-full-coverage yes +# This option, when set to yes, prevents replicas from trying to failover its +# master during master failures. However the master can still perform a +# manual failover, if forced to do so. +# +# This is useful in different scenarios, especially in the case of multiple +# data center operations, where we want one side to never be promoted if not +# in the case of a total DC failure. +# +# cluster-replica-no-failover no + # In order to setup your cluster make sure to read the documentation # available at http://redis.io web site. +########################## CLUSTER DOCKER/NAT support ######################## + +# In certain deployments, Redis Cluster nodes address discovery fails, because +# addresses are NAT-ted or because ports are forwarded (the typical case is +# Docker and other containers). +# +# In order to make Redis Cluster working in such environments, a static +# configuration where each node knows its public address is needed. The +# following two options are used for this scope, and are: +# +# * cluster-announce-ip +# * cluster-announce-port +# * cluster-announce-bus-port +# +# Each instruct the node about its address, client port, and cluster message +# bus port. The information is then published in the header of the bus packets +# so that other nodes will be able to correctly map the address of the node +# publishing the information. +# +# If the above options are not used, the normal Redis Cluster auto-detection +# will be used instead. +# +# Note that when remapped, the bus port may not be at the fixed offset of +# clients port + 10000, so you can specify any port and bus-port depending +# on how they get remapped. If the bus-port is not set, a fixed offset of +# 10000 will be used as usually. +# +# Example: +# +# cluster-announce-ip 10.1.1.5 +# cluster-announce-port 6379 +# cluster-announce-bus-port 6380 + ################################## SLOW LOG ################################### # The Redis Slow Log is a system to log queries that exceeded a specified @@ -942,6 +1125,17 @@ zset-max-ziplist-value 64 # composed of many HyperLogLogs with cardinality in the 0 - 15000 range. hll-sparse-max-bytes 3000 +# Streams macro node max size / items. The stream data structure is a radix +# tree of big nodes that encode multiple items inside. Using this configuration +# it is possible to configure how big a single node can be in bytes, and the +# maximum number of items it may contain before switching to a new node when +# appending new stream entries. If any of the following settings are set to +# zero, the limit is ignored, so for instance it is possible to set just a +# max entires limit by setting max-bytes to 0 and max-entries to the desired +# value. +stream-node-max-bytes 4096 +stream-node-max-entries 100 + # Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in # order to help rehashing the main Redis hash table (the one mapping top-level # keys to values). The hash table implementation Redis uses (see dict.c) @@ -970,7 +1164,7 @@ activerehashing yes # The limit can be set differently for the three different classes of clients: # # normal -> normal clients including MONITOR clients -# slave -> slave clients +# replica -> replica clients # pubsub -> clients subscribed to at least one pubsub channel or pattern # # The syntax of every client-output-buffer-limit directive is the following: @@ -991,19 +1185,33 @@ activerehashing yes # asynchronous clients may create a scenario where data is requested faster # than it can read. # -# Instead there is a default limit for pubsub and slave clients, since -# subscribers and slaves receive data in a push fashion. +# Instead there is a default limit for pubsub and replica clients, since +# subscribers and replicas receive data in a push fashion. # # Both the hard or the soft limit can be disabled by setting them to zero. client-output-buffer-limit normal 0 0 0 -client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit replica 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 +# Client query buffers accumulate new commands. They are limited to a fixed +# amount by default in order to avoid that a protocol desynchronization (for +# instance due to a bug in the client) will lead to unbound memory usage in +# the query buffer. However you can configure it here if you have very special +# needs, such us huge multi/exec requests or alike. +# +# client-query-buffer-limit 1gb + +# In the Redis protocol, bulk requests, that are, elements representing single +# strings, are normally limited ot 512 mb. However you can change this limit +# here. +# +# proto-max-bulk-len 512mb + # Redis calls an internal function to perform many background tasks, like -# closing connections of clients in timeot, purging expired keys that are +# closing connections of clients in timeout, purging expired keys that are # never requested, and so forth. # -# Not all tasks are perforemd with the same frequency, but Redis checks for +# Not all tasks are performed with the same frequency, but Redis checks for # tasks to perform according to the specified "hz" value. # # By default "hz" is set to 10. Raising the value will use more CPU when @@ -1016,18 +1224,149 @@ client-output-buffer-limit pubsub 32mb 8mb 60 # 100 only in environments where very low latency is required. hz 10 +# Normally it is useful to have an HZ value which is proportional to the +# number of clients connected. This is useful in order, for instance, to +# avoid too many clients are processed for each background task invocation +# in order to avoid latency spikes. +# +# Since the default HZ value by default is conservatively set to 10, Redis +# offers, and enables by default, the ability to use an adaptive HZ value +# which will temporary raise when there are many connected clients. +# +# When dynamic HZ is enabled, the actual configured HZ will be used as +# as a baseline, but multiples of the configured HZ value will be actually +# used as needed once more clients are connected. In this way an idle +# instance will use very little CPU time while a busy instance will be +# more responsive. +dynamic-hz yes + # When a child rewrites the AOF file, if the following option is enabled # the file will be fsync-ed every 32 MB of data generated. This is useful # in order to commit the file to the disk more incrementally and avoid # big latency spikes. aof-rewrite-incremental-fsync yes -################################## INCLUDES ################################### +# When redis saves RDB file, if the following option is enabled +# the file will be fsync-ed every 32 MB of data generated. This is useful +# in order to commit the file to the disk more incrementally and avoid +# big latency spikes. +rdb-save-incremental-fsync yes -# Include one or more other config files here. This is useful if you -# have a standard template that goes to all Redis server but also need -# to customize a few per-server settings. Include files can include -# other files, so use this wisely. +# Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good +# idea to start with the default settings and only change them after investigating +# how to improve the performances and how the keys LFU change over time, which +# is possible to inspect via the OBJECT FREQ command. # -# include /path/to/local.conf -# include /path/to/other.conf +# There are two tunable parameters in the Redis LFU implementation: the +# counter logarithm factor and the counter decay time. It is important to +# understand what the two parameters mean before changing them. +# +# The LFU counter is just 8 bits per key, it's maximum value is 255, so Redis +# uses a probabilistic increment with logarithmic behavior. Given the value +# of the old counter, when a key is accessed, the counter is incremented in +# this way: +# +# 1. A random number R between 0 and 1 is extracted. +# 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1). +# 3. The counter is incremented only if R < P. +# +# The default lfu-log-factor is 10. This is a table of how the frequency +# counter changes with a different number of accesses with different +# logarithmic factors: +# +# +--------+------------+------------+------------+------------+------------+ +# | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits | +# +--------+------------+------------+------------+------------+------------+ +# | 0 | 104 | 255 | 255 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 1 | 18 | 49 | 255 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 10 | 10 | 18 | 142 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 100 | 8 | 11 | 49 | 143 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# +# NOTE: The above table was obtained by running the following commands: +# +# redis-benchmark -n 1000000 incr foo +# redis-cli object freq foo +# +# NOTE 2: The counter initial value is 5 in order to give new objects a chance +# to accumulate hits. +# +# The counter decay time is the time, in minutes, that must elapse in order +# for the key counter to be divided by two (or decremented if it has a value +# less <= 10). +# +# The default value for the lfu-decay-time is 1. A Special value of 0 means to +# decay the counter every time it happens to be scanned. +# +# lfu-log-factor 10 +# lfu-decay-time 1 + +########################### ACTIVE DEFRAGMENTATION ####################### +# +# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested +# even in production and manually tested by multiple engineers for some +# time. +# +# What is active defragmentation? +# ------------------------------- +# +# Active (online) defragmentation allows a Redis server to compact the +# spaces left between small allocations and deallocations of data in memory, +# thus allowing to reclaim back memory. +# +# Fragmentation is a natural process that happens with every allocator (but +# less so with Jemalloc, fortunately) and certain workloads. Normally a server +# restart is needed in order to lower the fragmentation, or at least to flush +# away all the data and create it again. However thanks to this feature +# implemented by Oran Agra for Redis 4.0 this process can happen at runtime +# in an "hot" way, while the server is running. +# +# Basically when the fragmentation is over a certain level (see the +# configuration options below) Redis will start to create new copies of the +# values in contiguous memory regions by exploiting certain specific Jemalloc +# features (in order to understand if an allocation is causing fragmentation +# and to allocate it in a better place), and at the same time, will release the +# old copies of the data. This process, repeated incrementally for all the keys +# will cause the fragmentation to drop back to normal values. +# +# Important things to understand: +# +# 1. This feature is disabled by default, and only works if you compiled Redis +# to use the copy of Jemalloc we ship with the source code of Redis. +# This is the default with Linux builds. +# +# 2. You never need to enable this feature if you don't have fragmentation +# issues. +# +# 3. Once you experience fragmentation, you can enable this feature when +# needed with the command "CONFIG SET activedefrag yes". +# +# The configuration parameters are able to fine tune the behavior of the +# defragmentation process. If you are not sure about what they mean it is +# a good idea to leave the defaults untouched. + +# Enabled active defragmentation +# activedefrag yes + +# Minimum amount of fragmentation waste to start active defrag +# active-defrag-ignore-bytes 100mb + +# Minimum percentage of fragmentation to start active defrag +# active-defrag-threshold-lower 10 + +# Maximum percentage of fragmentation at which we use maximum effort +# active-defrag-threshold-upper 100 + +# Minimal effort for defrag in CPU percentage +# active-defrag-cycle-min 5 + +# Maximal effort for defrag in CPU percentage +# active-defrag-cycle-max 75 + +# Maximum number of set/hash/zset/list fields that will be processed from +# the main dictionary scan +# active-defrag-max-scan-fields 1000 + diff --git a/runtest b/runtest index d8451df5..ade1bd09 100755 --- a/runtest +++ b/runtest @@ -11,4 +11,4 @@ then echo "You need tcl 8.5 or newer in order to run the Redis test" exit 1 fi -$TCLSH tests/test_helper.tcl $* +$TCLSH tests/test_helper.tcl "${@}" diff --git a/sentinel.conf b/sentinel.conf index a4af6756..bc9a705a 100644 --- a/sentinel.conf +++ b/sentinel.conf @@ -1,9 +1,40 @@ # Example sentinel.conf +# *** IMPORTANT *** +# +# By default Sentinel will not be reachable from interfaces different than +# localhost, either use the 'bind' directive to bind to a list of network +# interfaces, or disable protected mode with "protected-mode no" by +# adding it to this configuration file. +# +# Before doing that MAKE SURE the instance is protected from the outside +# world via firewalling or other means. +# +# For example you may use one of the following: +# +# bind 127.0.0.1 192.168.1.1 +# +# protected-mode no + # port # The port that this sentinel instance will run on port 26379 +# By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it. +# Note that Redis will write a pid file in /var/run/redis-sentinel.pid when +# daemonized. +daemonize no + +# When running daemonized, Redis Sentinel writes a pid file in +# /var/run/redis-sentinel.pid by default. You can specify a custom pid file +# location here. +pidfile /var/run/redis-sentinel.pid + +# Specify the log file name. Also the empty string can be used to force +# Sentinel to log on the standard output. Note that if you use standard +# output for logging but daemonize, logs will be sent to /dev/null +logfile "" + # sentinel announce-ip # sentinel announce-port # @@ -42,11 +73,11 @@ dir /tmp # be elected by the majority of the known Sentinels in order to # start a failover, so no failover can be performed in minority. # -# Slaves are auto-discovered, so you don't need to specify slaves in +# Replicas are auto-discovered, so you don't need to specify replicas in # any way. Sentinel itself will rewrite this configuration file adding -# the slaves using additional configuration options. +# the replicas using additional configuration options. # Also note that the configuration file is rewritten when a -# slave is promoted to master. +# replica is promoted to master. # # Note: master name should not include special characters or spaces. # The valid charset is A-z 0-9 and the three characters ".-_". @@ -54,11 +85,11 @@ sentinel monitor mymaster 127.0.0.1 6379 2 # sentinel auth-pass # -# Set the password to use to authenticate with the master and slaves. +# Set the password to use to authenticate with the master and replicas. # Useful if there is a password set in the Redis instances to monitor. # -# Note that the master password is also used for slaves, so it is not -# possible to set a different password in masters and slaves instances +# Note that the master password is also used for replicas, so it is not +# possible to set a different password in masters and replicas instances # if you want to be able to monitor these instances with Sentinel. # # However you can have Redis instances without the authentication enabled @@ -73,7 +104,7 @@ sentinel monitor mymaster 127.0.0.1 6379 2 # sentinel down-after-milliseconds # -# Number of milliseconds the master (or any attached slave or sentinel) should +# Number of milliseconds the master (or any attached replica or sentinel) should # be unreachable (as in, not acceptable reply to PING, continuously, for the # specified period) in order to consider it in S_DOWN state (Subjectively # Down). @@ -81,11 +112,11 @@ sentinel monitor mymaster 127.0.0.1 6379 2 # Default is 30 seconds. sentinel down-after-milliseconds mymaster 30000 -# sentinel parallel-syncs +# sentinel parallel-syncs # -# How many slaves we can reconfigure to point to the new slave simultaneously -# during the failover. Use a low number if you use the slaves to serve query -# to avoid that all the slaves will be unreachable at about the same +# How many replicas we can reconfigure to point to the new replica simultaneously +# during the failover. Use a low number if you use the replicas to serve query +# to avoid that all the replicas will be unreachable at about the same # time while performing the synchronization with the master. sentinel parallel-syncs mymaster 1 @@ -97,18 +128,18 @@ sentinel parallel-syncs mymaster 1 # already tried against the same master by a given Sentinel, is two # times the failover timeout. # -# - The time needed for a slave replicating to a wrong master according +# - The time needed for a replica replicating to a wrong master according # to a Sentinel current configuration, to be forced to replicate # with the right master, is exactly the failover timeout (counting since # the moment a Sentinel detected the misconfiguration). # # - The time needed to cancel a failover that is already in progress but # did not produced any configuration change (SLAVEOF NO ONE yet not -# acknowledged by the promoted slave). +# acknowledged by the promoted replica). # -# - The maximum time a failover in progress waits for all the slaves to be -# reconfigured as slaves of the new master. However even after this time -# the slaves will be reconfigured by the Sentinels anyway, but not with +# - The maximum time a failover in progress waits for all the replicas to be +# reconfigured as replicas of the new master. However even after this time +# the replicas will be reconfigured by the Sentinels anyway, but not with # the exact parallel-syncs progression as specified. # # Default is 3 minutes. @@ -169,7 +200,7 @@ sentinel failover-timeout mymaster 180000 # is either "leader" or "observer" # # The arguments from-ip, from-port, to-ip, to-port are used to communicate -# the old address of the master and the new address of the elected slave +# the old address of the master and the new address of the elected replica # (now a master). # # This script should be resistant to multiple invocations. @@ -177,13 +208,37 @@ sentinel failover-timeout mymaster 180000 # Example: # # sentinel client-reconfig-script mymaster /var/redis/reconfig.sh -# + # SECURITY # # By default SENTINEL SET will not be able to change the notification-script # and client-reconfig-script at runtime. This avoids a trivial security issue # where clients can set the script to anything and trigger a failover in order # to get the program executed. - sentinel deny-scripts-reconfig yes +sentinel deny-scripts-reconfig yes +# REDIS COMMANDS RENAMING +# +# Sometimes the Redis server has certain commands, that are needed for Sentinel +# to work correctly, renamed to unguessable strings. This is often the case +# of CONFIG and SLAVEOF in the context of providers that provide Redis as +# a service, and don't want the customers to reconfigure the instances outside +# of the administration console. +# +# In such case it is possible to tell Sentinel to use different command names +# instead of the normal ones. For example if the master "mymaster", and the +# associated replicas, have "CONFIG" all renamed to "GUESSME", I could use: +# +# SENTINEL rename-command mymaster CONFIG GUESSME +# +# After such configuration is set, every time Sentinel would use CONFIG it will +# use GUESSME instead. Note that there is no actual need to respect the command +# case, so writing "config guessme" is the same in the example above. +# +# SENTINEL SET can also be used in order to perform this configuration at runtime. +# +# In order to set a command back to its original name (undo the renaming), it +# is possible to just rename a command to itsef: +# +# SENTINEL rename-command mymaster CONFIG CONFIG diff --git a/src/Makefile b/src/Makefile index 86e0b3fe..2a686492 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,6 +21,11 @@ NODEPS:=clean distclean # Default settings STD=-std=c99 -pedantic -DREDIS_STATIC='' +ifneq (,$(findstring clang,$(CC))) +ifneq (,$(findstring FreeBSD,$(uname_S))) + STD+=-Wno-c11-extensions +endif +endif WARN=-Wall -W -Wno-missing-field-initializers OPT=$(OPTIMIZATION) @@ -39,9 +44,13 @@ endif endif # To get ARM stack traces if Redis crashes we need a special C flag. +ifneq (,$(filter aarch64 armv,$(uname_M))) + CFLAGS+=-funwind-tables +else ifneq (,$(findstring armv,$(uname_M))) CFLAGS+=-funwind-tables endif +endif # Backwards compatibility for selecting an allocator ifeq ($(USE_TCMALLOC),yes) @@ -93,14 +102,25 @@ else ifeq ($(uname_S),OpenBSD) # OpenBSD FINAL_LIBS+= -lpthread + ifeq ($(USE_BACKTRACE),yes) + FINAL_CFLAGS+= -DUSE_BACKTRACE -I/usr/local/include + FINAL_LDFLAGS+= -L/usr/local/lib + FINAL_LIBS+= -lexecinfo + endif + else ifeq ($(uname_S),FreeBSD) # FreeBSD - FINAL_LIBS+= -lpthread + FINAL_LIBS+= -lpthread -lexecinfo +else +ifeq ($(uname_S),DragonFly) + # FreeBSD + FINAL_LIBS+= -lpthread -lexecinfo else # All the other OSes (notably Linux) FINAL_LDFLAGS+= -rdynamic - FINAL_LIBS+=-ldl -pthread + FINAL_LIBS+=-ldl -pthread -lrt +endif endif endif endif @@ -122,7 +142,7 @@ endif ifeq ($(MALLOC),jemalloc) DEPENDENCY_TARGETS+= jemalloc FINAL_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include - FINAL_LIBS+= ../deps/jemalloc/lib/libjemalloc.a + FINAL_LIBS := ../deps/jemalloc/lib/libjemalloc.a $(FINAL_LIBS) endif REDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS) @@ -144,9 +164,9 @@ endif REDIS_SERVER_NAME=redis-server REDIS_SENTINEL_NAME=redis-sentinel -REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o +REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o REDIS_CLI_NAME=redis-cli -REDIS_CLI_OBJ=anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o +REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o REDIS_BENCHMARK_NAME=redis-benchmark REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o zmalloc.o redis-benchmark.o REDIS_CHECK_RDB_NAME=redis-check-rdb @@ -290,3 +310,6 @@ install: all $(REDIS_INSTALL) $(REDIS_CHECK_RDB_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_CHECK_AOF_NAME) $(INSTALL_BIN) @ln -sf $(REDIS_SERVER_NAME) $(INSTALL_BIN)/$(REDIS_SENTINEL_NAME) + +uninstall: + rm -f $(INSTALL_BIN)/{$(REDIS_SERVER_NAME),$(REDIS_BENCHMARK_NAME),$(REDIS_CLI_NAME),$(REDIS_CHECK_RDB_NAME),$(REDIS_CHECK_AOF_NAME),$(REDIS_SENTINEL_NAME)} diff --git a/src/Win32_Interop/Win32_CommandLine.cpp b/src/Win32_Interop/Win32_CommandLine.cpp index 8b62fcd6..d71df471 100644 --- a/src/Win32_Interop/Win32_CommandLine.cpp +++ b/src/Win32_Interop/Win32_CommandLine.cpp @@ -76,7 +76,7 @@ public: virtual vector Extract(vector tokens, int StartIndex = 0) = 0; } ParamExtractor; -typedef map RedisParamterMapper; +typedef map RedisParameterMapper; typedef class FixedParam : public ParamExtractor { private: @@ -282,11 +282,11 @@ static BindParams bp = BindParams(); typedef class SentinelParams : public ParamExtractor { private: - RedisParamterMapper subCommands; + RedisParameterMapper subCommands; public: SentinelParams() { - subCommands = RedisParamterMapper + subCommands = RedisParameterMapper { { "monitor", &fp4 }, // sentinel monitor [master name] [ip] [port] [quorum] { "auth-pass", &fp2 }, // sentinel auth-pass [master name] [password] @@ -357,7 +357,7 @@ public: static SentinelParams sp = SentinelParams(); // Map of argument name to argument processing engine. -static RedisParamterMapper g_redisArgMap = +static RedisParameterMapper g_redisArgMap = { // QFork flags { cQFork, &fp2 }, // qfork [QForkControlMemoryMap handle] [parent process id] @@ -371,69 +371,85 @@ static RedisParamterMapper g_redisArgMap = { cServiceStart, &fp0 }, // service-start { cServiceStop, &fp0 }, // service-stop - // redis commands - { "daemonize", &fp1 }, // daemonize [yes/no] - { "pidfile", &fp1 }, // pidfile [file] + // redis commands (ordered as they appear in config.c/loadServerConfigFromString()) + { "timeout", &fp1 }, // timeout [value] + { "tcp-keepalive", &fp1 }, // tcp-keepalive [value] + { "protected-mode", &fp1 }, // protected-mode [yes/no] { "port", &fp1 }, // port [port number] { "tcp-backlog", &fp1 }, // tcp-backlog [number] { "bind", &bp }, // bind [address] [address] ... { "unixsocket", &fp1 }, // unixsocket [path] - { "timeout", &fp1 }, // timeout [value] - { "tcp-keepalive", &fp1 }, // tcp-keepalive [value] + { "unixsocketperm", &fp1 }, // unixsocketperm [perm] + { "save", &savep }, // save [seconds] [changes] or save "" + { cDir, &fp1 }, // dir [path] { "loglevel", &fp1 }, // lovlevel [value] { "logfile", &fp1 }, // logfile [file] + { "always-show-logo", &fp1 }, // always-show-logo [yes/no] { "syslog-enabled", &fp1 }, // syslog-enabled [yes/no] { "syslog-ident", &fp1 }, // syslog-ident [string] { "syslog-facility", &fp1 }, // syslog-facility [string] { "databases", &fp1 }, // databases [number] - { "save", &savep }, // save [seconds] [changes] or save "" - { "stop-writes-on-bgsave-error", &fp1 }, // stop-writes-on-bgsave-error [yes/no] - { "rdbcompression", &fp1 }, // rdbcompression [yes/no] - { "rdbchecksum", &fp1 }, // rdbchecksum [yes/no] - { "dbfilename", &fp1 }, // dbfilename [filename] - { cDir, &fp1 }, // dir [path] + //"include" is handled in ParseConfFile() + { "maxclients", &fp1 }, // maxclients [number] + { "maxmemory", &fp1 }, // maxmemory [bytes] + { "maxmemory-policy", &fp1 }, // maxmemory-policy [policy] + { "maxmemory-samples", &fp1 }, // maxmemory-samples [number] + { "proto-max-bulk-len", &fp1 }, // proto-max-bulk-len [number] + { "client-query-buffer-limit", &fp1 }, // client-query-buffer-limit [number] + { "lfu-log-factor", &fp1 }, // lfu-log-factor [number] + { "lfu-decay-time", &fp1 }, // lfu-decay-time [number] { "slaveof", &fp2 }, // slaveof [masterip] [master port] - { "replicaof", &fp2 }, // replicaof [masterip] [master port] - { "masterauth", &fp1 }, // masterauth [master-password] - { "slave-serve-stale-data", &fp1 }, // slave-serve-stale-data [yes/no] - { "replica-serve-stale-data", &fp1 }, // replica-serve-stale-data [yes/no] - { "replica-lazy-flush", &fp1}, - { "lazyfree-lazy-server-del", &fp1}, - { "lazyfree-lazy-expire", &fp1}, - { "lazyfree-lazy-eviction", &fp1}, - { "slave-read-only", &fp1 }, // slave-read-only [yes/no] + { "replicaof", &fp2 }, // replicaof [masterip] [master port] { "repl-ping-slave-period", &fp1 }, // repl-ping-slave-period [number] + { "repl-ping-replica-period", &fp1 }, // repl-ping-replica-period [number] { "repl-timeout", &fp1 }, // repl-timeout [number] { "repl-disable-tcp-nodelay", &fp1 }, // repl-disable-tcp-nodelay [yes/no] { "repl-diskless-sync", &fp1 }, // repl-diskless-sync [yes/no] { "repl-diskless-sync-delay", &fp1 }, // repl-diskless-sync-delay [number] { "repl-backlog-size", &fp1 }, // repl-backlog-size [number] { "repl-backlog-ttl", &fp1 }, // repl-backlog-ttl [number] - { "slave-priority", &fp1 }, // slave-priority [number] - { "min-slaves-to-write", &fp1 }, // min-slaves-to-write [number] - { "min-slaves-max-lag", &fp1 }, // min-slaves-max-lag [number] - { "requirepass", &fp1 }, // requirepass [string] - { "rename-command", &fp2 }, // rename-command [command] [string] - { "maxclients", &fp1 }, // maxclients [number] - { "maxmemory", &fp1 }, // maxmemory [bytes] - { "maxmemory-policy", &fp1 }, // maxmemory-policy [policy] - { "maxmemory-samples", &fp1 }, // maxmemory-samples [number] - { "rdb-save-incremental-fsync", &fp1 }, - { "appendonly", &fp1 }, // appendonly [yes/no] + { "masterauth", &fp1 }, // masterauth [master-password] + { "slave-serve-stale-data", &fp1 }, // slave-serve-stale-data [yes/no] + { "replica-serve-stale-data", &fp1 }, // replica-serve-stale-data [yes/no] + { "slave-read-only", &fp1 }, // slave-read-only [yes/no] + { "replica-read-only", &fp1 }, // replica-read-only [yes/no] + { "slave-ignore-maxmemory", &fp1 }, // slave-ignore-maxmemory [yes/no] + { "replica-ignore-maxmemory", &fp1 }, // replica-ignore-maxmemory [yes/no] + { "rdbcompression", &fp1 }, // rdbcompression [yes/no] + { "rdbchecksum", &fp1 }, // rdbchecksum [yes/no] + { "activerehashing", &fp1 }, // activerehashing [yes/no] + { "lazyfree-lazy-eviction", &fp1 }, // lazyfree-lazy-eviction [yes/no] + { "lazyfree-lazy-expire", &fp1 }, // lazyfree-lazy-expire [yes/no] + { "lazyfree-lazy-server-del", &fp1 }, // lazyfree-lazy-server-del [yes/no] + { "slave-lazy-flush", &fp1 }, // slave-lazy-flush [yes/no] + { "replica-lazy-flush", &fp1 }, // replica-lazy-flush [yes/no] + { "activedefrag", &fp1 }, // activedefrag [yes/no] + { "daemonize", &fp1 }, // daemonize [yes/no] + { "dynamic-hz", &fp1 }, // dynamic-hz [yes/no] + { "hz", &fp1 }, // hz [number] + { "appendonly", &fp1 }, // appendonly [yes/no] { "appendfilename", &fp1 }, // appendfilename [filename] + { "no-appendfsync-on-rewrite", &fp1 }, // no-appendfsync-on-rewrite [value] { "appendfsync", &fp1 }, // appendfsync [value] - { "aof-load-truncated", &fp1 }, - { "aof-use-rdb-preamble", &fp1 }, - { "rdb-save-incremental-fsync", &fp1 }, - { "no-appendfsync-on-rewrite", &fp1 }, // no-appendfsync-on-rewrite [value] { "auto-aof-rewrite-percentage", &fp1 }, // auto-aof-rewrite-percentage [number] { "auto-aof-rewrite-min-size", &fp1 }, // auto-aof-rewrite-min-size [number] - { "lua-time-limit", &fp1 }, // lua-time-limit [number] - { "slowlog-log-slower-than", &fp1 }, // slowlog-log-slower-than [number] - { "slowlog-max-len", &fp1 }, // slowlog-max-len [number] - { "notify-keyspace-events", &fp1 }, // notify-keyspace-events [string] + { "aof-rewrite-incremental-fsync", &fp1 }, // aof-rewrite-incremental-fsync [yes/no] + { "rdb-save-incremental-fsync", &fp1 }, // rdb-save-incremental-fsync [yes/no] + { "aof-load-truncated", &fp1 }, // aof-load-truncated [yes/no] + { "aof-use-rdb-preamble", &fp1 }, // aof-use-rdb-preamble [yes/no] + { "requirepass", &fp1 }, // requirepass [string] + { "pidfile", &fp1 }, // pidfile [file] + { "dbfilename", &fp1 }, // dbfilename [filename] + { "active-defrag-threshold-lower", &fp1 }, // active-defrag-threshold-lower [number] + { "active-defrag-threshold-upper", &fp1 }, // active-defrag-threshold-upper [number] + { "active-defrag-ignore-bytes", &fp1 }, // active-defrag-ignore-bytes [number] + { "active-defrag-cycle-min", &fp1 }, // active-defrag-cycle-min [number] + { "active-defrag-cycle-max", &fp1 }, // active-defrag-cycle-max [number] + { "active-defrag-max-scan-fields", &fp1 }, // active-defrag-max-scan-fields [number] { "hash-max-ziplist-entries", &fp1 }, // hash-max-ziplist-entries [number] { "hash-max-ziplist-value", &fp1 }, // hash-max-ziplist-value [number] + { "stream-node-max-bytes", &fp1 }, // stream-node-max-bytes [number] + { "stream-node-max-entries", &fp1 }, // stream-node-max-entries [number] { "list-max-ziplist-entries", &fp1 }, // list-max-ziplist-entries [number] DEAD OPTION { "list-max-ziplist-value", &fp1 }, // list-max-ziplist-value [number] DEAD OPTION { "list-max-ziplist-size", &fp1 }, // list-max-ziplist-size [number] @@ -442,36 +458,42 @@ static RedisParamterMapper g_redisArgMap = { "zset-max-ziplist-entries", &fp1 }, // zset-max-ziplist-entries [number] { "zset-max-ziplist-value", &fp1 }, // zset-max-ziplist-value [number] { "hll-sparse-max-bytes", &fp1 }, // hll-sparse-max-bytes [number] - { "activerehashing", &fp1 }, // activerehashing [yes/no] - { "client-output-buffer-limit", &fp4 }, // client-output-buffer-limit [class] [hard limit] [soft limit] [soft seconds] - { "hz", &fp1 }, // hz [number] - { "aof-rewrite-incremental-fsync", &fp1 }, // aof-rewrite-incremental-fsync [yes/no] - { "aof-load-truncated", &fp1 }, // aof-load-truncated [yes/no] + { "rename-command", &fp2 }, // rename-command [command] [string] + { "cluster-enabled", &fp1 }, // cluster-enabled [yes/no] + { "cluster-config-file", &fp1 }, // cluster-config-file [filename] + { "cluster-announce-ip", &fp1 }, // cluster-announce-ip [string] + { "cluster-announce-port", &fp1 }, // cluster-announce-port [number] + { "cluster-announce-bus-port", &fp1 }, // cluster-announce-bus-port [number] + { "cluster-require-full-coverage", &fp1 }, // cluster-require-full-coverage [yes/no] + { "cluster-node-timeout", &fp1 }, // cluster-node-timeout [number] + { "cluster-migration-barrier", &fp1 }, // cluster-migration-barrier [number] + { "cluster-slave-validity-factor", &fp1 }, // cluster-slave-validity-factor [number] + { "cluster-replica-validity-factor",&fp1 }, // cluster-replica-validity-factor [number] + { "cluster-slave-no-failover", &fp1 }, // cluster-slave-no-failover [yes/no] + { "cluster-replica-no-failover", &fp1 }, // cluster-replica-no-failover [yes/no] + { "lua-time-limit", &fp1 }, // lua-time-limit [number] + { "lua-replicate-commands", &fp1 }, // lua-replicate-commands [yes/no] + { "slowlog-log-slower-than", &fp1 }, // slowlog-log-slower-than [number] { "latency-monitor-threshold", &fp1 }, // latency-monitor-threshold [number] - { "protected-mode", &fp1 }, // protected-mode [yes/no] + { "slowlog-max-len", &fp1 }, // slowlog-max-len [number] + { "client-output-buffer-limit", &fp4 }, // client-output-buffer-limit [class] [hard limit] [soft limit] [soft seconds] + { "stop-writes-on-bgsave-error", &fp1 }, // stop-writes-on-bgsave-error [yes/no] + { "slave-priority", &fp1 }, // slave-priority [number] + { "replica-priority", &fp1 }, // replica-priority [number] + { "slave-announce-ip", &fp1 }, // slave-announce-ip [string] + { "replica-announce-ip", &fp1 }, // replica-announce-ip [string] + { "slave-announce-port", &fp1 }, // slave-announce-port [number] + { "replica-announce-port", &fp1 }, // replica-announce-port [number] + { "min-slaves-to-write", &fp1 }, // min-slaves-to-write [number] + { "min-replicas-to-write", &fp1 }, // min-replicas-to-write [number] + { "min-slaves-max-lag", &fp1 }, // min-slaves-max-lag [number] + { "min-replicas-max-lag", &fp1 }, // min-replicas-max-lag [number] + { "notify-keyspace-events", &fp1 }, // notify-keyspace-events [string] + { "supervised", &fp1 }, // supervised [upstart|systemd|auto|no] + { "loadmodule", &fp1 }, // loadmodule [filename] + { "sentinel", &sp }, // sentinel commands { "watchdog-period", &fp1 }, // watchdog-period [number] - { "supervised", &fp1}, // supervised [upstart|systemd|auto|no] - { cInclude, &fp1 }, // include [path] - {"dynamic-hz", &fp1}, - - // sentinel commands - { "sentinel", &sp }, - - // cluster commands - {"cluster-enabled", &fp1}, // [yes/no] - {"cluster-config-file", &fp1}, // [filename] - {"cluster-node-timeout", &fp1}, // [number] - {"cluster-slave-validity-factor", &fp1}, // [number] - {"cluster-migration-barrier", &fp1}, // [1/0] - {"cluster-require-full-coverage", &fp1}, // [yes/no] - - //streams commands - {"stream-node-max-bytes", &fp1}, - {"stream-node-max-entries", &fp1}, - {"stream-node-max-entries", &fp1}, - - //modules - {"loadmodule", &fp1} // [filename] + { cInclude, &fp1 } // include [path] }; std::vector &split(const std::string &s, char delim, std::vector &elems) { diff --git a/src/ae.c b/src/ae.c index 85ffc6ed..c01df69e 100644 --- a/src/ae.c +++ b/src/ae.c @@ -462,7 +462,7 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags) * before replying to a client. */ int invert = fe->mask & AE_BARRIER; - /* Note the "fe->mask & mask & ..." code: maybe an already + /* Note the "fe->mask & mask & ..." code: maybe an already * processed event removed an element that fired and we still * didn't processed, so we check if the event is still valid. * diff --git a/src/anet.c b/src/anet.c index c3a1cf75..e47a5bd9 100644 --- a/src/anet.c +++ b/src/anet.c @@ -273,7 +273,7 @@ int anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len) { static int anetSetReuseAddr(char *err, int fd) { int yes = 1; - /* Make sure connection-intensive things like the redis benckmark + /* Make sure connection-intensive things like the redis benchmark * will be able to close/open sockets a zillion of times */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { anetSetError(err, "setsockopt SO_REUSEADDR: %s", IF_WIN32(wsa_strerror(errno), strerror(errno))); diff --git a/src/aof.c b/src/aof.c index 510cc806..a33b2122 100644 --- a/src/aof.c +++ b/src/aof.c @@ -900,7 +900,7 @@ uxeof: /* Unexpected AOF end of file. */ if (valid_up_to == -1) { serverLog(LL_WARNING,"Last valid command offset is invalid"); } else { - serverLog(LL_WARNING, "Error truncating the AOF file: %s", + serverLog(LL_WARNING,"Error truncating the AOF file: %s", IF_WIN32(wsa_strerror(errno), strerror(errno))); } } else { @@ -936,7 +936,7 @@ int rioWriteBulkObject(rio *r, robj *obj) { /* Avoid using getDecodedObject to help copy-on-write (we are often * in a child process when this function is called). */ if (obj->encoding == OBJ_ENCODING_INT) { - return (int)rioWriteBulkLongLong(r,(PORT_LONGLONG)((int)obj->ptr)); WIN_PORT_FIX /* cast (int) */ + return (int)rioWriteBulkLongLong(r,(PORT_LONG)obj->ptr); WIN_PORT_FIX /* cast (int) */ } else if (sdsEncodedObject(obj)) { return (int)rioWriteBulkString(r,obj->ptr,sdslen(obj->ptr)); WIN_PORT_FIX /* cast (int) */ } else { diff --git a/src/bio.c b/src/bio.c index 7947d180..76ac51f3 100644 --- a/src/bio.c +++ b/src/bio.c @@ -222,7 +222,7 @@ void *bioProcessBackgroundJobs(void *arg) { } zfree(job); - /* Lock again before reiterating the loop, if there are no longer + /* Lock again before reiterating the loop, if there are no longer * jobs to process we'll block again in pthread_cond_wait(). */ pthread_mutex_lock(&bio_mutex[type]); listDelNode(bio_jobs[type],ln); diff --git a/src/bitops.c b/src/bitops.c index c8c51335..7bf5d293 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -112,10 +112,10 @@ PORT_LONG redisBitpos(void *s, PORT_ULONG count, int bit) { * blocks of 1 or 0 bits compared to the vanilla bit per bit processing. * * Note that if we start from an address that is not aligned - * to sizeof(PORT_ULONG) we consume it byte by byte until it is + * to sizeof(unsigned long) we consume it byte by byte until it is * aligned. */ - /* Skip initial bits not aligned to sizeof(PORT_ULONG) byte by byte. */ + /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */ skipval = bit ? 0 : UCHAR_MAX; c = (unsigned char*) s; found = 0; diff --git a/src/cluster.c b/src/cluster.c index 45daad13..c6aca26e 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -2197,7 +2197,7 @@ void clusterWriteHandler(aeEventLoop *el, int fd, void *privdata, int mask) { nwritten = write(fd, link->sndbuf, sdslen(link->sndbuf)); if (nwritten <= 0) { serverLog(LL_DEBUG,"I/O error writing to node link: %s", - strerror(errno)); + (nwritten == -1) ? strerror(errno) : "short write"); handleLinkIOError(link); return; } @@ -3645,7 +3645,7 @@ void clusterCron(void) { if (nodeIsSlave(myself)) { clusterHandleManualFailover(); if (!(server.cluster_module_flags & CLUSTER_MODULE_FLAG_NO_FAILOVER)) - clusterHandleSlaveFailover(); + clusterHandleSlaveFailover(); /* If there are orphaned slaves, and we are a slave among the masters * with the max number of non-failing slaves, consider migrating to * the orphaned masters. Note that it does not make sense to try @@ -4572,7 +4572,7 @@ NULL /* Produce the reply protocol. */ addReplySds(c,sdscatprintf(sdsempty(),"$%Iu\r\n", WIN_PORT_FIX /* %lu -> %Iu */ - (PORT_ULONG)sdslen(info))); + (PORT_ULONG)sdslen(info))); addReplySds(c,info); addReply(c,shared.crlf); } else if (!strcasecmp(c->argv[1]->ptr,"saveconfig") && c->argc == 2) { diff --git a/src/config.c b/src/config.c index d709b82f..84075bf8 100644 --- a/src/config.c +++ b/src/config.c @@ -129,7 +129,7 @@ const char *configEnumGetName(configEnum *ce, int val) { return NULL; } -/* Wrapper for configEnumGetName() returning "unknown" insetad of NULL if +/* Wrapper for configEnumGetName() returning "unknown" instead of NULL if * there is no match. */ const char *configEnumGetNameOrUnknown(configEnum *ce, int val) { const char *name = configEnumGetName(ce,val); @@ -2376,6 +2376,6 @@ NULL } } else { addReplySubcommandSyntaxError(c); - return; + return; } } diff --git a/src/db.c b/src/db.c index ed917fa6..d8e7328b 100644 --- a/src/db.c +++ b/src/db.c @@ -182,7 +182,7 @@ void dbAdd(redisDb *db, robj *key, robj *val) { val->type == OBJ_ZSET) signalKeyAsReady(db, key); if (server.cluster_enabled) slotToKeyAdd(key); - } +} /* Overwrite an existing key with a new value. Incrementing the reference * count of the new value is up to the caller. @@ -194,7 +194,7 @@ void dbOverwrite(redisDb *db, robj *key, robj *val) { serverAssertWithInfo(NULL,key,de != NULL); dictEntry auxentry = *de; - robj *old = dictGetVal(de); + robj *old = dictGetVal(de); if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { val->lru = old->lru; } @@ -343,7 +343,7 @@ robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) { * database(s). Otherwise -1 is returned in the specific case the * DB number is out of range, and errno is set to EINVAL. */ PORT_LONGLONG emptyDb(int dbnum, int flags, void(callback)(void*)) { - int j, async = (flags & EMPTYDB_ASYNC); + int async = (flags & EMPTYDB_ASYNC); PORT_LONGLONG removed = 0; if (dbnum < -1 || dbnum >= server.dbnum) { @@ -1397,7 +1397,7 @@ int *georadiusGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numk for (i = 5; i < argc; i++) { char *arg = argv[i]->ptr; /* For the case when user specifies both "store" and "storedist" options, the - * second key specified would override the first key. This behavior is kept + * second key specified would override the first key. This behavior is kept * the same as in georadiusCommand method. */ if ((!strcasecmp(arg, "store") || !strcasecmp(arg, "storedist")) && ((i+1) < argc)) { @@ -1418,7 +1418,7 @@ int *georadiusGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numk if(num > 1) { keys[1] = stored_key; } - *numkeys = num; + *numkeys = num; return keys; } diff --git a/src/debug.c b/src/debug.c index 008e5a39..39df0789 100644 --- a/src/debug.c +++ b/src/debug.c @@ -42,7 +42,11 @@ #ifdef HAVE_BACKTRACE #include +#ifndef __OpenBSD__ #include +#else +typedef ucontext_t sigcontext_t; +#endif #include #include "bio.h" #include @@ -121,98 +125,98 @@ void mixStringObjectDigest(unsigned char *digest, robj *o) { * present. */ void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o) { uint32_t aux = htonl(o->type); - mixDigest(digest,&aux,sizeof(aux)); - PORT_LONGLONG expiretime = getExpire(db,keyobj); - char buf[128]; + mixDigest(digest,&aux,sizeof(aux)); + PORT_LONGLONG expiretime = getExpire(db,keyobj); + char buf[128]; - /* Save the key and associated value */ - if (o->type == OBJ_STRING) { + /* Save the key and associated value */ + if (o->type == OBJ_STRING) { mixStringObjectDigest(digest,o); - } else if (o->type == OBJ_LIST) { - listTypeIterator *li = listTypeInitIterator(o,0,LIST_TAIL); - listTypeEntry entry; - while(listTypeNext(li,&entry)) { - robj *eleobj = listTypeGet(&entry); + } else if (o->type == OBJ_LIST) { + listTypeIterator *li = listTypeInitIterator(o,0,LIST_TAIL); + listTypeEntry entry; + while(listTypeNext(li,&entry)) { + robj *eleobj = listTypeGet(&entry); mixStringObjectDigest(digest,eleobj); - decrRefCount(eleobj); - } - listTypeReleaseIterator(li); - } else if (o->type == OBJ_SET) { - setTypeIterator *si = setTypeInitIterator(o); - sds sdsele; - while((sdsele = setTypeNextObject(si)) != NULL) { - xorDigest(digest,sdsele,sdslen(sdsele)); - sdsfree(sdsele); - } - setTypeReleaseIterator(si); - } else if (o->type == OBJ_ZSET) { - unsigned char eledigest[20]; + decrRefCount(eleobj); + } + listTypeReleaseIterator(li); + } else if (o->type == OBJ_SET) { + setTypeIterator *si = setTypeInitIterator(o); + sds sdsele; + while((sdsele = setTypeNextObject(si)) != NULL) { + xorDigest(digest,sdsele,sdslen(sdsele)); + sdsfree(sdsele); + } + setTypeReleaseIterator(si); + } else if (o->type == OBJ_ZSET) { + unsigned char eledigest[20]; - if (o->encoding == OBJ_ENCODING_ZIPLIST) { - unsigned char *zl = o->ptr; - unsigned char *eptr, *sptr; - unsigned char *vstr; - unsigned int vlen; - PORT_LONGLONG vll; - double score; + if (o->encoding == OBJ_ENCODING_ZIPLIST) { + unsigned char *zl = o->ptr; + unsigned char *eptr, *sptr; + unsigned char *vstr; + unsigned int vlen; + PORT_LONGLONG vll; + double score; - eptr = ziplistIndex(zl,0); - serverAssert(eptr != NULL); - sptr = ziplistNext(zl,eptr); - serverAssert(sptr != NULL); + eptr = ziplistIndex(zl,0); + serverAssert(eptr != NULL); + sptr = ziplistNext(zl,eptr); + serverAssert(sptr != NULL); - while (eptr != NULL) { - serverAssert(ziplistGet(eptr,&vstr,&vlen,&vll)); - score = zzlGetScore(sptr); + while (eptr != NULL) { + serverAssert(ziplistGet(eptr,&vstr,&vlen,&vll)); + score = zzlGetScore(sptr); - memset(eledigest,0,20); - if (vstr != NULL) { - mixDigest(eledigest,vstr,vlen); - } else { - ll2string(buf,sizeof(buf),vll); - mixDigest(eledigest,buf,strlen(buf)); - } - - snprintf(buf,sizeof(buf),"%.17g",score); - mixDigest(eledigest,buf,strlen(buf)); - xorDigest(digest,eledigest,20); - zzlNext(zl,&eptr,&sptr); - } - } else if (o->encoding == OBJ_ENCODING_SKIPLIST) { - zset *zs = o->ptr; - dictIterator *di = dictGetIterator(zs->dict); - dictEntry *de; - - while((de = dictNext(di)) != NULL) { - sds sdsele = dictGetKey(de); - double *score = dictGetVal(de); - - snprintf(buf,sizeof(buf),"%.17g",*score); - memset(eledigest,0,20); - mixDigest(eledigest,sdsele,sdslen(sdsele)); - mixDigest(eledigest,buf,strlen(buf)); - xorDigest(digest,eledigest,20); - } - dictReleaseIterator(di); + memset(eledigest,0,20); + if (vstr != NULL) { + mixDigest(eledigest,vstr,vlen); } else { - serverPanic("Unknown sorted set encoding"); + ll2string(buf,sizeof(buf),vll); + mixDigest(eledigest,buf,strlen(buf)); } - } else if (o->type == OBJ_HASH) { - hashTypeIterator *hi = hashTypeInitIterator(o); - while (hashTypeNext(hi) != C_ERR) { - unsigned char eledigest[20]; - sds sdsele; - memset(eledigest,0,20); - sdsele = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_KEY); - mixDigest(eledigest,sdsele,sdslen(sdsele)); - sdsfree(sdsele); - sdsele = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_VALUE); - mixDigest(eledigest,sdsele,sdslen(sdsele)); - sdsfree(sdsele); - xorDigest(digest,eledigest,20); - } - hashTypeReleaseIterator(hi); + snprintf(buf,sizeof(buf),"%.17g",score); + mixDigest(eledigest,buf,strlen(buf)); + xorDigest(digest,eledigest,20); + zzlNext(zl,&eptr,&sptr); + } + } else if (o->encoding == OBJ_ENCODING_SKIPLIST) { + zset *zs = o->ptr; + dictIterator *di = dictGetIterator(zs->dict); + dictEntry *de; + + while((de = dictNext(di)) != NULL) { + sds sdsele = dictGetKey(de); + double *score = dictGetVal(de); + + snprintf(buf,sizeof(buf),"%.17g",*score); + memset(eledigest,0,20); + mixDigest(eledigest,sdsele,sdslen(sdsele)); + mixDigest(eledigest,buf,strlen(buf)); + xorDigest(digest,eledigest,20); + } + dictReleaseIterator(di); + } else { + serverPanic("Unknown sorted set encoding"); + } + } else if (o->type == OBJ_HASH) { + hashTypeIterator *hi = hashTypeInitIterator(o); + while (hashTypeNext(hi) != C_ERR) { + unsigned char eledigest[20]; + sds sdsele; + + memset(eledigest,0,20); + sdsele = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_KEY); + mixDigest(eledigest,sdsele,sdslen(sdsele)); + sdsfree(sdsele); + sdsele = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_VALUE); + mixDigest(eledigest,sdsele,sdslen(sdsele)); + sdsfree(sdsele); + xorDigest(digest,eledigest,20); + } + hashTypeReleaseIterator(hi); } else if (o->type == OBJ_STREAM) { streamIterator si; streamIteratorStart(&si,o->ptr,NULL,NULL,0); @@ -234,20 +238,20 @@ void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o) } } streamIteratorStop(&si); - } else if (o->type == OBJ_MODULE) { - RedisModuleDigest md; - moduleValue *mv = o->ptr; - moduleType *mt = mv->type; - moduleInitDigestContext(md); - if (mt->digest) { - mt->digest(&md,mv->value); - xorDigest(digest,md.x,sizeof(md.x)); - } - } else { - serverPanic("Unknown object type"); - } - /* If the key has an expire, add it to the mix */ - if (expiretime != -1) xorDigest(digest,"!!expire!!",10); + } else if (o->type == OBJ_MODULE) { + RedisModuleDigest md; + moduleValue *mv = o->ptr; + moduleType *mt = mv->type; + moduleInitDigestContext(md); + if (mt->digest) { + mt->digest(&md,mv->value); + xorDigest(digest,md.x,sizeof(md.x)); + } + } else { + serverPanic("Unknown object type"); + } + /* If the key has an expire, add it to the mix */ + if (expiretime != -1) xorDigest(digest,"!!expire!!",10); } /* Compute the dataset digest. Since keys, sets elements, hashes elements @@ -527,8 +531,8 @@ NULL sds d = sdsempty(); for (int i = 0; i < 20; i++) d = sdscatprintf(d, "%02x",digest[i]); - addReplyStatus(c,d); - sdsfree(d); + addReplyStatus(c,d); + sdsfree(d); } } else if (!strcasecmp(c->argv[1]->ptr,"sleep") && c->argc == 3) { double dtime = strtod(c->argv[2]->ptr,NULL); diff --git a/src/defrag.c b/src/defrag.c index 4aa44d11..95854e51 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -838,7 +838,7 @@ PORT_LONG defragKey(redisDb *db, dictEntry *de) { /* Defrag scan callback for the main db dictionary. */ void defragScanCallback(void *privdata, const dictEntry *de) { - int defragged = defragKey((redisDb*)privdata, (dictEntry*)de); + PORT_LONG defragged = defragKey((redisDb*)privdata, (dictEntry*)de); server.stat_active_defrag_hits += defragged; if(defragged) server.stat_active_defrag_key_hits++; @@ -876,7 +876,7 @@ float getAllocatorFragmentation(size_t *out_frag_bytes) { if(out_frag_bytes) *out_frag_bytes = frag_bytes; serverLog(LL_DEBUG, - "allocated=%zu, active=%zu, resident=%zu, frag=%.0f%% (%.0f%% rss), frag_bytes=%zu (%zu%% rss)", + "allocated=%zu, active=%zu, resident=%zu, frag=%.0f%% (%.0f%% rss), frag_bytes=%zu (%zu rss)", allocated, active, resident, frag_pct, rss_pct, frag_bytes, rss_bytes); return frag_pct; } @@ -995,35 +995,35 @@ int defragLaterStep(redisDb *db, PORT_LONGLONG endtime) { /* decide if defrag is needed, and at what CPU effort to invest in it */ void computeDefragCycles() { - size_t frag_bytes; - float frag_pct = getAllocatorFragmentation(&frag_bytes); - /* If we're not already running, and below the threshold, exit. */ - if (!server.active_defrag_running) { - if(frag_pct < server.active_defrag_threshold_lower || frag_bytes < server.active_defrag_ignore_bytes) - return; - } - - /* Calculate the adaptive aggressiveness of the defrag */ - int cpu_pct = INTERPOLATE(frag_pct, - server.active_defrag_threshold_lower, - server.active_defrag_threshold_upper, - server.active_defrag_cycle_min, - server.active_defrag_cycle_max); - cpu_pct = LIMIT(cpu_pct, - server.active_defrag_cycle_min, - server.active_defrag_cycle_max); - /* We allow increasing the aggressiveness during a scan, but don't - * reduce it. */ - if (!server.active_defrag_running || - cpu_pct > server.active_defrag_running) - { - server.active_defrag_running = cpu_pct; - serverLog(LL_VERBOSE, - "Starting active defrag, frag=%.0f%%, frag_bytes=%zu, cpu=%d%%", - frag_pct, frag_bytes, cpu_pct); - } + size_t frag_bytes; + float frag_pct = getAllocatorFragmentation(&frag_bytes); + /* If we're not already running, and below the threshold, exit. */ + if (!server.active_defrag_running) { + if(frag_pct < server.active_defrag_threshold_lower || frag_bytes < server.active_defrag_ignore_bytes) + return; } + /* Calculate the adaptive aggressiveness of the defrag */ + int cpu_pct = INTERPOLATE(frag_pct, + server.active_defrag_threshold_lower, + server.active_defrag_threshold_upper, + server.active_defrag_cycle_min, + server.active_defrag_cycle_max); + cpu_pct = LIMIT(cpu_pct, + server.active_defrag_cycle_min, + server.active_defrag_cycle_max); + /* We allow increasing the aggressiveness during a scan, but don't + * reduce it. */ + if (!server.active_defrag_running || + cpu_pct > server.active_defrag_running) + { + server.active_defrag_running = cpu_pct; + serverLog(LL_VERBOSE, + "Starting active defrag, frag=%.0f%%, frag_bytes=%zu, cpu=%d%%", + frag_pct, frag_bytes, cpu_pct); + } +} + /* Perform incremental defragmentation work from the serverCron. * This works in a similar way to activeExpireCycle, in the sense that * we do incremental work across calls. */ @@ -1058,6 +1058,7 @@ void activeDefragCycle(void) { latencyStartMonitor(latency); do { + /* if we're not continuing a scan from the last call or loop, start a new one */ if (!cursor) { /* finish any leftovers from previous db before moving to the next one */ if (db && defragLaterStep(db, endtime)) { diff --git a/src/dict.c b/src/dict.c index f1db7f41..ada0b427 100644 --- a/src/dict.c +++ b/src/dict.c @@ -250,7 +250,7 @@ PORT_LONGLONG timeInMilliseconds(void) { struct timeval tv; gettimeofday(&tv,NULL); - return (((PORT_LONGLONG)tv.tv_sec)*1000)+(tv.tv_usec/1000); + return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000); #endif } @@ -723,9 +723,9 @@ unsigned int dictGetSomeKeys(dict *d, dictEntry **des, unsigned int count) { * the current rehashing index, so we jump if possible. * (this happens when going from big to small table). */ if (i >= d->ht[1].size) - i = (PORT_ULONG) d->rehashidx; WIN_PORT_FIX /* cast (unsigned long) */ - else - continue; + i = (PORT_ULONG) d->rehashidx; WIN_PORT_FIX /* cast (unsigned long) */ + else + continue; } if (i >= d->ht[j].size) continue; /* Out of range for this table. */ dictEntry *he = d->ht[j].table[i]; diff --git a/src/geohash.c b/src/geohash.c index 1ae7a7e0..db5ae025 100644 --- a/src/geohash.c +++ b/src/geohash.c @@ -127,8 +127,8 @@ int geohashEncode(const GeoHashRange *long_range, const GeoHashRange *lat_range, /* Return an error when trying to index outside the supported * constraints. */ - if (longitude > 180 || longitude < -180 || - latitude > 85.05112878 || latitude < -85.05112878) return 0; + if (longitude > GEO_LONG_MAX || longitude < GEO_LONG_MIN || + latitude > GEO_LAT_MAX || latitude < GEO_LAT_MIN) return 0; hash->bits = 0; hash->step = step; @@ -144,8 +144,8 @@ int geohashEncode(const GeoHashRange *long_range, const GeoHashRange *lat_range, (longitude - long_range->min) / (long_range->max - long_range->min); /* convert to fixed point based on the step size */ - lat_offset *= (1 << step); - long_offset *= (1 << step); + lat_offset *= (1ULL << step); + long_offset *= (1ULL << step); hash->bits = interleave64(lat_offset, long_offset); return 1; } diff --git a/src/hyperloglog.c b/src/hyperloglog.c index 4b055135..d7199798 100644 --- a/src/hyperloglog.c +++ b/src/hyperloglog.c @@ -404,11 +404,11 @@ uint64_t MurmurHash64A (const void * key, int len, unsigned int seed) { uint64_t k; #if (BYTE_ORDER == LITTLE_ENDIAN) - #ifdef USE_ALIGNED_ACCESS - memcpy(&k,data,sizeof(uint64_t)); - #else + #ifdef USE_ALIGNED_ACCESS + memcpy(&k,data,sizeof(uint64_t)); + #else k = *((uint64_t*)data); - #endif + #endif #else k = (uint64_t) data[0]; k |= (uint64_t) data[1] << 8; @@ -565,7 +565,7 @@ void hllDenseRegHisto(uint8_t *registers, int* reghisto) { r += 12; } } else { - for (j = 0; j < HLL_REGISTERS; j++) { + for(j = 0; j < HLL_REGISTERS; j++) { PORT_ULONG reg; HLL_DENSE_GET_REGISTER(reg,registers,j); reghisto[reg]++; diff --git a/src/mkreleasehdr.sh b/src/mkreleasehdr.sh index 1ae95886..e6d558b1 100755 --- a/src/mkreleasehdr.sh +++ b/src/mkreleasehdr.sh @@ -2,6 +2,9 @@ GIT_SHA1=`(git show-ref --head --hash=8 2> /dev/null || echo 00000000) | head -n1` GIT_DIRTY=`git diff --no-ext-diff 2> /dev/null | wc -l` BUILD_ID=`uname -n`"-"`date +%s` +if [ -n "$SOURCE_DATE_EPOCH" ]; then + BUILD_ID=$(date -u -d "@$SOURCE_DATE_EPOCH" +%s 2>/dev/null || date -u -r "$SOURCE_DATE_EPOCH" +%s 2>/dev/null || date -u %s) +fi test -f release.h || touch release.h (cat release.h | grep SHA1 | grep $GIT_SHA1) && \ (cat release.h | grep DIRTY | grep $GIT_DIRTY) && exit 0 # Already up-to-date diff --git a/src/module.c b/src/module.c index 5bc77ad3..84008ac3 100644 --- a/src/module.c +++ b/src/module.c @@ -889,7 +889,6 @@ RedisModuleString *RM_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t return o; } - /* Create a new module string object from a printf format and arguments. * The returned string must be freed with RedisModule_FreeString(), unless * automatic memory is enabled. @@ -1112,10 +1111,10 @@ int RM_WrongArity(RedisModuleCtx *ctx) { * initialized to run the timers callbacks. */ client *moduleGetReplyClient(RedisModuleCtx *ctx) { if (ctx->flags & REDISMODULE_CTX_THREAD_SAFE) { - if (ctx->blocked_client) - return ctx->blocked_client->reply_client; + if (ctx->blocked_client) + return ctx->blocked_client->reply_client; else - return NULL; + return NULL; } else { /* If this is a non thread safe context, just return the client * that is running the command if any. This may be NULL as well @@ -1428,33 +1427,33 @@ int RM_GetSelectedDb(RedisModuleCtx *ctx) { } -/* Return the current context's flags. The flags provide information on the +/* Return the current context's flags. The flags provide information on the * current request context (whether the client is a Lua script or in a MULTI), - * and about the Redis instance in general, i.e replication and persistence. - * + * and about the Redis instance in general, i.e replication and persistence. + * * The available flags are: - * + * * * REDISMODULE_CTX_FLAGS_LUA: The command is running in a Lua script - * + * * * REDISMODULE_CTX_FLAGS_MULTI: The command is running inside a transaction - * + * * * REDISMODULE_CTX_FLAGS_REPLICATED: The command was sent over the replication * link by the MASTER * * * REDISMODULE_CTX_FLAGS_MASTER: The Redis instance is a master - * + * * * REDISMODULE_CTX_FLAGS_SLAVE: The Redis instance is a slave - * + * * * REDISMODULE_CTX_FLAGS_READONLY: The Redis instance is read-only - * + * * * REDISMODULE_CTX_FLAGS_CLUSTER: The Redis instance is in cluster mode - * + * * * REDISMODULE_CTX_FLAGS_AOF: The Redis instance has AOF enabled - * + * * * REDISMODULE_CTX_FLAGS_RDB: The instance has RDB enabled - * + * * * REDISMODULE_CTX_FLAGS_MAXMEMORY: The instance has Maxmemory set - * + * * * REDISMODULE_CTX_FLAGS_EVICT: Maxmemory is set and has an eviction * policy that may delete keys * @@ -1465,13 +1464,13 @@ int RM_GetSelectedDb(RedisModuleCtx *ctx) { * reaching the maxmemory level. */ int RM_GetContextFlags(RedisModuleCtx *ctx) { - + int flags = 0; /* Client specific flags */ if (ctx->client) { - if (ctx->client->flags & CLIENT_LUA) + if (ctx->client->flags & CLIENT_LUA) flags |= REDISMODULE_CTX_FLAGS_LUA; - if (ctx->client->flags & CLIENT_MULTI) + if (ctx->client->flags & CLIENT_MULTI) flags |= REDISMODULE_CTX_FLAGS_MULTI; /* Module command recieved from MASTER, is replicated. */ if (ctx->client->flags & CLIENT_MASTER) @@ -1480,14 +1479,14 @@ int RM_GetContextFlags(RedisModuleCtx *ctx) { if (server.cluster_enabled) flags |= REDISMODULE_CTX_FLAGS_CLUSTER; - + if (server.loading) flags |= REDISMODULE_CTX_FLAGS_LOADING; /* Maxmemory and eviction policy */ if (server.maxmemory > 0) { flags |= REDISMODULE_CTX_FLAGS_MAXMEMORY; - + if (server.maxmemory_policy != MAXMEMORY_NO_EVICTION) flags |= REDISMODULE_CTX_FLAGS_EVICT; } @@ -1506,7 +1505,7 @@ int RM_GetContextFlags(RedisModuleCtx *ctx) { if (server.repl_slave_ro) flags |= REDISMODULE_CTX_FLAGS_READONLY; } - + /* OOM flag. */ float level; int retval = getMaxmemoryState(NULL,NULL,NULL,&level); @@ -2726,7 +2725,7 @@ robj **moduleCreateArgvFromUserFormat(const char *cmdname, const char *fmt, int size_t len = va_arg(ap,size_t); argv[argc++] = createStringObject(buf,len); } else if (*p == 'l') { - PORT_LONG ll = va_arg(ap, PORT_LONGLONG); + PORT_LONG ll = va_arg(ap,PORT_LONGLONG); argv[argc++] = createObject(OBJ_STRING,sdsfromlonglong(ll)); } else if (*p == 'v') { /* A vector of strings */ @@ -3382,7 +3381,6 @@ loaderr: /* Iterate over modules, and trigger rdb aux saving for the ones modules types * who asked for it. */ ssize_t rdbSaveModulesAux(rio *rdb, int when) { - size_t total_written = 0; dictIterator *di = dictGetIterator(modules); dictEntry *de; diff --git a/src/networking.c b/src/networking.c index 5a3e1664..4306a221 100644 --- a/src/networking.c +++ b/src/networking.c @@ -261,14 +261,14 @@ int _addReplyToBuffer(client *c, const char *s, size_t len) { if (len > available) return C_ERR; memcpy(c->buf+c->bufpos,s,len); - c->bufpos+= (int)len; WIN_PORT_FIX /* cast (int) */ + c->bufpos+=(int)len; WIN_PORT_FIX /* cast (int) */ return C_OK; } void _addReplyStringToList(client *c, const char *s, size_t len) { if (c->flags & CLIENT_CLOSE_AFTER_REPLY) return; - listNode *ln = listLast(c->reply); + listNode *ln = listLast(c->reply); clientReplyBlock *tail = ln? listNodeValue(ln): NULL; /* Note that 'tail' may be NULL even if we have a tail node, becuase when @@ -317,7 +317,7 @@ void addReply(client *c, robj *obj) { /* For integer encoded strings we just convert it into a string * using our optimized function, and attach the resulting string * to the output buffer. */ - char buf[32]; + char buf[32]; size_t len = ll2string(buf,sizeof(buf),(PORT_LONG)obj->ptr); if (_addReplyToBuffer(c,buf,len) != C_OK) _addReplyStringToList(c,buf,len); @@ -336,7 +336,7 @@ void addReplySds(client *c, sds s) { } if (_addReplyToBuffer(c,s,sdslen(s)) != C_OK) _addReplyStringToList(c,s,sdslen(s)); - sdsfree(s); + sdsfree(s); } /* This low level function just adds whatever protocol you send it to the @@ -902,7 +902,7 @@ void freeClient(client *c) { /* Log link disconnection with slave */ if ((c->flags & CLIENT_SLAVE) && !(c->flags & CLIENT_MONITOR)) { - serverLog(LL_WARNING,"Connection with slave %s lost.", + serverLog(LL_WARNING,"Connection with replica %s lost.", replicationGetSlaveName(c)); } @@ -1088,10 +1088,9 @@ int writeToClient(int fd, client *c, int handler_installed) { /* If we fully sent the object on head go to the next one */ if (c->sentlen == objlen) { - c->reply_bytes -= (PORT_ULONG)o->size; + c->reply_bytes -= (PORT_ULONG)o->size; listDelNode(c->reply,listFirst(c->reply)); c->sentlen = 0; - /* If there are no longer objects in the list, we expect * the count of reply bytes to be exactly zero. */ if (listLength(c->reply) == 0) @@ -1120,13 +1119,8 @@ int writeToClient(int fd, client *c, int handler_installed) { if (errno == EAGAIN) { nwritten = 0; } else { -#ifdef _WIN32 serverLog(LL_VERBOSE, - "Error writing to client: %s", wsa_strerror(errno)); -#else - serverLog(LL_VERBOSE, - "Error writing to client: %s", strerror(errno)); -#endif + "Error writing to client: %s", IF_WIN32(wsa_strerror,strerror)(errno)); freeClient(c); return C_ERR; } @@ -1392,7 +1386,7 @@ static void setProtocolError(const char *errstr, client *c) { * to be '*'. Otherwise for inline commands processInlineBuffer() is called. */ int processMultibulkBuffer(client *c) { char *newline = NULL; - int ok; + int ok; PORT_LONGLONG ll; if (c->multibulklen == 0) { @@ -1482,11 +1476,11 @@ int processMultibulkBuffer(client *c) { if (sdslen(c->querybuf)-c->qb_pos <= (size_t)ll+2) { sdsrange(c->querybuf,c->qb_pos,-1); c->qb_pos = 0; - /* Hint the sds library about the amount of bytes this string is - * going to contain. */ + /* Hint the sds library about the amount of bytes this string is + * going to contain. */ c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2); - } - } + } + } c->bulklen = (PORT_LONG)ll; WIN_PORT_FIX /* cast (PORT_LONG) */ } @@ -1531,6 +1525,7 @@ int processMultibulkBuffer(client *c) { * pending query buffer, already representing a full command, to process. */ void processInputBuffer(client *c) { server.current_client = c; + /* Keep processing while there is something in the input buffer */ while(c->qb_pos < sdslen(c->querybuf)) { /* Return if clients are paused. */ @@ -1992,7 +1987,7 @@ NULL } else { addReply(c,shared.czero); } - }else if (!strcasecmp(c->argv[1]->ptr,"setname") && c->argc == 3) { + } else if (!strcasecmp(c->argv[1]->ptr,"setname") && c->argc == 3) { int j, len = (int)sdslen(c->argv[2]->ptr); WIN_PORT_FIX /* cast (int) */ char *p = c->argv[2]->ptr; diff --git a/src/object.c b/src/object.c index 4193b8a0..a2b0a517 100644 --- a/src/object.c +++ b/src/object.c @@ -473,9 +473,9 @@ robj *tryObjectEncoding(robj *o) { } else { if (o->encoding == OBJ_ENCODING_RAW) { sdsfree(o->ptr); - o->encoding = OBJ_ENCODING_INT; - o->ptr = (void*) value; - return o; + o->encoding = OBJ_ENCODING_INT; + o->ptr = (void*) value; + return o; } else if (o->encoding == OBJ_ENCODING_EMBSTR) { decrRefCount(o); return createStringObjectFromLongLongForValue(value); diff --git a/src/pubsub.c b/src/pubsub.c index f3862652..ed2aee56 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -334,7 +334,7 @@ NULL }; addReplyHelp(c, help); } else if (!strcasecmp(c->argv[1]->ptr,"channels") && - (c->argc == 2 || c->argc ==3)) + (c->argc == 2 || c->argc == 3)) { /* PUBSUB CHANNELS [] */ sds pat = (c->argc == 2) ? NULL : c->argv[2]->ptr; diff --git a/src/quicklist.c b/src/quicklist.c index 8b44bfc5..b2f22cd4 100644 --- a/src/quicklist.c +++ b/src/quicklist.c @@ -149,7 +149,7 @@ REDIS_STATIC quicklistNode *quicklistCreateNode(void) { } /* Return cached quicklist count */ -PORT_ULONG quicklistCount(const quicklist *ql) { return (unsigned int)(ql->count); } WIN_PORT_FIX /* cast (unsigned int) */ +PORT_ULONG quicklistCount(const quicklist *ql) { return (PORT_ULONG)(ql->count); } WIN_PORT_FIX /* cast (unsigned int) */ /* Free entire quicklist. */ void quicklistRelease(quicklist *quicklist) { diff --git a/src/rax.c b/src/rax.c index 0cabaf36..1d896599 100644 --- a/src/rax.c +++ b/src/rax.c @@ -1674,8 +1674,8 @@ int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len) { * * So in that case, we don't seek backward. */ } else { - if (gt && !raxIteratorNextStep(it,0)) return 0; - if (lt && !raxIteratorPrevStep(it,0)) return 0; + if (gt && !raxIteratorNextStep(it,0)) return 0; + if (lt && !raxIteratorPrevStep(it,0)) return 0; } it->flags |= RAX_ITER_JUST_SEEKED; /* Ignore next call. */ } diff --git a/src/rdb.c b/src/rdb.c index 27d02d21..8e810381 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -1009,7 +1009,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) { if (retval == -1) io.error = 1; else - io.bytes += retval; + io.bytes += retval; if (io.ctx) { moduleFreeContext(io.ctx); @@ -1226,7 +1226,7 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) { } } dictReleaseIterator(di); - di = NULL; /* So that we don't release it again on error. */ + di = NULL; /* So that we don't release it again on error. */ } /* If we are storing the replication information on disk, persist @@ -2119,19 +2119,19 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) { decrRefCount(key); decrRefCount(val); } else { - /* Add the new object in the hash table */ - dbAdd(db,key,val); - - /* Set the expire time if needed */ - if (expiretime != -1) setExpire(NULL,db,key,expiretime); + /* Add the new object in the hash table */ + dbAdd(db,key,val); + /* Set the expire time if needed */ + if (expiretime != -1) setExpire(NULL,db,key,expiretime); + /* Set usage information (for eviction). */ objectSetLRUOrLFU(val,lfu_freq,lru_idle,lru_clock); /* Decrement the key refcount since dbAdd() will take its * own reference. */ - decrRefCount(key); - } + decrRefCount(key); + } /* Reset the state that is key-specified and is populated by * opcodes before the key, so that we start from scratch again. */ diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index 43515d88..99ce6eba 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -124,10 +124,10 @@ static PORT_LONGLONG ustime(void) { return GetHighResRelativeTime(1000000); #else struct timeval tv; - PORT_LONGLONG ust; + long long ust; gettimeofday(&tv, NULL); - ust = ((PORT_LONG)tv.tv_sec)*1000000; + ust = ((long)tv.tv_sec)*1000000; ust += tv.tv_usec; return ust; #endif @@ -138,10 +138,10 @@ static PORT_LONGLONG mstime(void) { return GetHighResRelativeTime(1000); #else struct timeval tv; - PORT_LONGLONG mst; + long long mst; gettimeofday(&tv, NULL); - mst = ((PORT_LONGLONG)tv.tv_sec)*1000; + mst = ((long long)tv.tv_sec)*1000; mst += tv.tv_usec/1000; return mst; #endif diff --git a/src/redis-check-aof.c b/src/redis-check-aof.c index 167ac3c3..017bd3ce 100644 --- a/src/redis-check-aof.c +++ b/src/redis-check-aof.c @@ -49,7 +49,7 @@ snprintf(error, sizeof(error), "0x%16llx: %s", (PORT_LONGLONG)epos, __buf); \ } -static char error[1024]; +static char error[1044]; static off_t epos; int consumeNewline(char *buf) { diff --git a/src/redis-check-rdb.c b/src/redis-check-rdb.c index 19ca333a..faebdfa2 100644 --- a/src/redis-check-rdb.c +++ b/src/redis-check-rdb.c @@ -46,7 +46,6 @@ void createSharedObjects(void); void rdbLoadProgressCallback(rio *r, const void *buf, size_t len); -PORT_LONGLONG rdbLoadMillisecondTime(rio *rdb); int rdbCheckMode = 0; struct { diff --git a/src/redis-cli.c b/src/redis-cli.c index 3c2148a5..81e7c5ed 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -811,11 +811,11 @@ static int cliConnect(int flags) { if (context->err) { if (!(flags & CC_QUIET)) { - fprintf(stderr,"Could not connect to Redis at "); - if (config.hostsocket == NULL) + fprintf(stderr,"Could not connect to Redis at "); + if (config.hostsocket == NULL) fprintf(stderr,"%s:%d: %s\n", config.hostip,config.hostport,context->errstr); - else + else fprintf(stderr,"%s: %s\n", config.hostsocket,context->errstr); } @@ -6478,7 +6478,7 @@ static void findBigKeys(int memkeys, unsigned memkeys_samples) { /* Reallocate our type and size array if we need to */ if(keys->elements > arrsize) { - types = zrealloc(types, sizeof(int)*keys->elements); + types = zrealloc(types, sizeof(typeinfo*)*keys->elements); sizes = zrealloc(sizes, sizeof(PORT_ULONGLONG)*keys->elements); if(!types || !sizes) { diff --git a/src/redis-trib.rb b/src/redis-trib.rb index ddf75700..b1af8306 100755 --- a/src/redis-trib.rb +++ b/src/redis-trib.rb @@ -16,7 +16,7 @@ def colorized(str, color) }[color] return str if !color_code "\033[#{color_code}m#{str}\033[0m" - end +end class String @@ -24,10 +24,10 @@ class String color = :"#{color}" define_method(color){ colorized(self, color) - } } + } - end +end COMMANDS = %w(create check info fix reshard rebalance add-node del-node set-timeout call import help) @@ -39,49 +39,49 @@ ALLOWED_OPTIONS={ "reshard" => {"from" => true, "to" => true, "slots" => true, "yes" => false, "timeout" => true, "pipeline" => true}, "rebalance" => {"weight" => [], "auto-weights" => false, "use-empty-masters" => false, "timeout" => true, "simulate" => false, "pipeline" => true, "threshold" => true}, "fix" => {"timeout" => 0}, - } +} - def parse_options(cmd) +def parse_options(cmd) cmd = cmd.downcase idx = 0 - options={} + options = {} args = [] while (arg = ARGV.shift) if arg[0..1] == "--" option = arg[2..-1] - # --verbose is a global option + # --verbose is a global option if option == "--verbose" options['verbose'] = true - next - end + next + end if ALLOWED_OPTIONS[cmd] == nil || ALLOWED_OPTIONS[cmd][option] == nil next - end - if ALLOWED_OPTIONS[cmd][option] != false + end + if ALLOWED_OPTIONS[cmd][option] != false value = ARGV.shift next if !value - else - value = true - end - - # If the option is set to [], it's a multiple arguments - # option. We just queue every new value into an array. - if ALLOWED_OPTIONS[cmd][option] == [] - options[option] = [] if !options[option] - options[option] << value - else - options[option] = value - end else + value = true + end + + # If the option is set to [], it's a multiple arguments + # option. We just queue every new value into an array. + if ALLOWED_OPTIONS[cmd][option] == [] + options[option] = [] if !options[option] + options[option] << value + else + options[option] = value + end + else next if arg[0,1] == '-' args << arg - end end + end return options,args - end +end def command_example(cmd, args, opts) cmd = "redis-cli --cluster #{cmd}" @@ -126,4 +126,4 @@ puts '' puts "To get help about all subcommands, type:" puts "redis-cli --cluster help".bold puts '' - exit 1 +exit 1 diff --git a/src/redisassert.h b/src/redisassert.h index 23af9ba8..908e9ec6 100644 --- a/src/redisassert.h +++ b/src/redisassert.h @@ -38,12 +38,12 @@ #ifndef __REDIS_ASSERT_H__ #define __REDIS_ASSERT_H__ +POSIX_ONLY(#include ) /* for _exit() */ + #ifdef _WIN32 #include "Win32_Interop/Win32_Portability.h" #endif -POSIX_ONLY(#include ) /* for _exit() */ - #define assert(_e) ((_e)?(void)0 : (_serverAssert(#_e,__FILE__,__LINE__),_exit(1))) #define panic(...) _serverPanic(__FILE__,__LINE__,__VA_ARGS__),_exit(1) diff --git a/src/redismodule.h b/src/redismodule.h index 740436d1..bd78e171 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -164,9 +164,9 @@ typedef struct RedisModuleDictIter RedisModuleDictIter; typedef struct RedisModuleCommandFilterCtx RedisModuleCommandFilterCtx; typedef struct RedisModuleCommandFilter RedisModuleCommandFilter; -typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, RedisModuleString **argv, int argc); +typedef int (*RedisModuleCmdFunc)(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); typedef void (*RedisModuleDisconnectFunc)(RedisModuleCtx *ctx, RedisModuleBlockedClient *bc); -typedef int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key); +typedef int (*RedisModuleNotificationFunc)(RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key); typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver); typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value); typedef int (*RedisModuleTypeAuxLoadFunc)(RedisModuleIO *rdb, int encver, int when); diff --git a/src/replication.c b/src/replication.c index 489f5abe..f0d0fd0c 100644 --- a/src/replication.c +++ b/src/replication.c @@ -1355,8 +1355,8 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { server.repl_transfer_lastio = server.unixtime; if ((nwritten = write(server.repl_transfer_fd,buf,nread)) != nread) { - serverLog(LL_WARNING, "Write error or short write writing to the DB dump file needed for MASTER <-> REPLICA synchronization: %s", - (nwritten == -1) ? IF_WIN32(wsa_strerror(errno), strerror(errno)) : "short write"); + serverLog(LL_WARNING,"Write error or short write writing to the DB dump file needed for MASTER <-> REPLICA synchronization: %s", + (nwritten == -1) ? IF_WIN32(wsa_strerror(errno), strerror(errno)) : "short write"); goto error; } server.repl_transfer_read += nread; @@ -1399,7 +1399,7 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { server.repl_transfer_fd = -1; #endif - /* Ensure background save doesn't overwrite synced data */ + /* Ensure background save doesn't overwrite synced data */ if (server.rdb_child_pid != -1) { serverLog(LL_NOTICE, "Replica is about to load the RDB file received from the " @@ -1411,8 +1411,9 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { IF_WIN32(AbortForkOperation(), kill(server.rdb_child_pid,SIGUSR1)); rdbRemoveTempFile(server.rdb_child_pid); } + if (rename(server.repl_transfer_tmpfile,server.rdb_filename) == -1) { - serverLog(LL_WARNING,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", IF_WIN32(wsa_strerror(errno),strerror(errno))); + serverLog(LL_WARNING,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> REPLICA synchronization: %s", IF_WIN32(wsa_strerror(errno),strerror(errno))); cancelReplicationHandshake(); return; } @@ -1507,7 +1508,7 @@ char *sendSynchronousCommand(int flags, int fd, ...) { } va_end(ap); - + cmd = sdscatprintf(cmd,"*%Iu\r\n",argslen); WIN_PORT_FIX /* zu->Iu */ cmd = sdscatsds(cmd,cmdargs); sdsfree(cmdargs); @@ -1527,7 +1528,7 @@ char *sendSynchronousCommand(int flags, int fd, ...) { if (flags & SYNC_CMD_READ) { char buf[256]; - if (syncReadLine(fd,buf,sizeof(buf), (PORT_LONGLONG)server.repl_syncio_timeout*1000) WIN_PORT_FIX /* cast (PORT_LONGLONG) */ + if (syncReadLine(fd,buf,sizeof(buf),(PORT_LONGLONG)server.repl_syncio_timeout*1000) WIN_PORT_FIX /* cast (PORT_LONGLONG) */ == -1) { return sdscatprintf(sdsempty(),"-Reading from master: %s", @@ -2763,11 +2764,11 @@ void replicationCron(void) { clientsArePaused(); if (!manual_failover_in_progress) { - ping_argv[0] = createStringObject("PING",4); - replicationFeedSlaves(server.slaves, server.slaveseldb, - ping_argv, 1); - decrRefCount(ping_argv[0]); - } + ping_argv[0] = createStringObject("PING",4); + replicationFeedSlaves(server.slaves, server.slaveseldb, + ping_argv, 1); + decrRefCount(ping_argv[0]); + } } /* Second, send a newline to all the slaves in pre-synchronization diff --git a/src/rio.c b/src/rio.c index 34159405..32f15e63 100644 --- a/src/rio.c +++ b/src/rio.c @@ -121,7 +121,7 @@ static size_t rioFileWrite(rio *r, const void *buf, size_t len) { r->io.file.buffered >= r->io.file.autosync) { fflush(r->io.file.fp); - redis_fsync(fileno(r->io.file.fp)); + redis_fsync(fileno(r->io.file.fp)); r->io.file.buffered = 0; } return retval; diff --git a/src/scripting.c b/src/scripting.c index af1c8e59..468f97e7 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -504,7 +504,7 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) { goto cleanup; } else if (deny_write_type != DISK_ERROR_TYPE_NONE) { if (deny_write_type == DISK_ERROR_TYPE_RDB) { - luaPushError(lua, shared.bgsaveerr->ptr); + luaPushError(lua, shared.bgsaveerr->ptr); } else { sds aof_write_err = sdscatfmt(sdsempty(), "-MISCONF Errors writing to the AOF file: %s\r\n", @@ -1457,9 +1457,9 @@ void evalGenericCommand(client *c, int evalsha) { resetRefCount(createStringObject("LOAD",4)), script); } else { - rewriteClientCommandArgument(c,0, - resetRefCount(createStringObject("EVAL",4))); - rewriteClientCommandArgument(c,1,script); + rewriteClientCommandArgument(c,0, + resetRefCount(createStringObject("EVAL",4))); + rewriteClientCommandArgument(c,1,script); } forceCommandPropagation(c,PROPAGATE_REPL|PROPAGATE_AOF); } diff --git a/src/sds.c b/src/sds.c index 2481defc..dd9a25bf 100644 --- a/src/sds.c +++ b/src/sds.c @@ -720,7 +720,7 @@ sds sdscatfmt(sds s, char const *fmt, ...) { * s = sdstrim(s,"Aa. :"); * printf("%s\n", s); * - * Output will be just "Hello World". + * Output will be just "HelloWorld". */ sds sdstrim(sds s, const char *cset) { char *start, *end, *sp, *ep; diff --git a/src/sentinel.c b/src/sentinel.c index 7e06b95d..8705e54f 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -2198,7 +2198,7 @@ void sentinelReconnectInstance(sentinelRedisInstance *ri) { retval = redisAsyncCommand(link->pc, sentinelReceiveHelloMessages, ri, "%s %s", sentinelInstanceMapCommand(ri,"SUBSCRIBE"), - SENTINEL_HELLO_CHANNEL); + SENTINEL_HELLO_CHANNEL); if (retval != C_OK) { /* If we can't subscribe, the Pub/Sub connection is useless * and we can simply disconnect it and try again. */ @@ -2744,7 +2744,7 @@ int sentinelSendHello(sentinelRedisInstance *ri) { retval = redisAsyncCommand(ri->link->cc, sentinelPublishReplyCallback, ri, "%s %s %s", sentinelInstanceMapCommand(ri,"PUBLISH"), - SENTINEL_HELLO_CHANNEL,payload); + SENTINEL_HELLO_CHANNEL,payload); if (retval != C_OK) return C_ERR; ri->link->pending_commands++; return C_OK; @@ -3195,7 +3195,7 @@ void sentinelCommand(client *c) { != C_OK) return; ri = getSentinelRedisInstanceByAddrAndRunID(sentinel.masters, - c->argv[2]->ptr, (int) port, NULL); WIN_PORT_FIX /* cast (int) */ + c->argv[2]->ptr,(int)port,NULL); WIN_PORT_FIX /* cast (int) */ /* It exists? Is actually a master? Is subjectively down? It's down. * Note: if we are in tilt mode we always reply with "0". */ @@ -4000,7 +4000,7 @@ char *sentinelGetLeader(sentinelRedisInstance *master, uint64_t epoch) { serverAssert(master->flags & (SRI_O_DOWN|SRI_FAILOVER_IN_PROGRESS)); counters = dictCreate(&leaderVotesDictType,NULL); - voters = (unsigned int)dictSize(master->sentinels)+1; /* All the other sentinels and me. */ WIN_PORT_FIX /* cast (unsigned int) */ + voters = (unsigned int)dictSize(master->sentinels)+1; /* All the other sentinels and me.*/ WIN_PORT_FIX /* cast (unsigned int) */ /* Count other sentinels votes */ di = dictGetIterator(master->sentinels); diff --git a/src/server.c b/src/server.c index a9d5b400..00a0a1c6 100644 --- a/src/server.c +++ b/src/server.c @@ -485,8 +485,8 @@ int dictSdsKeyCompare(void *privdata, const void *key1, int l1,l2; DICT_NOTUSED(privdata); - l1 = (int) sdslen((sds)key1); WIN_PORT_FIX /* cast (int) */ - l2 = (int) sdslen((sds)key2); WIN_PORT_FIX /* cast (int) */ + l1 = (int)sdslen((sds)key1); WIN_PORT_FIX /* cast (int) */ + l2 = (int)sdslen((sds)key2); WIN_PORT_FIX /* cast (int) */ if (l1 != l2) return 0; return memcmp(key1, key2, l1) == 0; } @@ -584,7 +584,7 @@ dictType objectKeyPointerValueDictType = { NULL, /* key dup */ NULL, /* val dup */ dictEncObjKeyCompare, /* key compare */ - dictObjectDestructor, /* key destructor */ + dictObjectDestructor, /* key destructor */ NULL /* val destructor */ }; @@ -796,7 +796,7 @@ void updateDictResizePolicy(void) { void trackInstantaneousMetric(int metric, PORT_LONGLONG current_reading) { PORT_LONGLONG t = mstime() - server.inst_metric[metric].last_sample_time; PORT_LONGLONG ops = current_reading - - server.inst_metric[metric].last_sample_count; + server.inst_metric[metric].last_sample_count; PORT_LONGLONG ops_sec; ops_sec = t > 0 ? (ops*1000/t) : 0; @@ -1013,10 +1013,10 @@ void databasesCron(void) { * as master will synthesize DELs for us. */ if (server.active_expire_enabled) { if (server.masterhost == NULL) { - activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW); + activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW); } else { - expireSlaveKeys(); - } + expireSlaveKeys(); + } } /* Defrag keys gradually. */ @@ -1075,16 +1075,13 @@ void updateCachedTime(void) { * and cache the result. However calling localtime_r in this context is safe * since we will never fork() while here, in the main thread. The logging * function will call a thread safe version of localtime that has no locks. */ -#if _WIN32 - server.daylight_active = 0; //TODO port call to windows -#else - struct tm tm; - localtime_r(&server.unixtime, &tm); - server.daylight_active = tm.tm_isdst; + struct tm tm; +#ifdef _WIN32 + localtime_s(&tm,&server.unixtime); + #else + localtime_r(&server.unixtime,&tm); #endif - - - + server.daylight_active = tm.tm_isdst; } /* This is our timer interrupt, called server.hz times per second. @@ -1297,7 +1294,7 @@ int serverCron(struct aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData } else { /* If there is not a background saving/rewrite in progress check if * we have to save/rewrite now. */ - for (j = 0; j < server.saveparamslen; j++) { + for (j = 0; j < server.saveparamslen; j++) { struct saveparam *sp = server.saveparams+j; /* Save if we reached the given amount of changes, @@ -1317,23 +1314,23 @@ int serverCron(struct aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData rdbSaveBackground(server.rdb_filename,rsiptr); break; } - } + } - /* Trigger an AOF rewrite if needed. */ - if (server.aof_state == AOF_ON && - server.rdb_child_pid == -1 && - server.aof_child_pid == -1 && - server.aof_rewrite_perc && - server.aof_current_size > server.aof_rewrite_min_size) - { + /* Trigger an AOF rewrite if needed. */ + if (server.aof_state == AOF_ON && + server.rdb_child_pid == -1 && + server.aof_child_pid == -1 && + server.aof_rewrite_perc && + server.aof_current_size > server.aof_rewrite_min_size) + { PORT_LONGLONG base = server.aof_rewrite_base_size ? - server.aof_rewrite_base_size : 1; + server.aof_rewrite_base_size : 1; PORT_LONGLONG growth = (server.aof_current_size*100/base) - 100; if (growth >= server.aof_rewrite_perc) { serverLog(LL_NOTICE,"Starting automatic rewriting of AOF on %lld%% growth",growth); rewriteAppendOnlyFileBackground(); } - } + } } @@ -1366,7 +1363,7 @@ int serverCron(struct aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData } /* Run the Sentinel timer if we are in sentinel mode. */ - if (server.sentinel_mode) sentinelTimer(); + if (server.sentinel_mode) sentinelTimer(); /* Cleanup expired MIGRATE cached sockets. */ run_with_period(1000) { @@ -1588,7 +1585,7 @@ void initServerConfig(void) { server.configfile = NULL; server.executable = NULL; server.hz = server.config_hz = CONFIG_DEFAULT_HZ; - server.dynamic_hz = CONFIG_DEFAULT_DYNAMIC_HZ; + server.dynamic_hz = CONFIG_DEFAULT_DYNAMIC_HZ; server.arch_bits = (sizeof(PORT_LONG) == 8) ? 64 : 32; server.port = CONFIG_DEFAULT_SERVER_PORT; server.tcp_backlog = CONFIG_DEFAULT_TCP_BACKLOG; @@ -1787,7 +1784,6 @@ void initServerConfig(void) { extern char **environ; - /* Restart the server, executing the same executable that started this * instance, with the same arguments and configuration file. * @@ -1825,7 +1821,7 @@ int restartServer(int flags, mstime_t delay) { } /* Perform a proper shutdown. */ - if (flags & RESTART_SERVER_GRACEFULLY && + if (flags & RESTART_SERVER_GRACEFULLY && prepareForShutdown(SHUTDOWN_NOFLAGS) != C_OK) { serverLog(LL_WARNING,"Can't restart: error preparing for shutdown"); @@ -1837,16 +1833,19 @@ int restartServer(int flags, mstime_t delay) { for (j = 3; j < server.maxclients + 1024; j++) { /* Test the descriptor validity before closing it, otherwise * Valgrind issues a warning on close(). */ - if (fcntl(j, IF_WIN32(F_GETFL, 1), 0) != -1) close(j); +#if _WIN32 + if (fcntl(j, F_GETFL, 0) != -1) close(j); +#else + if (fcntl(j,F_GETFD) != -1) close(j); +#endif } - /* Execute the server with the original command line. */ if (delay) usleep(delay*1000); zfree(server.exec_argv[0]); server.exec_argv[0] = zstrdup(server.executable); - execve(server.executable, server.exec_argv, environ); - + execve(server.executable,server.exec_argv,environ); + /* If an error occurred here, there is nothing we can do, but exit. */ _exit(1); @@ -3131,9 +3130,9 @@ NULL if (!keys) { addReplyError(c,"Invalid arguments specified for command"); } else { - addReplyMultiBulkLen(c,numkeys); - for (j = 0; j < numkeys; j++) addReplyBulk(c,c->argv[keys[j]+2]); - getKeysFreeResult(keys); + addReplyMultiBulkLen(c,numkeys); + for (j = 0; j < numkeys; j++) addReplyBulk(c,c->argv[keys[j]+2]); + getKeysFreeResult(keys); } } else { addReplySubcommandSyntaxError(c); @@ -3176,7 +3175,7 @@ sds genRedisInfoString(char *section) { sds info = sdsempty(); time_t uptime = server.unixtime-server.stat_starttime; int j; - struct rusage self_ru, c_ru; + struct rusage self_ru, c_ru; int allsections = 0, defsections = 0; int sections = 0; @@ -3186,7 +3185,7 @@ sds genRedisInfoString(char *section) { getrusage(RUSAGE_SELF, &self_ru); getrusage(RUSAGE_CHILDREN, &c_ru); - + /* Server */ if (allsections || defsections || !strcasecmp(section,"server")) { POSIX_ONLY(static int call_uname = 1;) @@ -3227,8 +3226,8 @@ sds genRedisInfoString(char *section) { "uptime_in_seconds:%lld\r\n" WIN_PORT_FIX /* %jd -> %lld */ "uptime_in_days:%lld\r\n" WIN_PORT_FIX /* %jd -> %lld */ "hz:%d\r\n" - "configured_hz:%d\r\n" - "lru_clock:%Id\r\n" WIN_PORT_FIX /* %ld -> %Id */ + "configured_hz:%d\r\n" + "lru_clock:%Id\r\n" WIN_PORT_FIX /* %ld -> %Id */ "executable:%s\r\n" "config_file:%s\r\n", REDIS_VERSION, @@ -3291,7 +3290,7 @@ sds genRedisInfoString(char *section) { size_t zmalloc_used = zmalloc_used_memory(); size_t total_system_mem = server.system_memory_size; const char *evict_policy = evictPolicyToString(); - PORT_LONGLONG memory_lua = (PORT_LONGLONG) lua_gc(server.lua,LUA_GCCOUNT,0)*1024; + PORT_LONGLONG memory_lua = (PORT_LONGLONG)lua_gc(server.lua,LUA_GCCOUNT,0)*1024; struct redisMemOverhead *mh = getMemoryOverheadData(); /* Peak memory is updated from time to time by serverCron() so it @@ -3363,7 +3362,7 @@ sds genRedisInfoString(char *section) { mh->startup_allocated, mh->dataset, mh->dataset_perc, - server.cron_malloc_stats.allocator_allocated, + server.cron_malloc_stats.allocator_allocated, server.cron_malloc_stats.allocator_active, server.cron_malloc_stats.allocator_resident, (PORT_ULONG)total_system_mem, @@ -3582,7 +3581,7 @@ sds genRedisInfoString(char *section) { "master_sync_left_bytes:%lld\r\n" "master_sync_last_io_seconds_ago:%d\r\n" , (PORT_LONGLONG) - (server.repl_transfer_size - server.repl_transfer_read), + (server.repl_transfer_size - server.repl_transfer_read), (int)(server.unixtime-server.repl_transfer_lastio) ); } @@ -3678,14 +3677,14 @@ sds genRedisInfoString(char *section) { if (sections++) info = sdscat(info,"\r\n"); info = sdscatprintf(info, "# CPU\r\n" - "used_cpu_sys:%.2f\r\n" - "used_cpu_user:%.2f\r\n" - "used_cpu_sys_children:%.2f\r\n" - "used_cpu_user_children:%.2f\r\n", - (IF_WIN32(double,float))self_ru.ru_stime.tv_sec+(float)self_ru.ru_stime.tv_usec/1000000, WIN_PORT_FIX /* warning 26451 */ - (IF_WIN32(double,float))self_ru.ru_utime.tv_sec+(float)self_ru.ru_utime.tv_usec/1000000, WIN_PORT_FIX /* warning 26451 */ - (IF_WIN32(double,float))c_ru.ru_stime.tv_sec+(float)c_ru.ru_stime.tv_usec/1000000, WIN_PORT_FIX /* warning 26451 */ - (IF_WIN32(double,float))c_ru.ru_utime.tv_sec+(float)c_ru.ru_utime.tv_usec/1000000); WIN_PORT_FIX /* warning 26451 */ + "used_cpu_sys:%ld.%06ld\r\n" + "used_cpu_user:%ld.%06ld\r\n" + "used_cpu_sys_children:%ld.%06ld\r\n" + "used_cpu_user_children:%ld.%06ld\r\n", + (PORT_LONG)self_ru.ru_stime.tv_sec, (PORT_LONG)self_ru.ru_stime.tv_usec, + (PORT_LONG)self_ru.ru_utime.tv_sec, (PORT_LONG)self_ru.ru_utime.tv_usec, + (PORT_LONG)c_ru.ru_stime.tv_sec, (PORT_LONG)c_ru.ru_stime.tv_usec, + (PORT_LONG)c_ru.ru_utime.tv_sec, (PORT_LONG)c_ru.ru_utime.tv_usec); } /* Command statistics */ @@ -4157,8 +4156,9 @@ int main(int argc, char **argv) { pthread_mutex_init(&moduleGIL, NULL); #endif - srand((unsigned int)time(NULL)^getpid()); WIN_PORT_FIX /* cast (unsigned int) */ + srand((unsigned int)time(NULL)^getpid()); WIN_PORT_FIX /* cast (unsigned int) */ gettimeofday(&tv,NULL); + char hashseed[16]; getRandomHexChars(hashseed,sizeof(hashseed)); dictSetHashFunctionSeed((uint8_t*)hashseed); @@ -4169,7 +4169,7 @@ int main(int argc, char **argv) { /* Store the executable path and arguments in a safe place in order * to be able to restart the server later. */ server.executable = getAbsolutePath(argv[0]); - server.exec_argv = zmalloc(sizeof(char*)*((size_t)argc+1)); + server.exec_argv = zmalloc(sizeof(char*)*((size_t)argc+1)); server.exec_argv[argc] = NULL; for (j = 0; j < argc; j++) server.exec_argv[j] = zstrdup(argv[j]); diff --git a/src/server.h b/src/server.h index 3fed08fc..36f8db86 100644 --- a/src/server.h +++ b/src/server.h @@ -93,7 +93,7 @@ typedef PORT_LONGLONG mstime_t; /* millisecond time type. */ /* Static server configuration */ #define CONFIG_DEFAULT_DYNAMIC_HZ 1 /* Adapt hz to # of clients.*/ -#define CONFIG_DEFAULT_HZ 10 /* Time interrupt calls/sec. */ +#define CONFIG_DEFAULT_HZ 10 /* Time interrupt calls/sec. */ #define CONFIG_MIN_HZ 1 #define CONFIG_MAX_HZ 500 #define MAX_CLIENTS_PER_CLOCK_TICK 200 /* HZ is adapted based on that. */ @@ -666,7 +666,7 @@ typedef struct redisDb { dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */ int id; /* Database ID */ PORT_LONGLONG avg_ttl; /* Average TTL, just for stats */ - list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */ + list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */ } redisDb; /* Client MULTI/EXEC state */ @@ -1049,7 +1049,7 @@ struct redisServer { PORT_LONGLONG slowlog_entry_id; /* SLOWLOG current entry ID */ PORT_LONGLONG slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */ PORT_ULONG slowlog_max_len; /* SLOWLOG max number of items logged */ - struct malloc_stats cron_malloc_stats; /* sampled in serverCron(). */ + struct malloc_stats cron_malloc_stats; /* sampled in serverCron(). */ PORT_LONGLONG stat_net_input_bytes; /* Bytes read from network. */ PORT_LONGLONG stat_net_output_bytes; /* Bytes written to network. */ size_t stat_rdb_cow_bytes; /* Copy on write bytes during RDB saving. */ @@ -1103,7 +1103,7 @@ struct redisServer { int aof_lastbgrewrite_status; /* C_OK or C_ERR */ PORT_ULONG aof_delayed_fsync; /* delayed AOF fsync() counter */ int aof_rewrite_incremental_fsync;/* fsync incrementally while aof rewriting? */ - int rdb_save_incremental_fsync; /* fsync incrementally while rdb saving? */ + int rdb_save_incremental_fsync; /* fsync incrementally while rdb saving? */ int aof_last_write_status; /* C_OK or C_ERR */ int aof_last_write_errno; /* Valid if aof_last_write_status is ERR */ int aof_load_truncated; /* Don't stop on unexpected AOF EOF. */ @@ -1212,7 +1212,7 @@ struct redisServer { list *clients_waiting_acks; /* Clients waiting in WAIT command. */ int get_ack_from_slaves; /* If true we send REPLCONF GETACK. */ /* Limits */ - PORT_ULONGLONG maxclients; /* Max number of simultaneous clients */ + unsigned int maxclients; /* Max number of simultaneous clients */ PORT_ULONGLONG maxmemory; /* Max number of memory bytes to use */ int maxmemory_policy; /* Policy for key eviction */ int maxmemory_samples; /* Pricision of random sampling */ diff --git a/src/server_options.txt b/src/server_options.txt new file mode 100644 index 00000000..b465b2b2 --- /dev/null +++ b/src/server_options.txt @@ -0,0 +1,632 @@ + /* 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],"tcp-keepalive") && argc == 2) { + server.tcpkeepalive = atoi(argv[1]); + if (server.tcpkeepalive < 0) { + err = "Invalid tcp-keepalive value"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"protected-mode") && argc == 2) { + if ((server.protected_mode = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"port") && argc == 2) { + server.port = atoi(argv[1]); + if (server.port < 0 || server.port > 65535) { + err = "Invalid port"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"tcp-backlog") && argc == 2) { + server.tcp_backlog = atoi(argv[1]); + if (server.tcp_backlog < 0) { + err = "Invalid backlog value"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"bind") && argc >= 2) { + int j, addresses = argc-1; + + if (addresses > CONFIG_BINDADDR_MAX) { + err = "Too many bind addresses specified"; goto loaderr; + } + for (j = 0; j < addresses; j++) + server.bindaddr[j] = zstrdup(argv[j+1]); + server.bindaddr_count = addresses; + } else if (!strcasecmp(argv[0],"unixsocket") && argc == 2) { + server.unixsocket = zstrdup(argv[1]); + } else if (!strcasecmp(argv[0],"unixsocketperm") && argc == 2) { + errno = 0; + server.unixsocketperm = (mode_t)strtol(argv[1], NULL, 8); + if (errno || server.unixsocketperm > 0777) { + err = "Invalid socket file permissions"; goto loaderr; + } + } 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(); + } + } else if (!strcasecmp(argv[0],"dir") && argc == 2) { + if (chdir(argv[1]) == -1) { + serverLog(LL_WARNING,"Can't chdir to '%s': %s", + argv[1], IF_WIN32(wsa_strerror(errno), strerror(errno))); + exit(1); + } + } else if (!strcasecmp(argv[0],"loglevel") && argc == 2) { + server.verbosity = configEnumGetValue(loglevel_enum,argv[1]); + if (server.verbosity == INT_MIN) { + err = "Invalid log level. " + "Must be one of debug, verbose, notice, warning"; + goto loaderr; + } +#ifdef _WIN32 + setLogVerbosityLevel(server.verbosity); +#endif + } else if (!strcasecmp(argv[0],"logfile") && argc == 2) { + FILE *logfp; + + zfree(server.logfile); +#ifdef _WIN32 + int length = (int)sdslen(argv[1]); + if ((argv[1][0] == '\'' && argv[1][length-1] == '\'') || + (argv[1][0] == '\"' && argv[1][length-1] == '\"')) { + if (length == 2) { + server.logfile = zstrdup("\0"); + } else { + size_t l = (size_t) length - 2 + 1; + char *p = zmalloc(l); + memcpy(p, argv[1]+1, l); + server.logfile = p; + } + } else { + server.logfile = zstrdup(argv[1]); + } +#else + server.logfile = zstrdup(argv[1]); +#endif + if (server.logfile[0] != '\0') { + /* 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", IF_WIN32(wsa_strerror(errno), strerror(errno))); + goto loaderr; +#ifdef _WIN32 + } else { + setLogFile(server.logfile); +#endif + } + fclose(logfp); + } + } else if (!strcasecmp(argv[0],"always-show-logo") && argc == 2) { + if ((server.always_show_logo = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } 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; + } +#ifdef _WIN32 + setSyslogEnabled(server.syslog_enabled); +#endif + } else if (!strcasecmp(argv[0],"syslog-ident") && argc == 2) { + if (server.syslog_ident) zfree(server.syslog_ident); + server.syslog_ident = zstrdup(argv[1]); +#ifdef _WIN32 + setSyslogIdent(server.syslog_ident); +#endif + } else if (!strcasecmp(argv[0],"syslog-facility") && argc == 2) { +#ifdef _WIN32 + // Skip error - just ignore syslog-facility +#else + server.syslog_facility = + configEnumGetValue(syslog_facility_enum,argv[1]); + if (server.syslog_facility == INT_MIN) { + err = "Invalid log facility. Must be one of USER or between LOCAL0-LOCAL7"; + goto loaderr; + } +#endif + } 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) { + loadServerConfig(argv[1],NULL); + } else if (!strcasecmp(argv[0],"maxclients") && argc == 2) { + server.maxclients = atoi(argv[1]); + if (server.maxclients < 1) { + err = "Invalid max clients limit"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"maxmemory") && argc == 2) { + server.maxmemory = memtoll(argv[1],NULL); + } else if (!strcasecmp(argv[0],"maxmemory-policy") && argc == 2) { + server.maxmemory_policy = + configEnumGetValue(maxmemory_policy_enum,argv[1]); + if (server.maxmemory_policy == INT_MIN) { + err = "Invalid maxmemory policy"; + goto loaderr; + } + } 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; + } + } else if ((!strcasecmp(argv[0],"proto-max-bulk-len")) && argc == 2) { + server.proto_max_bulk_len = memtoll(argv[1],NULL); + } else if ((!strcasecmp(argv[0],"client-query-buffer-limit")) && argc == 2) { + server.client_max_querybuf_len = memtoll(argv[1],NULL); + } else if (!strcasecmp(argv[0],"lfu-log-factor") && argc == 2) { + server.lfu_log_factor = atoi(argv[1]); + if (server.lfu_log_factor < 0) { + err = "lfu-log-factor must be 0 or greater"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"lfu-decay-time") && argc == 2) { + server.lfu_decay_time = atoi(argv[1]); + if (server.lfu_decay_time < 0) { + err = "lfu-decay-time must be 0 or greater"; + goto loaderr; + } + } else if ((!strcasecmp(argv[0],"slaveof") || + !strcasecmp(argv[0],"replicaof")) && argc == 3) { + slaveof_linenum = linenum; + server.masterhost = sdsnew(argv[1]); + server.masterport = atoi(argv[2]); + server.repl_state = REPL_STATE_CONNECT; + } else if ((!strcasecmp(argv[0],"repl-ping-slave-period") || + !strcasecmp(argv[0],"repl-ping-replica-period")) && + argc == 2) + { + server.repl_ping_slave_period = atoi(argv[1]); + if (server.repl_ping_slave_period <= 0) { + err = "repl-ping-replica-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; + } + } else if (!strcasecmp(argv[0],"repl-disable-tcp-nodelay") && argc==2) { + if ((server.repl_disable_tcp_nodelay = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"repl-diskless-sync") && argc==2) { + if ((server.repl_diskless_sync = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"repl-diskless-sync-delay") && argc==2) { + server.repl_diskless_sync_delay = atoi(argv[1]); + if (server.repl_diskless_sync_delay < 0) { + err = "repl-diskless-sync-delay can't be negative"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"repl-backlog-size") && argc == 2) { + PORT_LONGLONG size = memtoll(argv[1],NULL); + if (size <= 0) { + err = "repl-backlog-size must be 1 or greater."; + goto loaderr; + } + resizeReplicationBacklog(size); + } else if (!strcasecmp(argv[0],"repl-backlog-ttl") && argc == 2) { + server.repl_backlog_time_limit = atoi(argv[1]); + if (server.repl_backlog_time_limit < 0) { + err = "repl-backlog-ttl can't be negative "; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"masterauth") && argc == 2) { + zfree(server.masterauth); + server.masterauth = argv[1][0] ? zstrdup(argv[1]) : NULL; + } else if ((!strcasecmp(argv[0],"slave-serve-stale-data") || + !strcasecmp(argv[0],"replica-serve-stale-data")) + && argc == 2) + { + if ((server.repl_serve_stale_data = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if ((!strcasecmp(argv[0],"slave-read-only") || + !strcasecmp(argv[0],"replica-read-only")) + && argc == 2) + { + if ((server.repl_slave_ro = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if ((!strcasecmp(argv[0],"slave-ignore-maxmemory") || + !strcasecmp(argv[0],"replica-ignore-maxmemory")) + && argc == 2) + { + if ((server.repl_slave_ignore_maxmemory = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"rdbcompression") && argc == 2) { + if ((server.rdb_compression = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } 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; + } + } 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],"lazyfree-lazy-eviction") && argc == 2) { + if ((server.lazyfree_lazy_eviction = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"lazyfree-lazy-expire") && argc == 2) { + if ((server.lazyfree_lazy_expire = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"lazyfree-lazy-server-del") && argc == 2){ + if ((server.lazyfree_lazy_server_del = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if ((!strcasecmp(argv[0],"slave-lazy-flush") || + !strcasecmp(argv[0],"replica-lazy-flush")) && argc == 2) + { + if ((server.repl_slave_lazy_flush = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"activedefrag") && argc == 2) { + if ((server.active_defrag_enabled = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + if (server.active_defrag_enabled) { +#ifndef HAVE_DEFRAG + err = "active defrag can't be enabled without proper jemalloc support"; goto loaderr; +#endif + } + } else if (!strcasecmp(argv[0],"daemonize") && argc == 2) { + if ((server.daemonize = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"dynamic-hz") && argc == 2) { + if ((server.dynamic_hz = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"hz") && argc == 2) { + server.config_hz = atoi(argv[1]); + if (server.config_hz < CONFIG_MIN_HZ) server.config_hz = CONFIG_MIN_HZ; + if (server.config_hz > CONFIG_MAX_HZ) server.config_hz = CONFIG_MAX_HZ; + } else if (!strcasecmp(argv[0],"appendonly") && argc == 2) { + int yes; + + if ((yes = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + server.aof_state = yes ? AOF_ON : AOF_OFF; + } else if (!strcasecmp(argv[0],"appendfilename") && argc == 2) { + if (!pathIsBaseName(argv[1])) { + err = "appendfilename can't be a path, just a filename"; + goto loaderr; + } + zfree(server.aof_filename); + server.aof_filename = zstrdup(argv[1]); + } else if (!strcasecmp(argv[0],"no-appendfsync-on-rewrite") + && argc == 2) { + if ((server.aof_no_fsync_on_rewrite= yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"appendfsync") && argc == 2) { + server.aof_fsync = configEnumGetValue(aof_fsync_enum,argv[1]); + if (server.aof_fsync == INT_MIN) { + err = "argument must be 'no', 'always' or 'everysec'"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"auto-aof-rewrite-percentage") && + argc == 2) + { + server.aof_rewrite_perc = atoi(argv[1]); + if (server.aof_rewrite_perc < 0) { + err = "Invalid negative percentage for AOF auto rewrite"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"auto-aof-rewrite-min-size") && + argc == 2) + { + server.aof_rewrite_min_size = memtoll(argv[1],NULL); + } else if (!strcasecmp(argv[0],"aof-rewrite-incremental-fsync") && + argc == 2) + { + if ((server.aof_rewrite_incremental_fsync = + yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"rdb-save-incremental-fsync") && + argc == 2) + { + if ((server.rdb_save_incremental_fsync = + yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"aof-load-truncated") && argc == 2) { + if ((server.aof_load_truncated = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"aof-use-rdb-preamble") && argc == 2) { + if ((server.aof_use_rdb_preamble = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"requirepass") && argc == 2) { + if (strlen(argv[1]) > CONFIG_AUTHPASS_MAX_LEN) { + err = "Password is longer than CONFIG_AUTHPASS_MAX_LEN"; + goto loaderr; + } + server.requirepass = argv[1][0] ? zstrdup(argv[1]) : NULL; + } else if (!strcasecmp(argv[0],"pidfile") && argc == 2) { + zfree(server.pidfile); + server.pidfile = zstrdup(argv[1]); + } else if (!strcasecmp(argv[0],"dbfilename") && argc == 2) { + if (!pathIsBaseName(argv[1])) { + err = "dbfilename can't be a path, just a filename"; + goto loaderr; + } + zfree(server.rdb_filename); + server.rdb_filename = zstrdup(argv[1]); + } else if (!strcasecmp(argv[0],"active-defrag-threshold-lower") && argc == 2) { + server.active_defrag_threshold_lower = atoi(argv[1]); + if (server.active_defrag_threshold_lower < 0 || + server.active_defrag_threshold_lower > 1000) { + err = "active-defrag-threshold-lower must be between 0 and 1000"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"active-defrag-threshold-upper") && argc == 2) { + server.active_defrag_threshold_upper = atoi(argv[1]); + if (server.active_defrag_threshold_upper < 0 || + server.active_defrag_threshold_upper > 1000) { + err = "active-defrag-threshold-upper must be between 0 and 1000"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"active-defrag-ignore-bytes") && argc == 2) { + server.active_defrag_ignore_bytes = memtoll(argv[1], NULL); + if (server.active_defrag_ignore_bytes <= 0) { + err = "active-defrag-ignore-bytes must above 0"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"active-defrag-cycle-min") && argc == 2) { + server.active_defrag_cycle_min = atoi(argv[1]); + if (server.active_defrag_cycle_min < 1 || server.active_defrag_cycle_min > 99) { + err = "active-defrag-cycle-min must be between 1 and 99"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"active-defrag-cycle-max") && argc == 2) { + server.active_defrag_cycle_max = atoi(argv[1]); + if (server.active_defrag_cycle_max < 1 || server.active_defrag_cycle_max > 99) { + err = "active-defrag-cycle-max must be between 1 and 99"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"active-defrag-max-scan-fields") && argc == 2) { + server.active_defrag_max_scan_fields = strtoll(argv[1],NULL,10); + if (server.active_defrag_max_scan_fields < 1) { + err = "active-defrag-max-scan-fields must be positive"; + goto loaderr; + } + } 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); + } else if (!strcasecmp(argv[0],"stream-node-max-bytes") && argc == 2) { + server.stream_node_max_bytes = memtoll(argv[1], NULL); + } else if (!strcasecmp(argv[0],"stream-node-max-entries") && argc == 2) { + server.stream_node_max_entries = atoi(argv[1]); + } else if (!strcasecmp(argv[0],"list-max-ziplist-entries") && argc == 2){ + /* DEAD OPTION */ + } else if (!strcasecmp(argv[0],"list-max-ziplist-value") && argc == 2) { + /* DEAD OPTION */ + } else if (!strcasecmp(argv[0],"list-max-ziplist-size") && argc == 2) { + server.list_max_ziplist_size = atoi(argv[1]); + } else if (!strcasecmp(argv[0],"list-compress-depth") && argc == 2) { + server.list_compress_depth = atoi(argv[1]); + } else if (!strcasecmp(argv[0],"set-max-intset-entries") && argc == 2) { + server.set_max_intset_entries = memtoll(argv[1], NULL); + } 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); + } else if (!strcasecmp(argv[0],"hll-sparse-max-bytes") && argc == 2) { + server.hll_sparse_max_bytes = memtoll(argv[1], NULL); + } 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; + } + + /* If the target command name is the empty string we just + * remove it from the command table. */ + retval = dictDelete(server.commands, argv[1]); + serverAssert(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; + } + } + } 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; + } + } else if (!strcasecmp(argv[0],"cluster-config-file") && argc == 2) { + zfree(server.cluster_configfile); + server.cluster_configfile = zstrdup(argv[1]); + } else if (!strcasecmp(argv[0],"cluster-announce-ip") && argc == 2) { + zfree(server.cluster_announce_ip); + server.cluster_announce_ip = zstrdup(argv[1]); + } else if (!strcasecmp(argv[0],"cluster-announce-port") && argc == 2) { + server.cluster_announce_port = atoi(argv[1]); + if (server.cluster_announce_port < 0 || + server.cluster_announce_port > 65535) + { + err = "Invalid port"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"cluster-announce-bus-port") && + argc == 2) + { + server.cluster_announce_bus_port = atoi(argv[1]); + if (server.cluster_announce_bus_port < 0 || + server.cluster_announce_bus_port > 65535) + { + err = "Invalid port"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"cluster-require-full-coverage") && + argc == 2) + { + if ((server.cluster_require_full_coverage = yesnotoi(argv[1])) == -1) + { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"cluster-node-timeout") && argc == 2) { + server.cluster_node_timeout = strtoll(argv[1],NULL,10); + if (server.cluster_node_timeout <= 0) { + err = "cluster node timeout must be 1 or greater"; goto loaderr; + } + } else if (!strcasecmp(argv[0],"cluster-migration-barrier") + && argc == 2) + { + server.cluster_migration_barrier = atoi(argv[1]); + if (server.cluster_migration_barrier < 0) { + err = "cluster migration barrier must zero or positive"; + goto loaderr; + } + } else if ((!strcasecmp(argv[0],"cluster-slave-validity-factor") || + !strcasecmp(argv[0],"cluster-replica-validity-factor")) + && argc == 2) + { + server.cluster_slave_validity_factor = atoi(argv[1]); + if (server.cluster_slave_validity_factor < 0) { + err = "cluster replica validity factor must be zero or positive"; + goto loaderr; + } + } else if ((!strcasecmp(argv[0],"cluster-slave-no-failover") || + !strcasecmp(argv[0],"cluster-replica-no-failover")) && + argc == 2) + { + server.cluster_slave_no_failover = yesnotoi(argv[1]); + if (server.cluster_slave_no_failover == -1) { + err = "argument must be 'yes' or 'no'"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"lua-time-limit") && argc == 2) { + server.lua_time_limit = strtoll(argv[1],NULL,10); + } else if (!strcasecmp(argv[0],"lua-replicate-commands") && argc == 2) { + server.lua_always_replicate_commands = yesnotoi(argv[1]); + } 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],"latency-monitor-threshold") && + argc == 2) + { + server.latency_monitor_threshold = strtoll(argv[1],NULL,10); + if (server.latency_monitor_threshold < 0) { + err = "The latency threshold can't be negative"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"slowlog-max-len") && argc == 2) { + server.slowlog_max_len = (PORT_ULONG)(strtoll(argv[1],NULL,10)); WIN_PORT_FIX /* cast (PORT_ULONG) */ + } else if (!strcasecmp(argv[0],"client-output-buffer-limit") && + argc == 5) + { + int class = getClientTypeByName(argv[1]); + PORT_ULONGLONG hard, soft; + int soft_seconds; + + if (class == -1 || class == CLIENT_TYPE_MASTER) { + err = "Unrecognized client limit class: the user specified " + "an invalid one, or 'master' which has no buffer limits."; + goto loaderr; + } + hard = memtoll(argv[2],NULL); + soft = memtoll(argv[3],NULL); + soft_seconds = atoi(argv[4]); + if (soft_seconds < 0) { + err = "Negative number of seconds in soft limit is invalid"; + 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; + } 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; + } + } else if ((!strcasecmp(argv[0],"slave-priority") || + !strcasecmp(argv[0],"replica-priority")) && argc == 2) + { + server.slave_priority = atoi(argv[1]); + } else if ((!strcasecmp(argv[0],"slave-announce-ip") || + !strcasecmp(argv[0],"replica-announce-ip")) && argc == 2) + { + zfree(server.slave_announce_ip); + server.slave_announce_ip = zstrdup(argv[1]); + } else if ((!strcasecmp(argv[0],"slave-announce-port") || + !strcasecmp(argv[0],"replica-announce-port")) && argc == 2) + { + server.slave_announce_port = atoi(argv[1]); + if (server.slave_announce_port < 0 || + server.slave_announce_port > 65535) + { + err = "Invalid port"; goto loaderr; + } + } else if ((!strcasecmp(argv[0],"min-slaves-to-write") || + !strcasecmp(argv[0],"min-replicas-to-write")) && argc == 2) + { + server.repl_min_slaves_to_write = atoi(argv[1]); + if (server.repl_min_slaves_to_write < 0) { + err = "Invalid value for min-replicas-to-write."; goto loaderr; + } + } else if ((!strcasecmp(argv[0],"min-slaves-max-lag") || + !strcasecmp(argv[0],"min-replicas-max-lag")) && argc == 2) + { + server.repl_min_slaves_max_lag = atoi(argv[1]); + if (server.repl_min_slaves_max_lag < 0) { + err = "Invalid value for min-replicas-max-lag."; goto loaderr; + } + } else if (!strcasecmp(argv[0],"notify-keyspace-events") && argc == 2) { + int flags = keyspaceEventsStringToFlags(argv[1]); + + if (flags == -1) { + err = "Invalid event class character. Use 'g$lshzxeA'."; + goto loaderr; + } + server.notify_keyspace_events = flags; + } else if (!strcasecmp(argv[0],"supervised") && argc == 2) { + server.supervised_mode = + configEnumGetValue(supervised_mode_enum,argv[1]); + + if (server.supervised_mode == INT_MIN) { + err = "Invalid option for 'supervised'. " + "Allowed values: 'upstart', 'systemd', 'auto', or 'no'"; + goto loaderr; + } + } else if (!strcasecmp(argv[0],"loadmodule") && argc >= 2) { + queueLoadModule(argv[1],&argv[2],argc-2); + } 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; + } diff --git a/src/siphash.c b/src/siphash.c index 6c41fe6b..6b941903 100644 --- a/src/siphash.c +++ b/src/siphash.c @@ -142,12 +142,12 @@ uint64_t siphash(const uint8_t *in, const size_t inlen, const uint8_t *k) { } switch (left) { - case 7: b |= ((uint64_t)in[6]) << 48; - case 6: b |= ((uint64_t)in[5]) << 40; - case 5: b |= ((uint64_t)in[4]) << 32; - case 4: b |= ((uint64_t)in[3]) << 24; - case 3: b |= ((uint64_t)in[2]) << 16; - case 2: b |= ((uint64_t)in[1]) << 8; + case 7: b |= ((uint64_t)in[6]) << 48; /* fall-thru */ + case 6: b |= ((uint64_t)in[5]) << 40; /* fall-thru */ + case 5: b |= ((uint64_t)in[4]) << 32; /* fall-thru */ + case 4: b |= ((uint64_t)in[3]) << 24; /* fall-thru */ + case 3: b |= ((uint64_t)in[2]) << 16; /* fall-thru */ + case 2: b |= ((uint64_t)in[1]) << 8; /* fall-thru */ case 1: b |= ((uint64_t)in[0]); break; case 0: break; } @@ -202,12 +202,12 @@ uint64_t siphash_nocase(const uint8_t *in, const size_t inlen, const uint8_t *k) } switch (left) { - case 7: b |= ((uint64_t)siptlw(in[6])) << 48; - case 6: b |= ((uint64_t)siptlw(in[5])) << 40; - case 5: b |= ((uint64_t)siptlw(in[4])) << 32; - case 4: b |= ((uint64_t)siptlw(in[3])) << 24; - case 3: b |= ((uint64_t)siptlw(in[2])) << 16; - case 2: b |= ((uint64_t)siptlw(in[1])) << 8; + case 7: b |= ((uint64_t)siptlw(in[6])) << 48; /* fall-thru */ + case 6: b |= ((uint64_t)siptlw(in[5])) << 40; /* fall-thru */ + case 5: b |= ((uint64_t)siptlw(in[4])) << 32; /* fall-thru */ + case 4: b |= ((uint64_t)siptlw(in[3])) << 24; /* fall-thru */ + case 3: b |= ((uint64_t)siptlw(in[2])) << 16; /* fall-thru */ + case 2: b |= ((uint64_t)siptlw(in[1])) << 8; /* fall-thru */ case 1: b |= ((uint64_t)siptlw(in[0])); break; case 0: break; } diff --git a/src/t_stream.c b/src/t_stream.c index d120b866..6ef8c644 100644 --- a/src/t_stream.c +++ b/src/t_stream.c @@ -1123,7 +1123,7 @@ int streamGenericParseIDOrReply(client *c, robj *o, streamID *id, uint64_t missi /* Parse - form. */ char *dot = strchr(buf,'-'); if (dot) *dot = '\0'; - PORT_LONGLONG ms, seq; + PORT_ULONGLONG ms, seq; if (string2ull(buf,&ms) == 0) goto invalid; if (dot && string2ull(dot+1,&seq) == 0) goto invalid; if (!dot) seq = missing_seq; diff --git a/src/t_string.c b/src/t_string.c index f406ec06..02498083 100644 --- a/src/t_string.c +++ b/src/t_string.c @@ -307,16 +307,17 @@ void msetGenericCommand(client *c, int nx) { addReplyError(c,"wrong number of arguments for MSET"); return; } + /* Handle the NX flag. The MSETNX semantic is to return zero and don't * set anything if at least one key alerady exists. */ if (nx) { for (j = 1; j < c->argc; j += 2) { if (lookupKeyWrite(c->db,c->argv[j]) != NULL) { - addReply(c, shared.czero); - return; + addReply(c, shared.czero); + return; + } } } - } for (j = 1; j < c->argc; j += 2) { c->argv[j+1] = tryObjectEncoding(c->argv[j+1]); diff --git a/src/t_zset.c b/src/t_zset.c index a73237d5..c5c32860 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -162,7 +162,7 @@ zskiplistNode *zslInsert(zskiplist *zsl, double score, sds ele) { for (i = zsl->level; i < level; i++) { rank[i] = 0; update[i] = zsl->header; - update[i]->level[i].span = zsl->length; + update[i]->level[i].span = zsl->length; } zsl->level = level; } @@ -787,45 +787,42 @@ unsigned int zzlLength(unsigned char *zl) { /* Move to next entry based on the values in eptr and sptr. Both are set to * NULL when there is no next entry. */ -void zzlNext(unsigned char* zl, unsigned char** eptr, unsigned char** sptr) { - unsigned char* l_eptr, * l_sptr; WIN_PORT_FIX /* compiler error: _sptr -> l_sptr */ - serverAssert(*eptr != NULL && *sptr != NULL); +void zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) { + unsigned char *l_eptr, *l_sptr; WIN_PORT_FIX /* compiler error: _sptr -> l_sptr */ + serverAssert(*eptr != NULL && *sptr != NULL); - l_eptr = ziplistNext(zl, *sptr); - if (l_eptr != NULL) { - l_sptr = ziplistNext(zl, l_eptr); - serverAssert(l_sptr != NULL); - } - else { - /* No next entry. */ - l_sptr = NULL; - } + l_eptr = ziplistNext(zl, *sptr); + if (l_eptr != NULL) { + l_sptr = ziplistNext(zl, l_eptr); + serverAssert(l_sptr != NULL); + } else { + /* No next entry. */ + l_sptr = NULL; + } - *eptr = l_eptr; - *sptr = l_sptr; + *eptr = l_eptr; + *sptr = l_sptr; } /* Move to the previous entry based on the values in eptr and sptr. Both are * set to NULL when there is no next entry. */ -void zzlPrev(unsigned char* zl, unsigned char** eptr, unsigned char** sptr) { - unsigned char* l_eptr, * l_sptr; WIN_PORT_FIX /* compiler error: _sptr -> l_sptr */ - serverAssert(*eptr != NULL && *sptr != NULL); +void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) { + unsigned char *l_eptr, *l_sptr; WIN_PORT_FIX /* compiler error: _sptr -> l_sptr */ + serverAssert(*eptr != NULL && *sptr != NULL); - l_sptr = ziplistPrev(zl, *eptr); - if (l_sptr != NULL) { - l_eptr = ziplistPrev(zl, l_sptr); - serverAssert(l_eptr != NULL); - } - else { - /* No previous entry. */ - l_eptr = NULL; - } + l_sptr = ziplistPrev(zl, *eptr); + if (l_sptr != NULL) { + l_eptr = ziplistPrev(zl, l_sptr); + serverAssert(l_eptr != NULL); + } else { + /* No previous entry. */ + l_eptr = NULL; + } - *eptr = l_eptr; - *sptr = l_sptr; + *eptr = l_eptr; + *sptr = l_sptr; } - /* Returns if there is a part of the zset is in range. Should only be used * internally by zzlFirstInRange and zzlLastInRange. */ int zzlIsInRange(unsigned char *zl, zrangespec *range) { @@ -1931,7 +1928,7 @@ void zuiClearIterator(zsetopsrc *op) { } } -int zuiLength(zsetopsrc *op) { +PORT_ULONG zuiLength(zsetopsrc *op) { if (op->subject == NULL) return 0; @@ -1940,7 +1937,7 @@ int zuiLength(zsetopsrc *op) { return intsetLen(op->subject->ptr); } else if (op->encoding == OBJ_ENCODING_HT) { dict *ht = op->subject->ptr; - return (int)dictSize(ht); WIN_PORT_FIX /* cast (int) */ + return dictSize(ht); } else { serverPanic("Unknown set encoding"); } @@ -1949,7 +1946,7 @@ int zuiLength(zsetopsrc *op) { return zzlLength(op->subject->ptr); } else if (op->encoding == OBJ_ENCODING_SKIPLIST) { zset *zs = op->subject->ptr; - return (int)zs->zsl->length; WIN_PORT_FIX /* cast (int) */ + return zs->zsl->length; } else { serverPanic("Unknown sorted set encoding"); } @@ -2186,7 +2183,7 @@ void zunionInterGenericCommand(client *c, robj *dstkey, int op) { zsetopsrc *src; zsetopval zval; sds tmp; - unsigned int maxelelen = 0; + size_t maxelelen = 0; robj *dstobj; zset *dstzset; zskiplistNode *znode; @@ -2310,7 +2307,7 @@ void zunionInterGenericCommand(client *c, robj *dstkey, int op) { tmp = zuiNewSdsFromValue(&zval); znode = zslInsert(dstzset->zsl,score,tmp); dictAdd(dstzset->dict,tmp,&znode->score); - if (sdslen(tmp) > maxelelen) maxelelen = (unsigned int)sdslen(tmp); WIN_PORT_FIX /* cast (unsigned int) */ + if (sdslen(tmp) > maxelelen) maxelelen = sdslen(tmp); } } zuiClearIterator(&src[0]); @@ -2346,7 +2343,7 @@ void zunionInterGenericCommand(client *c, robj *dstkey, int op) { /* Remember the longest single element encountered, * to understand if it's possible to convert to ziplist * at the end. */ - if (sdslen(tmp) > maxelelen) maxelelen = (unsigned int)sdslen(tmp); WIN_PORT_FIX /* cast (unsigned int) */ + if (sdslen(tmp) > maxelelen) maxelelen = sdslen(tmp); /* Update the element with its initial score. */ dictSetKey(accumulator, de, tmp); dictSetDoubleVal(de,score); diff --git a/src/util.c b/src/util.c index 5bb2118a..3c5d3ebf 100644 --- a/src/util.c +++ b/src/util.c @@ -455,7 +455,7 @@ int string2l(const char *s, size_t slen, PORT_LONG *lval) { * a double: no spaces or other characters before or after the string * representing the number are accepted. */ int string2ld(const char *s, size_t slen, PORT_LONGDOUBLE *dp) { - char buf[256]; + char buf[MAX_LONG_DOUBLE_CHARS]; PORT_LONGDOUBLE value; char *eptr; @@ -575,45 +575,44 @@ void getRandomBytes(unsigned char *p, size_t len) { static unsigned char seed[20]; /* The SHA1 seed, from /dev/urandom. */ static uint64_t counter = 0; /* The counter we hash with the seed. */ - - if (!seed_initialized) { - /* Initialize a seed and use SHA1 in counter mode, where we hash - * the same seed with a progressive counter. For the goals of this - * function we just need non-colliding strings, there are no - * cryptographic security needs. */ - FILE *fp = fopen("/dev/urandom","r"); - if (fp == NULL || fread(seed,sizeof(seed),1,fp) != 1) { - /* Revert to a weaker seed, and in this case reseed again - * at every call.*/ - for (unsigned int j = 0; j < sizeof(seed); j++) { - struct timeval tv; - gettimeofday(&tv,NULL); - pid_t pid = getpid(); - seed[j] = tv.tv_sec ^ tv.tv_usec ^ pid ^ (PORT_LONG)fp; - } - } else { - seed_initialized = 1; - } - if (fp) fclose(fp); - } - - while(len) { - unsigned char digest[20]; - SHA1_CTX ctx; - unsigned int copylen = len > 20 ? 20 : len; - - SHA1Init(&ctx); - SHA1Update(&ctx, seed, sizeof(seed)); - SHA1Update(&ctx, (unsigned char*)&counter,sizeof(counter)); - SHA1Final(digest, &ctx); - counter++; - - memcpy(p,digest,copylen); - len -= copylen; - p += copylen; + if (!seed_initialized) { + /* Initialize a seed and use SHA1 in counter mode, where we hash + * the same seed with a progressive counter. For the goals of this + * function we just need non-colliding strings, there are no + * cryptographic security needs. */ + FILE *fp = fopen("/dev/urandom","r"); + if (fp == NULL || fread(seed,sizeof(seed),1,fp) != 1) { + /* Revert to a weaker seed, and in this case reseed again + * at every call.*/ + for (unsigned int j = 0; j < sizeof(seed); j++) { + struct timeval tv; + gettimeofday(&tv,NULL); + pid_t pid = getpid(); + seed[j] = tv.tv_sec ^ tv.tv_usec ^ pid ^ (PORT_LONG)fp; + } + } else { + seed_initialized = 1; } + if (fp) fclose(fp); } + while(len) { + unsigned char digest[20]; + SHA1_CTX ctx; + unsigned int copylen = len > 20 ? 20 : len; + + SHA1Init(&ctx); + SHA1Update(&ctx, seed, sizeof(seed)); + SHA1Update(&ctx, (unsigned char*)&counter,sizeof(counter)); + SHA1Final(digest, &ctx); + counter++; + + memcpy(p,digest,copylen); + len -= copylen; + p += copylen; + } +} + /* Generate the Redis "Run ID", a SHA1-sized random number that identifies a * given execution of Redis, so that if you are talking with an instance * having run_id == A, and you reconnect and it has run_id == B, you can be diff --git a/src/zmalloc.c b/src/zmalloc.c index c08c70f7..980723eb 100644 --- a/src/zmalloc.c +++ b/src/zmalloc.c @@ -37,6 +37,7 @@ #include #include +#include /* This function provide us access to the original libc free(). This is useful * for instance to free results obtained by backtrace_symbols(). We need diff --git a/tests/assets/default.conf b/tests/assets/default.conf index 06e4a61c..d7b8a75c 100644 --- a/tests/assets/default.conf +++ b/tests/assets/default.conf @@ -1,6 +1,6 @@ # Redis configuration for testing. -#always-show-logo yes +always-show-logo yes notify-keyspace-events KEA daemonize no pidfile /var/run/redis.pid diff --git a/tests/cluster/tests/04-resharding.tcl b/tests/cluster/tests/04-resharding.tcl index 40647d6f..68fba135 100644 --- a/tests/cluster/tests/04-resharding.tcl +++ b/tests/cluster/tests/04-resharding.tcl @@ -72,14 +72,13 @@ test "Cluster consistency during live resharding" { puts -nonewline "...Starting resharding..." flush stdout set target [dict get [get_myself [randomInt 5]] id] - # WIN_PORT_FIX: 'exec' -> 'exec ruby' - set tribpid [lindex [exec ruby \ - ../../../src/redis-trib.rb reshard \ - --from all \ - --to $target \ - --slots 100 \ - --yes \ + set tribpid [lindex [exec \ + ../../../src/redis-cli --cluster reshard \ 127.0.0.1:[get_instance_attrib redis 0 port] \ + --cluster-from all \ + --cluster-to $target \ + --cluster-slots 100 \ + --cluster-yes \ | [info nameofexecutable] \ ../tests/helpers/onlydots.tcl \ &] 0] diff --git a/tests/cluster/tests/12-replica-migration-2.tcl b/tests/cluster/tests/12-replica-migration-2.tcl index 175b6d77..3d8b7b04 100644 --- a/tests/cluster/tests/12-replica-migration-2.tcl +++ b/tests/cluster/tests/12-replica-migration-2.tcl @@ -30,11 +30,10 @@ test "Each master should have at least two replicas attached" { set master0_id [dict get [get_myself 0] id] test "Resharding all the master #0 slots away from it" { - # WIN_PORT_FIX: 'exec' -> 'exec ruby' - set output [exec ruby \ - ../../../src/redis-trib.rb rebalance \ - --weight ${master0_id}=0 \ - 127.0.0.1:[get_instance_attrib redis 0 port] >@ stdout] + set output [exec \ + ../../../src/redis-cli --cluster rebalance \ + 127.0.0.1:[get_instance_attrib redis 0 port] \ + --cluster-weight ${master0_id}=0 >@ stdout ] } test "Master #0 should lose its replicas" { @@ -49,12 +48,11 @@ test "Resharding back some slot to master #0" { # Wait for the cluster config to propagate before attempting a # new resharding. after 10000 - # WIN_PORT_FIX: 'exec' -> 'exec ruby' - set output [exec ruby \ - ../../../src/redis-trib.rb rebalance \ - --weight ${master0_id}=.01 \ - --use-empty-masters \ - 127.0.0.1:[get_instance_attrib redis 0 port] >@ stdout] + set output [exec \ + ../../../src/redis-cli --cluster rebalance \ + 127.0.0.1:[get_instance_attrib redis 0 port] \ + --cluster-weight ${master0_id}=.01 \ + --cluster-use-empty-masters >@ stdout] } test "Master #0 should re-acquire one or more replicas" { diff --git a/tests/instances.tcl b/tests/instances.tcl index 3330ffeb..50e1b662 100644 --- a/tests/instances.tcl +++ b/tests/instances.tcl @@ -334,7 +334,7 @@ proc end_tests {} { puts "GOOD! No errors." exit 0 } else { - puts "WARNING $::failed tests faield." + puts "WARNING $::failed test(s) failed." exit 1 } } diff --git a/tests/integration/psync2.tcl b/tests/integration/psync2.tcl index f558618e..d1212b64 100644 --- a/tests/integration/psync2.tcl +++ b/tests/integration/psync2.tcl @@ -34,7 +34,7 @@ start_server {} { set cycle 1 while {([clock seconds]-$start_time) < $duration} { test "PSYNC2: --- CYCLE $cycle ---" {} - incr cycle + incr cycle # Create a random replication layout. # Start with switching master (this simulates a failover). diff --git a/tests/sentinel/tests/00-base.tcl b/tests/sentinel/tests/00-base.tcl index a79d0c37..7fb1a8be 100644 --- a/tests/sentinel/tests/00-base.tcl +++ b/tests/sentinel/tests/00-base.tcl @@ -17,7 +17,7 @@ test "Basic failover works if the master is down" { wait_for_condition 1000 50 { [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port } else { - fail "At least one Sentinel did not received failover info" + fail "At least one Sentinel did not receive failover info" } } restart_instance redis $master_id @@ -108,7 +108,7 @@ test "Failover works if we configure for absolute agreement" { wait_for_condition 1000 50 { [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port } else { - fail "At least one Sentinel did not received failover info" + fail "At least one Sentinel did not receive failover info" } } restart_instance redis $master_id diff --git a/tests/sentinel/tests/01-conf-update.tcl b/tests/sentinel/tests/01-conf-update.tcl index 4998104d..d45b1b08 100644 --- a/tests/sentinel/tests/01-conf-update.tcl +++ b/tests/sentinel/tests/01-conf-update.tcl @@ -16,7 +16,7 @@ test "We can failover with Sentinel 1 crashed" { wait_for_condition 1000 50 { [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port } else { - fail "Sentinel $id did not received failover info" + fail "Sentinel $id did not receive failover info" } } } @@ -30,7 +30,7 @@ test "After Sentinel 1 is restarted, its config gets updated" { wait_for_condition 1000 50 { [lindex [S 1 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port } else { - fail "Restarted Sentinel did not received failover info" + fail "Restarted Sentinel did not receive failover info" } } diff --git a/tests/sentinel/tests/02-slaves-reconf.tcl b/tests/sentinel/tests/02-slaves-reconf.tcl index fa15d2ef..28964c96 100644 --- a/tests/sentinel/tests/02-slaves-reconf.tcl +++ b/tests/sentinel/tests/02-slaves-reconf.tcl @@ -36,7 +36,7 @@ proc 02_crash_and_failover {} { wait_for_condition 1000 50 { [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port } else { - fail "At least one Sentinel did not received failover info" + fail "At least one Sentinel did not receive failover info" } } restart_instance redis $master_id diff --git a/tests/sentinel/tests/05-manual.tcl b/tests/sentinel/tests/05-manual.tcl index 5214fdce..ed568aa0 100644 --- a/tests/sentinel/tests/05-manual.tcl +++ b/tests/sentinel/tests/05-manual.tcl @@ -12,7 +12,7 @@ test "Manual failover works" { wait_for_condition 1000 50 { [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port } else { - fail "At least one Sentinel did not received failover info" + fail "At least one Sentinel did not receive failover info" } } set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] diff --git a/tests/unit/dump.tcl b/tests/unit/dump.tcl index 8bb0165c..09768b80 100644 --- a/tests/unit/dump.tcl +++ b/tests/unit/dump.tcl @@ -25,6 +25,39 @@ start_server {tags {"dump"}} { assert {$ttl >= (2569591501-3000) && $ttl <= 2569591501} r get foo } {bar} + + test {RESTORE can set an absolute expire} { + r set foo bar + set encoded [r dump foo] + r del foo + set now [clock milliseconds] + r restore foo [expr $now+3000] $encoded absttl + set ttl [r pttl foo] + assert {$ttl >= 2900 && $ttl <= 3100} + r get foo + } {bar} + + test {RESTORE can set LRU} { + r set foo bar + set encoded [r dump foo] + r del foo + r config set maxmemory-policy allkeys-lru + r restore foo 0 $encoded idletime 1000 + set idle [r object idletime foo] + assert {$idle >= 1000 && $idle <= 1010} + r get foo + } {bar} + + test {RESTORE can set LFU} { + r set foo bar + set encoded [r dump foo] + r del foo + r config set maxmemory-policy allkeys-lfu + r restore foo 0 $encoded freq 100 + set freq [r object freq foo] + assert {$freq == 100} + r get foo + } {bar} test {RESTORE returns an error of the key already exists} { r set foo bar @@ -246,7 +279,7 @@ start_server {tags {"dump"}} { set e } {*empty string*} - test {MIGRATE with mutliple keys migrate just existing ones} { + test {MIGRATE with multiple keys migrate just existing ones} { set first [srv 0 client] r set key1 "v1" r set key2 "v2" diff --git a/tests/unit/expire.tcl b/tests/unit/expire.tcl index eddc7c30..de24eabe 100644 --- a/tests/unit/expire.tcl +++ b/tests/unit/expire.tcl @@ -121,7 +121,7 @@ start_server {tags {"expire"}} { list $a $b } {somevalue {}} - test {TTL returns tiem to live in seconds} { + test {TTL returns time to live in seconds} { r del x r setex x 10 somevalue set ttl [r ttl x] diff --git a/tests/unit/maxmemory.tcl b/tests/unit/maxmemory.tcl index a5674472..a6e359ba 100644 --- a/tests/unit/maxmemory.tcl +++ b/tests/unit/maxmemory.tcl @@ -186,7 +186,7 @@ proc test_slave_buffers {test_name cmd_count payload_len limit_memory pipeline} # put the slave to sleep set rd_slave [redis_deferring_client] - catch {exec taskkill.exe -F -T -PID $slave_pid} + exec kill -SIGSTOP $slave_pid # send some 10mb worth of commands that don't increase the memory usage if {$pipeline == 1} { @@ -226,7 +226,7 @@ proc test_slave_buffers {test_name cmd_count payload_len limit_memory pipeline} } # unfreeze slave process (after the 'test' succeeded or failed, but before we attempt to terminate the server - catch {exec taskkill.exe -F -T -PID $slave_pid} + exec kill -SIGCONT $slave_pid } } } @@ -235,9 +235,12 @@ proc test_slave_buffers {test_name cmd_count payload_len limit_memory pipeline} # we wanna use many small commands, and we don't wanna wait long # so we need to use a pipeline (redis_deferring_client) # that may cause query buffer to fill and induce eviction, so we disable it -test_slave_buffers {slave buffer are counted correctly} 1000000 10 0 1 +# Redis for Windows: disabled as it requires stopping the slave process (SIGSTOP) and then +# letting it continue (SIGCONT) +#test_slave_buffers {slave buffer are counted correctly} 1000000 10 0 1 # test that slave buffer don't induce eviction # test again with fewer (and bigger) commands without pipeline, but with eviction -test_slave_buffers "replica buffer don't induce eviction" 100000 100 1 0 - +# Redis for Windows: disabled as it requires stopping the slave process (SIGSTOP) and then +# letting it continue (SIGCONT) +#test_slave_buffers "replica buffer don't induce eviction" 100000 100 1 0 diff --git a/tests/unit/memefficiency.tcl b/tests/unit/memefficiency.tcl index 49cef8be..d152e212 100644 --- a/tests/unit/memefficiency.tcl +++ b/tests/unit/memefficiency.tcl @@ -36,18 +36,18 @@ start_server {tags {"memefficiency"}} { } } - start_server {tags {"defrag"}} { - if {[string match {*jemalloc*} [s mem_allocator]]} { - test "Active defrag" { - r config set activedefrag no - r config set active-defrag-threshold-lower 5 +start_server {tags {"defrag"}} { + if {[string match {*jemalloc*} [s mem_allocator]]} { + test "Active defrag" { + r config set activedefrag no + r config set active-defrag-threshold-lower 5 r config set active-defrag-cycle-min 65 r config set active-defrag-cycle-max 75 - r config set active-defrag-ignore-bytes 2mb - r config set maxmemory 100mb - r config set maxmemory-policy allkeys-lru - r debug populate 700000 asdf 150 - r debug populate 170000 asdf 300 + r config set active-defrag-ignore-bytes 2mb + r config set maxmemory 100mb + r config set maxmemory-policy allkeys-lru + r debug populate 700000 asdf 150 + r debug populate 170000 asdf 300 r ping ;# trigger eviction following the previous population after 120 ;# serverCron only updates the info once in 100ms set frag [s allocator_frag_ratio] @@ -191,8 +191,8 @@ start_server {tags {"memefficiency"}} { lassign $event eventname time latency max if {$eventname == "active-defrag-cycle"} { set max_latency $max - } - } + } + } if {$::verbose} { puts "frag $frag" puts "max latency $max_latency" diff --git a/tests/unit/type/hash.tcl b/tests/unit/type/hash.tcl index d2c679d3..deed6419 100644 --- a/tests/unit/type/hash.tcl +++ b/tests/unit/type/hash.tcl @@ -525,12 +525,12 @@ start_server {tags {"hash"}} { # 1.23 cannot be represented correctly with 64 bit doubles, so we skip # the test, since we are only testing pretty printing here and is not # a bug if the program outputs things like 1.299999... - if {!$::valgrind && [string match *x86_64* [exec uname -a]]} { - test {Test HINCRBYFLOAT for correct float representation (issue #2846)} { - r del myhash - assert {[r hincrbyfloat myhash float 1.23] eq {1.23}} - assert {[r hincrbyfloat myhash float 0.77] eq {2}} - assert {[r hincrbyfloat myhash float -0.1] eq {1.9}} - } - } +# if {!$::valgrind && [string match *x86_64* [exec uname -a]]} { +# test {Test HINCRBYFLOAT for correct float representation (issue #2846)} { +# r del myhash +# assert {[r hincrbyfloat myhash float 1.23] eq {1.23}} +# assert {[r hincrbyfloat myhash float 0.77] eq {2}} +# assert {[r hincrbyfloat myhash float -0.1] eq {1.9}} +# } +# } }