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

Merge pull request #10829 from oranagra/release-7.0.1

Release 7.0.1
parents d375595d 595e725d
--- ---
name: Crash report name: Crash report
about: Submit a crash report about: Submit a crash report
title: '[CRASH]' title: '[CRASH] <short description>'
labels: '' labels: ''
assignees: '' assignees: ''
--- ---
Notice!
- If a Redis module was involved, please open an issue in the module's repo instead!
- If you're using docker on Apple M1, please make sure the image you're using was compiled for ARM!
**Crash report** **Crash report**
Paste the complete crash log between the quotes below. Please include a few lines from the log preceding the crash report to provide some context. Paste the complete crash log between the quotes below. Please include a few lines from the log preceding the crash report to provide some context.
......
name: "CodeQL" name: "CodeQL"
on: on:
push:
pull_request: pull_request:
schedule: schedule:
# run weekly new vulnerability was added to the database # run weekly new vulnerability was added to the database
...@@ -23,12 +22,12 @@ jobs: ...@@ -23,12 +22,12 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v1 uses: github/codeql-action/init@v2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v1 uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1 uses: github/codeql-action/analyze@v2
...@@ -11,6 +11,89 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP. ...@@ -11,6 +11,89 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
SECURITY: There are security fixes in the release. SECURITY: There are security fixes in the release.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
================================================================================
Redis 7.0.1 Released Wed Jun 8 12:00:00 IST 2022
================================================================================
Upgrade urgency: MODERATE, specifically if you're using a previous release of
Redis 7.0, contains some behavior changes for new 7.0 features and important
fixes for bugs in previous 7.0 releases.
Improvements
============
* Add warning for suspected slow system clocksource setting
Add --check-system command line option. (#10636)
* Allow read-only scripts (*_RO commands, and ones with `no-writes` flag)
during CLIENT PAUSE WRITE (#10744)
* Add `readonly` flag in COMMAND command for EVAL_RO, EVALSHA_RO and FCALL_RO (#10728)
* redis-server command line arguments now accept one string with spaces
for multi-arg configs (#10660)
Potentially Breaking Changes
============================
* Omitting a config option value in command line argument no longer works (#10660)
* Hide the `may_replicate` flag from the COMMAND command response (#10744)
Potentially Breaking Changes for new Redis 7.0 features
-------------------------------------------------------
* Protocol: Sharded pubsub publish emits `smessage` instead of `message` (#10792)
* CLUSTER SHARDS returns slots as RESP integers, not strings (#10683)
* Block PFCOUNT and PUBLISH in read-only scripts (*_RO commands, and no-writes) (#10744)
* Scripts that declare the `no-writes` flag are implicitly `allow-oom` too (#10699)
Changes in CLI tools
====================
* redis-cli --bigkeys, --memkeys, --hotkeys, --scan. Finish nicely after Ctrl+C (#10736)
Platform / toolchain support related improvements
=================================================
* Support tcp-keepalive config interval on MacOs (#10667)
* Support RSS metrics on Haiku OS (#10687)
INFO fields and introspection changes
=====================================
* Add isolated network metrics for replication. (#10062, #10810)
Module API changes
==================
* Add two more new checks to RM_Call script mode (#10786)
* Add new RM_Call flag to let Redis automatically refuse `deny-oom` commands (#10786)
* Add module API RM_MallocUsableSize (#10795)
* Add missing REDISMODULE_NOTIFY_NEW (#10688)
* Fix cursor type in RedisModuleScanCursor to handle more than 2^31 elements (#10698)
* Fix RM_Yield bugs and RM_Call("EVAL") OOM check bug (#10786)
* Fix bugs in enum configs with overlapping bit flags (#10661)
Bug Fixes
=========
* FLUSHALL correctly resets rdb_changes_since_last_save INFO field (#10691)
* FLUSHDB is now propagated to replicas / AOF, even if the db is empty (#10691)
* Replica fail and retry the PSYNC if the master is unresponsive (#10726)
* Fix ZRANGESTORE crash when zset_max_listpack_entries is 0 (#10767)
Fixes for issues in previous release candidates of Redis 7.0
------------------------------------------------------------
* CONFIG REWRITE could cause a config change to be dropped for aliased configs (#10811)
* CONFIG REWRITE would omit rename-command and include lines (#10761)
NOTE: Affected users who used Redis 7.0.0 to rewrite their configuration file
should review and fix the file.
* Fix broken protocol after MISCONF (persistence) error (#10786)
* Fix --save command line regression (#10690)
* Fix possible regression around TLS config changes. re-load files even if the
file name didn't change. (#10713)
* Re-add SENTINEL SLAVES command, missing in redis 7.0 (#10723)
* BZMPOP gets unblocked by non-key args and returns them (#10764)
* Fix possible memory leak in XADD and XTRIM (#10753)
================================================================================ ================================================================================
Redis 7.0.0 GA Released Wed Apr 27 12:00:00 IST 2022 Redis 7.0.0 GA Released Wed Apr 27 12:00:00 IST 2022
================================================================================ ================================================================================
......
...@@ -11,10 +11,10 @@ unless this is not possible or feasible with a reasonable effort. ...@@ -11,10 +11,10 @@ unless this is not possible or feasible with a reasonable effort.
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ------- | ------------------ |
| 7.0.x | :white_check_mark: |
| 6.2.x | :white_check_mark: | | 6.2.x | :white_check_mark: |
| 6.0.x | :white_check_mark: | | 6.0.x | :white_check_mark: |
| 5.0.x | :white_check_mark: | | < 6.0 | :x: |
| < 5.0 | :x: |
## Reporting a Vulnerability ## Reporting a Vulnerability
......
...@@ -100,8 +100,8 @@ Hdr_Histogram ...@@ -100,8 +100,8 @@ Hdr_Histogram
--- ---
Updated source can be found here: https://github.com/HdrHistogram/HdrHistogram_c Updated source can be found here: https://github.com/HdrHistogram/HdrHistogram_c
We use a customized version 0.11.5 We use a customized version based on master branch commit e4448cf6d1cd08fff519812d3b1e58bd5a94ac42.
1. Compare all changes under /hdr_histogram directory to version 0.11.5 1. Compare all changes under /hdr_histogram directory to upstream master commit e4448cf6d1cd08fff519812d3b1e58bd5a94ac42
2. Copy updated files from newer version onto files in /hdr_histogram. 2. Copy updated files from newer version onto files in /hdr_histogram.
3. Apply the changes from 1 above to the updated files. 3. Apply the changes from 1 above to the updated files.
HdrHistogram_c v0.11.5 HdrHistogram_c: 'C' port of High Dynamic Range (HDR) Histogram
HdrHistogram
---------------------------------------------- ----------------------------------------------
This port contains a subset of the 'C' version of High Dynamic Range (HDR) Histogram available at [github.com/HdrHistogram/HdrHistogram_c](https://github.com/HdrHistogram/HdrHistogram_c). [![Gitter chat](https://badges.gitter.im/HdrHistogram/HdrHistogram.png)](https://gitter.im/HdrHistogram/HdrHistogram)
This port contains a subset of the functionality supported by the Java
implementation. The current supported features are:
The code present on `hdr_histogram.c`, `hdr_histogram.h`, and `hdr_atomic.c` was Written by Gil Tene, Michael Barker, * Standard histogram with 64 bit counts (32/16 bit counts not supported)
and Matt Warren, and released to the public domain, as explained at * All iterator types (all values, recorded, percentiles, linear, logarithmic)
http://creativecommons.org/publicdomain/zero/1.0/. * Histogram serialisation (encoding version 1.2, decoding 1.0-1.2)
* Reader/writer phaser and interval recorder
Features not supported, but planned
* Auto-resizing of histograms
Features unlikely to be implemented
* Double histograms
* Atomic/Concurrent histograms
* 16/32 bit histograms
# Simple Tutorial
## Recording values
```C
#include <hdr_histogram.h>
struct hdr_histogram* histogram;
// Initialise the histogram
hdr_init(
1, // Minimum value
INT64_C(3600000000), // Maximum value
3, // Number of significant figures
&histogram) // Pointer to initialise
// Record value
hdr_record_value(
histogram, // Histogram to record to
value) // Value to record
// Record value n times
hdr_record_values(
histogram, // Histogram to record to
value, // Value to record
10) // Record value 10 times
// Record value with correction for co-ordinated omission.
hdr_record_corrected_value(
histogram, // Histogram to record to
value, // Value to record
1000) // Record with expected interval of 1000.
// Print out the values of the histogram
hdr_percentiles_print(
histogram,
stdout, // File to write to
5, // Granularity of printed values
1.0, // Multiplier for results
CLASSIC); // Format CLASSIC/CSV supported.
```
## More examples
For more detailed examples of recording and logging results look at the
[hdr_decoder](examples/hdr_decoder.c)
and [hiccup](examples/hiccup.c)
examples. You can run hiccup and decoder
and pipe the results of one into the other.
```
$ ./examples/hiccup | ./examples/hdr_decoder
```
...@@ -165,16 +165,6 @@ static int32_t count_leading_zeros_64(int64_t value) ...@@ -165,16 +165,6 @@ 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 */
...@@ -679,33 +669,21 @@ int64_t hdr_min(const struct hdr_histogram* h) ...@@ -679,33 +669,21 @@ int64_t hdr_min(const struct hdr_histogram* h)
static int64_t get_value_from_idx_up_to_count(const struct hdr_histogram* h, int64_t count_at_percentile) 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 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 count_at_percentile = 0 < count_at_percentile ? count_at_percentile : 1;
if (count_at_percentile > h->total_count) for (int32_t idx = 0; idx < h->counts_len; idx++)
{ {
count_at_percentile = h->total_count; count_to_idx += h->counts[idx];
} if (count_to_idx >= count_at_percentile)
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; return hdr_value_at_index(h, idx);
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;
return 0;
} }
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)
{ {
double requested_percentile = percentile < 100.0 ? percentile : 100.0; double requested_percentile = percentile < 100.0 ? percentile : 100.0;
......
...@@ -98,7 +98,8 @@ static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) } ...@@ -98,7 +98,8 @@ static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) }
#define BIT_OP(func, opr) \ #define BIT_OP(func, opr) \
static int func(lua_State *L) { int i; UBits b = barg(L, 1); \ static int func(lua_State *L) { int i; UBits b = barg(L, 1); \
for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) } for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); \
BRET(b) }
BIT_OP(bit_band, &=) BIT_OP(bit_band, &=)
BIT_OP(bit_bor, |=) BIT_OP(bit_bor, |=)
BIT_OP(bit_bxor, ^=) BIT_OP(bit_bxor, ^=)
......
...@@ -316,13 +316,14 @@ endif ...@@ -316,13 +316,14 @@ endif
REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX) REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX)
REDIS_SENTINEL_NAME=redis-sentinel$(PROG_SUFFIX) REDIS_SENTINEL_NAME=redis-sentinel$(PROG_SUFFIX)
REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o tracking.o connection.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o tracking.o connection.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o
REDIS_CLI_NAME=redis-cli$(PROG_SUFFIX) REDIS_CLI_NAME=redis-cli$(PROG_SUFFIX)
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o redisassert.o crcspeed.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o redisassert.o crcspeed.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o
REDIS_BENCHMARK_NAME=redis-benchmark$(PROG_SUFFIX) REDIS_BENCHMARK_NAME=redis-benchmark$(PROG_SUFFIX)
REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o redisassert.o release.o crcspeed.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o redisassert.o release.o crcspeed.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o
REDIS_CHECK_RDB_NAME=redis-check-rdb$(PROG_SUFFIX) REDIS_CHECK_RDB_NAME=redis-check-rdb$(PROG_SUFFIX)
REDIS_CHECK_AOF_NAME=redis-check-aof$(PROG_SUFFIX) REDIS_CHECK_AOF_NAME=redis-check-aof$(PROG_SUFFIX)
ALL_SOURCES=$(sort $(patsubst %.o,%.c,$(REDIS_SERVER_OBJ) $(REDIS_CLI_OBJ) $(REDIS_BENCHMARK_OBJ)))
all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME)
@echo "" @echo ""
...@@ -330,7 +331,7 @@ all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCH ...@@ -330,7 +331,7 @@ all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCH
@echo "" @echo ""
Makefile.dep: Makefile.dep:
-$(REDIS_CC) -MM *.c > Makefile.dep 2> /dev/null || true -$(REDIS_CC) -MM $(ALL_SOURCES) > Makefile.dep 2> /dev/null || true
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS)))) ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include Makefile.dep -include Makefile.dep
......
...@@ -144,7 +144,7 @@ void ACLFreeLogEntry(void *le); ...@@ -144,7 +144,7 @@ void ACLFreeLogEntry(void *le);
int ACLSetSelector(aclSelector *selector, const char *op, size_t oplen); int ACLSetSelector(aclSelector *selector, const char *op, size_t oplen);
/* The length of the string representation of a hashed password. */ /* The length of the string representation of a hashed password. */
#define HASH_PASSWORD_LEN SHA256_BLOCK_SIZE*2 #define HASH_PASSWORD_LEN (SHA256_BLOCK_SIZE*2)
/* ============================================================================= /* =============================================================================
* Helper functions for the rest of the ACL implementation * Helper functions for the rest of the ACL implementation
...@@ -153,42 +153,13 @@ int ACLSetSelector(aclSelector *selector, const char *op, size_t oplen); ...@@ -153,42 +153,13 @@ int ACLSetSelector(aclSelector *selector, const char *op, size_t oplen);
/* Return zero if strings are the same, non-zero if they are not. /* Return zero if strings are the same, non-zero if they are not.
* The comparison is performed in a way that prevents an attacker to obtain * The comparison is performed in a way that prevents an attacker to obtain
* information about the nature of the strings just monitoring the execution * information about the nature of the strings just monitoring the execution
* time of the function. * time of the function. Note: The two strings must be the same length.
*
* Note that limiting the comparison length to strings up to 512 bytes we
* can avoid leaking any information about the password length and any
* possible branch misprediction related leak.
*/ */
int time_independent_strcmp(char *a, char *b) { int time_independent_strcmp(char *a, char *b, int len) {
char bufa[CONFIG_AUTHPASS_MAX_LEN], bufb[CONFIG_AUTHPASS_MAX_LEN];
/* The above two strlen perform len(a) + len(b) operations where either
* a or b are fixed (our password) length, and the difference is only
* relative to the length of the user provided string, so no information
* leak is possible in the following two lines of code. */
unsigned int alen = strlen(a);
unsigned int blen = strlen(b);
unsigned int j;
int diff = 0; int diff = 0;
for (int j = 0; j < len; j++) {
/* We can't compare strings longer than our static buffers. diff |= (a[j] ^ b[j]);
* Note that this will never pass the first test in practical circumstances }
* so there is no info leak. */
if (alen > sizeof(bufa) || blen > sizeof(bufb)) return 1;
memset(bufa,0,sizeof(bufa)); /* Constant time. */
memset(bufb,0,sizeof(bufb)); /* Constant time. */
/* Again the time of the following two copies is proportional to
* len(a) + len(b) so no info is leaked. */
memcpy(bufa,a,alen);
memcpy(bufb,b,blen);
/* Always compare all the chars in the two buffers without
* conditional expressions. */
for (j = 0; j < sizeof(bufa); j++) {
diff |= (bufa[j] ^ bufb[j]);
}
/* Length must be equal as well. */
diff |= alen ^ blen;
return diff; /* If zero strings are the same. */ return diff; /* If zero strings are the same. */
} }
...@@ -1414,7 +1385,7 @@ int ACLCheckUserCredentials(robj *username, robj *password) { ...@@ -1414,7 +1385,7 @@ int ACLCheckUserCredentials(robj *username, robj *password) {
sds hashed = ACLHashPassword(password->ptr,sdslen(password->ptr)); sds hashed = ACLHashPassword(password->ptr,sdslen(password->ptr));
while((ln = listNext(&li))) { while((ln = listNext(&li))) {
sds thispass = listNodeValue(ln); sds thispass = listNodeValue(ln);
if (!time_independent_strcmp(hashed, thispass)) { if (!time_independent_strcmp(hashed, thispass, HASH_PASSWORD_LEN)) {
sdsfree(hashed); sdsfree(hashed);
return C_OK; return C_OK;
} }
......
...@@ -50,6 +50,7 @@ static int aeApiCreate(aeEventLoop *eventLoop) { ...@@ -50,6 +50,7 @@ static int aeApiCreate(aeEventLoop *eventLoop) {
} }
static int aeApiResize(aeEventLoop *eventLoop, int setsize) { static int aeApiResize(aeEventLoop *eventLoop, int setsize) {
AE_NOTUSED(eventLoop);
/* Just ensure we have enough room in the fd_set type. */ /* Just ensure we have enough room in the fd_set type. */
if (setsize >= FD_SETSIZE) return -1; if (setsize >= FD_SETSIZE) return -1;
return 0; return 0;
......
...@@ -162,6 +162,13 @@ int anetKeepAlive(char *err, int fd, int interval) ...@@ -162,6 +162,13 @@ int anetKeepAlive(char *err, int fd, int interval)
anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno)); anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno));
return ANET_ERR; return ANET_ERR;
} }
#elif defined(__APPLE__)
/* Set idle time with interval */
val = interval;
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {
anetSetError(err, "setsockopt TCP_KEEPALIVE: %s\n", strerror(errno));
return ANET_ERR;
}
#else #else
((void) interval); /* Avoid unused var warning for non Linux systems. */ ((void) interval); /* Avoid unused var warning for non Linux systems. */
#endif #endif
......
...@@ -231,14 +231,14 @@ sds getAofManifestAsString(aofManifest *am) { ...@@ -231,14 +231,14 @@ sds getAofManifestAsString(aofManifest *am) {
void aofLoadManifestFromDisk(void) { void aofLoadManifestFromDisk(void) {
server.aof_manifest = aofManifestCreate(); server.aof_manifest = aofManifestCreate();
if (!dirExists(server.aof_dirname)) { if (!dirExists(server.aof_dirname)) {
serverLog(LL_NOTICE, "The AOF directory %s doesn't exist", server.aof_dirname); serverLog(LL_DEBUG, "The AOF directory %s doesn't exist", server.aof_dirname);
return; return;
} }
sds am_name = getAofManifestFileName(); sds am_name = getAofManifestFileName();
sds am_filepath = makePath(server.aof_dirname, am_name); sds am_filepath = makePath(server.aof_dirname, am_name);
if (!fileExist(am_filepath)) { if (!fileExist(am_filepath)) {
serverLog(LL_NOTICE, "The AOF manifest file %s doesn't exist", am_name); serverLog(LL_DEBUG, "The AOF manifest file %s doesn't exist", am_name);
sdsfree(am_name); sdsfree(am_name);
sdsfree(am_filepath); sdsfree(am_filepath);
return; return;
...@@ -714,15 +714,16 @@ void aofOpenIfNeededOnServerStart(void) { ...@@ -714,15 +714,16 @@ void aofOpenIfNeededOnServerStart(void) {
} }
/* If we start with an empty dataset, we will force create a BASE file. */ /* If we start with an empty dataset, we will force create a BASE file. */
if (!server.aof_manifest->base_aof_info && size_t incr_aof_len = listLength(server.aof_manifest->incr_aof_list);
!listLength(server.aof_manifest->incr_aof_list)) if (!server.aof_manifest->base_aof_info && !incr_aof_len) {
{
sds base_name = getNewBaseFileNameAndMarkPreAsHistory(server.aof_manifest); sds base_name = getNewBaseFileNameAndMarkPreAsHistory(server.aof_manifest);
sds base_filepath = makePath(server.aof_dirname, base_name); sds base_filepath = makePath(server.aof_dirname, base_name);
if (rewriteAppendOnlyFile(base_filepath) != C_OK) { if (rewriteAppendOnlyFile(base_filepath) != C_OK) {
exit(1); exit(1);
} }
sdsfree(base_filepath); sdsfree(base_filepath);
serverLog(LL_NOTICE, "Creating AOF base file %s on server start",
base_name);
} }
/* Because we will 'exit(1)' if open AOF or persistent manifest fails, so /* Because we will 'exit(1)' if open AOF or persistent manifest fails, so
...@@ -746,6 +747,12 @@ void aofOpenIfNeededOnServerStart(void) { ...@@ -746,6 +747,12 @@ void aofOpenIfNeededOnServerStart(void) {
} }
server.aof_last_incr_size = getAppendOnlyFileSize(aof_name, NULL); server.aof_last_incr_size = getAppendOnlyFileSize(aof_name, NULL);
if (incr_aof_len) {
serverLog(LL_NOTICE, "Opening AOF incr file %s on server start", aof_name);
} else {
serverLog(LL_NOTICE, "Creating AOF incr file %s on server start", aof_name);
}
} }
int aofFileExist(char *filename) { int aofFileExist(char *filename) {
...@@ -801,6 +808,9 @@ int openNewIncrAofForAppend(void) { ...@@ -801,6 +808,9 @@ int openNewIncrAofForAppend(void) {
goto cleanup; goto cleanup;
} }
} }
serverLog(LL_NOTICE, "Creating AOF incr file %s on background rewrite",
new_aof_name);
sdsfree(new_aof_name); sdsfree(new_aof_name);
/* If reaches here, we can safely modify the `server.aof_manifest` /* If reaches here, we can safely modify the `server.aof_manifest`
...@@ -1343,7 +1353,7 @@ int loadSingleAppendOnlyFile(char *filename) { ...@@ -1343,7 +1353,7 @@ int loadSingleAppendOnlyFile(char *filename) {
off_t valid_up_to = 0; /* Offset of latest well-formed command loaded. */ off_t valid_up_to = 0; /* Offset of latest well-formed command loaded. */
off_t valid_before_multi = 0; /* Offset before MULTI command loaded. */ off_t valid_before_multi = 0; /* Offset before MULTI command loaded. */
off_t last_progress_report_size = 0; off_t last_progress_report_size = 0;
int ret = C_OK; int ret = AOF_OK;
sds aof_filepath = makePath(server.aof_dirname, filename); sds aof_filepath = makePath(server.aof_dirname, filename);
FILE *fp = fopen(aof_filepath, "r"); FILE *fp = fopen(aof_filepath, "r");
...@@ -1492,7 +1502,10 @@ int loadSingleAppendOnlyFile(char *filename) { ...@@ -1492,7 +1502,10 @@ int loadSingleAppendOnlyFile(char *filename) {
if (fakeClient->flags & CLIENT_MULTI && if (fakeClient->flags & CLIENT_MULTI &&
fakeClient->cmd->proc != execCommand) fakeClient->cmd->proc != execCommand)
{ {
queueMultiCommand(fakeClient); /* Note: we don't have to attempt calling evalGetCommandFlags,
* since this is AOF, the checks in processCommand are not made
* anyway.*/
queueMultiCommand(fakeClient, cmd->flags);
} else { } else {
cmd->proc(fakeClient); cmd->proc(fakeClient);
} }
...@@ -1523,7 +1536,7 @@ int loadSingleAppendOnlyFile(char *filename) { ...@@ -1523,7 +1536,7 @@ int loadSingleAppendOnlyFile(char *filename) {
goto uxeof; goto uxeof;
} }
loaded_ok: /* DB loaded, cleanup and return C_OK to the caller. */ loaded_ok: /* DB loaded, cleanup and return success (AOF_OK or AOF_TRUNCATED). */
loadingIncrProgress(ftello(fp) - last_progress_report_size); loadingIncrProgress(ftello(fp) - last_progress_report_size);
server.aof_state = old_aof_state; server.aof_state = old_aof_state;
goto cleanup; goto cleanup;
...@@ -1584,7 +1597,7 @@ cleanup: ...@@ -1584,7 +1597,7 @@ cleanup:
/* Load the AOF files according the aofManifest pointed by am. */ /* Load the AOF files according the aofManifest pointed by am. */
int loadAppendOnlyFiles(aofManifest *am) { int loadAppendOnlyFiles(aofManifest *am) {
serverAssert(am != NULL); serverAssert(am != NULL);
int status, ret = C_OK; int status, ret = AOF_OK;
long long start; long long start;
off_t total_size = 0, base_size = 0; off_t total_size = 0, base_size = 0;
sds aof_name; sds aof_name;
...@@ -2258,7 +2271,7 @@ int rewriteAppendOnlyFileRio(rio *aof) { ...@@ -2258,7 +2271,7 @@ int rewriteAppendOnlyFileRio(rio *aof) {
} }
/* In fork child process, we can try to release memory back to the /* In fork child process, we can try to release memory back to the
* OS and possibly avoid or decrease COW. We guve the dismiss * OS and possibly avoid or decrease COW. We give the dismiss
* mechanism a hint about an estimated size of the object we stored. */ * mechanism a hint about an estimated size of the object we stored. */
size_t dump_size = aof->processed_bytes - aof_bytes_before_key; size_t dump_size = aof->processed_bytes - aof_bytes_before_key;
if (server.in_fork_child) dismissObject(o, dump_size); if (server.in_fork_child) dismissObject(o, dump_size);
...@@ -2348,7 +2361,6 @@ int rewriteAppendOnlyFile(char *filename) { ...@@ -2348,7 +2361,6 @@ int rewriteAppendOnlyFile(char *filename) {
stopSaving(0); stopSaving(0);
return C_ERR; return C_ERR;
} }
serverLog(LL_NOTICE,"SYNC append only file rewrite performed");
stopSaving(1); stopSaving(1);
return C_OK; return C_OK;
...@@ -2403,6 +2415,8 @@ int rewriteAppendOnlyFileBackground(void) { ...@@ -2403,6 +2415,8 @@ int rewriteAppendOnlyFileBackground(void) {
redisSetCpuAffinity(server.aof_rewrite_cpulist); redisSetCpuAffinity(server.aof_rewrite_cpulist);
snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid()); snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid());
if (rewriteAppendOnlyFile(tmpfile) == C_OK) { if (rewriteAppendOnlyFile(tmpfile) == C_OK) {
serverLog(LL_NOTICE,
"Successfully created the temporary AOF base file %s", tmpfile);
sendChildCowInfo(CHILD_INFO_TYPE_AOF_COW_SIZE, "AOF rewrite"); sendChildCowInfo(CHILD_INFO_TYPE_AOF_COW_SIZE, "AOF rewrite");
exitFromChild(0); exitFromChild(0);
} else { } else {
...@@ -2543,7 +2557,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { ...@@ -2543,7 +2557,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
latencyStartMonitor(latency); latencyStartMonitor(latency);
if (rename(tmpfile, new_base_filepath) == -1) { if (rename(tmpfile, new_base_filepath) == -1) {
serverLog(LL_WARNING, serverLog(LL_WARNING,
"Error trying to rename the temporary AOF file %s into %s: %s", "Error trying to rename the temporary AOF base file %s into %s: %s",
tmpfile, tmpfile,
new_base_filepath, new_base_filepath,
strerror(errno)); strerror(errno));
...@@ -2553,20 +2567,21 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { ...@@ -2553,20 +2567,21 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
} }
latencyEndMonitor(latency); latencyEndMonitor(latency);
latencyAddSampleIfNeeded("aof-rename", latency); latencyAddSampleIfNeeded("aof-rename", latency);
serverLog(LL_NOTICE,
"Successfully renamed the temporary AOF base file %s into %s", tmpfile, new_base_filename);
/* Rename the temporary incr aof file to 'new_incr_filename'. */ /* Rename the temporary incr aof file to 'new_incr_filename'. */
if (server.aof_state == AOF_WAIT_REWRITE) { if (server.aof_state == AOF_WAIT_REWRITE) {
/* Get temporary incr aof name. */ /* Get temporary incr aof name. */
sds temp_incr_aof_name = getTempIncrAofName(); sds temp_incr_aof_name = getTempIncrAofName();
sds temp_incr_filepath = makePath(server.aof_dirname, temp_incr_aof_name); sds temp_incr_filepath = makePath(server.aof_dirname, temp_incr_aof_name);
sdsfree(temp_incr_aof_name);
/* Get next new incr aof name. */ /* Get next new incr aof name. */
sds new_incr_filename = getNewIncrAofName(temp_am); sds new_incr_filename = getNewIncrAofName(temp_am);
new_incr_filepath = makePath(server.aof_dirname, new_incr_filename); new_incr_filepath = makePath(server.aof_dirname, new_incr_filename);
latencyStartMonitor(latency); latencyStartMonitor(latency);
if (rename(temp_incr_filepath, new_incr_filepath) == -1) { if (rename(temp_incr_filepath, new_incr_filepath) == -1) {
serverLog(LL_WARNING, serverLog(LL_WARNING,
"Error trying to rename the temporary incr AOF file %s into %s: %s", "Error trying to rename the temporary AOF incr file %s into %s: %s",
temp_incr_filepath, temp_incr_filepath,
new_incr_filepath, new_incr_filepath,
strerror(errno)); strerror(errno));
...@@ -2575,11 +2590,15 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { ...@@ -2575,11 +2590,15 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
aofManifestFree(temp_am); aofManifestFree(temp_am);
sdsfree(temp_incr_filepath); sdsfree(temp_incr_filepath);
sdsfree(new_incr_filepath); sdsfree(new_incr_filepath);
sdsfree(temp_incr_aof_name);
goto cleanup; goto cleanup;
} }
latencyEndMonitor(latency); latencyEndMonitor(latency);
latencyAddSampleIfNeeded("aof-rename", latency); latencyAddSampleIfNeeded("aof-rename", latency);
serverLog(LL_NOTICE,
"Successfully renamed the temporary AOF incr file %s into %s", temp_incr_aof_name, new_incr_filename);
sdsfree(temp_incr_filepath); sdsfree(temp_incr_filepath);
sdsfree(temp_incr_aof_name);
} }
/* Change the AOF file type in 'incr_aof_list' from AOF_FILE_TYPE_INCR /* Change the AOF file type in 'incr_aof_list' from AOF_FILE_TYPE_INCR
......
...@@ -528,7 +528,10 @@ CallReply *callReplyCreate(sds reply, list *deferred_error_list, void *private_d ...@@ -528,7 +528,10 @@ CallReply *callReplyCreate(sds reply, list *deferred_error_list, void *private_d
/* Create a new CallReply struct from the reply blob representing an error message. /* Create a new CallReply struct from the reply blob representing an error message.
* Automatically creating deferred_error_list and set a copy of the reply in it. * Automatically creating deferred_error_list and set a copy of the reply in it.
* Refer to callReplyCreate for detailed explanation. */ * Refer to callReplyCreate for detailed explanation.
* Reply string can come in one of two forms:
* 1. A protocol reply starting with "-CODE" and ending with "\r\n"
* 2. A plain string, in which case this function adds the protocol header and footer. */
CallReply *callReplyCreateError(sds reply, void *private_data) { CallReply *callReplyCreateError(sds reply, void *private_data) {
sds err_buff = reply; sds err_buff = reply;
if (err_buff[0] != '-') { if (err_buff[0] != '-') {
......
...@@ -4077,7 +4077,7 @@ void clusterCron(void) { ...@@ -4077,7 +4077,7 @@ void clusterCron(void) {
orphaned_masters++; orphaned_masters++;
} }
if (okslaves > max_slaves) max_slaves = okslaves; if (okslaves > max_slaves) max_slaves = okslaves;
if (nodeIsSlave(myself) && myself->slaveof == node) if (myself->slaveof == node)
this_slaves = okslaves; this_slaves = okslaves;
} }
...@@ -5071,7 +5071,7 @@ void addShardReplyForClusterShards(client *c, clusterNode *node, uint16_t *slot_ ...@@ -5071,7 +5071,7 @@ void addShardReplyForClusterShards(client *c, clusterNode *node, uint16_t *slot_
serverAssert((slot_pairs_count % 2) == 0); serverAssert((slot_pairs_count % 2) == 0);
addReplyArrayLen(c, slot_pairs_count); addReplyArrayLen(c, slot_pairs_count);
for (int i = 0; i < slot_pairs_count; i++) for (int i = 0; i < slot_pairs_count; i++)
addReplyBulkLongLong(c, (unsigned long)slot_info_pairs[i]); addReplyLongLong(c, (unsigned long)slot_info_pairs[i]);
} else { } else {
/* If no slot info pair is provided, the node owns no slots */ /* If no slot info pair is provided, the node owns no slots */
addReplyArrayLen(c, 0); addReplyArrayLen(c, 0);
......
...@@ -124,7 +124,7 @@ struct redisCommandArg BITFIELD_RO_encoding_offset_Subargs[] = { ...@@ -124,7 +124,7 @@ struct redisCommandArg BITFIELD_RO_encoding_offset_Subargs[] = {
/* BITFIELD_RO argument table */ /* BITFIELD_RO argument table */
struct redisCommandArg BITFIELD_RO_Args[] = { struct redisCommandArg BITFIELD_RO_Args[] = {
{"key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE}, {"key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE},
{"encoding_offset",ARG_TYPE_BLOCK,-1,"GET",NULL,NULL,CMD_ARG_MULTIPLE,.subargs=BITFIELD_RO_encoding_offset_Subargs}, {"encoding_offset",ARG_TYPE_BLOCK,-1,"GET",NULL,NULL,CMD_ARG_MULTIPLE|CMD_ARG_MULTIPLE_TOKEN,.subargs=BITFIELD_RO_encoding_offset_Subargs},
{0} {0}
}; };
...@@ -1595,7 +1595,7 @@ NULL ...@@ -1595,7 +1595,7 @@ NULL
/* RENAME argument table */ /* RENAME argument table */
struct redisCommandArg RENAME_Args[] = { struct redisCommandArg RENAME_Args[] = {
{"key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE}, {"key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE},
{"newkey",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE}, {"newkey",ARG_TYPE_KEY,1,NULL,NULL,NULL,CMD_ARG_NONE},
{0} {0}
}; };
...@@ -1613,7 +1613,7 @@ commandHistory RENAMENX_History[] = { ...@@ -1613,7 +1613,7 @@ commandHistory RENAMENX_History[] = {
/* RENAMENX argument table */ /* RENAMENX argument table */
struct redisCommandArg RENAMENX_Args[] = { struct redisCommandArg RENAMENX_Args[] = {
{"key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE}, {"key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE},
{"newkey",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE}, {"newkey",ARG_TYPE_KEY,1,NULL,NULL,NULL,CMD_ARG_NONE},
{0} {0}
}; };
...@@ -2602,6 +2602,13 @@ struct redisCommandArg PFCOUNT_Args[] = { ...@@ -2602,6 +2602,13 @@ struct redisCommandArg PFCOUNT_Args[] = {
/* PFDEBUG tips */ /* PFDEBUG tips */
#define PFDEBUG_tips NULL #define PFDEBUG_tips NULL
/* PFDEBUG argument table */
struct redisCommandArg PFDEBUG_Args[] = {
{"subcommand",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE},
{"key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE},
{0}
};
/********** PFMERGE ********************/ /********** PFMERGE ********************/
/* PFMERGE history */ /* PFMERGE history */
...@@ -3153,7 +3160,7 @@ struct redisCommandArg PUBSUB_SHARDCHANNELS_Args[] = { ...@@ -3153,7 +3160,7 @@ struct redisCommandArg PUBSUB_SHARDCHANNELS_Args[] = {
/* PUBSUB SHARDNUMSUB argument table */ /* PUBSUB SHARDNUMSUB argument table */
struct redisCommandArg PUBSUB_SHARDNUMSUB_Args[] = { struct redisCommandArg PUBSUB_SHARDNUMSUB_Args[] = {
{"channel",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_OPTIONAL|CMD_ARG_MULTIPLE}, {"shardchannel",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_OPTIONAL|CMD_ARG_MULTIPLE},
{0} {0}
}; };
...@@ -3163,8 +3170,8 @@ struct redisCommand PUBSUB_Subcommands[] = { ...@@ -3163,8 +3170,8 @@ struct redisCommand PUBSUB_Subcommands[] = {
{"help","Show helpful text about the different subcommands","O(1)","6.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_HELP_History,PUBSUB_HELP_tips,pubsubCommand,2,CMD_LOADING|CMD_STALE,0}, {"help","Show helpful text about the different subcommands","O(1)","6.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_HELP_History,PUBSUB_HELP_tips,pubsubCommand,2,CMD_LOADING|CMD_STALE,0},
{"numpat","Get the count of unique patterns pattern subscriptions","O(1)","2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_NUMPAT_History,PUBSUB_NUMPAT_tips,pubsubCommand,2,CMD_PUBSUB|CMD_LOADING|CMD_STALE,0}, {"numpat","Get the count of unique patterns pattern subscriptions","O(1)","2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_NUMPAT_History,PUBSUB_NUMPAT_tips,pubsubCommand,2,CMD_PUBSUB|CMD_LOADING|CMD_STALE,0},
{"numsub","Get the count of subscribers for channels","O(N) for the NUMSUB subcommand, where N is the number of requested channels","2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_NUMSUB_History,PUBSUB_NUMSUB_tips,pubsubCommand,-2,CMD_PUBSUB|CMD_LOADING|CMD_STALE,0,.args=PUBSUB_NUMSUB_Args}, {"numsub","Get the count of subscribers for channels","O(N) for the NUMSUB subcommand, where N is the number of requested channels","2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_NUMSUB_History,PUBSUB_NUMSUB_tips,pubsubCommand,-2,CMD_PUBSUB|CMD_LOADING|CMD_STALE,0,.args=PUBSUB_NUMSUB_Args},
{"shardchannels","List active shard channels","O(N) where N is the number of active shard channels, and assuming constant time pattern matching (relatively short channels).","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_SHARDCHANNELS_History,PUBSUB_SHARDCHANNELS_tips,pubsubCommand,-2,CMD_PUBSUB|CMD_LOADING|CMD_STALE,0,.args=PUBSUB_SHARDCHANNELS_Args}, {"shardchannels","List active shard channels","O(N) where N is the number of active shard channels, and assuming constant time pattern matching (relatively short shard channels).","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_SHARDCHANNELS_History,PUBSUB_SHARDCHANNELS_tips,pubsubCommand,-2,CMD_PUBSUB|CMD_LOADING|CMD_STALE,0,.args=PUBSUB_SHARDCHANNELS_Args},
{"shardnumsub","Get the count of subscribers for shard channels","O(N) for the SHARDNUMSUB subcommand, where N is the number of requested channels","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_SHARDNUMSUB_History,PUBSUB_SHARDNUMSUB_tips,pubsubCommand,-2,CMD_PUBSUB|CMD_LOADING|CMD_STALE,0,.args=PUBSUB_SHARDNUMSUB_Args}, {"shardnumsub","Get the count of subscribers for shard channels","O(N) for the SHARDNUMSUB subcommand, where N is the number of requested shard channels","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,PUBSUB_SHARDNUMSUB_History,PUBSUB_SHARDNUMSUB_tips,pubsubCommand,-2,CMD_PUBSUB|CMD_LOADING|CMD_STALE,0,.args=PUBSUB_SHARDNUMSUB_Args},
{0} {0}
}; };
...@@ -3200,7 +3207,7 @@ struct redisCommandArg PUNSUBSCRIBE_Args[] = { ...@@ -3200,7 +3207,7 @@ struct redisCommandArg PUNSUBSCRIBE_Args[] = {
/* SPUBLISH argument table */ /* SPUBLISH argument table */
struct redisCommandArg SPUBLISH_Args[] = { struct redisCommandArg SPUBLISH_Args[] = {
{"channel",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE}, {"shardchannel",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE},
{"message",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE}, {"message",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE},
{0} {0}
}; };
...@@ -3215,7 +3222,7 @@ struct redisCommandArg SPUBLISH_Args[] = { ...@@ -3215,7 +3222,7 @@ struct redisCommandArg SPUBLISH_Args[] = {
/* SSUBSCRIBE argument table */ /* SSUBSCRIBE argument table */
struct redisCommandArg SSUBSCRIBE_Args[] = { struct redisCommandArg SSUBSCRIBE_Args[] = {
{"channel",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE}, {"shardchannel",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_MULTIPLE},
{0} {0}
}; };
...@@ -3243,7 +3250,7 @@ struct redisCommandArg SUBSCRIBE_Args[] = { ...@@ -3243,7 +3250,7 @@ struct redisCommandArg SUBSCRIBE_Args[] = {
/* SUNSUBSCRIBE argument table */ /* SUNSUBSCRIBE argument table */
struct redisCommandArg SUNSUBSCRIBE_Args[] = { struct redisCommandArg SUNSUBSCRIBE_Args[] = {
{"channel",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_OPTIONAL|CMD_ARG_MULTIPLE}, {"shardchannel",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_OPTIONAL|CMD_ARG_MULTIPLE},
{0} {0}
}; };
...@@ -3951,6 +3958,20 @@ struct redisCommandArg SENTINEL_SIMULATE_FAILURE_Args[] = { ...@@ -3951,6 +3958,20 @@ struct redisCommandArg SENTINEL_SIMULATE_FAILURE_Args[] = {
{0} {0}
}; };
/********** SENTINEL SLAVES ********************/
/* SENTINEL SLAVES history */
#define SENTINEL_SLAVES_History NULL
/* SENTINEL SLAVES tips */
#define SENTINEL_SLAVES_tips NULL
/* SENTINEL SLAVES argument table */
struct redisCommandArg SENTINEL_SLAVES_Args[] = {
{"master-name",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE},
{0}
};
/* SENTINEL command table */ /* SENTINEL command table */
struct redisCommand SENTINEL_Subcommands[] = { struct redisCommand SENTINEL_Subcommands[] = {
{"ckquorum","Check for a Sentinel quorum",NULL,"2.8.4",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_CKQUORUM_History,SENTINEL_CKQUORUM_tips,sentinelCommand,3,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_CKQUORUM_Args}, {"ckquorum","Check for a Sentinel quorum",NULL,"2.8.4",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_CKQUORUM_History,SENTINEL_CKQUORUM_tips,sentinelCommand,3,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_CKQUORUM_Args},
...@@ -3973,6 +3994,7 @@ struct redisCommand SENTINEL_Subcommands[] = { ...@@ -3973,6 +3994,7 @@ struct redisCommand SENTINEL_Subcommands[] = {
{"sentinels","List the Sentinel instances","O(N) where N is the number of Sentinels","2.8.4",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_SENTINELS_History,SENTINEL_SENTINELS_tips,sentinelCommand,3,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_SENTINELS_Args}, {"sentinels","List the Sentinel instances","O(N) where N is the number of Sentinels","2.8.4",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_SENTINELS_History,SENTINEL_SENTINELS_tips,sentinelCommand,3,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_SENTINELS_Args},
{"set","Change the configuration of a monitored master","O(1)","2.8.4",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_SET_History,SENTINEL_SET_tips,sentinelCommand,-5,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_SET_Args}, {"set","Change the configuration of a monitored master","O(1)","2.8.4",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_SET_History,SENTINEL_SET_tips,sentinelCommand,-5,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_SET_Args},
{"simulate-failure","Simulate failover scenarios",NULL,"3.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_SIMULATE_FAILURE_History,SENTINEL_SIMULATE_FAILURE_tips,sentinelCommand,-3,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_SIMULATE_FAILURE_Args}, {"simulate-failure","Simulate failover scenarios",NULL,"3.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_SIMULATE_FAILURE_History,SENTINEL_SIMULATE_FAILURE_tips,sentinelCommand,-3,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_SIMULATE_FAILURE_Args},
{"slaves","List the monitored slaves","O(N) where N is the number of slaves","2.8.0",CMD_DOC_DEPRECATED,"`SENTINEL REPLICAS`","5.0.0",COMMAND_GROUP_SENTINEL,SENTINEL_SLAVES_History,SENTINEL_SLAVES_tips,sentinelCommand,3,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.args=SENTINEL_SLAVES_Args},
{0} {0}
}; };
...@@ -4924,11 +4946,28 @@ struct redisCommandArg REPLICAOF_Args[] = { ...@@ -4924,11 +4946,28 @@ struct redisCommandArg REPLICAOF_Args[] = {
/********** RESTORE_ASKING ********************/ /********** RESTORE_ASKING ********************/
/* RESTORE_ASKING history */ /* RESTORE_ASKING history */
#define RESTORE_ASKING_History NULL commandHistory RESTORE_ASKING_History[] = {
{"3.0.0","Added the `REPLACE` modifier."},
{"5.0.0","Added the `ABSTTL` modifier."},
{"5.0.0","Added the `IDLETIME` and `FREQ` options."},
{0}
};
/* RESTORE_ASKING tips */ /* RESTORE_ASKING tips */
#define RESTORE_ASKING_tips NULL #define RESTORE_ASKING_tips NULL
/* RESTORE_ASKING argument table */
struct redisCommandArg RESTORE_ASKING_Args[] = {
{"key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE},
{"ttl",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE},
{"serialized-value",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE},
{"replace",ARG_TYPE_PURE_TOKEN,-1,"REPLACE",NULL,"3.0.0",CMD_ARG_OPTIONAL},
{"absttl",ARG_TYPE_PURE_TOKEN,-1,"ABSTTL",NULL,"5.0.0",CMD_ARG_OPTIONAL},
{"seconds",ARG_TYPE_INTEGER,-1,"IDLETIME",NULL,"5.0.0",CMD_ARG_OPTIONAL},
{"frequency",ARG_TYPE_INTEGER,-1,"FREQ",NULL,"5.0.0",CMD_ARG_OPTIONAL},
{0}
};
/********** ROLE ********************/ /********** ROLE ********************/
/* ROLE history */ /* ROLE history */
...@@ -6437,6 +6476,7 @@ struct redisCommandArg XINFO_GROUPS_Args[] = { ...@@ -6437,6 +6476,7 @@ struct redisCommandArg XINFO_GROUPS_Args[] = {
/* XINFO STREAM history */ /* XINFO STREAM history */
commandHistory XINFO_STREAM_History[] = { commandHistory XINFO_STREAM_History[] = {
{"6.0.0","Added the `FULL` modifier."},
{"7.0.0","Added the `max-deleted-entry-id`, `entries-added`, `recorded-first-entry-id`, `entries-read` and `lag` fields"}, {"7.0.0","Added the `max-deleted-entry-id`, `entries-added`, `recorded-first-entry-id`, `entries-read` and `lag` fields"},
{0} {0}
}; };
...@@ -6862,7 +6902,7 @@ struct redisCommandArg INCRBYFLOAT_Args[] = { ...@@ -6862,7 +6902,7 @@ struct redisCommandArg INCRBYFLOAT_Args[] = {
/* LCS argument table */ /* LCS argument table */
struct redisCommandArg LCS_Args[] = { struct redisCommandArg LCS_Args[] = {
{"key1",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE}, {"key1",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE},
{"key2",ARG_TYPE_KEY,1,NULL,NULL,NULL,CMD_ARG_NONE}, {"key2",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE},
{"len",ARG_TYPE_PURE_TOKEN,-1,"LEN",NULL,NULL,CMD_ARG_OPTIONAL}, {"len",ARG_TYPE_PURE_TOKEN,-1,"LEN",NULL,NULL,CMD_ARG_OPTIONAL},
{"idx",ARG_TYPE_PURE_TOKEN,-1,"IDX",NULL,NULL,CMD_ARG_OPTIONAL}, {"idx",ARG_TYPE_PURE_TOKEN,-1,"IDX",NULL,NULL,CMD_ARG_OPTIONAL},
{"len",ARG_TYPE_INTEGER,-1,"MINMATCHLEN",NULL,NULL,CMD_ARG_OPTIONAL}, {"len",ARG_TYPE_INTEGER,-1,"MINMATCHLEN",NULL,NULL,CMD_ARG_OPTIONAL},
...@@ -7122,7 +7162,7 @@ struct redisCommand redisCommandTable[] = { ...@@ -7122,7 +7162,7 @@ struct redisCommand redisCommandTable[] = {
/* bitmap */ /* bitmap */
{"bitcount","Count set bits in a string","O(N)","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITCOUNT_History,BITCOUNT_tips,bitcountCommand,-2,CMD_READONLY,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=BITCOUNT_Args}, {"bitcount","Count set bits in a string","O(N)","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITCOUNT_History,BITCOUNT_tips,bitcountCommand,-2,CMD_READONLY,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=BITCOUNT_Args},
{"bitfield","Perform arbitrary bitfield integer operations on strings","O(1) for each subcommand specified","3.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITFIELD_History,BITFIELD_tips,bitfieldCommand,-2,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_BITMAP,{{"This command allows both access and modification of the key",CMD_KEY_RW|CMD_KEY_UPDATE|CMD_KEY_ACCESS|CMD_KEY_VARIABLE_FLAGS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},bitfieldGetKeys,.args=BITFIELD_Args}, {"bitfield","Perform arbitrary bitfield integer operations on strings","O(1) for each subcommand specified","3.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITFIELD_History,BITFIELD_tips,bitfieldCommand,-2,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_BITMAP,{{"This command allows both access and modification of the key",CMD_KEY_RW|CMD_KEY_UPDATE|CMD_KEY_ACCESS|CMD_KEY_VARIABLE_FLAGS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},bitfieldGetKeys,.args=BITFIELD_Args},
{"bitfield_ro","Perform arbitrary bitfield integer operations on strings. Read-only variant of BITFIELD","O(1) for each subcommand specified","6.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITFIELD_RO_History,BITFIELD_RO_tips,bitfieldroCommand,-2,CMD_READONLY|CMD_FAST,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=BITFIELD_RO_Args}, {"bitfield_ro","Perform arbitrary bitfield integer operations on strings. Read-only variant of BITFIELD","O(1) for each subcommand specified","6.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITFIELD_RO_History,BITFIELD_RO_tips,bitfieldroCommand,-2,CMD_READONLY|CMD_FAST,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=BITFIELD_RO_Args},
{"bitop","Perform bitwise operations between strings","O(N)","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITOP_History,BITOP_tips,bitopCommand,-4,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_OW|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_RANGE,.fk.range={0,1,0}},{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={3},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=BITOP_Args}, {"bitop","Perform bitwise operations between strings","O(N)","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITOP_History,BITOP_tips,bitopCommand,-4,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_OW|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_RANGE,.fk.range={0,1,0}},{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={3},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=BITOP_Args},
{"bitpos","Find first bit set or clear in a string","O(N)","2.8.7",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITPOS_History,BITPOS_tips,bitposCommand,-3,CMD_READONLY,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=BITPOS_Args}, {"bitpos","Find first bit set or clear in a string","O(N)","2.8.7",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,BITPOS_History,BITPOS_tips,bitposCommand,-3,CMD_READONLY,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=BITPOS_Args},
{"getbit","Returns the bit value at offset in the string value stored at key","O(1)","2.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,GETBIT_History,GETBIT_tips,getbitCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=GETBIT_Args}, {"getbit","Returns the bit value at offset in the string value stored at key","O(1)","2.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_BITMAP,GETBIT_History,GETBIT_tips,getbitCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_BITMAP,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=GETBIT_Args},
...@@ -7201,7 +7241,7 @@ struct redisCommand redisCommandTable[] = { ...@@ -7201,7 +7241,7 @@ struct redisCommand redisCommandTable[] = {
/* hyperloglog */ /* hyperloglog */
{"pfadd","Adds the specified elements to the specified HyperLogLog.","O(1) to add every element.","2.8.9",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFADD_History,PFADD_tips,pfaddCommand,-2,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HYPERLOGLOG,{{NULL,CMD_KEY_RW|CMD_KEY_INSERT,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=PFADD_Args}, {"pfadd","Adds the specified elements to the specified HyperLogLog.","O(1) to add every element.","2.8.9",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFADD_History,PFADD_tips,pfaddCommand,-2,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HYPERLOGLOG,{{NULL,CMD_KEY_RW|CMD_KEY_INSERT,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=PFADD_Args},
{"pfcount","Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).","O(1) with a very small average constant time when called with a single key. O(N) with N being the number of keys, and much bigger constant times, when called with multiple keys.","2.8.9",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFCOUNT_History,PFCOUNT_tips,pfcountCommand,-2,CMD_READONLY|CMD_MAY_REPLICATE,ACL_CATEGORY_HYPERLOGLOG,{{"RW because it may change the internal representation of the key, and propagate to replicas",CMD_KEY_RW|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=PFCOUNT_Args}, {"pfcount","Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).","O(1) with a very small average constant time when called with a single key. O(N) with N being the number of keys, and much bigger constant times, when called with multiple keys.","2.8.9",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFCOUNT_History,PFCOUNT_tips,pfcountCommand,-2,CMD_READONLY|CMD_MAY_REPLICATE,ACL_CATEGORY_HYPERLOGLOG,{{"RW because it may change the internal representation of the key, and propagate to replicas",CMD_KEY_RW|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=PFCOUNT_Args},
{"pfdebug","Internal commands for debugging HyperLogLog values","N/A","2.8.9",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFDEBUG_History,PFDEBUG_tips,pfdebugCommand,-3,CMD_WRITE|CMD_DENYOOM|CMD_ADMIN,ACL_CATEGORY_HYPERLOGLOG,{{NULL,CMD_KEY_RW|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_RANGE,.fk.range={0,1,0}}}}, {"pfdebug","Internal commands for debugging HyperLogLog values","N/A","2.8.9",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFDEBUG_History,PFDEBUG_tips,pfdebugCommand,3,CMD_WRITE|CMD_DENYOOM|CMD_ADMIN,ACL_CATEGORY_HYPERLOGLOG,{{NULL,CMD_KEY_RW|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=PFDEBUG_Args},
{"pfmerge","Merge N different HyperLogLogs into a single one.","O(N) to merge N HyperLogLogs, but with high constant times.","2.8.9",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFMERGE_History,PFMERGE_tips,pfmergeCommand,-2,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_HYPERLOGLOG,{{NULL,CMD_KEY_RW|CMD_KEY_ACCESS|CMD_KEY_INSERT,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}},{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=PFMERGE_Args}, {"pfmerge","Merge N different HyperLogLogs into a single one.","O(N) to merge N HyperLogLogs, but with high constant times.","2.8.9",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFMERGE_History,PFMERGE_tips,pfmergeCommand,-2,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_HYPERLOGLOG,{{NULL,CMD_KEY_RW|CMD_KEY_ACCESS|CMD_KEY_INSERT,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}},{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=PFMERGE_Args},
{"pfselftest","An internal command for testing HyperLogLog values","N/A","2.8.9",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFSELFTEST_History,PFSELFTEST_tips,pfselftestCommand,1,CMD_ADMIN,ACL_CATEGORY_HYPERLOGLOG}, {"pfselftest","An internal command for testing HyperLogLog values","N/A","2.8.9",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_HYPERLOGLOG,PFSELFTEST_History,PFSELFTEST_tips,pfselftestCommand,1,CMD_ADMIN,ACL_CATEGORY_HYPERLOGLOG},
/* list */ /* list */
...@@ -7235,15 +7275,15 @@ struct redisCommand redisCommandTable[] = { ...@@ -7235,15 +7275,15 @@ struct redisCommand redisCommandTable[] = {
{"spublish","Post a message to a shard channel","O(N) where N is the number of clients subscribed to the receiving shard channel.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,SPUBLISH_History,SPUBLISH_tips,spublishCommand,3,CMD_PUBSUB|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_MAY_REPLICATE,0,{{NULL,CMD_KEY_NOT_KEY,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=SPUBLISH_Args}, {"spublish","Post a message to a shard channel","O(N) where N is the number of clients subscribed to the receiving shard channel.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,SPUBLISH_History,SPUBLISH_tips,spublishCommand,3,CMD_PUBSUB|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_MAY_REPLICATE,0,{{NULL,CMD_KEY_NOT_KEY,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=SPUBLISH_Args},
{"ssubscribe","Listen for messages published to the given shard channels","O(N) where N is the number of shard channels to subscribe to.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,SSUBSCRIBE_History,SSUBSCRIBE_tips,ssubscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0,{{NULL,CMD_KEY_NOT_KEY,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=SSUBSCRIBE_Args}, {"ssubscribe","Listen for messages published to the given shard channels","O(N) where N is the number of shard channels to subscribe to.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,SSUBSCRIBE_History,SSUBSCRIBE_tips,ssubscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0,{{NULL,CMD_KEY_NOT_KEY,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=SSUBSCRIBE_Args},
{"subscribe","Listen for messages published to the given channels","O(N) where N is the number of channels to subscribe to.","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,SUBSCRIBE_History,SUBSCRIBE_tips,subscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,.args=SUBSCRIBE_Args}, {"subscribe","Listen for messages published to the given channels","O(N) where N is the number of channels to subscribe to.","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,SUBSCRIBE_History,SUBSCRIBE_tips,subscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,.args=SUBSCRIBE_Args},
{"sunsubscribe","Stop listening for messages posted to the given shard channels","O(N) where N is the number of clients already subscribed to a channel.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,SUNSUBSCRIBE_History,SUNSUBSCRIBE_tips,sunsubscribeCommand,-1,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0,{{NULL,CMD_KEY_NOT_KEY,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=SUNSUBSCRIBE_Args}, {"sunsubscribe","Stop listening for messages posted to the given shard channels","O(N) where N is the number of clients already subscribed to a shard channel.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,SUNSUBSCRIBE_History,SUNSUBSCRIBE_tips,sunsubscribeCommand,-1,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0,{{NULL,CMD_KEY_NOT_KEY,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=SUNSUBSCRIBE_Args},
{"unsubscribe","Stop listening for messages posted to the given channels","O(N) where N is the number of clients already subscribed to a channel.","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,UNSUBSCRIBE_History,UNSUBSCRIBE_tips,unsubscribeCommand,-1,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,.args=UNSUBSCRIBE_Args}, {"unsubscribe","Stop listening for messages posted to the given channels","O(N) where N is the number of clients already subscribed to a channel.","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_PUBSUB,UNSUBSCRIBE_History,UNSUBSCRIBE_tips,unsubscribeCommand,-1,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,.args=UNSUBSCRIBE_Args},
/* scripting */ /* scripting */
{"eval","Execute a Lua script server side","Depends on the script that is executed.","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,EVAL_History,EVAL_tips,evalCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_MAY_REPLICATE|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{"We cannot tell how the keys will be used so we assume the worst, RW and UPDATE",CMD_KEY_RW|CMD_KEY_ACCESS|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},evalGetKeys,.args=EVAL_Args}, {"eval","Execute a Lua script server side","Depends on the script that is executed.","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,EVAL_History,EVAL_tips,evalCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_MAY_REPLICATE|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{"We cannot tell how the keys will be used so we assume the worst, RW and UPDATE",CMD_KEY_RW|CMD_KEY_ACCESS|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},evalGetKeys,.args=EVAL_Args},
{"evalsha","Execute a Lua script server side","Depends on the script that is executed.","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,EVALSHA_History,EVALSHA_tips,evalShaCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_MAY_REPLICATE|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{NULL,CMD_KEY_RW|CMD_KEY_ACCESS|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},evalGetKeys,.args=EVALSHA_Args}, {"evalsha","Execute a Lua script server side","Depends on the script that is executed.","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,EVALSHA_History,EVALSHA_tips,evalShaCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_MAY_REPLICATE|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{NULL,CMD_KEY_RW|CMD_KEY_ACCESS|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},evalGetKeys,.args=EVALSHA_Args},
{"evalsha_ro","Execute a read-only Lua script server side","Depends on the script that is executed.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,EVALSHA_RO_History,EVALSHA_RO_tips,evalShaRoCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},evalGetKeys,.args=EVALSHA_RO_Args}, {"evalsha_ro","Execute a read-only Lua script server side","Depends on the script that is executed.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,EVALSHA_RO_History,EVALSHA_RO_tips,evalShaRoCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_NO_MANDATORY_KEYS|CMD_STALE|CMD_READONLY,ACL_CATEGORY_SCRIPTING,{{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},evalGetKeys,.args=EVALSHA_RO_Args},
{"eval_ro","Execute a read-only Lua script server side","Depends on the script that is executed.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,EVAL_RO_History,EVAL_RO_tips,evalRoCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{"We cannot tell how the keys will be used so we assume the worst, RO and ACCESS",CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},evalGetKeys,.args=EVAL_RO_Args}, {"eval_ro","Execute a read-only Lua script server side","Depends on the script that is executed.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,EVAL_RO_History,EVAL_RO_tips,evalRoCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_NO_MANDATORY_KEYS|CMD_STALE|CMD_READONLY,ACL_CATEGORY_SCRIPTING,{{"We cannot tell how the keys will be used so we assume the worst, RO and ACCESS",CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},evalGetKeys,.args=EVAL_RO_Args},
{"fcall","Invoke a function","Depends on the function that is executed.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,FCALL_History,FCALL_tips,fcallCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_MAY_REPLICATE|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{"We cannot tell how the keys will be used so we assume the worst, RW and UPDATE",CMD_KEY_RW|CMD_KEY_ACCESS|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},functionGetKeys,.args=FCALL_Args}, {"fcall","Invoke a function","Depends on the function that is executed.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,FCALL_History,FCALL_tips,fcallCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_MAY_REPLICATE|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{"We cannot tell how the keys will be used so we assume the worst, RW and UPDATE",CMD_KEY_RW|CMD_KEY_ACCESS|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},functionGetKeys,.args=FCALL_Args},
{"fcall_ro","Invoke a read-only function","Depends on the function that is executed.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,FCALL_RO_History,FCALL_RO_tips,fcallroCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_NO_MANDATORY_KEYS|CMD_STALE,ACL_CATEGORY_SCRIPTING,{{"We cannot tell how the keys will be used so we assume the worst, RO and ACCESS",CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},functionGetKeys,.args=FCALL_RO_Args}, {"fcall_ro","Invoke a read-only function","Depends on the function that is executed.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,FCALL_RO_History,FCALL_RO_tips,fcallroCommand,-3,CMD_NOSCRIPT|CMD_SKIP_MONITOR|CMD_NO_MANDATORY_KEYS|CMD_STALE|CMD_READONLY,ACL_CATEGORY_SCRIPTING,{{"We cannot tell how the keys will be used so we assume the worst, RO and ACCESS",CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={2},KSPEC_FK_KEYNUM,.fk.keynum={0,1,1}}},functionGetKeys,.args=FCALL_RO_Args},
{"function","A container for function commands","Depends on subcommand.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,FUNCTION_History,FUNCTION_tips,NULL,-2,0,0,.subcommands=FUNCTION_Subcommands}, {"function","A container for function commands","Depends on subcommand.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,FUNCTION_History,FUNCTION_tips,NULL,-2,0,0,.subcommands=FUNCTION_Subcommands},
{"script","A container for Lua scripts management commands","Depends on subcommand.","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,SCRIPT_History,SCRIPT_tips,NULL,-2,0,0,.subcommands=SCRIPT_Subcommands}, {"script","A container for Lua scripts management commands","Depends on subcommand.","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SCRIPTING,SCRIPT_History,SCRIPT_tips,NULL,-2,0,0,.subcommands=SCRIPT_Subcommands},
/* sentinel */ /* sentinel */
...@@ -7269,7 +7309,7 @@ struct redisCommand redisCommandTable[] = { ...@@ -7269,7 +7309,7 @@ struct redisCommand redisCommandTable[] = {
{"psync","Internal command used for replication",NULL,"2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,PSYNC_History,PSYNC_tips,syncCommand,-3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NO_MULTI|CMD_NOSCRIPT,0,.args=PSYNC_Args}, {"psync","Internal command used for replication",NULL,"2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,PSYNC_History,PSYNC_tips,syncCommand,-3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NO_MULTI|CMD_NOSCRIPT,0,.args=PSYNC_Args},
{"replconf","An internal command for configuring the replication stream","O(1)","3.0.0",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_SERVER,REPLCONF_History,REPLCONF_tips,replconfCommand,-1,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_ALLOW_BUSY,0}, {"replconf","An internal command for configuring the replication stream","O(1)","3.0.0",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_SERVER,REPLCONF_History,REPLCONF_tips,replconfCommand,-1,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_ALLOW_BUSY,0},
{"replicaof","Make the server a replica of another instance, or promote it as master.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,REPLICAOF_History,REPLICAOF_tips,replicaofCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0,.args=REPLICAOF_Args}, {"replicaof","Make the server a replica of another instance, or promote it as master.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,REPLICAOF_History,REPLICAOF_tips,replicaofCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0,.args=REPLICAOF_Args},
{"restore-asking","An internal command for migrating keys in a cluster","O(1) to create the new key and additional O(N*M) to reconstruct the serialized value, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1*M) where M is small, so simply O(1). However for sorted set values the complexity is O(N*M*log(N)) because inserting values into sorted sets is O(log(N)).","3.0.0",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_SERVER,RESTORE_ASKING_History,RESTORE_ASKING_tips,restoreCommand,-4,CMD_WRITE|CMD_DENYOOM|CMD_ASKING,ACL_CATEGORY_KEYSPACE|ACL_CATEGORY_DANGEROUS,{{NULL,CMD_KEY_OW|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}}}, {"restore-asking","An internal command for migrating keys in a cluster","O(1) to create the new key and additional O(N*M) to reconstruct the serialized value, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1*M) where M is small, so simply O(1). However for sorted set values the complexity is O(N*M*log(N)) because inserting values into sorted sets is O(log(N)).","3.0.0",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_SERVER,RESTORE_ASKING_History,RESTORE_ASKING_tips,restoreCommand,-4,CMD_WRITE|CMD_DENYOOM|CMD_ASKING,ACL_CATEGORY_KEYSPACE|ACL_CATEGORY_DANGEROUS,{{NULL,CMD_KEY_OW|CMD_KEY_UPDATE,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=RESTORE_ASKING_Args},
{"role","Return the role of the instance in the context of replication","O(1)","2.8.12",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,ROLE_History,ROLE_tips,roleCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_SENTINEL,ACL_CATEGORY_ADMIN|ACL_CATEGORY_DANGEROUS}, {"role","Return the role of the instance in the context of replication","O(1)","2.8.12",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,ROLE_History,ROLE_tips,roleCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_SENTINEL,ACL_CATEGORY_ADMIN|ACL_CATEGORY_DANGEROUS},
{"save","Synchronously save the dataset to disk","O(N) where N is the total number of keys in all databases","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SAVE_History,SAVE_tips,saveCommand,1,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT|CMD_NO_MULTI,0}, {"save","Synchronously save the dataset to disk","O(N) where N is the total number of keys in all databases","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SAVE_History,SAVE_tips,saveCommand,1,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT|CMD_NO_MULTI,0},
{"shutdown","Synchronously save the dataset to disk and then shut down the server","O(N) when saving, where N is the total number of keys in all databases when saving data, otherwise O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SHUTDOWN_History,SHUTDOWN_tips,shutdownCommand,-1,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_NO_MULTI|CMD_SENTINEL|CMD_ALLOW_BUSY,0,.args=SHUTDOWN_Args}, {"shutdown","Synchronously save the dataset to disk and then shut down the server","O(N) when saving, where N is the total number of keys in all databases when saving data, otherwise O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SHUTDOWN_History,SHUTDOWN_tips,shutdownCommand,-1,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_NO_MULTI|CMD_SENTINEL|CMD_ALLOW_BUSY,0,.args=SHUTDOWN_Args},
...@@ -7376,6 +7416,6 @@ struct redisCommand redisCommandTable[] = { ...@@ -7376,6 +7416,6 @@ struct redisCommand redisCommandTable[] = {
{"exec","Execute all commands issued after MULTI","Depends on commands in the transaction","1.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_TRANSACTIONS,EXEC_History,EXEC_tips,execCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SKIP_SLOWLOG,ACL_CATEGORY_TRANSACTION}, {"exec","Execute all commands issued after MULTI","Depends on commands in the transaction","1.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_TRANSACTIONS,EXEC_History,EXEC_tips,execCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SKIP_SLOWLOG,ACL_CATEGORY_TRANSACTION},
{"multi","Mark the start of a transaction block","O(1)","1.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_TRANSACTIONS,MULTI_History,MULTI_tips,multiCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_ALLOW_BUSY,ACL_CATEGORY_TRANSACTION}, {"multi","Mark the start of a transaction block","O(1)","1.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_TRANSACTIONS,MULTI_History,MULTI_tips,multiCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_ALLOW_BUSY,ACL_CATEGORY_TRANSACTION},
{"unwatch","Forget about all watched keys","O(1)","2.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_TRANSACTIONS,UNWATCH_History,UNWATCH_tips,unwatchCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_ALLOW_BUSY,ACL_CATEGORY_TRANSACTION}, {"unwatch","Forget about all watched keys","O(1)","2.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_TRANSACTIONS,UNWATCH_History,UNWATCH_tips,unwatchCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_ALLOW_BUSY,ACL_CATEGORY_TRANSACTION},
{"watch","Watch the given keys to determine execution of the MULTI/EXEC block","O(1) for every key.","2.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_TRANSACTIONS,WATCH_History,WATCH_tips,watchCommand,-2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_ALLOW_BUSY,ACL_CATEGORY_TRANSACTION,{{NULL,0,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=WATCH_Args}, {"watch","Watch the given keys to determine execution of the MULTI/EXEC block","O(1) for every key.","2.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_TRANSACTIONS,WATCH_History,WATCH_tips,watchCommand,-2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_ALLOW_BUSY,ACL_CATEGORY_TRANSACTION,{{NULL,CMD_KEY_RO,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}},.args=WATCH_Args},
{0} {0}
}; };
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
{ {
"name": "operation", "name": "operation",
"type": "oneof", "type": "oneof",
"multiple": "true", "multiple": true,
"arguments": [ "arguments": [
{ {
"token": "GET", "token": "GET",
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"summary": "Perform arbitrary bitfield integer operations on strings. Read-only variant of BITFIELD", "summary": "Perform arbitrary bitfield integer operations on strings. Read-only variant of BITFIELD",
"complexity": "O(1) for each subcommand specified", "complexity": "O(1) for each subcommand specified",
"group": "bitmap", "group": "bitmap",
"since": "6.2.0", "since": "6.0.0",
"arity": -2, "arity": -2,
"function": "bitfieldroCommand", "function": "bitfieldroCommand",
"command_flags": [ "command_flags": [
...@@ -43,7 +43,8 @@ ...@@ -43,7 +43,8 @@
"token": "GET", "token": "GET",
"name": "encoding_offset", "name": "encoding_offset",
"type": "block", "type": "block",
"multiple": "true", "multiple": true,
"multiple_token": true,
"arguments": [ "arguments": [
{ {
"name": "encoding", "name": "encoding",
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
"NOSCRIPT", "NOSCRIPT",
"SKIP_MONITOR", "SKIP_MONITOR",
"NO_MANDATORY_KEYS", "NO_MANDATORY_KEYS",
"STALE" "STALE",
"READONLY"
], ],
"acl_categories": [ "acl_categories": [
"SCRIPTING" "SCRIPTING"
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
"NOSCRIPT", "NOSCRIPT",
"SKIP_MONITOR", "SKIP_MONITOR",
"NO_MANDATORY_KEYS", "NO_MANDATORY_KEYS",
"STALE" "STALE",
"READONLY"
], ],
"acl_categories": [ "acl_categories": [
"SCRIPTING" "SCRIPTING"
......
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