"docs/modules/rtctime.md" did not exist on "ebcf6b771eecf8be0f54e1be0e14bb5b4c6ceb18"
Commit 1cf48a34 authored by Vitaly Arbuzov's avatar Vitaly Arbuzov
Browse files

Merge branch 'unstable' into dict-split-by-slot

parents 8b723d2d 557ca05d
...@@ -922,10 +922,10 @@ jobs: ...@@ -922,10 +922,10 @@ jobs:
run: sudo apt-get install tcl8.6 tclx run: sudo apt-get install tcl8.6 tclx
- name: test - name: test
if: true && !contains(github.event.inputs.skiptests, 'redis') if: true && !contains(github.event.inputs.skiptests, 'redis')
run: ./runtest --log-req-res --dont-clean --force-resp3 --tags -slow --verbose --dump-logs ${{github.event.inputs.test_args}} run: ./runtest --log-req-res --no-latency --dont-clean --force-resp3 --tags -slow --verbose --dump-logs ${{github.event.inputs.test_args}}
- name: module api test - name: module api test
if: true && !contains(github.event.inputs.skiptests, 'modules') if: true && !contains(github.event.inputs.skiptests, 'modules')
run: ./runtest-moduleapi --log-req-res --dont-clean --force-resp3 --dont-pre-clean --verbose --dump-logs ${{github.event.inputs.test_args}} run: ./runtest-moduleapi --log-req-res --no-latency --dont-clean --force-resp3 --dont-pre-clean --verbose --dump-logs ${{github.event.inputs.test_args}}
- name: sentinel tests - name: sentinel tests
if: true && !contains(github.event.inputs.skiptests, 'sentinel') if: true && !contains(github.event.inputs.skiptests, 'sentinel')
run: ./runtest-sentinel --log-req-res --dont-clean --force-resp3 ${{github.event.inputs.cluster_test_args}} run: ./runtest-sentinel --log-req-res --dont-clean --force-resp3 ${{github.event.inputs.cluster_test_args}}
......
...@@ -15,9 +15,14 @@ ...@@ -15,9 +15,14 @@
release_hdr := $(shell sh -c './mkreleasehdr.sh') release_hdr := $(shell sh -c './mkreleasehdr.sh')
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not') uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
CLANG := $(findstring clang,$(shell sh -c '$(CC) --version | head -1'))
OPTIMIZATION?=-O3 OPTIMIZATION?=-O3
ifeq ($(OPTIMIZATION),-O3) ifeq ($(OPTIMIZATION),-O3)
REDIS_CFLAGS+=-flto=auto ifeq (clang,$(CLANG))
REDIS_CFLAGS+=-flto
else
REDIS_CFLAGS+=-flto=auto
endif
REDIS_LDFLAGS+=-flto REDIS_LDFLAGS+=-flto
endif endif
DEPENDENCY_TARGETS=hiredis linenoise lua hdr_histogram fpconv DEPENDENCY_TARGETS=hiredis linenoise lua hdr_histogram fpconv
...@@ -28,7 +33,7 @@ STD=-pedantic -DREDIS_STATIC='' ...@@ -28,7 +33,7 @@ STD=-pedantic -DREDIS_STATIC=''
# Use -Wno-c11-extensions on clang, either where explicitly used or on # Use -Wno-c11-extensions on clang, either where explicitly used or on
# platforms we can assume it's being used. # platforms we can assume it's being used.
ifneq (,$(findstring clang,$(CC))) ifeq (clang,$(CLANG))
STD+=-Wno-c11-extensions STD+=-Wno-c11-extensions
else else
ifneq (,$(findstring FreeBSD,$(uname_S))) ifneq (,$(findstring FreeBSD,$(uname_S)))
......
...@@ -958,6 +958,27 @@ struct redisCommandArg CLIENT_REPLY_Args[] = { ...@@ -958,6 +958,27 @@ struct redisCommandArg CLIENT_REPLY_Args[] = {
{0} {0}
}; };
/********** CLIENT SETINFO ********************/
/* CLIENT SETINFO history */
#define CLIENT_SETINFO_History NULL
/* CLIENT SETINFO tips */
#define CLIENT_SETINFO_tips NULL
/* CLIENT SETINFO attr argument table */
struct redisCommandArg CLIENT_SETINFO_attr_Subargs[] = {
{"libname",ARG_TYPE_STRING,-1,"LIB-NAME",NULL,NULL,CMD_ARG_NONE},
{"libver",ARG_TYPE_STRING,-1,"LIB-VER",NULL,NULL,CMD_ARG_NONE},
{0}
};
/* CLIENT SETINFO argument table */
struct redisCommandArg CLIENT_SETINFO_Args[] = {
{"attr",ARG_TYPE_ONEOF,-1,NULL,NULL,NULL,CMD_ARG_NONE,.subargs=CLIENT_SETINFO_attr_Subargs},
{0}
};
/********** CLIENT SETNAME ********************/ /********** CLIENT SETNAME ********************/
/* CLIENT SETNAME history */ /* CLIENT SETNAME history */
...@@ -1051,6 +1072,7 @@ struct redisCommand CLIENT_Subcommands[] = { ...@@ -1051,6 +1072,7 @@ struct redisCommand CLIENT_Subcommands[] = {
{"no-touch","Controls whether commands sent by the client will alter the LRU/LFU of the keys they access.","O(1)","7.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_NO_TOUCH_History,CLIENT_NO_TOUCH_tips,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,.args=CLIENT_NO_TOUCH_Args}, {"no-touch","Controls whether commands sent by the client will alter the LRU/LFU of the keys they access.","O(1)","7.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_NO_TOUCH_History,CLIENT_NO_TOUCH_tips,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,.args=CLIENT_NO_TOUCH_Args},
{"pause","Stop processing commands from clients for some time","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_PAUSE_History,CLIENT_PAUSE_tips,clientCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_PAUSE_Args}, {"pause","Stop processing commands from clients for some time","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_PAUSE_History,CLIENT_PAUSE_tips,clientCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_PAUSE_Args},
{"reply","Instruct the server whether to reply to commands","O(1)","3.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_REPLY_History,CLIENT_REPLY_tips,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_REPLY_Args}, {"reply","Instruct the server whether to reply to commands","O(1)","3.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_REPLY_History,CLIENT_REPLY_tips,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_REPLY_Args},
{"setinfo","Set client or connection specific info","O(1)","7.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_SETINFO_History,CLIENT_SETINFO_tips,clientSetinfoCommand,4,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_SETINFO_Args},
{"setname","Set the current connection name","O(1)","2.6.9",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_SETNAME_History,CLIENT_SETNAME_tips,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_SETNAME_Args}, {"setname","Set the current connection name","O(1)","2.6.9",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_SETNAME_History,CLIENT_SETNAME_tips,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_SETNAME_Args},
{"tracking","Enable or disable server assisted client side caching support","O(1). Some options may introduce additional complexity.","6.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_TRACKING_History,CLIENT_TRACKING_tips,clientCommand,-3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_TRACKING_Args}, {"tracking","Enable or disable server assisted client side caching support","O(1). Some options may introduce additional complexity.","6.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_TRACKING_History,CLIENT_TRACKING_tips,clientCommand,-3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.args=CLIENT_TRACKING_Args},
{"trackinginfo","Return information about server assisted client side caching for the current connection","O(1)","6.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_TRACKINGINFO_History,CLIENT_TRACKINGINFO_tips,clientCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION}, {"trackinginfo","Return information about server assisted client side caching for the current connection","O(1)","6.2.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CONNECTION,CLIENT_TRACKINGINFO_History,CLIENT_TRACKINGINFO_tips,clientCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION},
...@@ -6485,7 +6507,10 @@ struct redisCommand XGROUP_Subcommands[] = { ...@@ -6485,7 +6507,10 @@ struct redisCommand XGROUP_Subcommands[] = {
/********** XINFO CONSUMERS ********************/ /********** XINFO CONSUMERS ********************/
/* XINFO CONSUMERS history */ /* XINFO CONSUMERS history */
#define XINFO_CONSUMERS_History NULL commandHistory XINFO_CONSUMERS_History[] = {
{"7.2.0","Added the `inactive` field."},
{0}
};
/* XINFO CONSUMERS tips */ /* XINFO CONSUMERS tips */
const char *XINFO_CONSUMERS_tips[] = { const char *XINFO_CONSUMERS_tips[] = {
...@@ -6531,6 +6556,7 @@ struct redisCommandArg XINFO_GROUPS_Args[] = { ...@@ -6531,6 +6556,7 @@ struct redisCommandArg XINFO_GROUPS_Args[] = {
commandHistory XINFO_STREAM_History[] = { commandHistory XINFO_STREAM_History[] = {
{"6.0.0","Added the `FULL` modifier."}, {"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"},
{"7.2.0","Added the `active-time` field, and changed the meaning of `seen-time`."},
{0} {0}
}; };
......
{
"SETINFO": {
"summary": "Set client or connection specific info",
"complexity": "O(1)",
"group": "connection",
"since": "7.2.0",
"arity": 4,
"container": "CLIENT",
"function": "clientSetinfoCommand",
"command_flags": [
"NOSCRIPT",
"LOADING",
"STALE",
"SENTINEL"
],
"acl_categories": [
"CONNECTION"
],
"reply_schema": {
"const": "OK"
},
"arguments": [
{
"name": "attr",
"type": "oneof",
"arguments": [
{
"token": "lib-name",
"name": "libname",
"type": "string"
},
{
"token": "lib-ver",
"name": "libver",
"type": "string"
}
]
}
]
}
}
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
"arity": 4, "arity": 4,
"container": "XINFO", "container": "XINFO",
"function": "xinfoCommand", "function": "xinfoCommand",
"history": [
[
"7.2.0",
"Added the `inactive` field."
]
],
"command_flags": [ "command_flags": [
"READONLY" "READONLY"
], ],
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
[ [
"7.0.0", "7.0.0",
"Added the `max-deleted-entry-id`, `entries-added`, `recorded-first-entry-id`, `entries-read` and `lag` fields" "Added the `max-deleted-entry-id`, `entries-added`, `recorded-first-entry-id`, `entries-read` and `lag` fields"
],
[
"7.2.0",
"Added the `active-time` field, and changed the meaning of `seen-time`."
] ]
], ],
"function": "xinfoCommand", "function": "xinfoCommand",
......
...@@ -130,17 +130,17 @@ struct commandHelp { ...@@ -130,17 +130,17 @@ struct commandHelp {
15, 15,
"2.6.0" }, "2.6.0" },
{ "BITFIELD", { "BITFIELD",
"key GET encoding offset|[OVERFLOW WRAP|SAT|FAIL] SET encoding offset value|INCRBY encoding offset increment [GET encoding offset|[OVERFLOW WRAP|SAT|FAIL] SET encoding offset value|INCRBY encoding offset increment ...]", "key [GET encoding offset|[OVERFLOW WRAP|SAT|FAIL] SET encoding offset value|INCRBY encoding offset increment [GET encoding offset|[OVERFLOW WRAP|SAT|FAIL] SET encoding offset value|INCRBY encoding offset increment ...]]",
"Perform arbitrary bitfield integer operations on strings", "Perform arbitrary bitfield integer operations on strings",
15, 15,
"3.2.0" }, "3.2.0" },
{ "BITFIELD_RO", { "BITFIELD_RO",
"key GET encoding offset [GET encoding offset ...]", "key [GET encoding offset [GET encoding offset ...]]",
"Perform arbitrary bitfield integer operations on strings. Read-only variant of BITFIELD", "Perform arbitrary bitfield integer operations on strings. Read-only variant of BITFIELD",
15, 15,
"6.0.0" }, "6.0.0" },
{ "BITOP", { "BITOP",
"operation destkey key [key ...]", "AND|OR|XOR|NOT destkey key [key ...]",
"Perform bitwise operations between strings", "Perform bitwise operations between strings",
15, 15,
"2.6.0" }, "2.6.0" },
...@@ -225,7 +225,7 @@ struct commandHelp { ...@@ -225,7 +225,7 @@ struct commandHelp {
8, 8,
"6.2.0" }, "6.2.0" },
{ "CLIENT KILL", { "CLIENT KILL",
"[ip:port] [ID client-id] [TYPE NORMAL|MASTER|SLAVE|REPLICA|PUBSUB] [USER username] [ADDR ip:port] [LADDR ip:port] [SKIPME yes/no]", "old-format|[ID client-id]|[TYPE NORMAL|MASTER|SLAVE|REPLICA|PUBSUB]|[USER username]|[ADDR addr]|[LADDR laddr]|[SKIPME YES|NO] [[ID client-id]|[TYPE NORMAL|MASTER|SLAVE|REPLICA|PUBSUB]|[USER username]|[ADDR addr]|[LADDR laddr]|[SKIPME YES|NO] ...]",
"Kill the connection of a client", "Kill the connection of a client",
8, 8,
"2.4.0" }, "2.4.0" },
...@@ -239,16 +239,26 @@ struct commandHelp { ...@@ -239,16 +239,26 @@ struct commandHelp {
"Set client eviction mode for the current connection", "Set client eviction mode for the current connection",
8, 8,
"7.0.0" }, "7.0.0" },
{ "CLIENT NO-TOUCH",
"ON|OFF",
"Controls whether commands sent by the client will alter the LRU/LFU of the keys they access.",
8,
"7.2.0" },
{ "CLIENT PAUSE", { "CLIENT PAUSE",
"timeout [WRITE|ALL]", "timeout [WRITE|ALL]",
"Stop processing commands from clients for some time", "Stop processing commands from clients for some time",
8, 8,
"2.9.50" }, "3.0.0" },
{ "CLIENT REPLY", { "CLIENT REPLY",
"ON|OFF|SKIP", "ON|OFF|SKIP",
"Instruct the server whether to reply to commands", "Instruct the server whether to reply to commands",
8, 8,
"3.2.0" }, "3.2.0" },
{ "CLIENT SETINFO",
"LIB-NAME libname|LIB-VER libver",
"Set client or connection specific info",
8,
"7.2.0" },
{ "CLIENT SETNAME", { "CLIENT SETNAME",
"connection-name", "connection-name",
"Set the current connection name", "Set the current connection name",
...@@ -355,7 +365,7 @@ struct commandHelp { ...@@ -355,7 +365,7 @@ struct commandHelp {
12, 12,
"7.0.0" }, "7.0.0" },
{ "CLUSTER MEET", { "CLUSTER MEET",
"ip port [cluster_bus_port]", "ip port [cluster-bus-port]",
"Force a node cluster to handshake with another node", "Force a node cluster to handshake with another node",
12, 12,
"3.0.0" }, "3.0.0" },
...@@ -364,6 +374,11 @@ struct commandHelp { ...@@ -364,6 +374,11 @@ struct commandHelp {
"Return the node id", "Return the node id",
12, 12,
"3.0.0" }, "3.0.0" },
{ "CLUSTER MYSHARDID",
"",
"Return the node shard id",
12,
"7.2.0" },
{ "CLUSTER NODES", { "CLUSTER NODES",
"", "",
"Get Cluster config for the node", "Get Cluster config for the node",
...@@ -395,7 +410,7 @@ struct commandHelp { ...@@ -395,7 +410,7 @@ struct commandHelp {
12, 12,
"3.0.0" }, "3.0.0" },
{ "CLUSTER SETSLOT", { "CLUSTER SETSLOT",
"slot IMPORTING node-id|MIGRATING node-id|NODE node-id|STABLE", "slot IMPORTING importing|MIGRATING migrating|NODE node|STABLE",
"Bind a hash slot to a specific node", "Bind a hash slot to a specific node",
12, 12,
"3.0.0" }, "3.0.0" },
...@@ -430,12 +445,12 @@ struct commandHelp { ...@@ -430,12 +445,12 @@ struct commandHelp {
9, 9,
"7.0.0" }, "7.0.0" },
{ "COMMAND GETKEYS", { "COMMAND GETKEYS",
"", "command [arg [arg ...]]",
"Extract keys given a full Redis command", "Extract keys given a full Redis command",
9, 9,
"2.8.13" }, "2.8.13" },
{ "COMMAND GETKEYSANDFLAGS", { "COMMAND GETKEYSANDFLAGS",
"", "command [arg [arg ...]]",
"Extract keys and access flags given a full Redis command", "Extract keys and access flags given a full Redis command",
9, 9,
"7.0.0" }, "7.0.0" },
...@@ -540,12 +555,12 @@ struct commandHelp { ...@@ -540,12 +555,12 @@ struct commandHelp {
10, 10,
"2.6.0" }, "2.6.0" },
{ "EVALSHA_RO", { "EVALSHA_RO",
"sha1 numkeys key [key ...] arg [arg ...]", "sha1 numkeys [key [key ...]] [arg [arg ...]]",
"Execute a read-only Lua script server side", "Execute a read-only Lua script server side",
10, 10,
"7.0.0" }, "7.0.0" },
{ "EVAL_RO", { "EVAL_RO",
"script numkeys key [key ...] arg [arg ...]", "script numkeys [key [key ...]] [arg [arg ...]]",
"Execute a read-only Lua script server side", "Execute a read-only Lua script server side",
10, 10,
"7.0.0" }, "7.0.0" },
...@@ -580,12 +595,12 @@ struct commandHelp { ...@@ -580,12 +595,12 @@ struct commandHelp {
9, 9,
"6.2.0" }, "6.2.0" },
{ "FCALL", { "FCALL",
"function numkeys key [key ...] arg [arg ...]", "function numkeys [key [key ...]] [arg [arg ...]]",
"Invoke a function", "Invoke a function",
10, 10,
"7.0.0" }, "7.0.0" },
{ "FCALL_RO", { "FCALL_RO",
"function numkeys key [key ...] arg [arg ...]", "function numkeys [key [key ...]] [arg [arg ...]]",
"Invoke a read-only function", "Invoke a read-only function",
10, 10,
"7.0.0" }, "7.0.0" },
...@@ -660,22 +675,22 @@ struct commandHelp { ...@@ -660,22 +675,22 @@ struct commandHelp {
13, 13,
"3.2.0" }, "3.2.0" },
{ "GEOHASH", { "GEOHASH",
"key member [member ...]", "key [member [member ...]]",
"Returns members of a geospatial index as standard geohash strings", "Returns members of a geospatial index as standard geohash strings",
13, 13,
"3.2.0" }, "3.2.0" },
{ "GEOPOS", { "GEOPOS",
"key member [member ...]", "key [member [member ...]]",
"Returns longitude and latitude of members of a geospatial index", "Returns longitude and latitude of members of a geospatial index",
13, 13,
"3.2.0" }, "3.2.0" },
{ "GEORADIUS", { "GEORADIUS",
"key longitude latitude radius M|KM|FT|MI [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]", "key longitude latitude radius M|KM|FT|MI [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE storekey] [STOREDIST storedistkey]",
"Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point", "Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point",
13, 13,
"3.2.0" }, "3.2.0" },
{ "GEORADIUSBYMEMBER", { "GEORADIUSBYMEMBER",
"key member radius M|KM|FT|MI [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]", "key member radius M|KM|FT|MI [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE storekey] [STOREDIST storedistkey]",
"Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member", "Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member",
13, 13,
"3.2.0" }, "3.2.0" },
...@@ -885,7 +900,7 @@ struct commandHelp { ...@@ -885,7 +900,7 @@ struct commandHelp {
9, 9,
"2.8.13" }, "2.8.13" },
{ "LCS", { "LCS",
"key1 key2 [LEN] [IDX] [MINMATCHLEN len] [WITHMATCHLEN]", "key1 key2 [LEN] [IDX] [MINMATCHLEN min-match-len] [WITHMATCHLEN]",
"Find longest common substring", "Find longest common substring",
1, 1,
"7.0.0" }, "7.0.0" },
...@@ -1000,7 +1015,7 @@ struct commandHelp { ...@@ -1000,7 +1015,7 @@ struct commandHelp {
1, 1,
"1.0.0" }, "1.0.0" },
{ "MIGRATE", { "MIGRATE",
"host port key| destination-db timeout [COPY] [REPLACE] [[AUTH password]|[AUTH2 username password]] [KEYS key [key ...]]", "host port key| destination-db timeout [COPY] [REPLACE] [AUTH auth|AUTH2 username password] [KEYS keys [keys ...]]",
"Atomically transfer a key from a Redis instance to another one.", "Atomically transfer a key from a Redis instance to another one.",
0, 0,
"2.6.0" }, "2.6.0" },
...@@ -1025,7 +1040,7 @@ struct commandHelp { ...@@ -1025,7 +1040,7 @@ struct commandHelp {
9, 9,
"4.0.0" }, "4.0.0" },
{ "MODULE LOADEX", { "MODULE LOADEX",
"path [CONFIG name value [CONFIG name value ...]] [ARGS arg [arg ...]]", "path [CONFIG name value [CONFIG name value ...]] [ARGS args [args ...]]",
"Load a module with extended parameters", "Load a module with extended parameters",
9, 9,
"7.0.0" }, "7.0.0" },
...@@ -1450,12 +1465,12 @@ struct commandHelp { ...@@ -1450,12 +1465,12 @@ struct commandHelp {
3, 3,
"1.0.0" }, "1.0.0" },
{ "SORT", { "SORT",
"key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]", "key [BY by-pattern] [LIMIT offset count] [GET get-pattern [GET get-pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]",
"Sort the elements in a list, set or sorted set", "Sort the elements in a list, set or sorted set",
0, 0,
"1.0.0" }, "1.0.0" },
{ "SORT_RO", { "SORT_RO",
"key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA]", "key [BY by-pattern] [LIMIT offset count] [GET get-pattern [GET get-pattern ...]] [ASC|DESC] [ALPHA]",
"Sort the elements in a list, set or sorted set. Read-only variant of SORT.", "Sort the elements in a list, set or sorted set. Read-only variant of SORT.",
0, 0,
"7.0.0" }, "7.0.0" },
...@@ -1569,6 +1584,11 @@ struct commandHelp { ...@@ -1569,6 +1584,11 @@ struct commandHelp {
"Wait for the synchronous replication of all the write commands sent in the context of the current connection", "Wait for the synchronous replication of all the write commands sent in the context of the current connection",
0, 0,
"3.0.0" }, "3.0.0" },
{ "WAITAOF",
"numlocal numreplicas timeout",
"Wait for all write commands sent in the context of the current connection to be synced to AOF of local host and/or replicas",
0,
"7.2.0" },
{ "WATCH", { "WATCH",
"key [key ...]", "key [key ...]",
"Watch the given keys to determine execution of the MULTI/EXEC block", "Watch the given keys to determine execution of the MULTI/EXEC block",
...@@ -1590,7 +1610,7 @@ struct commandHelp { ...@@ -1590,7 +1610,7 @@ struct commandHelp {
14, 14,
"6.2.0" }, "6.2.0" },
{ "XCLAIM", { "XCLAIM",
"key group consumer min-idle-time id [id ...] [IDLE ms] [TIME unix-time-milliseconds] [RETRYCOUNT count] [FORCE] [JUSTID]", "key group consumer min-idle-time id [id ...] [IDLE ms] [TIME unix-time-milliseconds] [RETRYCOUNT count] [FORCE] [JUSTID] [LASTID lastid]",
"Changes (or acquires) ownership of a message in a consumer group, as if the message was delivered to the specified consumer.", "Changes (or acquires) ownership of a message in a consumer group, as if the message was delivered to the specified consumer.",
14, 14,
"5.0.0" }, "5.0.0" },
...@@ -1605,22 +1625,22 @@ struct commandHelp { ...@@ -1605,22 +1625,22 @@ struct commandHelp {
14, 14,
"5.0.0" }, "5.0.0" },
{ "XGROUP CREATE", { "XGROUP CREATE",
"key groupname id|$ [MKSTREAM] [ENTRIESREAD entries_read]", "key group id|$ [MKSTREAM] [ENTRIESREAD entries-read]",
"Create a consumer group.", "Create a consumer group.",
14, 14,
"5.0.0" }, "5.0.0" },
{ "XGROUP CREATECONSUMER", { "XGROUP CREATECONSUMER",
"key groupname consumername", "key group consumer",
"Create a consumer in a consumer group.", "Create a consumer in a consumer group.",
14, 14,
"6.2.0" }, "6.2.0" },
{ "XGROUP DELCONSUMER", { "XGROUP DELCONSUMER",
"key groupname consumername", "key group consumer",
"Delete a consumer from a consumer group.", "Delete a consumer from a consumer group.",
14, 14,
"5.0.0" }, "5.0.0" },
{ "XGROUP DESTROY", { "XGROUP DESTROY",
"key groupname", "key group",
"Destroy a consumer group.", "Destroy a consumer group.",
14, 14,
"5.0.0" }, "5.0.0" },
...@@ -1630,7 +1650,7 @@ struct commandHelp { ...@@ -1630,7 +1650,7 @@ struct commandHelp {
14, 14,
"5.0.0" }, "5.0.0" },
{ "XGROUP SETID", { "XGROUP SETID",
"key groupname id|$ [ENTRIESREAD entries_read]", "key group id|$ [ENTRIESREAD entriesread]",
"Set a consumer group to an arbitrary last delivered ID value.", "Set a consumer group to an arbitrary last delivered ID value.",
14, 14,
"5.0.0" }, "5.0.0" },
...@@ -1640,7 +1660,7 @@ struct commandHelp { ...@@ -1640,7 +1660,7 @@ struct commandHelp {
14, 14,
"5.0.0" }, "5.0.0" },
{ "XINFO CONSUMERS", { "XINFO CONSUMERS",
"key groupname", "key group",
"List the consumers in a consumer group", "List the consumers in a consumer group",
14, 14,
"5.0.0" }, "5.0.0" },
...@@ -1690,7 +1710,7 @@ struct commandHelp { ...@@ -1690,7 +1710,7 @@ struct commandHelp {
14, 14,
"5.0.0" }, "5.0.0" },
{ "XSETID", { "XSETID",
"key last-id [ENTRIESADDED entries_added] [MAXDELETEDID max_deleted_entry_id]", "key last-id [ENTRIESADDED entries-added] [MAXDELETEDID max-deleted-id]",
"An internal command for replicating stream values", "An internal command for replicating stream values",
14, 14,
"5.0.0" }, "5.0.0" },
...@@ -1795,7 +1815,7 @@ struct commandHelp { ...@@ -1795,7 +1815,7 @@ struct commandHelp {
4, 4,
"6.2.0" }, "6.2.0" },
{ "ZRANK", { "ZRANK",
"key member", "key member [WITHSCORE]",
"Determine the index of a member in a sorted set", "Determine the index of a member in a sorted set",
4, 4,
"2.0.0" }, "2.0.0" },
...@@ -1835,7 +1855,7 @@ struct commandHelp { ...@@ -1835,7 +1855,7 @@ struct commandHelp {
4, 4,
"2.2.0" }, "2.2.0" },
{ "ZREVRANK", { "ZREVRANK",
"key member", "key member [WITHSCORE]",
"Determine the index of a member in a sorted set, with scores ordered from high to low", "Determine the index of a member in a sorted set, with scores ordered from high to low",
4, 4,
"2.0.0" }, "2.0.0" },
......
...@@ -147,6 +147,8 @@ client *createClient(connection *conn) { ...@@ -147,6 +147,8 @@ client *createClient(connection *conn) {
#endif #endif
c->conn = conn; c->conn = conn;
c->name = NULL; c->name = NULL;
c->lib_name = NULL;
c->lib_ver = NULL;
c->bufpos = 0; c->bufpos = 0;
c->buf_usable_size = zmalloc_usable_size(c->buf); c->buf_usable_size = zmalloc_usable_size(c->buf);
c->buf_peak = c->buf_usable_size; c->buf_peak = c->buf_usable_size;
...@@ -1496,7 +1498,11 @@ void clearClientConnectionState(client *c) { ...@@ -1496,7 +1498,11 @@ void clearClientConnectionState(client *c) {
if (c->flags & CLIENT_TRACKING) disableTracking(c); if (c->flags & CLIENT_TRACKING) disableTracking(c);
selectDb(c,0); selectDb(c,0);
#ifdef LOG_REQ_RES
c->resp = server.client_default_resp;
#else
c->resp = 2; c->resp = 2;
#endif
clientSetDefaultAuth(c); clientSetDefaultAuth(c);
moduleNotifyUserChanged(c); moduleNotifyUserChanged(c);
...@@ -1511,6 +1517,9 @@ void clearClientConnectionState(client *c) { ...@@ -1511,6 +1517,9 @@ void clearClientConnectionState(client *c) {
c->name = NULL; c->name = NULL;
} }
/* Note: lib_name and lib_ver are not reset since they still
* represent the client library behind the connection. */
/* Selectively clear state flags not covered above */ /* Selectively clear state flags not covered above */
c->flags &= ~(CLIENT_ASKING|CLIENT_READONLY|CLIENT_PUBSUB|CLIENT_REPLY_OFF| c->flags &= ~(CLIENT_ASKING|CLIENT_READONLY|CLIENT_PUBSUB|CLIENT_REPLY_OFF|
CLIENT_REPLY_SKIP_NEXT|CLIENT_NO_TOUCH|CLIENT_NO_EVICT); CLIENT_REPLY_SKIP_NEXT|CLIENT_NO_TOUCH|CLIENT_NO_EVICT);
...@@ -1662,6 +1671,8 @@ void freeClient(client *c) { ...@@ -1662,6 +1671,8 @@ void freeClient(client *c) {
/* Release other dynamically allocated client structure fields, /* Release other dynamically allocated client structure fields,
* and finally release the client structure itself. */ * and finally release the client structure itself. */
if (c->name) decrRefCount(c->name); if (c->name) decrRefCount(c->name);
if (c->lib_name) decrRefCount(c->lib_name);
if (c->lib_ver) decrRefCount(c->lib_ver);
freeClientMultiState(c); freeClientMultiState(c);
sdsfree(c->peerid); sdsfree(c->peerid);
sdsfree(c->sockname); sdsfree(c->sockname);
...@@ -2775,7 +2786,7 @@ sds catClientInfoString(sds s, client *client) { ...@@ -2775,7 +2786,7 @@ sds catClientInfoString(sds s, client *client) {
} }
sds ret = sdscatfmt(s, sds ret = sdscatfmt(s,
"id=%U addr=%s laddr=%s %s name=%s age=%I idle=%I flags=%s db=%i sub=%i psub=%i ssub=%i multi=%i qbuf=%U qbuf-free=%U argv-mem=%U multi-mem=%U rbs=%U rbp=%U obl=%U oll=%U omem=%U tot-mem=%U events=%s cmd=%s user=%s redir=%I resp=%i", "id=%U addr=%s laddr=%s %s name=%s age=%I idle=%I flags=%s db=%i sub=%i psub=%i ssub=%i multi=%i qbuf=%U qbuf-free=%U argv-mem=%U multi-mem=%U rbs=%U rbp=%U obl=%U oll=%U omem=%U tot-mem=%U events=%s cmd=%s user=%s redir=%I resp=%i lib-name=%s lib-ver=%s",
(unsigned long long) client->id, (unsigned long long) client->id,
getClientPeerId(client), getClientPeerId(client),
getClientSockname(client), getClientSockname(client),
...@@ -2803,7 +2814,10 @@ sds catClientInfoString(sds s, client *client) { ...@@ -2803,7 +2814,10 @@ sds catClientInfoString(sds s, client *client) {
client->lastcmd ? client->lastcmd->fullname : "NULL", client->lastcmd ? client->lastcmd->fullname : "NULL",
client->user ? client->user->name : "(superuser)", client->user ? client->user->name : "(superuser)",
(client->flags & CLIENT_TRACKING) ? (long long) client->client_tracking_redirection : -1, (client->flags & CLIENT_TRACKING) ? (long long) client->client_tracking_redirection : -1,
client->resp); client->resp,
client->lib_name ? (char*)client->lib_name->ptr : "",
client->lib_ver ? (char*)client->lib_ver->ptr : ""
);
return ret; return ret;
} }
...@@ -2823,6 +2837,20 @@ sds getAllClientsInfoString(int type) { ...@@ -2823,6 +2837,20 @@ sds getAllClientsInfoString(int type) {
return o; return o;
} }
/* Check validity of an attribute that's gonna be shown in CLIENT LIST. */
int validateClientAttr(const char *val) {
/* Check if the charset is ok. We need to do this otherwise
* CLIENT LIST format will break. You should always be able to
* split by space to get the different fields. */
while (*val) {
if (*val < '!' || *val > '~') { /* ASCII is assumed. */
return C_ERR;
}
val++;
}
return C_OK;
}
/* Returns C_OK if the name is valid. Returns C_ERR & sets `err` (when provided) otherwise. */ /* Returns C_OK if the name is valid. Returns C_ERR & sets `err` (when provided) otherwise. */
int validateClientName(robj *name, const char **err) { int validateClientName(robj *name, const char **err) {
const char *err_msg = "Client names cannot contain spaces, newlines or special characters."; const char *err_msg = "Client names cannot contain spaces, newlines or special characters.";
...@@ -2830,15 +2858,9 @@ int validateClientName(robj *name, const char **err) { ...@@ -2830,15 +2858,9 @@ int validateClientName(robj *name, const char **err) {
/* We allow setting the client name to an empty string. */ /* We allow setting the client name to an empty string. */
if (len == 0) if (len == 0)
return C_OK; return C_OK;
/* Otherwise check if the charset is ok. We need to do this otherwise if (validateClientAttr(name->ptr) == C_ERR) {
* CLIENT LIST format will break. You should always be able to if (err) *err = err_msg;
* split by space to get the different fields. */ return C_ERR;
char *p = name->ptr;
for (int j = 0; j < len; j++) {
if (p[j] < '!' || p[j] > '~') { /* ASCII is assumed. */
if (err) *err = err_msg;
return C_ERR;
}
} }
return C_OK; return C_OK;
} }
...@@ -2880,6 +2902,35 @@ int clientSetNameOrReply(client *c, robj *name) { ...@@ -2880,6 +2902,35 @@ int clientSetNameOrReply(client *c, robj *name) {
return result; return result;
} }
/* Set client or connection related info */
void clientSetinfoCommand(client *c) {
sds attr = c->argv[2]->ptr;
robj *valob = c->argv[3];
sds val = valob->ptr;
robj **destvar = NULL;
if (!strcasecmp(attr,"lib-name")) {
destvar = &c->lib_name;
} else if (!strcasecmp(attr,"lib-ver")) {
destvar = &c->lib_ver;
} else {
addReplyErrorFormat(c,"Unrecognized option '%s'", attr);
return;
}
if (validateClientAttr(val)==C_ERR) {
addReplyErrorFormat(c,
"%s cannot contain spaces, newlines or special characters.", attr);
return;
}
if (*destvar) decrRefCount(*destvar);
if (sdslen(val)) {
*destvar = valob;
incrRefCount(valob);
} else
*destvar = NULL;
addReply(c,shared.ok);
}
/* Reset the client state to resemble a newly connected client. /* Reset the client state to resemble a newly connected client.
*/ */
void resetCommand(client *c) { void resetCommand(client *c) {
......
...@@ -1155,6 +1155,8 @@ typedef struct client { ...@@ -1155,6 +1155,8 @@ typedef struct client {
int resp; /* RESP protocol version. Can be 2 or 3. */ int resp; /* RESP protocol version. Can be 2 or 3. */
redisDb *db; /* Pointer to currently SELECTed DB. */ redisDb *db; /* Pointer to currently SELECTed DB. */
robj *name; /* As set by CLIENT SETNAME. */ robj *name; /* As set by CLIENT SETNAME. */
robj *lib_name; /* The client library name as set by CLIENT SETINFO. */
robj *lib_ver; /* The client library version as set by CLIENT SETINFO. */
sds querybuf; /* Buffer we use to accumulate client queries. */ sds querybuf; /* Buffer we use to accumulate client queries. */
size_t qb_pos; /* The position we have read in querybuf. */ size_t qb_pos; /* The position we have read in querybuf. */
size_t querybuf_peak; /* Recent (100ms or more) peak of querybuf size. */ size_t querybuf_peak; /* Recent (100ms or more) peak of querybuf size. */
...@@ -3668,6 +3670,7 @@ void objectCommand(client *c); ...@@ -3668,6 +3670,7 @@ void objectCommand(client *c);
void memoryCommand(client *c); void memoryCommand(client *c);
void clientCommand(client *c); void clientCommand(client *c);
void helloCommand(client *c); void helloCommand(client *c);
void clientSetinfoCommand(client *c);
void evalCommand(client *c); void evalCommand(client *c);
void evalRoCommand(client *c); void evalRoCommand(client *c);
void evalShaCommand(client *c); void evalShaCommand(client *c);
......
...@@ -12,10 +12,22 @@ if {$::simulate_error} { ...@@ -12,10 +12,22 @@ if {$::simulate_error} {
} }
} }
test "Sentinel commands sanity check" { test "Sentinel command flag infrastructure works correctly" {
foreach_sentinel_id id { foreach_sentinel_id id {
assert_equal {72} [llength [S $id command list]] set command_list [S $id command list]
assert_equal {15} [S $id command count]
foreach cmd {ping info subscribe client|setinfo} {
assert_not_equal [S $id command docs $cmd] {}
assert_not_equal [lsearch $command_list $cmd] -1
}
foreach cmd {save bgrewriteaof blpop replicaof} {
assert_equal [S $id command docs $cmd] {}
assert_equal [lsearch $command_list $cmd] -1
assert_error {ERR unknown command*} {S $id $cmd}
}
assert_error {ERR unknown subcommand*} {S $id client no-touch}
} }
} }
......
...@@ -36,7 +36,7 @@ proc wait_for_cluster_propagation {} { ...@@ -36,7 +36,7 @@ proc wait_for_cluster_propagation {} {
# Wait for cluster size to be consistent across nodes. # Wait for cluster size to be consistent across nodes.
proc wait_for_cluster_size {cluster_size} { proc wait_for_cluster_size {cluster_size} {
wait_for_condition 50 100 { wait_for_condition 1000 50 {
[cluster_size_consistent $cluster_size] eq 1 [cluster_size_consistent $cluster_size] eq 1
} else { } else {
fail "cluster size did not reach a consistent size $cluster_size" fail "cluster size did not reach a consistent size $cluster_size"
......
...@@ -118,6 +118,10 @@ start_server {tags {"introspection"}} { ...@@ -118,6 +118,10 @@ start_server {tags {"introspection"}} {
assert_match {*calls=1,*} [cmdstat geoadd] assert_match {*calls=1,*} [cmdstat geoadd]
} {} {needs:config-resetstat} } {} {needs:config-resetstat}
test {COMMAND COUNT get total number of Redis commands} {
assert_morethan [r command count] 0
}
test {COMMAND GETKEYS GET} { test {COMMAND GETKEYS GET} {
assert_equal {key} [r command getkeys get key] assert_equal {key} [r command getkeys get key]
} }
......
...@@ -325,6 +325,31 @@ start_server {tags {"introspection"}} { ...@@ -325,6 +325,31 @@ start_server {tags {"introspection"}} {
} }
} }
test {CLIENT SETINFO can set a library name to this connection} {
r CLIENT SETINFO lib-name redis.py
r CLIENT SETINFO lib-ver 1.2.3
r client info
} {*lib-name=redis.py lib-ver=1.2.3*}
test {CLIENT SETINFO invalid args} {
assert_error {*wrong number of arguments*} {r CLIENT SETINFO lib-name}
assert_error {*cannot contain spaces*} {r CLIENT SETINFO lib-name "redis py"}
assert_error {*newlines*} {r CLIENT SETINFO lib-name "redis.py\n"}
assert_error {*Unrecognized*} {r CLIENT SETINFO badger hamster}
# test that all of these didn't affect the previously set values
r client info
} {*lib-name=redis.py lib-ver=1.2.3*}
test {RESET does NOT clean library name} {
r reset
r client info
} {*lib-name=redis.py*} {needs:reset}
test {CLIENT SETINFO can clear library name} {
r CLIENT SETINFO lib-name ""
r client info
} {*lib-name= *}
test {CONFIG save params special case handled properly} { test {CONFIG save params special case handled properly} {
# No "save" keyword - defaults should apply # No "save" keyword - defaults should apply
start_server {config "minimal.conf"} { start_server {config "minimal.conf"} {
......
...@@ -12,7 +12,6 @@ import argparse ...@@ -12,7 +12,6 @@ import argparse
import multiprocessing import multiprocessing
import collections import collections
import io import io
import signal
import traceback import traceback
from datetime import timedelta from datetime import timedelta
from functools import partial from functools import partial
...@@ -169,7 +168,7 @@ class Response(object): ...@@ -169,7 +168,7 @@ class Response(object):
value = Response(f, line_counter) value = Response(f, line_counter)
self.json[field] = value.json self.json[field] = value.json
if line[0] == '|': if line[0] == '|':
# We don't care abou the attributes, read the real response # We don't care about the attributes, read the real response
real_res = Response(f, line_counter) real_res = Response(f, line_counter)
self.__dict__.update(real_res.__dict__) self.__dict__.update(real_res.__dict__)
...@@ -180,7 +179,7 @@ class Response(object): ...@@ -180,7 +179,7 @@ class Response(object):
def process_file(docs, path): def process_file(docs, path):
""" """
This function processes a single filegenerated by logreqres.c This function processes a single file generated by logreqres.c
""" """
line_counter = [0] # A list with one integer: to force python to pass it by reference line_counter = [0] # A list with one integer: to force python to pass it by reference
command_counter = dict() command_counter = dict()
...@@ -190,7 +189,7 @@ def process_file(docs, path): ...@@ -190,7 +189,7 @@ def process_file(docs, path):
# Convert file to StringIO in order to minimize IO operations # Convert file to StringIO in order to minimize IO operations
with open(path, "r", newline="\r\n", encoding="latin-1") as f: with open(path, "r", newline="\r\n", encoding="latin-1") as f:
content = f.read() content = f.read()
with io.StringIO(content) as fakefile: with io.StringIO(content) as fakefile:
while True: while True:
try: try:
...@@ -244,7 +243,7 @@ def fetch_schemas(cli, port, args, docs): ...@@ -244,7 +243,7 @@ def fetch_schemas(cli, port, args, docs):
break break
except Exception as e: except Exception as e:
time.sleep(0.1) time.sleep(0.1)
pass
print('Connected') print('Connected')
cli_proc = subprocess.Popen([cli, '-p', str(port), '--json', 'command', 'docs'], stdout=subprocess.PIPE) cli_proc = subprocess.Popen([cli, '-p', str(port), '--json', 'command', 'docs'], stdout=subprocess.PIPE)
...@@ -310,7 +309,7 @@ if __name__ == '__main__': ...@@ -310,7 +309,7 @@ if __name__ == '__main__':
start = time.time() start = time.time()
# Obtain all the files toprocesses # Obtain all the files to processes
paths = [] paths = []
for path in glob.glob('%s/tmp/*/*.reqres' % testdir): for path in glob.glob('%s/tmp/*/*.reqres' % testdir):
paths.append(path) paths.append(path)
......
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