Unverified Commit d375595d authored by Oran Agra's avatar Oran Agra Committed by GitHub
Browse files

Merge pull request #10652 from oranagra/redis-7.0.0

Redis 7.0.0
parents fb4e0d40 c1f30206
...@@ -15,3 +15,4 @@ tre ...@@ -15,3 +15,4 @@ tre
cancelability cancelability
ist ist
statics statics
filetest
...@@ -26,7 +26,7 @@ jobs: ...@@ -26,7 +26,7 @@ jobs:
--tags -slow --tags -slow
- name: Archive redis log - name: Archive redis log
if: ${{ failure() }} if: ${{ failure() }}
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: test-external-redis-log name: test-external-redis-log
path: external-redis.log path: external-redis.log
...@@ -53,7 +53,7 @@ jobs: ...@@ -53,7 +53,7 @@ jobs:
--tags -slow --tags -slow
- name: Archive redis log - name: Archive redis log
if: ${{ failure() }} if: ${{ failure() }}
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: test-external-cluster-log name: test-external-cluster-log
path: external-redis.log path: external-redis.log
...@@ -76,7 +76,7 @@ jobs: ...@@ -76,7 +76,7 @@ jobs:
--tags "-slow -needs:debug" --tags "-slow -needs:debug"
- name: Archive redis log - name: Archive redis log
if: ${{ failure() }} if: ${{ failure() }}
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: test-external-redis-log name: test-external-redis-log
path: external-redis.log path: external-redis.log
Redis 7.0 release notes
=======================
--------------------------------------------------------------------------------
Upgrade urgency levels:
LOW: No need to upgrade unless there are new features you want to use.
MODERATE: Program an upgrade of the server, but it's not urgent.
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.
SECURITY: There are security fixes in the release.
--------------------------------------------------------------------------------
================================================================================
Redis 7.0.0 GA Released Wed Apr 27 12:00:00 IST 2022
================================================================================
Upgrade urgency: SECURITY, contains fixes to security issues.
Security Fixes:
* (CVE-2022-24736) An attacker attempting to load a specially crafted Lua script
can cause NULL pointer dereference which will result with a crash of the
redis-server process. This issue affects all versions of Redis.
[reported by Aviv Yahav].
* (CVE-2022-24735) By exploiting weaknesses in the Lua script execution
environment, an attacker with access to Redis can inject Lua code that will
execute with the (potentially higher) privileges of another Redis user.
[reported by Aviv Yahav].
New Features
============
* Keyspace event for new keys (#10512)
Command replies that have been extended
---------------------------------------
* COMMAND DOCS shows deprecated_since field in command args (#10545)
* COMMAND DOCS shows module name where applicable (#10544)
Potentially Breaking Changes
============================
* Replicas panic when they fail writing persistence (#10504)
* Prevent cross slot operations in functions and scripts with shebang (#10615)
* Rephrased some error responses about invalid commands or args (#10612)
* Lua scripts do not have access to the print() function (#10651)
Performance and resource utilization improvements
=================================================
* Speed optimization in streams (#10574)
* Speed optimization in command execution pipeline (#10502)
* Speed optimization in listpack encoded sorted (#10486)
* Speed optimization in latency tracking at INFO (relevant for 7.0 RCs) (#10606)
* Speed optimization when there are many replicas (relevant for 7.0 RCs) (#10588)
New configuration options
=========================
* Allow ignoring disk persistence errors on replicas (#10504)
* Allow abort with panic when replica fails to execute a command sent by the master (#10504)
* Allow configuring shutdown flags of SIGTERM and SIGINT (#10594)
* Allow attaching an operating system-specific identifier to Redis sockets (#10349)
Module API changes
==================
* Add argument specifying ACL reason for module log entry (#10559)
Breaking API compatibility with 7.0 RCs
* Add the deprecated_since field in command args of COMMAND DOCS (#10545)
Breaking API/ABI compatibility with 7.0 RCs
* Add module API flag for using enum configs as bit flags (#10643)
* Add RM_PublishMessageShard (#10543)
* Add RM_MallocSizeString, RM_MallocSizeDict (#10542)
* Add RM_TryAlloc (#10541)
Bug Fixes
=========
* Replica report disk persistence errors in PING (#10603)
* Fixes around rejecting commands on replicas and AOF when they must be respected (#10603)
* Durability fixes for appendfsync=always policy (#9678)
Fixes for issues in previous release candidates of Redis 7.0
------------------------------------------------------------
* Fix possible crash on CONFIG REWRITE (#10598)
* Fix regression not aborting transaction on errors (#10612)
* Fix auto-aof-rewrite-percentage based AOFRW trigger after restart (#10550)
* Fix bugs when AOF enabled after startup, in case of failure before the first rewrite completes (#10616)
* Fix RM_Yield module API bug processing future commands of the current client (#10573)
================================================================================ ================================================================================
Redis 7.0 RC3 Released Tue Apr 5 12:00:00 IST 2022 Redis 7.0 RC3 Released Tue Apr 5 12:00:00 IST 2022
================================================================================ ================================================================================
...@@ -491,18 +593,6 @@ Bug Fixes ...@@ -491,18 +593,6 @@ Bug Fixes
* Sentinel: Fix election failures on certain container environments (#10197) * Sentinel: Fix election failures on certain container environments (#10197)
Known Issues
============
This is a list of known issues that affect this release, and are planned to be
fixed or completed before Redis 7 is officially released:
* Module APIs for modules to provide additional command meta-data are still
missing.
* Module APIs for supporting the new ACL selectors are still missing.
* ACL key access selectors do not yet apply to SORT with GET/BY does.
* Multi-Part AOF support in redis-check-aof is still missing.
Thanks to all the users and developers who made this release possible. Thanks to all the users and developers who made this release possible.
We'll follow up with more RC releases, until the code looks production ready We'll follow up with more RC releases, until the code looks production ready
and we don't get reports of serious issues for a while. and we don't get reports of serious issues for a while.
......
...@@ -5,6 +5,7 @@ should be provided by the operating system. ...@@ -5,6 +5,7 @@ should be provided by the operating system.
* **hiredis** is the official C client library for Redis. It is used by redis-cli, redis-benchmark and Redis Sentinel. It is part of the Redis official ecosystem but is developed externally from the Redis repository, so we just upgrade it as needed. * **hiredis** is the official C client library for Redis. It is used by redis-cli, redis-benchmark and Redis Sentinel. It is part of the Redis official ecosystem but is developed externally from the Redis repository, so we just upgrade it as needed.
* **linenoise** is a readline replacement. It is developed by the same authors of Redis but is managed as a separated project and updated as needed. * **linenoise** is a readline replacement. It is developed by the same authors of Redis but is managed as a separated project and updated as needed.
* **lua** is Lua 5.1 with minor changes for security and additional libraries. * **lua** is Lua 5.1 with minor changes for security and additional libraries.
* **hdr_histogram** Used for per-command latency tracking histograms.
How to upgrade the above dependencies How to upgrade the above dependencies
=== ===
...@@ -94,3 +95,13 @@ and our version: ...@@ -94,3 +95,13 @@ and our version:
1. Makefile is modified to allow a different compiler than GCC. 1. Makefile is modified to allow a different compiler than GCC.
2. We have the implementation source code, and directly link to the following external libraries: `lua_cjson.o`, `lua_struct.o`, `lua_cmsgpack.o` and `lua_bit.o`. 2. We have the implementation source code, and directly link to the following external libraries: `lua_cjson.o`, `lua_struct.o`, `lua_cmsgpack.o` and `lua_bit.o`.
3. There is a security fix in `ldo.c`, line 498: The check for `LUA_SIGNATURE[0]` is removed in order to avoid direct bytecode execution. 3. There is a security fix in `ldo.c`, line 498: The check for `LUA_SIGNATURE[0]` is removed in order to avoid direct bytecode execution.
Hdr_Histogram
---
Updated source can be found here: https://github.com/HdrHistogram/HdrHistogram_c
We use a customized version 0.11.5
1. Compare all changes under /hdr_histogram directory to version 0.11.5
2. Copy updated files from newer version onto files in /hdr_histogram.
3. Apply the changes from 1 above to the updated files.
STD= STD= -std=c99
WARN= -Wall WARN= -Wall
OPT= -Os OPT= -Os
R_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) R_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) -DHDR_MALLOC_INCLUDE=\"hdr_redis_malloc.h\"
R_LDFLAGS= $(LDFLAGS) R_LDFLAGS= $(LDFLAGS)
DEBUG= -g DEBUG= -g
...@@ -12,12 +12,10 @@ R_LD=$(CC) $(R_LDFLAGS) ...@@ -12,12 +12,10 @@ R_LD=$(CC) $(R_LDFLAGS)
AR= ar AR= ar
ARFLAGS= rcs ARFLAGS= rcs
libhdrhistogram.a: hdr_histogram.o hdr_alloc.o libhdrhistogram.a: hdr_histogram.o
$(AR) $(ARFLAGS) $@ $+ $(AR) $(ARFLAGS) $@ $+
hdr_alloc.o: hdr_alloc.h hdr_alloc.c hdr_histogram.o: hdr_histogram.h hdr_histogram.c
hdr_histogram.o: hdr_alloc.o hdr_histogram.h hdr_histogram.c
.c.o: .c.o:
$(R_CC) -c $< $(R_CC) -c $<
......
HdrHistogram_c v0.11.0 HdrHistogram_c v0.11.5
---------------------------------------------- ----------------------------------------------
...@@ -7,4 +7,4 @@ This port contains a subset of the 'C' version of High Dynamic Range (HDR) Histo ...@@ -7,4 +7,4 @@ This port contains a subset of the 'C' version of High Dynamic Range (HDR) Histo
The code present on `hdr_histogram.c`, `hdr_histogram.h`, and `hdr_atomic.c` was Written by Gil Tene, Michael Barker, The code present on `hdr_histogram.c`, `hdr_histogram.h`, and `hdr_atomic.c` was Written by Gil Tene, Michael Barker,
and Matt Warren, and released to the public domain, as explained at and Matt Warren, and released to the public domain, as explained at
http://creativecommons.org/publicdomain/zero/1.0/. http://creativecommons.org/publicdomain/zero/1.0/.
\ No newline at end of file
/**
* hdr_alloc.c
* Written by Filipe Oliveira and released to the public domain,
* as explained at http://creativecommons.org/publicdomain/zero/1.0/
*/
#include "hdr_alloc.h"
#include <stdlib.h>
hdrAllocFuncs hdrAllocFns = {
.mallocFn = malloc,
.callocFn = calloc,
.reallocFn = realloc,
.freeFn = free,
};
/* Override hdr' allocators with ones supplied by the user */
hdrAllocFuncs hdrSetAllocators(hdrAllocFuncs *override) {
hdrAllocFuncs orig = hdrAllocFns;
hdrAllocFns = *override;
return orig;
}
/* Reset allocators to use build time defaults */
void hdrResetAllocators(void) {
hdrAllocFns = (hdrAllocFuncs){
.mallocFn = malloc,
.callocFn = calloc,
.reallocFn = realloc,
.freeFn = free,
};
}
/**
* hdr_alloc.h
* Written by Filipe Oliveira and released to the public domain,
* as explained at http://creativecommons.org/publicdomain/zero/1.0/
*
* Allocator selection.
*
* This file is used in order to change the HdrHistogram allocator at run
* time. */
#ifndef HDR_ALLOC_H
#define HDR_ALLOC_H
#include <stddef.h> /* for size_t */
#include <stdint.h>
/* Structure pointing to our actually configured allocators */
typedef struct hdrAllocFuncs {
void *(*mallocFn)(size_t);
void *(*callocFn)(size_t, size_t);
void *(*reallocFn)(void *, size_t);
void (*freeFn)(void *);
} hdrAllocFuncs;
/* hdr' configured allocator function pointer struct */
extern hdrAllocFuncs hdrAllocFns;
hdrAllocFuncs hdrSetAllocators(hdrAllocFuncs *ha);
void hdrResetAllocators(void);
static inline void *hdr_malloc(size_t size) {
return hdrAllocFns.mallocFn(size);
}
static inline void *hdr_calloc(size_t nmemb, size_t size) {
return hdrAllocFns.callocFn(nmemb, size);
}
static inline void *hdr_realloc(void *ptr, size_t size) {
return hdrAllocFns.reallocFn(ptr, size);
}
static inline void hdr_free(void *ptr) {
hdrAllocFns.freeFn(ptr);
}
#endif /* HDR_ALLOC_H */
...@@ -14,13 +14,14 @@ ...@@ -14,13 +14,14 @@
#include <inttypes.h> #include <inttypes.h>
#include "hdr_histogram.h" #include "hdr_histogram.h"
#include "hdr_tests.h"
#include "hdr_atomic.h" #include "hdr_atomic.h"
#include "hdr_alloc.h"
#define malloc hdr_malloc #ifndef HDR_MALLOC_INCLUDE
#define calloc hdr_calloc #define HDR_MALLOC_INCLUDE "hdr_malloc.h"
#define free hdr_free #endif
#define realloc hdr_realloc
#include HDR_MALLOC_INCLUDE
/* ###### ####### ## ## ## ## ######## ###### */ /* ###### ####### ## ## ## ## ######## ###### */
/* ## ## ## ## ## ## ### ## ## ## ## */ /* ## ## ## ## ## ## ### ## ## ## ## */
...@@ -164,6 +165,16 @@ static int32_t count_leading_zeros_64(int64_t value) ...@@ -164,6 +165,16 @@ static int32_t count_leading_zeros_64(int64_t value)
#endif #endif
} }
static int64_t get_count_at_index_given_bucket_base_idx(const struct hdr_histogram* h, int32_t bucket_base_idx, int32_t sub_bucket_idx)
{
return h->counts[(bucket_base_idx + sub_bucket_idx) - h->sub_bucket_half_count];
}
static int32_t get_bucket_base_index(const struct hdr_histogram* h, int32_t bucket_index)
{
return (bucket_index + 1) << h->sub_bucket_half_count_magnitude;
}
static int32_t get_bucket_index(const struct hdr_histogram* h, int64_t value) static int32_t get_bucket_index(const struct hdr_histogram* h, int64_t value)
{ {
int32_t pow2ceiling = 64 - count_leading_zeros_64(value | h->sub_bucket_mask); /* smallest power of 2 containing value */ int32_t pow2ceiling = 64 - count_leading_zeros_64(value | h->sub_bucket_mask); /* smallest power of 2 containing value */
...@@ -221,6 +232,15 @@ int64_t hdr_size_of_equivalent_value_range(const struct hdr_histogram* h, int64_ ...@@ -221,6 +232,15 @@ int64_t hdr_size_of_equivalent_value_range(const struct hdr_histogram* h, int64_
return INT64_C(1) << (h->unit_magnitude + adjusted_bucket); return INT64_C(1) << (h->unit_magnitude + adjusted_bucket);
} }
static int64_t size_of_equivalent_value_range_given_bucket_indices(
const struct hdr_histogram *h,
int32_t bucket_index,
int32_t sub_bucket_index)
{
const int32_t adjusted_bucket = (sub_bucket_index >= h->sub_bucket_count) ? (bucket_index + 1) : bucket_index;
return INT64_C(1) << (h->unit_magnitude + adjusted_bucket);
}
static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t value) static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t value)
{ {
int32_t bucket_index = get_bucket_index(h, value); int32_t bucket_index = get_bucket_index(h, value);
...@@ -228,6 +248,14 @@ static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t va ...@@ -228,6 +248,14 @@ static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t va
return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude); return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
} }
static int64_t lowest_equivalent_value_given_bucket_indices(
const struct hdr_histogram *h,
int32_t bucket_index,
int32_t sub_bucket_index)
{
return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
}
int64_t hdr_next_non_equivalent_value(const struct hdr_histogram *h, int64_t value) int64_t hdr_next_non_equivalent_value(const struct hdr_histogram *h, int64_t value)
{ {
return lowest_equivalent_value(h, value) + hdr_size_of_equivalent_value_range(h, value); return lowest_equivalent_value(h, value) + hdr_size_of_equivalent_value_range(h, value);
...@@ -323,7 +351,7 @@ static int32_t buckets_needed_to_cover_value(int64_t value, int32_t sub_bucket_c ...@@ -323,7 +351,7 @@ static int32_t buckets_needed_to_cover_value(int64_t value, int32_t sub_bucket_c
/* ## ## ######## ## ## ####### ## ## ## */ /* ## ## ######## ## ## ####### ## ## ## */
int hdr_calculate_bucket_config( int hdr_calculate_bucket_config(
int64_t lowest_trackable_value, int64_t lowest_discernible_value,
int64_t highest_trackable_value, int64_t highest_trackable_value,
int significant_figures, int significant_figures,
struct hdr_histogram_bucket_config* cfg) struct hdr_histogram_bucket_config* cfg)
...@@ -331,14 +359,14 @@ int hdr_calculate_bucket_config( ...@@ -331,14 +359,14 @@ int hdr_calculate_bucket_config(
int32_t sub_bucket_count_magnitude; int32_t sub_bucket_count_magnitude;
int64_t largest_value_with_single_unit_resolution; int64_t largest_value_with_single_unit_resolution;
if (lowest_trackable_value < 1 || if (lowest_discernible_value < 1 ||
significant_figures < 1 || 5 < significant_figures || significant_figures < 1 || 5 < significant_figures ||
lowest_trackable_value * 2 > highest_trackable_value) lowest_discernible_value * 2 > highest_trackable_value)
{ {
return EINVAL; return EINVAL;
} }
cfg->lowest_trackable_value = lowest_trackable_value; cfg->lowest_discernible_value = lowest_discernible_value;
cfg->significant_figures = significant_figures; cfg->significant_figures = significant_figures;
cfg->highest_trackable_value = highest_trackable_value; cfg->highest_trackable_value = highest_trackable_value;
...@@ -346,8 +374,13 @@ int hdr_calculate_bucket_config( ...@@ -346,8 +374,13 @@ int hdr_calculate_bucket_config(
sub_bucket_count_magnitude = (int32_t) ceil(log((double)largest_value_with_single_unit_resolution) / log(2)); sub_bucket_count_magnitude = (int32_t) ceil(log((double)largest_value_with_single_unit_resolution) / log(2));
cfg->sub_bucket_half_count_magnitude = ((sub_bucket_count_magnitude > 1) ? sub_bucket_count_magnitude : 1) - 1; cfg->sub_bucket_half_count_magnitude = ((sub_bucket_count_magnitude > 1) ? sub_bucket_count_magnitude : 1) - 1;
cfg->unit_magnitude = (int32_t) floor(log((double)lowest_trackable_value) / log(2)); double unit_magnitude = log((double)lowest_discernible_value) / log(2);
if (INT32_MAX < unit_magnitude)
{
return EINVAL;
}
cfg->unit_magnitude = (int32_t) unit_magnitude;
cfg->sub_bucket_count = (int32_t) pow(2, (cfg->sub_bucket_half_count_magnitude + 1)); cfg->sub_bucket_count = (int32_t) pow(2, (cfg->sub_bucket_half_count_magnitude + 1));
cfg->sub_bucket_half_count = cfg->sub_bucket_count / 2; cfg->sub_bucket_half_count = cfg->sub_bucket_count / 2;
cfg->sub_bucket_mask = ((int64_t) cfg->sub_bucket_count - 1) << cfg->unit_magnitude; cfg->sub_bucket_mask = ((int64_t) cfg->sub_bucket_count - 1) << cfg->unit_magnitude;
...@@ -365,7 +398,7 @@ int hdr_calculate_bucket_config( ...@@ -365,7 +398,7 @@ int hdr_calculate_bucket_config(
void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_config* cfg) void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_config* cfg)
{ {
h->lowest_trackable_value = cfg->lowest_trackable_value; h->lowest_discernible_value = cfg->lowest_discernible_value;
h->highest_trackable_value = cfg->highest_trackable_value; h->highest_trackable_value = cfg->highest_trackable_value;
h->unit_magnitude = (int32_t)cfg->unit_magnitude; h->unit_magnitude = (int32_t)cfg->unit_magnitude;
h->significant_figures = (int32_t)cfg->significant_figures; h->significant_figures = (int32_t)cfg->significant_figures;
...@@ -383,7 +416,7 @@ void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_ ...@@ -383,7 +416,7 @@ void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_
} }
int hdr_init( int hdr_init(
int64_t lowest_trackable_value, int64_t lowest_discernible_value,
int64_t highest_trackable_value, int64_t highest_trackable_value,
int significant_figures, int significant_figures,
struct hdr_histogram** result) struct hdr_histogram** result)
...@@ -392,22 +425,22 @@ int hdr_init( ...@@ -392,22 +425,22 @@ int hdr_init(
struct hdr_histogram_bucket_config cfg; struct hdr_histogram_bucket_config cfg;
struct hdr_histogram* histogram; struct hdr_histogram* histogram;
int r = hdr_calculate_bucket_config(lowest_trackable_value, highest_trackable_value, significant_figures, &cfg); int r = hdr_calculate_bucket_config(lowest_discernible_value, highest_trackable_value, significant_figures, &cfg);
if (r) if (r)
{ {
return r; return r;
} }
counts = (int64_t*) calloc((size_t) cfg.counts_len, sizeof(int64_t)); counts = (int64_t*) hdr_calloc((size_t) cfg.counts_len, sizeof(int64_t));
if (!counts) if (!counts)
{ {
return ENOMEM; return ENOMEM;
} }
histogram = (struct hdr_histogram*) calloc(1, sizeof(struct hdr_histogram)); histogram = (struct hdr_histogram*) hdr_calloc(1, sizeof(struct hdr_histogram));
if (!histogram) if (!histogram)
{ {
free(counts); hdr_free(counts);
return ENOMEM; return ENOMEM;
} }
...@@ -422,8 +455,8 @@ int hdr_init( ...@@ -422,8 +455,8 @@ int hdr_init(
void hdr_close(struct hdr_histogram* h) void hdr_close(struct hdr_histogram* h)
{ {
if (h) { if (h) {
free(h->counts); hdr_free(h->counts);
free(h); hdr_free(h);
} }
} }
...@@ -643,28 +676,80 @@ int64_t hdr_min(const struct hdr_histogram* h) ...@@ -643,28 +676,80 @@ int64_t hdr_min(const struct hdr_histogram* h)
return non_zero_min(h); return non_zero_min(h);
} }
static int64_t get_value_from_idx_up_to_count(const struct hdr_histogram* h, int64_t count_at_percentile)
{
int64_t count_to_idx = 0;
int64_t value_from_idx = 0;
int32_t sub_bucket_idx = -1;
int32_t bucket_idx = 0;
int32_t bucket_base_idx = get_bucket_base_index(h, bucket_idx);
// Overflow check
if (count_at_percentile > h->total_count)
{
count_at_percentile = h->total_count;
}
while (count_to_idx < count_at_percentile)
{
// increment bucket
sub_bucket_idx++;
if (sub_bucket_idx >= h->sub_bucket_count)
{
sub_bucket_idx = h->sub_bucket_half_count;
bucket_idx++;
bucket_base_idx = get_bucket_base_index(h, bucket_idx);
}
count_to_idx += get_count_at_index_given_bucket_base_idx(h, bucket_base_idx, sub_bucket_idx);
value_from_idx = ((int64_t)(sub_bucket_idx)) << (((int64_t)(bucket_idx)) + h->unit_magnitude);
}
return value_from_idx;
}
int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile) int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile)
{ {
struct hdr_iter iter;
int64_t total = 0;
double requested_percentile = percentile < 100.0 ? percentile : 100.0; double requested_percentile = percentile < 100.0 ? percentile : 100.0;
int64_t count_at_percentile = int64_t count_at_percentile =
(int64_t) (((requested_percentile / 100) * h->total_count) + 0.5); (int64_t) (((requested_percentile / 100) * h->total_count) + 0.5);
count_at_percentile = count_at_percentile > 1 ? count_at_percentile : 1; int64_t value_from_idx = get_value_from_idx_up_to_count(h, count_at_percentile);
if (percentile == 0.0)
{
return lowest_equivalent_value(h, value_from_idx);
}
return highest_equivalent_value(h, value_from_idx);
}
hdr_iter_init(&iter, h); int hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length)
{
if (NULL == percentiles || NULL == values)
{
return EINVAL;
}
while (hdr_iter_next(&iter)) struct hdr_iter iter;
const int64_t total_count = h->total_count;
// to avoid allocations we use the values array for intermediate computation
// i.e. to store the expected cumulative count at each percentile
for (size_t i = 0; i < length; i++)
{ {
total += iter.count; const double requested_percentile = percentiles[i] < 100.0 ? percentiles[i] : 100.0;
const int64_t count_at_percentile =
(int64_t) (((requested_percentile / 100) * total_count) + 0.5);
values[i] = count_at_percentile > 1 ? count_at_percentile : 1;
}
if (total >= count_at_percentile) hdr_iter_init(&iter, h);
int64_t total = 0;
size_t at_pos = 0;
while (hdr_iter_next(&iter) && at_pos < length)
{
total += iter.count;
while (at_pos < length && total >= values[at_pos])
{ {
int64_t value_from_index = iter.value; values[at_pos] = highest_equivalent_value(h, iter.value);
return highest_equivalent_value(h, value_from_index); at_pos++;
} }
} }
return 0; return 0;
} }
...@@ -757,11 +842,16 @@ static bool move_next(struct hdr_iter* iter) ...@@ -757,11 +842,16 @@ static bool move_next(struct hdr_iter* iter)
iter->count = counts_get_normalised(iter->h, iter->counts_index); iter->count = counts_get_normalised(iter->h, iter->counts_index);
iter->cumulative_count += iter->count; iter->cumulative_count += iter->count;
const int64_t value = hdr_value_at_index(iter->h, iter->counts_index);
iter->value = hdr_value_at_index(iter->h, iter->counts_index); const int32_t bucket_index = get_bucket_index(iter->h, value);
iter->highest_equivalent_value = highest_equivalent_value(iter->h, iter->value); const int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, iter->h->unit_magnitude);
iter->lowest_equivalent_value = lowest_equivalent_value(iter->h, iter->value); const int64_t leq = lowest_equivalent_value_given_bucket_indices(iter->h, bucket_index, sub_bucket_index);
iter->median_equivalent_value = hdr_median_equivalent_value(iter->h, iter->value); const int64_t size_of_equivalent_value_range = size_of_equivalent_value_range_given_bucket_indices(
iter->h, bucket_index, sub_bucket_index);
iter->lowest_equivalent_value = leq;
iter->value = value;
iter->highest_equivalent_value = leq + size_of_equivalent_value_range - 1;
iter->median_equivalent_value = leq + (size_of_equivalent_value_range >> 1);
return true; return true;
} }
......
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
struct hdr_histogram struct hdr_histogram
{ {
int64_t lowest_trackable_value; int64_t lowest_discernible_value;
int64_t highest_trackable_value; int64_t highest_trackable_value;
int32_t unit_magnitude; int32_t unit_magnitude;
int32_t significant_figures; int32_t significant_figures;
...@@ -44,8 +45,8 @@ extern "C" { ...@@ -44,8 +45,8 @@ extern "C" {
* involved math on the input parameters this function it is tricky to stack allocate. * involved math on the input parameters this function it is tricky to stack allocate.
* The histogram should be released with hdr_close * The histogram should be released with hdr_close
* *
* @param lowest_trackable_value The smallest possible value to be put into the * @param lowest_discernible_value The smallest possible value that is distinguishable from 0.
* histogram. * Must be a positive integer that is >= 1. May be internally rounded down to nearest power of 2.
* @param highest_trackable_value The largest possible value to be put into the * @param highest_trackable_value The largest possible value to be put into the
* histogram. * histogram.
* @param significant_figures The level of precision for this histogram, i.e. the number * @param significant_figures The level of precision for this histogram, i.e. the number
...@@ -53,12 +54,12 @@ extern "C" { ...@@ -53,12 +54,12 @@ extern "C" {
* the results from the histogram will be accurate up to the first three digits. Must * the results from the histogram will be accurate up to the first three digits. Must
* be a value between 1 and 5 (inclusive). * be a value between 1 and 5 (inclusive).
* @param result Output parameter to capture allocated histogram. * @param result Output parameter to capture allocated histogram.
* @return 0 on success, EINVAL if lowest_trackable_value is < 1 or the * @return 0 on success, EINVAL if lowest_discernible_value is < 1 or the
* significant_figure value is outside of the allowed range, ENOMEM if malloc * significant_figure value is outside of the allowed range, ENOMEM if malloc
* failed. * failed.
*/ */
int hdr_init( int hdr_init(
int64_t lowest_trackable_value, int64_t lowest_discernible_value,
int64_t highest_trackable_value, int64_t highest_trackable_value,
int significant_figures, int significant_figures,
struct hdr_histogram** result); struct hdr_histogram** result);
...@@ -158,10 +159,10 @@ bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t co ...@@ -158,10 +159,10 @@ bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t co
* Record a value in the histogram and backfill based on an expected interval. * Record a value in the histogram and backfill based on an expected interval.
* *
* Records a value in the histogram, will round this value of to a precision at or better * Records a value in the histogram, will round this value of to a precision at or better
* than the significant_figure specified at contruction time. This is specifically used * than the significant_figure specified at construction time. This is specifically used
* for recording latency. If the value is larger than the expected_interval then the * for recording latency. If the value is larger than the expected_interval then the
* latency recording system has experienced co-ordinated omission. This method fills in the * latency recording system has experienced co-ordinated omission. This method fills in the
* values that would have occured had the client providing the load not been blocked. * values that would have occurred had the client providing the load not been blocked.
* @param h "This" pointer * @param h "This" pointer
* @param value Value to add to the histogram * @param value Value to add to the histogram
...@@ -169,16 +170,16 @@ bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t co ...@@ -169,16 +170,16 @@ bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t co
* @return false if the value is larger than the highest_trackable_value and can't be recorded, * @return false if the value is larger than the highest_trackable_value and can't be recorded,
* true otherwise. * true otherwise.
*/ */
bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expexcted_interval); bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expected_interval);
/** /**
* Record a value in the histogram and backfill based on an expected interval. * Record a value in the histogram and backfill based on an expected interval.
* *
* Records a value in the histogram, will round this value of to a precision at or better * Records a value in the histogram, will round this value of to a precision at or better
* than the significant_figure specified at contruction time. This is specifically used * than the significant_figure specified at construction time. This is specifically used
* for recording latency. If the value is larger than the expected_interval then the * for recording latency. If the value is larger than the expected_interval then the
* latency recording system has experienced co-ordinated omission. This method fills in the * latency recording system has experienced co-ordinated omission. This method fills in the
* values that would have occured had the client providing the load not been blocked. * values that would have occurred had the client providing the load not been blocked.
* *
* Will record this value atomically, however the whole structure may appear inconsistent * Will record this value atomically, however the whole structure may appear inconsistent
* when read concurrently with this update. Do NOT mix calls to this method with calls * when read concurrently with this update. Do NOT mix calls to this method with calls
...@@ -190,7 +191,7 @@ bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t ...@@ -190,7 +191,7 @@ bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t
* @return false if the value is larger than the highest_trackable_value and can't be recorded, * @return false if the value is larger than the highest_trackable_value and can't be recorded,
* true otherwise. * true otherwise.
*/ */
bool hdr_record_corrected_value_atomic(struct hdr_histogram* h, int64_t value, int64_t expexcted_interval); bool hdr_record_corrected_value_atomic(struct hdr_histogram* h, int64_t value, int64_t expected_interval);
/** /**
* Record a value in the histogram 'count' times. Applies the same correcting logic * Record a value in the histogram 'count' times. Applies the same correcting logic
...@@ -225,7 +226,7 @@ bool hdr_record_corrected_values_atomic(struct hdr_histogram* h, int64_t value, ...@@ -225,7 +226,7 @@ bool hdr_record_corrected_values_atomic(struct hdr_histogram* h, int64_t value,
/** /**
* Adds all of the values from 'from' to 'this' histogram. Will return the * Adds all of the values from 'from' to 'this' histogram. Will return the
* number of values that are dropped when copying. Values will be dropped * number of values that are dropped when copying. Values will be dropped
* if they around outside of h.lowest_trackable_value and * if they around outside of h.lowest_discernible_value and
* h.highest_trackable_value. * h.highest_trackable_value.
* *
* @param h "This" pointer * @param h "This" pointer
...@@ -237,7 +238,7 @@ int64_t hdr_add(struct hdr_histogram* h, const struct hdr_histogram* from); ...@@ -237,7 +238,7 @@ int64_t hdr_add(struct hdr_histogram* h, const struct hdr_histogram* from);
/** /**
* Adds all of the values from 'from' to 'this' histogram. Will return the * Adds all of the values from 'from' to 'this' histogram. Will return the
* number of values that are dropped when copying. Values will be dropped * number of values that are dropped when copying. Values will be dropped
* if they around outside of h.lowest_trackable_value and * if they around outside of h.lowest_discernible_value and
* h.highest_trackable_value. * h.highest_trackable_value.
* *
* @param h "This" pointer * @param h "This" pointer
...@@ -271,6 +272,18 @@ int64_t hdr_max(const struct hdr_histogram* h); ...@@ -271,6 +272,18 @@ int64_t hdr_max(const struct hdr_histogram* h);
*/ */
int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile); int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile);
/**
* Get the values at the given percentiles.
*
* @param h "This" pointer.
* @param percentiles The ordered percentiles array to get the values for.
* @param length Number of elements in the arrays.
* @param values Destination array containing the values at the given percentiles.
* The values array should be allocated by the caller.
* @return 0 on success, ENOMEM if the provided destination array is null.
*/
int hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length);
/** /**
* Gets the standard deviation for the values in the histogram. * Gets the standard deviation for the values in the histogram.
* *
...@@ -469,7 +482,7 @@ int hdr_percentiles_print( ...@@ -469,7 +482,7 @@ int hdr_percentiles_print(
*/ */
struct hdr_histogram_bucket_config struct hdr_histogram_bucket_config
{ {
int64_t lowest_trackable_value; int64_t lowest_discernible_value;
int64_t highest_trackable_value; int64_t highest_trackable_value;
int64_t unit_magnitude; int64_t unit_magnitude;
int64_t significant_figures; int64_t significant_figures;
...@@ -482,7 +495,7 @@ struct hdr_histogram_bucket_config ...@@ -482,7 +495,7 @@ struct hdr_histogram_bucket_config
}; };
int hdr_calculate_bucket_config( int hdr_calculate_bucket_config(
int64_t lowest_trackable_value, int64_t lowest_discernible_value,
int64_t highest_trackable_value, int64_t highest_trackable_value,
int significant_figures, int significant_figures,
struct hdr_histogram_bucket_config* cfg); struct hdr_histogram_bucket_config* cfg);
...@@ -496,7 +509,7 @@ int64_t hdr_next_non_equivalent_value(const struct hdr_histogram* h, int64_t val ...@@ -496,7 +509,7 @@ int64_t hdr_next_non_equivalent_value(const struct hdr_histogram* h, int64_t val
int64_t hdr_median_equivalent_value(const struct hdr_histogram* h, int64_t value); int64_t hdr_median_equivalent_value(const struct hdr_histogram* h, int64_t value);
/** /**
* Used to reset counters after importing data manuallying into the histogram, used by the logging code * Used to reset counters after importing data manually into the histogram, used by the logging code
* and other custom serialisation tools. * and other custom serialisation tools.
*/ */
void hdr_reset_internal_counters(struct hdr_histogram* h); void hdr_reset_internal_counters(struct hdr_histogram* h);
......
#ifndef HDR_MALLOC_H__
#define HDR_MALLOC_H__
void *zmalloc(size_t size);
void *zcalloc_num(size_t num, size_t size);
void *zrealloc(void *ptr, size_t size);
void zfree(void *ptr);
#define hdr_malloc zmalloc
#define hdr_calloc zcalloc_num
#define hdr_realloc zrealloc
#define hdr_free zfree
#endif
#ifndef HDR_TESTS_H
#define HDR_TESTS_H
/* These are functions used in tests and are not intended for normal usage. */
#include "hdr_histogram.h"
#ifdef __cplusplus
extern "C" {
#endif
int32_t counts_index_for(const struct hdr_histogram* h, int64_t value);
int hdr_encode_compressed(struct hdr_histogram* h, uint8_t** compressed_histogram, size_t* compressed_len);
int hdr_decode_compressed(uint8_t* buffer, size_t length, struct hdr_histogram** histogram);
void hdr_base64_decode_block(const char* input, uint8_t* output);
void hdr_base64_encode_block(const uint8_t* input, char* output);
#ifdef __cplusplus
}
#endif
#endif
...@@ -674,6 +674,8 @@ LUA_API void lua_rawset (lua_State *L, int idx) { ...@@ -674,6 +674,8 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
api_checknelems(L, 2); api_checknelems(L, 2);
t = index2adr(L, idx); t = index2adr(L, idx);
api_check(L, ttistable(t)); api_check(L, ttistable(t));
if (hvalue(t)->readonly)
luaG_runerror(L, "Attempt to modify a readonly table");
setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
luaC_barriert(L, hvalue(t), L->top-1); luaC_barriert(L, hvalue(t), L->top-1);
L->top -= 2; L->top -= 2;
...@@ -687,6 +689,8 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) { ...@@ -687,6 +689,8 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
api_checknelems(L, 1); api_checknelems(L, 1);
o = index2adr(L, idx); o = index2adr(L, idx);
api_check(L, ttistable(o)); api_check(L, ttistable(o));
if (hvalue(o)->readonly)
luaG_runerror(L, "Attempt to modify a readonly table");
setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
luaC_barriert(L, hvalue(o), L->top-1); luaC_barriert(L, hvalue(o), L->top-1);
L->top--; L->top--;
...@@ -709,6 +713,8 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { ...@@ -709,6 +713,8 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
} }
switch (ttype(obj)) { switch (ttype(obj)) {
case LUA_TTABLE: { case LUA_TTABLE: {
if (hvalue(obj)->readonly)
luaG_runerror(L, "Attempt to modify a readonly table");
hvalue(obj)->metatable = mt; hvalue(obj)->metatable = mt;
if (mt) if (mt)
luaC_objbarriert(L, hvalue(obj), mt); luaC_objbarriert(L, hvalue(obj), mt);
...@@ -1085,3 +1091,19 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { ...@@ -1085,3 +1091,19 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
return name; return name;
} }
LUA_API void lua_enablereadonlytable (lua_State *L, int objindex, int enabled) {
const TValue* o = index2adr(L, objindex);
api_check(L, ttistable(o));
Table* t = hvalue(o);
api_check(L, t != hvalue(registry(L)));
t->readonly = enabled;
}
LUA_API int lua_isreadonlytable (lua_State *L, int objindex) {
const TValue* o = index2adr(L, objindex);
api_check(L, ttistable(o));
Table* t = hvalue(o);
api_check(L, t != hvalue(registry(L)));
return t->readonly;
}
...@@ -80,7 +80,6 @@ LUA_API int lua_gethookcount (lua_State *L) { ...@@ -80,7 +80,6 @@ LUA_API int lua_gethookcount (lua_State *L) {
return L->basehookcount; return L->basehookcount;
} }
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
int status; int status;
CallInfo *ci; CallInfo *ci;
......
...@@ -337,7 +337,8 @@ typedef struct Node { ...@@ -337,7 +337,8 @@ typedef struct Node {
typedef struct Table { typedef struct Table {
CommonHeader; CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */ lu_byte flags; /* 1<<p means tagmethod(p) is not present */
int readonly;
lu_byte lsizenode; /* log2 of size of `node' array */ lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable; struct Table *metatable;
TValue *array; /* array part */ TValue *array; /* array part */
......
...@@ -364,6 +364,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) { ...@@ -364,6 +364,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) {
t->array = NULL; t->array = NULL;
t->sizearray = 0; t->sizearray = 0;
t->lsizenode = 0; t->lsizenode = 0;
t->readonly = 0;
t->node = cast(Node *, dummynode); t->node = cast(Node *, dummynode);
setarrayvector(L, t, narray); setarrayvector(L, t, narray);
setnodevector(L, t, nhash); setnodevector(L, t, nhash);
......
...@@ -358,6 +358,9 @@ struct lua_Debug { ...@@ -358,6 +358,9 @@ struct lua_Debug {
int i_ci; /* active function */ int i_ci; /* active function */
}; };
LUA_API void lua_enablereadonlytable (lua_State *L, int index, int enabled);
LUA_API int lua_isreadonlytable (lua_State *L, int index);
/* }====================================================================== */ /* }====================================================================== */
......
...@@ -138,6 +138,8 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { ...@@ -138,6 +138,8 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
const TValue *tm; const TValue *tm;
if (ttistable(t)) { /* `t' is a table? */ if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t); Table *h = hvalue(t);
if (h->readonly)
luaG_runerror(L, "Attempt to modify a readonly table");
TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
if (!ttisnil(oldval) || /* result is no nil? */ if (!ttisnil(oldval) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
......
...@@ -175,6 +175,16 @@ timeout 0 ...@@ -175,6 +175,16 @@ timeout 0
# Redis default starting with Redis 3.2.1. # Redis default starting with Redis 3.2.1.
tcp-keepalive 300 tcp-keepalive 300
# Apply OS-specific mechanism to mark the listening socket with the specified
# ID, to support advanced routing and filtering capabilities.
#
# On Linux, the ID represents a connection mark.
# On FreeBSD, the ID represents a socket cookie ID.
# On OpenBSD, the ID represents a route table ID.
#
# The default value is 0, which implies no marking is required.
# socket-mark-id 0
################################# TLS/SSL ##################################### ################################# TLS/SSL #####################################
# By default, TLS/SSL is disabled. To enable it, the "tls-port" configuration # By default, TLS/SSL is disabled. To enable it, the "tls-port" configuration
...@@ -718,6 +728,31 @@ repl-disable-tcp-nodelay no ...@@ -718,6 +728,31 @@ repl-disable-tcp-nodelay no
# By default the priority is 100. # By default the priority is 100.
replica-priority 100 replica-priority 100
# The propagation error behavior controls how Redis will behave when it is
# unable to handle a command being processed in the replication stream from a master
# or processed while reading from an AOF file. Errors that occur during propagation
# are unexpected, and can cause data inconsistency. However, there are edge cases
# in earlier versions of Redis where it was possible for the server to replicate or persist
# commands that would fail on future versions. For this reason the default behavior
# is to ignore such errors and continue processing commands.
#
# If an application wants to ensure there is no data divergence, this configuration
# should be set to 'panic' instead. The value can also be set to 'panic-on-replicas'
# to only panic when a replica encounters an error on the replication stream. One of
# these two panic values will become the default value in the future once there are
# sufficient safety mechanisms in place to prevent false positive crashes.
#
# propagation-error-behavior ignore
# Replica ignore disk write errors controls the behavior of a replica when it is
# unable to persist a write command received from its master to disk. By default,
# this configuration is set to 'no' and will crash the replica in this condition.
# It is not recommended to change this default, however in order to be compatible
# with older versions of Redis this config can be toggled to 'yes' which will just
# log a warning and execute the write command it got from the master.
#
# replica-ignore-disk-write-errors no
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# By default, Redis Sentinel includes all replicas in its reports. A replica # By default, Redis Sentinel includes all replicas in its reports. A replica
# can be excluded from Redis Sentinel's announcements. An unannounced replica # can be excluded from Redis Sentinel's announcements. An unannounced replica
...@@ -1492,6 +1527,22 @@ aof-timestamp-enabled no ...@@ -1492,6 +1527,22 @@ aof-timestamp-enabled no
# #
# shutdown-timeout 10 # shutdown-timeout 10
# When Redis receives a SIGINT or SIGTERM, shutdown is initiated and by default
# an RDB snapshot is written to disk in a blocking operation if save points are configured.
# The options used on signaled shutdown can include the following values:
# default: Saves RDB snapshot only if save points are configured.
# Waits for lagging replicas to catch up.
# save: Forces a DB saving operation even if no save points are configured.
# nosave: Prevents DB saving operation even if one or more save points are configured.
# now: Skips waiting for lagging replicas.
# force: Ignores any errors that would normally prevent the server from exiting.
#
# Any combination of values is allowed as long as "save" and "nosave" are not set simultaneously.
# Example: "nosave force now"
#
# shutdown-on-sigint default
# shutdown-on-sigterm default
################ NON-DETERMINISTIC LONG BLOCKING COMMANDS ##################### ################ NON-DETERMINISTIC LONG BLOCKING COMMANDS #####################
# Maximum time in milliseconds for EVAL scripts, functions and in some cases # Maximum time in milliseconds for EVAL scripts, functions and in some cases
...@@ -1827,6 +1878,7 @@ latency-monitor-threshold 0 ...@@ -1827,6 +1878,7 @@ latency-monitor-threshold 0
# z Sorted set commands # z Sorted set commands
# x Expired events (events generated every time a key expires) # x Expired events (events generated every time a key expires)
# e Evicted events (events generated when a key is evicted for maxmemory) # e Evicted events (events generated when a key is evicted for maxmemory)
# n New key events (Note: not included in the 'A' class)
# t Stream commands # t Stream commands
# d Module key type events # d Module key type events
# m Key-miss events (Note: It is not included in the 'A' class) # m Key-miss events (Note: It is not included in the 'A' class)
......
...@@ -40,6 +40,7 @@ $TCLSH tests/test_helper.tcl \ ...@@ -40,6 +40,7 @@ $TCLSH tests/test_helper.tcl \
--single unit/moduleapi/zset \ --single unit/moduleapi/zset \
--single unit/moduleapi/list \ --single unit/moduleapi/list \
--single unit/moduleapi/stream \ --single unit/moduleapi/stream \
--single unit/moduleapi/mallocsize \
--single unit/moduleapi/datatype2 \ --single unit/moduleapi/datatype2 \
--single unit/moduleapi/cluster \ --single unit/moduleapi/cluster \
--single unit/moduleapi/aclcheck \ --single unit/moduleapi/aclcheck \
...@@ -48,4 +49,5 @@ $TCLSH tests/test_helper.tcl \ ...@@ -48,4 +49,5 @@ $TCLSH tests/test_helper.tcl \
--single unit/moduleapi/cmdintrospection \ --single unit/moduleapi/cmdintrospection \
--single unit/moduleapi/eventloop \ --single unit/moduleapi/eventloop \
--single unit/moduleapi/timer \ --single unit/moduleapi/timer \
--single unit/moduleapi/publish \
"${@}" "${@}"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment