summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorItamar Haber <itamar@redislabs.com>2020-07-10 16:22:58 +0300
committerGitHub <noreply@github.com>2020-07-10 16:22:58 +0300
commita6504a16f70511c06bd5460b7cdfee6247cb09a6 (patch)
treeed0a47f5c181e8bfc046d0d9bd6b7da64cf98e0a /src
parent91d309681cf9db8c3b8d4f2d828c336cff661efb (diff)
parentd5648d617e1ed5b9cfa575ad412bc9d450b16afd (diff)
downloadredis-conduct.tar.gz
Merge branch 'unstable' into conductconduct
Diffstat (limited to 'src')
-rw-r--r--src/Makefile18
-rw-r--r--src/bitops.c3
-rw-r--r--src/cluster.c30
-rw-r--r--src/config.c11
-rw-r--r--src/debug.c6
-rw-r--r--src/defrag.c2
-rw-r--r--src/expire.c18
-rw-r--r--src/redis-cli.c158
-rw-r--r--src/server.h4
-rw-r--r--src/tls.c16
10 files changed, 184 insertions, 82 deletions
diff --git a/src/Makefile b/src/Makefile
index b8c05c32b..80c627c24 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -192,9 +192,21 @@ ifeq ($(MALLOC),jemalloc)
endif
ifeq ($(BUILD_TLS),yes)
- FINAL_CFLAGS+=-DUSE_OPENSSL $(OPENSSL_CFLAGS)
- FINAL_LDFLAGS+=$(OPENSSL_LDFLAGS)
- FINAL_LIBS += ../deps/hiredis/libhiredis_ssl.a -lssl -lcrypto
+ FINAL_CFLAGS+=-DUSE_OPENSSL $(OPENSSL_CFLAGS)
+ FINAL_LDFLAGS+=$(OPENSSL_LDFLAGS)
+ LIBSSL_PKGCONFIG := $(shell $(PKG_CONFIG) --exists libssl && echo $$?)
+ifeq ($(LIBSSL_PKGCONFIG),0)
+ LIBSSL_LIBS=$(shell $(PKG_CONFIG) --libs libssl)
+else
+ LIBSSL_LIBS=-lssl
+endif
+ LIBCRYPTO_PKGCONFIG := $(shell $(PKG_CONFIG) --exists libcrypto && echo $$?)
+ifeq ($(LIBCRYPTO_PKGCONFIG),0)
+ LIBCRYPTO_LIBS=$(shell $(PKG_CONFIG) --libs libcrypto)
+else
+ LIBCRYPTO_LIBS=-lcrypto
+endif
+ FINAL_LIBS += ../deps/hiredis/libhiredis_ssl.a $(LIBSSL_LIBS) $(LIBCRYPTO_LIBS)
endif
REDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS)
diff --git a/src/bitops.c b/src/bitops.c
index b37bea2bf..4b1a09aa4 100644
--- a/src/bitops.c
+++ b/src/bitops.c
@@ -759,11 +759,12 @@ void bitopCommand(client *c) {
setKey(c,c->db,targetkey,o);
notifyKeyspaceEvent(NOTIFY_STRING,"set",targetkey,c->db->id);
decrRefCount(o);
+ server.dirty++;
} else if (dbDelete(c->db,targetkey)) {
signalModifiedKey(c,c->db,targetkey);
notifyKeyspaceEvent(NOTIFY_GENERIC,"del",targetkey,c->db->id);
+ server.dirty++;
}
- server.dirty++;
addReplyLongLong(c,maxlen); /* Return the output string length in bytes. */
}
diff --git a/src/cluster.c b/src/cluster.c
index e7a32a9a2..88b810d13 100644
--- a/src/cluster.c
+++ b/src/cluster.c
@@ -4988,7 +4988,8 @@ void restoreCommand(client *c) {
}
/* Make sure this key does not already exist here... */
- if (!replace && lookupKeyWrite(c->db,c->argv[1]) != NULL) {
+ robj *key = c->argv[1];
+ if (!replace && lookupKeyWrite(c->db,key) != NULL) {
addReply(c,shared.busykeyerr);
return;
}
@@ -5010,24 +5011,37 @@ void restoreCommand(client *c) {
rioInitWithBuffer(&payload,c->argv[3]->ptr);
if (((type = rdbLoadObjectType(&payload)) == -1) ||
- ((obj = rdbLoadObject(type,&payload,c->argv[1]->ptr)) == NULL))
+ ((obj = rdbLoadObject(type,&payload,key->ptr)) == NULL))
{
addReplyError(c,"Bad data format");
return;
}
/* Remove the old key if needed. */
- if (replace) dbDelete(c->db,c->argv[1]);
+ int deleted = 0;
+ if (replace)
+ deleted = dbDelete(c->db,key);
+
+ if (ttl && !absttl) ttl+=mstime();
+ if (ttl && checkAlreadyExpired(ttl)) {
+ if (deleted) {
+ rewriteClientCommandVector(c,2,shared.del,key);
+ signalModifiedKey(c,c->db,key);
+ notifyKeyspaceEvent(NOTIFY_GENERIC,"del",key,c->db->id);
+ server.dirty++;
+ }
+ addReply(c, shared.ok);
+ return;
+ }
/* Create the key and set the TTL if any */
- dbAdd(c->db,c->argv[1],obj);
+ dbAdd(c->db,key,obj);
if (ttl) {
- if (!absttl) ttl+=mstime();
- setExpire(c,c->db,c->argv[1],ttl);
+ setExpire(c,c->db,key,ttl);
}
objectSetLRUOrLFU(obj,lfu_freq,lru_idle,lru_clock,1000);
- signalModifiedKey(c,c->db,c->argv[1]);
- notifyKeyspaceEvent(NOTIFY_GENERIC,"restore",c->argv[1],c->db->id);
+ signalModifiedKey(c,c->db,key);
+ notifyKeyspaceEvent(NOTIFY_GENERIC,"restore",key,c->db->id);
addReply(c,shared.ok);
server.dirty++;
}
diff --git a/src/config.c b/src/config.c
index 64854592c..acf1b069f 100644
--- a/src/config.c
+++ b/src/config.c
@@ -2071,7 +2071,7 @@ static int updateTlsCfg(char *val, char *prev, char **err) {
UNUSED(prev);
UNUSED(err);
if (tlsConfigure(&server.tls_ctx_config) == C_ERR) {
- *err = "Unable to configure tls-cert-file. Check server logs.";
+ *err = "Unable to update TLS configuration. Check server logs.";
return 0;
}
return 1;
@@ -2081,6 +2081,12 @@ static int updateTlsCfgBool(int val, int prev, char **err) {
UNUSED(prev);
return updateTlsCfg(NULL, NULL, err);
}
+
+static int updateTlsCfgInt(long long val, long long prev, char **err) {
+ UNUSED(val);
+ UNUSED(prev);
+ return updateTlsCfg(NULL, NULL, err);
+}
#endif /* USE_OPENSSL */
standardConfig configs[] = {
@@ -2216,10 +2222,13 @@ standardConfig configs[] = {
#ifdef USE_OPENSSL
createIntConfig("tls-port", NULL, IMMUTABLE_CONFIG, 0, 65535, server.tls_port, 0, INTEGER_CONFIG, NULL, NULL), /* TCP port. */
+ createIntConfig("tls-session-cache-size", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.tls_ctx_config.session_cache_size, 20*1024, INTEGER_CONFIG, NULL, updateTlsCfgInt),
+ createIntConfig("tls-session-cache-timeout", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.tls_ctx_config.session_cache_timeout, 300, INTEGER_CONFIG, NULL, updateTlsCfgInt),
createBoolConfig("tls-cluster", NULL, MODIFIABLE_CONFIG, server.tls_cluster, 0, NULL, NULL),
createBoolConfig("tls-replication", NULL, MODIFIABLE_CONFIG, server.tls_replication, 0, NULL, NULL),
createBoolConfig("tls-auth-clients", NULL, MODIFIABLE_CONFIG, server.tls_auth_clients, 1, NULL, NULL),
createBoolConfig("tls-prefer-server-ciphers", NULL, MODIFIABLE_CONFIG, server.tls_ctx_config.prefer_server_ciphers, 0, NULL, updateTlsCfgBool),
+ createBoolConfig("tls-session-caching", NULL, MODIFIABLE_CONFIG, server.tls_ctx_config.session_caching, 1, NULL, updateTlsCfgBool),
createStringConfig("tls-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.cert_file, NULL, NULL, updateTlsCfg),
createStringConfig("tls-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.key_file, NULL, NULL, updateTlsCfg),
createStringConfig("tls-dh-params-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.dh_params_file, NULL, NULL, updateTlsCfg),
diff --git a/src/debug.c b/src/debug.c
index d79226bf2..a74c22647 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -378,6 +378,7 @@ void debugCommand(client *c) {
"DEBUG PROTOCOL [string|integer|double|bignum|null|array|set|map|attrib|push|verbatim|true|false]",
"ERROR <string> -- Return a Redis protocol error with <string> as message. Useful for clients unit tests to simulate Redis errors.",
"LOG <message> -- write message to the server log.",
+"LEAK <string> -- Create a memory leak of the input string.",
"HTSTATS <dbid> -- Return hash table statistics of the specified Redis database.",
"HTSTATS-KEY <key> -- Like htstats but for the hash table stored as key's value.",
"LOADAOF -- Flush the AOF buffers on disk and reload the AOF in memory.",
@@ -430,6 +431,9 @@ NULL
} else if (!strcasecmp(c->argv[1]->ptr,"log") && c->argc == 3) {
serverLog(LL_WARNING, "DEBUG LOG: %s", (char*)c->argv[2]->ptr);
addReply(c,shared.ok);
+ } else if (!strcasecmp(c->argv[1]->ptr,"leak") && c->argc == 3) {
+ sdsdup(c->argv[2]->ptr);
+ addReply(c,shared.ok);
} else if (!strcasecmp(c->argv[1]->ptr,"reload")) {
int flush = 1, save = 1;
int flags = RDBFLAGS_NONE;
@@ -1569,7 +1573,7 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
serverLogRaw(LL_WARNING|LL_RAW,
"\n=== REDIS BUG REPORT END. Make sure to include from START to END. ===\n\n"
" Please report the crash by opening an issue on github:\n\n"
-" http://github.com/antirez/redis/issues\n\n"
+" http://github.com/redis/redis/issues\n\n"
" Suspect RAM error? Use redis-server --test-memory to verify it.\n\n"
);
diff --git a/src/defrag.c b/src/defrag.c
index 6e5296632..2d8db8ea5 100644
--- a/src/defrag.c
+++ b/src/defrag.c
@@ -348,7 +348,7 @@ long activeDefragSdsListAndDict(list *l, dict *d, int dict_val_type) {
sdsele = ln->value;
if ((newsds = activeDefragSds(sdsele))) {
/* When defragging an sds value, we need to update the dict key */
- uint64_t hash = dictGetHash(d, sdsele);
+ uint64_t hash = dictGetHash(d, newsds);
replaceSateliteDictKeyPtrAndOrDefragDictEntry(d, sdsele, newsds, hash, &defragged);
ln->value = newsds;
defragged++;
diff --git a/src/expire.c b/src/expire.c
index 30a27193d..f2d135e2b 100644
--- a/src/expire.c
+++ b/src/expire.c
@@ -475,6 +475,16 @@ void flushSlaveKeysWithExpireList(void) {
}
}
+int checkAlreadyExpired(long long when) {
+ /* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past
+ * should never be executed as a DEL when load the AOF or in the context
+ * of a slave instance.
+ *
+ * Instead we add the already expired key to the database with expire time
+ * (possibly in the past) and wait for an explicit DEL from the master. */
+ return (when <= mstime() && !server.loading && !server.masterhost);
+}
+
/*-----------------------------------------------------------------------------
* Expires Commands
*----------------------------------------------------------------------------*/
@@ -502,13 +512,7 @@ void expireGenericCommand(client *c, long long basetime, int unit) {
return;
}
- /* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past
- * should never be executed as a DEL when load the AOF or in the context
- * of a slave instance.
- *
- * Instead we take the other branch of the IF statement setting an expire
- * (possibly in the past) and wait for an explicit DEL from the master. */
- if (when <= mstime() && !server.loading && !server.masterhost) {
+ if (checkAlreadyExpired(when)) {
robj *aux;
int deleted = server.lazyfree_lazy_expire ? dbAsyncDelete(c->db,key) :
diff --git a/src/redis-cli.c b/src/redis-cli.c
index 75845f346..0148964bf 100644
--- a/src/redis-cli.c
+++ b/src/redis-cli.c
@@ -1989,6 +1989,7 @@ static void repl(void) {
if (argv == NULL) {
printf("Invalid argument(s)\n");
+ fflush(stdout);
linenoiseFree(line);
continue;
} else if (argc > 0) {
@@ -6784,10 +6785,53 @@ void sendCapa() {
sendReplconf("capa", "eof");
}
+/* Wrapper around hiredis to allow arbitrary reads and writes.
+ *
+ * We piggybacks on top of hiredis to achieve transparent TLS support,
+ * and use its internal buffers so it can co-exist with commands
+ * previously/later issued on the connection.
+ *
+ * Interface is close to enough to read()/write() so things should mostly
+ * work transparently.
+ */
+
+/* Write a raw buffer through a redisContext. If we already have something
+ * in the buffer (leftovers from hiredis operations) it will be written
+ * as well.
+ */
+static ssize_t writeConn(redisContext *c, const char *buf, size_t buf_len)
+{
+ int done = 0;
+
+ c->obuf = sdscatlen(c->obuf, buf, buf_len);
+ if (redisBufferWrite(c, &done) == REDIS_ERR) {
+ sdsrange(c->obuf, 0, -(buf_len+1));
+ if (!(c->flags & REDIS_BLOCK))
+ errno = EAGAIN;
+ return -1;
+ }
+
+ size_t left = sdslen(c->obuf);
+ sdsclear(c->obuf);
+ if (!done) {
+ return buf_len - left;
+ }
+
+ return buf_len;
+}
+
+/* Read raw bytes through a redisContext. The read operation is not greedy
+ * and may not fill the buffer entirely.
+ */
+static ssize_t readConn(redisContext *c, char *buf, size_t len)
+{
+ return c->funcs->read(c, buf, len);
+}
+
/* Sends SYNC and reads the number of bytes in the payload. Used both by
* slaveMode() and getRDB().
* returns 0 in case an EOF marker is used. */
-unsigned long long sendSync(int fd, char *out_eof) {
+unsigned long long sendSync(redisContext *c, char *out_eof) {
/* To start we need to send the SYNC command and return the payload.
* The hiredis client lib does not understand this part of the protocol
* and we don't want to mess with its buffers, so everything is performed
@@ -6796,7 +6840,7 @@ unsigned long long sendSync(int fd, char *out_eof) {
ssize_t nread;
/* Send the SYNC command. */
- if (write(fd,"SYNC\r\n",6) != 6) {
+ if (writeConn(c, "SYNC\r\n", 6) != 6) {
fprintf(stderr,"Error writing to master\n");
exit(1);
}
@@ -6804,7 +6848,7 @@ unsigned long long sendSync(int fd, char *out_eof) {
/* Read $<payload>\r\n, making sure to read just up to "\n" */
p = buf;
while(1) {
- nread = read(fd,p,1);
+ nread = readConn(c,p,1);
if (nread <= 0) {
fprintf(stderr,"Error reading bulk length while SYNCing\n");
exit(1);
@@ -6825,11 +6869,10 @@ unsigned long long sendSync(int fd, char *out_eof) {
}
static void slaveMode(void) {
- int fd = context->fd;
static char eofmark[RDB_EOF_MARK_SIZE];
static char lastbytes[RDB_EOF_MARK_SIZE];
static int usemark = 0;
- unsigned long long payload = sendSync(fd, eofmark);
+ unsigned long long payload = sendSync(context,eofmark);
char buf[1024];
int original_output = config.output;
@@ -6849,7 +6892,7 @@ static void slaveMode(void) {
while(payload) {
ssize_t nread;
- nread = read(fd,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);
+ nread = readConn(context,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);
if (nread <= 0) {
fprintf(stderr,"Error reading RDB payload while SYNCing\n");
exit(1);
@@ -6892,14 +6935,15 @@ static void slaveMode(void) {
/* This function implements --rdb, so it uses the replication protocol in order
* to fetch the RDB file from a remote server. */
static void getRDB(clusterManagerNode *node) {
- int s, fd;
+ int fd;
+ redisContext *s;
char *filename;
if (node != NULL) {
assert(node->context);
- s = node->context->fd;
+ s = node->context;
filename = clusterManagerGetNodeRDBFilename(node);
} else {
- s = context->fd;
+ s = context;
filename = config.rdb_filename;
}
static char eofmark[RDB_EOF_MARK_SIZE];
@@ -6934,7 +6978,7 @@ static void getRDB(clusterManagerNode *node) {
while(payload) {
ssize_t nread, nwritten;
- nread = read(s,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);
+ nread = readConn(s,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);
if (nread <= 0) {
fprintf(stderr,"I/O Error reading RDB payload from socket\n");
exit(1);
@@ -6968,7 +7012,7 @@ static void getRDB(clusterManagerNode *node) {
} else {
fprintf(stderr,"Transfer finished with success.\n");
}
- close(s); /* Close the file descriptor ASAP as fsync() may take time. */
+ redisFree(s); /* Close the file descriptor ASAP as fsync() may take time. */
fsync(fd);
close(fd);
fprintf(stderr,"Transfer finished with success.\n");
@@ -6985,11 +7029,9 @@ static void getRDB(clusterManagerNode *node) {
#define PIPEMODE_WRITE_LOOP_MAX_BYTES (128*1024)
static void pipeMode(void) {
- int fd = context->fd;
long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0;
- char ibuf[1024*16], obuf[1024*16]; /* Input and output buffers */
+ char obuf[1024*16]; /* Output buffer */
char aneterr[ANET_ERR_LEN];
- redisReader *reader = redisReaderCreate();
redisReply *reply;
int eof = 0; /* True once we consumed all the standard input. */
int done = 0;
@@ -6999,47 +7041,38 @@ static void pipeMode(void) {
srand(time(NULL));
/* Use non blocking I/O. */
- if (anetNonBlock(aneterr,fd) == ANET_ERR) {
+ if (anetNonBlock(aneterr,context->fd) == ANET_ERR) {
fprintf(stderr, "Can't set the socket in non blocking mode: %s\n",
aneterr);
exit(1);
}
+ context->flags &= ~REDIS_BLOCK;
+
/* Transfer raw protocol and read replies from the server at the same
* time. */
while(!done) {
int mask = AE_READABLE;
if (!eof || obuf_len != 0) mask |= AE_WRITABLE;
- mask = aeWait(fd,mask,1000);
+ mask = aeWait(context->fd,mask,1000);
/* Handle the readable state: we can read replies from the server. */
if (mask & AE_READABLE) {
- ssize_t nread;
int read_error = 0;
- /* Read from socket and feed the hiredis reader. */
do {
- nread = read(fd,ibuf,sizeof(ibuf));
- if (nread == -1 && errno != EAGAIN && errno != EINTR) {
- fprintf(stderr, "Error reading from the server: %s\n",
- strerror(errno));
+ if (!read_error && redisBufferRead(context) == REDIS_ERR) {
read_error = 1;
- break;
- }
- if (nread > 0) {
- redisReaderFeed(reader,ibuf,nread);
- last_read_time = time(NULL);
}
- } while(nread > 0);
- /* Consume replies. */
- do {
- if (redisReaderGetReply(reader,(void**)&reply) == REDIS_ERR) {
+ reply = NULL;
+ if (redisGetReply(context, (void **) &reply) == REDIS_ERR) {
fprintf(stderr, "Error reading replies from server\n");
exit(1);
}
if (reply) {
+ last_read_time = time(NULL);
if (reply->type == REDIS_REPLY_ERROR) {
fprintf(stderr,"%s\n", reply->str);
errors++;
@@ -7072,7 +7105,7 @@ static void pipeMode(void) {
while(1) {
/* Transfer current buffer to server. */
if (obuf_len != 0) {
- ssize_t nwritten = write(fd,obuf+obuf_pos,obuf_len);
+ ssize_t nwritten = writeConn(context,obuf+obuf_pos,obuf_len);
if (nwritten == -1) {
if (errno != EAGAIN && errno != EINTR) {
@@ -7088,6 +7121,10 @@ static void pipeMode(void) {
loop_nwritten += nwritten;
if (obuf_len != 0) break; /* Can't accept more data. */
}
+ if (context->err) {
+ fprintf(stderr, "Server I/O Error: %s\n", context->errstr);
+ exit(1);
+ }
/* If buffer is empty, load from stdin. */
if (obuf_len == 0 && !eof) {
ssize_t nread = read(STDIN_FILENO,obuf,sizeof(obuf));
@@ -7138,7 +7175,6 @@ static void pipeMode(void) {
break;
}
}
- redisReaderFree(reader);
printf("errors: %lld, replies: %lld\n", errors, replies);
if (errors)
exit(1);
@@ -7246,7 +7282,9 @@ static void getKeyTypes(dict *types_dict, redisReply *keys, typeinfo **types) {
/* Pipeline TYPE commands */
for(i=0;i<keys->elements;i++) {
- redisAppendCommand(context, "TYPE %s", keys->element[i]->str);
+ const char* argv[] = {"TYPE", keys->element[i]->str};
+ size_t lens[] = {4, keys->element[i]->len};
+ redisAppendCommandArgv(context, 2, argv, lens);
}
/* Retrieve types */
@@ -7292,15 +7330,21 @@ static void getKeySizes(redisReply *keys, typeinfo **types,
if(!types[i] || (!types[i]->sizecmd && !memkeys))
continue;
- if (!memkeys)
- redisAppendCommand(context, "%s %s",
- types[i]->sizecmd, keys->element[i]->str);
- else if (memkeys_samples==0)
- redisAppendCommand(context, "%s %s %s",
- "MEMORY", "USAGE", keys->element[i]->str);
- else
- redisAppendCommand(context, "%s %s %s SAMPLES %u",
- "MEMORY", "USAGE", keys->element[i]->str, memkeys_samples);
+ if (!memkeys) {
+ const char* argv[] = {types[i]->sizecmd, keys->element[i]->str};
+ size_t lens[] = {strlen(types[i]->sizecmd), keys->element[i]->len};
+ redisAppendCommandArgv(context, 2, argv, lens);
+ } else if (memkeys_samples==0) {
+ const char* argv[] = {"MEMORY", "USAGE", keys->element[i]->str};
+ size_t lens[] = {6, 5, keys->element[i]->len};
+ redisAppendCommandArgv(context, 3, argv, lens);
+ } else {
+ sds samplesstr = sdsfromlonglong(memkeys_samples);
+ const char* argv[] = {"MEMORY", "USAGE", keys->element[i]->str, "SAMPLES", samplesstr};
+ size_t lens[] = {6, 5, keys->element[i]->len, 7, sdslen(samplesstr)};
+ redisAppendCommandArgv(context, 5, argv, lens);
+ sdsfree(samplesstr);
+ }
}
/* Retrieve sizes */
@@ -7396,20 +7440,20 @@ static void findBigKeys(int memkeys, unsigned memkeys_samples) {
sampled++;
if(type->biggest<sizes[i]) {
- printf(
- "[%05.2f%%] Biggest %-6s found so far '%s' with %llu %s\n",
- pct, type->name, keys->element[i]->str, sizes[i],
- !memkeys? type->sizeunit: "bytes");
-
/* Keep track of biggest key name for this type */
if (type->biggest_key)
sdsfree(type->biggest_key);
- type->biggest_key = sdsnew(keys->element[i]->str);
+ type->biggest_key = sdscatrepr(sdsempty(), keys->element[i]->str, keys->element[i]->len);
if(!type->biggest_key) {
fprintf(stderr, "Failed to allocate memory for key!\n");
exit(1);
}
+ printf(
+ "[%05.2f%%] Biggest %-6s found so far '%s' with %llu %s\n",
+ pct, type->name, type->biggest_key, sizes[i],
+ !memkeys? type->sizeunit: "bytes");
+
/* Keep track of the biggest size for this type */
type->biggest = sizes[i];
}
@@ -7473,21 +7517,27 @@ static void getKeyFreqs(redisReply *keys, unsigned long long *freqs) {
/* Pipeline OBJECT freq commands */
for(i=0;i<keys->elements;i++) {
- redisAppendCommand(context, "OBJECT freq %s", keys->element[i]->str);
+ const char* argv[] = {"OBJECT", "FREQ", keys->element[i]->str};
+ size_t lens[] = {6, 4, keys->element[i]->len};
+ redisAppendCommandArgv(context, 3, argv, lens);
}
/* Retrieve freqs */
for(i=0;i<keys->elements;i++) {
if(redisGetReply(context, (void**)&reply)!=REDIS_OK) {
+ sds keyname = sdscatrepr(sdsempty(), keys->element[i]->str, keys->element[i]->len);
fprintf(stderr, "Error getting freq for key '%s' (%d: %s)\n",
- keys->element[i]->str, context->err, context->errstr);
+ keyname, context->err, context->errstr);
+ sdsfree(keyname);
exit(1);
} else if(reply->type != REDIS_REPLY_INTEGER) {
if(reply->type == REDIS_REPLY_ERROR) {
fprintf(stderr, "Error: %s\n", reply->str);
exit(1);
} else {
- fprintf(stderr, "Warning: OBJECT freq on '%s' failed (may have been deleted)\n", keys->element[i]->str);
+ sds keyname = sdscatrepr(sdsempty(), keys->element[i]->str, keys->element[i]->len);
+ fprintf(stderr, "Warning: OBJECT freq on '%s' failed (may have been deleted)\n", keyname);
+ sdsfree(keyname);
freqs[i] = 0;
}
} else {
@@ -7558,10 +7608,10 @@ static void findHotKeys(void) {
memmove(hotkeys,hotkeys+1,sizeof(hotkeys[0])*k);
}
counters[k] = freqs[i];
- hotkeys[k] = sdsnew(keys->element[i]->str);
+ hotkeys[k] = sdscatrepr(sdsempty(), keys->element[i]->str, keys->element[i]->len);
printf(
"[%05.2f%%] Hot key '%s' found so far with counter %llu\n",
- pct, keys->element[i]->str, freqs[i]);
+ pct, hotkeys[k], freqs[i]);
}
/* Sleep if we've been directed to do so */
diff --git a/src/server.h b/src/server.h
index 6c36385e1..3f471efcb 100644
--- a/src/server.h
+++ b/src/server.h
@@ -1011,6 +1011,9 @@ typedef struct redisTLSContextConfig {
char *ciphers;
char *ciphersuites;
int prefer_server_ciphers;
+ int session_caching;
+ int session_cache_size;
+ int session_cache_timeout;
} redisTLSContextConfig;
/*-----------------------------------------------------------------------------
@@ -2070,6 +2073,7 @@ void propagateExpire(redisDb *db, robj *key, int lazy);
int expireIfNeeded(redisDb *db, robj *key);
long long getExpire(redisDb *db, robj *key);
void setExpire(client *c, redisDb *db, robj *key, long long when);
+int checkAlreadyExpired(long long when);
robj *lookupKey(redisDb *db, robj *key, int flags);
robj *lookupKeyRead(redisDb *db, robj *key);
robj *lookupKeyWrite(redisDb *db, robj *key);
diff --git a/src/tls.c b/src/tls.c
index a62f2284e..8b2bb58e1 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -148,9 +148,6 @@ void tlsInit(void) {
}
pending_list = listCreate();
-
- /* Server configuration */
- server.tls_auth_clients = 1; /* Secure by default */
}
/* Attempt to configure/reconfigure TLS. This operation is atomic and will
@@ -184,6 +181,15 @@ int tlsConfigure(redisTLSContextConfig *ctx_config) {
SSL_CTX_set_options(ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
#endif
+ if (ctx_config->session_caching) {
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
+ SSL_CTX_sess_set_cache_size(ctx, ctx_config->session_cache_size);
+ SSL_CTX_set_timeout(ctx, ctx_config->session_cache_timeout);
+ SSL_CTX_set_session_id_context(ctx, (void *) "redis", 5);
+ } else {
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+ }
+
int protocols = parseProtocolsConfig(ctx_config->protocols);
if (protocols == -1) goto error;
@@ -337,9 +343,7 @@ connection *connCreateAcceptedTLS(int fd, int require_auth) {
conn->c.state = CONN_STATE_ACCEPTING;
if (!require_auth) {
- /* We still verify certificates if provided, but don't require them.
- */
- SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, NULL);
+ SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
}
SSL_set_fd(conn->ssl, conn->c.fd);