summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--00-RELEASENOTES21
-rwxr-xr-xredis.conf67
-rwxr-xr-xruntest15
-rwxr-xr-xsrc/Makefile5
-rw-r--r--src/anet.c63
-rw-r--r--src/anet.h4
-rwxr-xr-xsrc/config.c21
-rw-r--r--src/networking.c4
-rwxr-xr-xsrc/redis.c6
-rwxr-xr-xsrc/redis.h2
-rwxr-xr-xsrc/replication.c7
-rw-r--r--src/sentinel.c10
-rw-r--r--src/t_set.c4
-rw-r--r--src/version.h2
-rw-r--r--src/ziplist.c4
-rw-r--r--tests/assets/default.conf2
-rw-r--r--tests/integration/replication-4.tcl3
-rw-r--r--tests/integration/replication.tcl3
-rw-r--r--tests/test_helper.tcl5
19 files changed, 206 insertions, 42 deletions
diff --git a/00-RELEASENOTES b/00-RELEASENOTES
index 2c5010660..3306784e5 100644
--- a/00-RELEASENOTES
+++ b/00-RELEASENOTES
@@ -14,6 +14,27 @@ HIGH: There is a critical bug that may affect a subset of users. Upgrade!
CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
--------------------------------------------------------------------------------
+--[ Redis 2.6.10 ]
+
+UPGRADE URGENCY: MODERATE, this release contains many non-critical fixes
+ and many small improvements.
+
+* [BUGFIX] redis-cli --rdb, fixed when the server sends newlines to ping.
+* [BUGFIX] redis-cli, minor fixes on connection handling, prompt.
+* [BUGFIX] Slow log: don't log EXEC, just executed commands.
+* [BUGFIX] On failed shutdown don't try again and again compulsively.
+* [BUGFIX] Fix build on sunos without backtrace().
+* [BUGFIX] UNSUBSCRIBE and PUNSUBSCRIBE: always provide a reply (see 742e580)
+* [BUGFIX] Lua struct library was broken, upgraded.
+* [BUGFIX] Fix a bug in srandmemberWithCountCommand() with count argument.
+* [BUGFIX] Test: disable clients timeout to prevent issues on slow systems.
+* [BUGFIX] Sentinel: don't advertise the promoted slave as master too early.
+* [IMPROVED] Whitelist SIGUSR1, see http://redis.io/topics/signals.
+* [IMPROVED] Simpler to understand redis-cli --bigkeys output.
+* [IMPROVED] Test now works with tclsh > 8.5.
+* [IMPROVED] Added option to turn of the Nagle algorithm in slave socket.
+* [IMPROVED] Optionally use SO_KEEPALIVE to detect dead peers.
+
--[ Redis 2.6.9 ]
UPGRADE URGENCY: MODERATE if you use replication.
diff --git a/redis.conf b/redis.conf
index 6da381361..24e0372f4 100755
--- a/redis.conf
+++ b/redis.conf
@@ -39,8 +39,24 @@ port 6379
# Close the connection after a client is idle for N seconds (0 to disable)
timeout 0
-# Set server verbosity to 'debug'
-# it can be one of:
+# TCP keepalive.
+#
+# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
+# of communication. This is useful for two reasons:
+#
+# 1) Detect dead peers.
+# 2) Take the connection alive from the point of view of network
+# equipment in the middle.
+#
+# On Linux, the specified value (in seconds) is the period used to send ACKs.
+# Note that to close the connection the double of the time is needed.
+# On other kernels the period depends on the kernel configuration.
+#
+# A reasonable value for this option is 60 seconds.
+tcp-keepalive 0
+
+# Specify the server verbosity level.
+# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
@@ -59,7 +75,7 @@ logfile stdout
# Specify the syslog identity.
# syslog-ident redis
-# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
+# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0
# Set the number of databases. The default database is DB 0, you can select
@@ -114,7 +130,7 @@ stop-writes-on-bgsave-error yes
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes
-# Since verison 5 of RDB a CRC64 checksum is placed at the end of the file.
+# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
# This makes the format more resistant to corruption but there is a performance
# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
# for maximum performances.
@@ -138,7 +154,7 @@ load-on-startup yes
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
-# Also the Append Only File will be created inside this directory.
+# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir ./
@@ -159,7 +175,7 @@ dir ./
#
# masterauth <master-password>
-# When a slave lost the connection with the master, or when the replication
+# 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:
#
# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will
@@ -207,6 +223,21 @@ slave-read-only yes
# to be maintained and has a slight affect on performance.
conditional-sync yes
+# Disable TCP_NODELAY on the slave 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
+# Linux kernels using a default configuration.
+#
+# If you select "no" the delay for data to appear on the slave 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
+# be a good idea.
+repl-disable-tcp-nodelay no
+
# 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
# master if the master is no longer working correctly.
@@ -241,14 +272,14 @@ slave-priority 100
#
# It is possible to change the name of dangerous commands in a shared
# environment. For instance the CONFIG command may be renamed into something
-# of hard to guess so that it will be still available for internal-use
-# tools but not available for general clients.
+# hard to guess so that it will still be available for internal-use tools
+# but not available for general clients.
#
# Example:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
-# It is also possible to completely kill a command renaming it into
+# It is also possible to completely kill a command by renaming it into
# an empty string:
#
# rename-command CONFIG ""
@@ -292,7 +323,7 @@ slave-priority 100
# maxmemory <bytes>
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
-# is reached? You can select among five behavior:
+# 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 accordingly to the LRU algorithm
@@ -301,7 +332,7 @@ slave-priority 100
# 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
#
-# Note: with all the kind of policies, Redis will return an error on write
+# Note: with any of the above policies, Redis will return an error on write
# operations, when there are not suitable keys for eviction.
#
# At the date of writing this commands are: set setnx setex append
@@ -363,7 +394,7 @@ appendonly no
# always: fsync after every write to the append only log . Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
-# The default is "everysec" that's usually the right compromise between
+# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
@@ -391,9 +422,9 @@ appendfsync everysec
# that will prevent fsync() from being called in the main process while a
# BGSAVE or BGREWRITEAOF is in progress.
#
-# This means that while another child is saving the durability of Redis is
-# the same as "appendfsync none", that in practical terms means that it is
-# possible to lost up to 30 seconds of log in the worst scenario (with the
+# This means that while another child is saving, the durability of Redis is
+# the same as "appendfsync none". In practical terms, this means that it is
+# possible to lose up to 30 seconds of log in the worst scenario (with the
# default Linux settings).
#
# If you have latency problems turn this to "yes". Otherwise leave it as
@@ -402,10 +433,10 @@ no-appendfsync-on-rewrite no
# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
-# BGREWRITEAOF when the AOF log size will growth by the specified percentage.
+# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
-# latest rewrite (or if no rewrite happened since the restart, the size of
+# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
@@ -541,7 +572,7 @@ activerehashing yes
# Instead there is a default limit for pubsub and slave clients, since
# subscribers and slaves receive data in a push fashion.
#
-# Both the hard or the soft limit can be disabled just setting it to zero.
+# 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 pubsub 32mb 8mb 60
diff --git a/runtest b/runtest
index 383e8486a..8c15b8fae 100755
--- a/runtest
+++ b/runtest
@@ -1,9 +1,14 @@
#!/bin/sh
-TCL=tclsh8.5
-which $TCL
-if [ "$?" != "0" ]
+TCL_VERSIONS="8.5 8.6"
+TCLSH=""
+
+for VERSION in $TCL_VERSIONS; do
+ TCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL
+done
+
+if [ -z $TCLSH ]
then
- echo "You need '$TCL' in order to run the Redis test"
+ echo "You need tcl 8.5 or newer in order to run the Redis test"
exit 1
fi
@@ -16,7 +21,7 @@ fi
ln -sf obj.${BUILD_ARCH}/redis-server src/redis-server
ln -sf obj.${BUILD_ARCH}/redis-check-aof src/redis-check-aof
-$TCL tests/test_helper.tcl $*
+$TCLSH tests/test_helper.tcl $*
rm src/redis-server
rm src/redis-check-aof
diff --git a/src/Makefile b/src/Makefile
index ebf5786e2..7a553d030 100755
--- a/src/Makefile
+++ b/src/Makefile
@@ -241,7 +241,10 @@ gcov:
$(MAKE) REDIS_CFLAGS="-fprofile-arcs -ftest-coverage -DCOVERAGE_TEST" REDIS_LDFLAGS="-fprofile-arcs -ftest-coverage"
noopt:
- $(MAKE) OPT="-O0"
+ $(MAKE) OPTIMIZATION="-O0"
+
+valgrind:
+ $(MAKE) OPTIMIZATION="-O0" MALLOC="libc"
src/help.h:
@$(SRCDIR)/../utils/generate-command-help.rb > help.h
diff --git a/src/anet.c b/src/anet.c
index 4da3e28db..963b6688e 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -75,10 +75,56 @@ int anetNonBlock(char *err, int fd)
return ANET_OK;
}
-int anetTcpNoDelay(char *err, int fd)
+/* Set TCP keep alive option to detect dead peers. The interval option
+ * is only used for Linux as we are using Linux-specific APIs to set
+ * the probe send time, interval, and count. */
+int anetKeepAlive(char *err, int fd, int interval)
{
- int yes = 1;
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1)
+ int val = 1;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)
+ {
+ anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno));
+ return ANET_ERR;
+ }
+
+#ifdef __linux__
+ /* Default settings are more or less garbage, with the keepalive time
+ * set to 7200 by default on Linux. Modify settings to make the feature
+ * actually useful. */
+
+ /* Send first probe after interval. */
+ val = interval;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
+ anetSetError(err, "setsockopt TCP_KEEPIDLE: %s\n", strerror(errno));
+ return ANET_ERR;
+ }
+
+ /* Send next probes after the specified interval. Note that we set the
+ * delay as interval / 3, as we send three probes before detecting
+ * an error (see the next setsockopt call). */
+ val = interval/3;
+ if (val == 0) val = 1;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {
+ anetSetError(err, "setsockopt TCP_KEEPINTVL: %s\n", strerror(errno));
+ return ANET_ERR;
+ }
+
+ /* Consider the socket in error state after three we send three ACK
+ * probes without getting a reply. */
+ val = 3;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
+ anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno));
+ return ANET_ERR;
+ }
+#endif
+
+ return ANET_OK;
+}
+
+static int anetSetTcpNoDelay(char *err, int fd, int val)
+{
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1)
{
anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno));
return ANET_ERR;
@@ -86,6 +132,17 @@ int anetTcpNoDelay(char *err, int fd)
return ANET_OK;
}
+int anetEnableTcpNoDelay(char *err, int fd)
+{
+ return anetSetTcpNoDelay(err, fd, 1);
+}
+
+int anetDisableTcpNoDelay(char *err, int fd)
+{
+ return anetSetTcpNoDelay(err, fd, 0);
+}
+
+
int anetSetSendBuffer(char *err, int fd, int buffsize)
{
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1)
diff --git a/src/anet.h b/src/anet.h
index 062b22c56..696c2c225 100644
--- a/src/anet.h
+++ b/src/anet.h
@@ -51,8 +51,10 @@ int anetTcpAccept(char *err, int serversock, char *ip, int *port);
int anetUnixAccept(char *err, int serversock);
int anetWrite(int fd, char *buf, int count);
int anetNonBlock(char *err, int fd);
-int anetTcpNoDelay(char *err, int fd);
+int anetEnableTcpNoDelay(char *err, int fd);
+int anetDisableTcpNoDelay(char *err, int fd);
int anetTcpKeepAlive(char *err, int fd);
int anetPeerToString(int fd, char *ip, int *port);
+int anetKeepAlive(char *err, int fd, int interval);
#endif
diff --git a/src/config.c b/src/config.c
index 71157313c..dbea5513d 100755
--- a/src/config.c
+++ b/src/config.c
@@ -81,6 +81,11 @@ void loadServerConfigFromString(char *config) {
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],"port") && argc == 2) {
server.port = atoi(argv[1]);
if (server.port < 0 || server.port > 65535) {
@@ -238,6 +243,10 @@ void loadServerConfigFromString(char *config) {
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],"masterauth") && argc == 2) {
server.masterauth = zstrdup(argv[1]);
} else if (!strcasecmp(argv[0],"slave-serve-stale-data") && argc == 2) {
@@ -521,6 +530,10 @@ void configSetCommand(redisClient *c) {
if (getLongLongFromObject(o,&ll) == REDIS_ERR ||
ll < 0 || ll > LONG_MAX) goto badfmt;
server.maxidletime = ll;
+ } else if (!strcasecmp(c->argv[2]->ptr,"tcp-keepalive")) {
+ if (getLongLongFromObject(o,&ll) == REDIS_ERR ||
+ ll < 0 || ll > INT_MAX) goto badfmt;
+ server.tcpkeepalive = ll;
} else if (!strcasecmp(c->argv[2]->ptr,"appendfsync")) {
if (!strcasecmp(o->ptr,"no")) {
server.aof_fsync = AOF_FSYNC_NO;
@@ -719,6 +732,11 @@ void configSetCommand(redisClient *c) {
if (yn == -1) goto badfmt;
server.rdb_checksum = yn;
+ } else if (!strcasecmp(c->argv[2]->ptr,"repl-disable-tcp-nodelay")) {
+ int yn = yesnotoi(o->ptr);
+
+ if (yn == -1) goto badfmt;
+ server.repl_disable_tcp_nodelay = yn;
} else if (!strcasecmp(c->argv[2]->ptr,"slave-priority")) {
if (getLongLongFromObject(o,&ll) == REDIS_ERR ||
ll <= 0) goto badfmt;
@@ -784,6 +802,7 @@ void configGetCommand(redisClient *c) {
config_get_numerical_field("maxmemory",server.maxmemory);
config_get_numerical_field("maxmemory-samples",server.maxmemory_samples);
config_get_numerical_field("timeout",server.maxidletime);
+ config_get_numerical_field("tcp-keepalive",server.tcpkeepalive);
config_get_numerical_field("auto-aof-rewrite-percentage",
server.aof_rewrite_perc);
config_get_numerical_field("auto-aof-rewrite-min-size",
@@ -828,6 +847,8 @@ void configGetCommand(redisClient *c) {
config_get_bool_field("rdbcompression", server.rdb_compression);
config_get_bool_field("rdbchecksum", server.rdb_checksum);
config_get_bool_field("activerehashing", server.activerehashing);
+ config_get_bool_field("repl-disable-tcp-nodelay",
+ server.repl_disable_tcp_nodelay);
/* Everything we can't handle with macros follows. */
diff --git a/src/networking.c b/src/networking.c
index 6e5d32489..3f14b17c8 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -58,7 +58,9 @@ redisClient *createClient(int fd) {
* contexts (for instance a Lua script) we need a non connected client. */
if (fd != -1) {
anetNonBlock(NULL,fd);
- anetTcpNoDelay(NULL,fd);
+ anetEnableTcpNoDelay(NULL,fd);
+ if (server.tcpkeepalive)
+ anetKeepAlive(NULL,fd,server.tcpkeepalive);
if (aeCreateFileEvent(server.el,fd,AE_READABLE,
readQueryFromClient, c) == AE_ERR)
{
diff --git a/src/redis.c b/src/redis.c
index 9b4e1ac28..e6faf8ada 100755
--- a/src/redis.c
+++ b/src/redis.c
@@ -215,7 +215,7 @@ struct redisCommand redisCommandTable[] = {
{"bgsaveto",bgsavetoCommand,2,"ar",0,NULL,0,0,0,0,0},
{"bgrewriteaof",bgrewriteaofCommand,1,"ar",0,NULL,0,0,0,0,0},
{"shutdown",shutdownCommand,-1,"ar",0,NULL,0,0,0,0,0},
- {"lastsave",lastsaveCommand,1,"r",0,NULL,0,0,0,0,0},
+ {"lastsave",lastsaveCommand,1,"rR",0,NULL,0,0,0,0,0},
{"type",typeCommand,2,"r",0,NULL,1,1,1,0,0},
{"multi",multiCommand,1,"rs",0,NULL,0,0,0,0,0},
{"exec",execCommand,1,"sM",0,NULL,0,0,0,0,0},
@@ -541,7 +541,7 @@ dictType commandTableDictType = {
NULL /* val destructor */
};
-/* Hash type hash table (note that small hashes are represented with zipmaps) */
+/* Hash type hash table (note that small hashes are represented with ziplists) */
dictType hashDictType = {
dictEncObjHash, /* hash function */
NULL, /* key dup */
@@ -1187,6 +1187,7 @@ void initServerConfig() {
server.dbnum = REDIS_DEFAULT_DBNUM;
server.verbosity = REDIS_NOTICE;
server.maxidletime = REDIS_MAXIDLETIME;
+ server.tcpkeepalive = 0;
server.client_max_querybuf_len = REDIS_MAX_QUERYBUF_LEN;
server.saveparams = NULL;
server.loading = 0;
@@ -1256,6 +1257,7 @@ void initServerConfig() {
server.repl_serve_stale_data = 1;
server.repl_slave_ro = 1;
server.repl_down_since = time(NULL);
+ server.repl_disable_tcp_nodelay = 0;
server.slave_priority = REDIS_DEFAULT_SLAVE_PRIORITY;
/* Client output buffer limits */
diff --git a/src/redis.h b/src/redis.h
index 3319aa87b..b4d58db40 100755
--- a/src/redis.h
+++ b/src/redis.h
@@ -574,6 +574,7 @@ struct redisServer {
/* Configuration */
int verbosity; /* Loglevel in redis.conf */
int maxidletime; /* Client timeout in seconds */
+ int tcpkeepalive; /* Set SO_KEEPALIVE if non-zero. */
size_t client_max_querybuf_len; /* Limit for client query buffer length */
int dbnum; /* Total number of configured DBs */
int daemonize; /* True if running as a daemon */
@@ -647,6 +648,7 @@ struct redisServer {
int repl_serve_stale_data; /* Serve stale data when link is down? */
int repl_slave_ro; /* Slave is read only? */
time_t repl_down_since; /* Unix time at which link with master went down */
+ int repl_disable_tcp_nodelay; /* Disable TCP_NODELAY after SYNC? */
int slave_priority; /* Reported in INFO and used by Sentinel. */
/* Limits */
unsigned int maxclients; /* Max number of simultaneous clients */
diff --git a/src/replication.c b/src/replication.c
index 9c6d4dff7..7fbc4591b 100755
--- a/src/replication.c
+++ b/src/replication.c
@@ -276,7 +276,11 @@ void syncCommand(redisClient *c) {
}
c->repldbfd = -1;
}
-
+
+ if (server.repl_disable_tcp_nodelay)
+ anetDisableTcpNoDelay(NULL, c->fd); /* Non critical if it fails. */
+ c->repldbfd = -1;
+
c->flags |= REDIS_SLAVE;
c->slaveseldb = 0;
listAddNodeTail(server.slaves,c);
@@ -539,6 +543,7 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) {
return;
}
redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Loading DB in memory");
+ signalFlushedDb(-1);
emptyDb();
/* Before loading the DB into memory we need to delete the readable
* handler, otherwise it will get called recursively since
diff --git a/src/sentinel.c b/src/sentinel.c
index 8009e5ed9..fc857344c 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -2035,8 +2035,16 @@ void sentinelCommand(redisClient *c) {
} else {
sentinelAddr *addr = ri->addr;
- if ((ri->flags & SRI_FAILOVER_IN_PROGRESS) && ri->promoted_slave)
+ /* If we are in the middle of a failover, and the slave was
+ * already successfully switched to master role, we can advertise
+ * the new address as slave in order to allow clients to talk
+ * with the new master ASAP. */
+ if ((ri->flags & SRI_FAILOVER_IN_PROGRESS) &&
+ ri->promoted_slave &&
+ ri->failover_state >= SENTINEL_FAILOVER_STATE_RECONF_SLAVES)
+ {
addr = ri->promoted_slave->addr;
+ }
addReplyMultiBulkLen(c,2);
addReplyBulkCString(c,addr->ip);
addReplyBulkLongLong(c,addr->port);
diff --git a/src/t_set.c b/src/t_set.c
index f384dc76c..2cdcf86c6 100644
--- a/src/t_set.c
+++ b/src/t_set.c
@@ -451,7 +451,7 @@ void srandmemberWithCountCommand(redisClient *c) {
* The number of requested elements is greater than the number of
* elements inside the set: simply return the whole set. */
if (count >= size) {
- sunionDiffGenericCommand(c,c->argv,c->argc-1,NULL,REDIS_OP_UNION);
+ sunionDiffGenericCommand(c,c->argv+1,1,NULL,REDIS_OP_UNION);
return;
}
@@ -473,7 +473,7 @@ void srandmemberWithCountCommand(redisClient *c) {
/* Add all the elements into the temporary dictionary. */
si = setTypeInitIterator(set);
while((encoding = setTypeNext(si,&ele,&llele)) != -1) {
- int retval;
+ int retval = DICT_ERR;
if (encoding == REDIS_ENCODING_INTSET) {
retval = dictAdd(d,createStringObjectFromLongLong(llele),NULL);
diff --git a/src/version.h b/src/version.h
index 293bd1bfb..765dc9100 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define REDIS_VERSION "2.6.9"
+#define REDIS_VERSION "2.6.10"
diff --git a/src/ziplist.c b/src/ziplist.c
index d4ac4f9b4..8a6b54a7c 100644
--- a/src/ziplist.c
+++ b/src/ziplist.c
@@ -739,10 +739,10 @@ unsigned char *ziplistPrev(unsigned char *zl, unsigned char *p) {
}
}
-/* Get entry pointer to by 'p' and store in either 'e' or 'v' depending
+/* Get entry pointed to by 'p' and store in either 'e' or 'v' depending
* on the encoding of the entry. 'e' is always set to NULL to be able
* to find out whether the string pointer or the integer value was set.
- * Return 0 if 'p' points to the end of the zipmap, 1 otherwise. */
+ * Return 0 if 'p' points to the end of the ziplist, 1 otherwise. */
unsigned int ziplistGet(unsigned char *p, unsigned char **sstr, unsigned int *slen, long long *sval) {
zlentry entry;
if (p == NULL || p[0] == ZIP_END) return 0;
diff --git a/tests/assets/default.conf b/tests/assets/default.conf
index 976852e91..c76eca3eb 100644
--- a/tests/assets/default.conf
+++ b/tests/assets/default.conf
@@ -35,7 +35,7 @@ port 6379
# unixsocket /tmp/redis.sock
# Close the connection after a client is idle for N seconds (0 to disable)
-timeout 300
+timeout 0
# Set server verbosity to 'debug'
# it can be one of:
diff --git a/tests/integration/replication-4.tcl b/tests/integration/replication-4.tcl
index 69fcab373..0a0dcdc2b 100644
--- a/tests/integration/replication-4.tcl
+++ b/tests/integration/replication-4.tcl
@@ -1,5 +1,6 @@
proc start_bg_complex_data {host port db ops} {
- exec tclsh8.5 tests/helpers/bg_complex_data.tcl $host $port $db $ops &
+ set tclsh [info nameofexecutable]
+ exec $tclsh tests/helpers/bg_complex_data.tcl $host $port $db $ops &
}
proc stop_bg_complex_data {handle} {
diff --git a/tests/integration/replication.tcl b/tests/integration/replication.tcl
index da94b0880..5ca6449f4 100644
--- a/tests/integration/replication.tcl
+++ b/tests/integration/replication.tcl
@@ -78,7 +78,8 @@ start_server {tags {"repl"}} {
}
proc start_write_load {host port seconds} {
- exec tclsh8.5 tests/helpers/gen_write_load.tcl $host $port $seconds &
+ set tclsh [info nameofexecutable]
+ exec $tclsh tests/helpers/gen_write_load.tcl $host $port $seconds &
}
proc stop_write_load {handle} {
diff --git a/tests/test_helper.tcl b/tests/test_helper.tcl
index 38fb1f539..483774219 100644
--- a/tests/test_helper.tcl
+++ b/tests/test_helper.tcl
@@ -2,6 +2,8 @@
# This softare is released under the BSD License. See the COPYING file for
# more information.
+package require Tcl 8.5
+
set tcl_precision 17
source tests/support/redis.tcl
source tests/support/server.tcl
@@ -176,6 +178,7 @@ proc find_available_port start {
proc test_server_main {} {
cleanup
+ set tclsh [info nameofexecutable]
# Open a listening socket, trying different ports in order to find a
# non busy one.
set port [find_available_port 11111]
@@ -189,7 +192,7 @@ proc test_server_main {} {
set start_port [expr {$::port+100}]
for {set j 0} {$j < $::numclients} {incr j} {
set start_port [find_available_port $start_port]
- set p [exec tclsh8.5 [info script] {*}$::argv \
+ set p [exec $tclsh [info script] {*}$::argv \
--client $port --port $start_port &]
lappend ::clients_pids $p
incr start_port 10