Commit 20618c71 authored by Oran Agra's avatar Oran Agra
Browse files

Merge remote-tracking branch 'origin/unstable' into 7.0

parents fb4e0d40 89772ed8
...@@ -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
...@@ -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
---------------------------------------------- ----------------------------------------------
......
/**
* 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;
......
...@@ -338,6 +338,7 @@ typedef struct Node { ...@@ -338,6 +338,7 @@ 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 \
"${@}" "${@}"
...@@ -49,6 +49,8 @@ ...@@ -49,6 +49,8 @@
#include "anet.h" #include "anet.h"
#include "config.h" #include "config.h"
#define UNUSED(x) (void)(x)
static void anetSetError(char *err, const char *fmt, ...) static void anetSetError(char *err, const char *fmt, ...)
{ {
va_list ap; va_list ap;
...@@ -680,3 +682,18 @@ error: ...@@ -680,3 +682,18 @@ error:
close(fds[1]); close(fds[1]);
return -1; return -1;
} }
int anetSetSockMarkId(char *err, int fd, uint32_t id) {
#ifdef HAVE_SOCKOPTMARKID
if (setsockopt(fd, SOL_SOCKET, SOCKOPTMARKID, (void *)&id, sizeof(id)) == -1) {
anetSetError(err, "setsockopt: %s", strerror(errno));
return ANET_ERR;
}
return ANET_OK;
#else
UNUSED(fd);
UNUSED(id);
anetSetError(err,"anetSetSockMarkid unsupported on this platform");
return ANET_OK;
#endif
}
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