Commit graph

8564 commits

Author SHA1 Message Date
zhaozhao.zz
f0005b5328
benchmark getRedisConfig exit only when meet NOAUTH error (#11096)
redis-benchmark: when trying to get the CONFIG before benchmark,
avoid printing any warning on most errors (e.g. NOPERM error).
avoid aborting the benchmark on NOPERM.
keep the warning only when we abort the benchmark on a NOAUTH error
2022-11-28 20:51:25 +08:00
C Charles
eeca7f2911
Add withscore option to ZRANK and ZREVRANK. (#11235)
Add an option "withscores" to ZRANK and ZREVRANK.

Add `[withscore]` option to both `zrank` and `zrevrank`, like this:
```
z[rev]rank key member [withscore]
```
2022-11-28 11:57:11 +02:00
filipe oliveira
376b689b03
Simplified geoAppendIfWithinShape() and removed spurious calls do sdsdup and sdsfree (#11522)
In scenarios in which we have large datasets and the elements are not
contained within the range we do spurious calls do sdsdup and sdsfree.
I.e. instead of pre-creating an sds before we know if we're gonna use it
or not, change the role of geoAppendIfWithinShape to just do geoWithinShape,
and let the caller create the string only when needed.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-11-28 10:37:41 +02:00
Madelyn Olson
fbdebc1d74
Add log message when PID file fails to create (#11544)
Add an error message when PID file fails to be written. This has historically been considered a best effort failure, but we don't even report the failure.
2022-11-27 08:57:50 -08:00
Binbin
a7cecf3713
Add redis_ prefix for member2struct, avoid redefined warning in FreeBSD (#11549)
It look like it will generate a warning in FreeBSD:
```
  ./server.h:105:9: warning: 'member2struct' macro redefined [-Wmacro-redefined]
  #define member2struct(struct_name, member_name, member_addr) \
          ^
  /usr/include/sys/param.h:365:9: note: previous definition is here
  #define member2struct(s, m, x)                                          \
          ^
```

Add a `redis_` prefix to it, avoid the warning, introduced in #11511
2022-11-27 10:18:48 +02:00
sundb
24282a381a
Remove duplicate postExecutionUnitOperation call (#11547)
Accidentally introduced when merging unstable in #11199
2022-11-27 08:58:44 +02:00
Tian
7be86177a3
Avoid spurious wakeup on deleted timer event (#11069)
Avoid spurious wakeup on deleted timer event

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
2022-11-25 20:36:33 -08:00
DevineLiu
25ffa79b64
[BUG] Fix announced ports not updating on local node when updated at runtime (#10745)
The cluster-announce-port/cluster-announce-bus-port/cluster-announce-tls-port should take effect at runtime

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
2022-11-25 18:01:01 -08:00
Viktor Söderqvist
abf70309eb
Shrink dict without rehashing (#11540)
When we're shrinking the hash table, we don't need to hash the keys. 
Since the table sizes are powers of two, we can simply mask the bucket 
index in the larger table to get the bucket index in the smaller table. We 
avoid loading the keys into memory and save CPU time.
2022-11-25 17:35:18 -08:00
DarrenJiang13
ce4ebe6ba8
Two minor fixes for cluster.c (#11441)
clusterNodeClearSlotBit()/clusterNodeSetSlotBit(), only set bit when slot does not exist and clear bit when slot does exist.
2022-11-25 11:58:19 -08:00
Meir Shpilraien (Spielrein)
abc345ad28
Module API to allow writes after key space notification hooks (#11199)
### Summary of API additions

* `RedisModule_AddPostNotificationJob` - new API to call inside a key space
  notification (and on more locations in the future) and allow to add a post job as describe above.
* New module option, `REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS`,
  allows to disable Redis protection of nested key-space notifications.
* `RedisModule_GetModuleOptionsAll` - gets the mask of all supported module options so a module
  will be able to check if a given option is supported by the current running Redis instance.

### Background

The following PR is a proposal of handling write operations inside module key space notifications.
After a lot of discussions we came to a conclusion that module should not perform any write
operations on key space notification.

Some examples of issues that such write operation can cause are describe on the following links:

* Bad replication oreder - https://github.com/redis/redis/pull/10969
* Used after free - https://github.com/redis/redis/pull/10969#issuecomment-1223771006
* Used after free - https://github.com/redis/redis/pull/9406#issuecomment-1221684054

There are probably more issues that are yet to be discovered. The underline problem with writing
inside key space notification is that the notification runs synchronously, this means that the notification
code will be executed in the middle on Redis logic (commands logic, eviction, expire).
Redis **do not assume** that the data might change while running the logic and such changes
can crash Redis or cause unexpected behaviour.

The solution is to state that modules **should not** perform any write command inside key space
notification (we can chose whether or not we want to force it). To still cover the use-case where
module wants to perform a write operation as a reaction to key space notifications, we introduce
a new API , `RedisModule_AddPostNotificationJob`, that allows to register a callback that will be
called by Redis when the following conditions hold:

* It is safe to perform any write operation.
* The job will be called atomically along side the operation that triggers it (in our case, key
  space notification).

Module can use this new API to safely perform any write operation and still achieve atomicity
between the notification and the write.

Although currently the API is supported on key space notifications, the API is written in a generic
way so that in the future we will be able to use it on other places (server events for example).

### Technical Details

Whenever a module uses `RedisModule_AddPostNotificationJob` the callback is added to a list
of callbacks (called `modulePostExecUnitJobs`) that need to be invoke after the current execution
unit ends (whether its a command, eviction, or active expire). In order to trigger those callback
atomically with the notification effect, we call those callbacks on `postExecutionUnitOperations`
(which was `propagatePendingCommands` before this PR). The new function fires the post jobs
and then calls `propagatePendingCommands`.

If the callback perform more operations that triggers more key space notifications. Those keys
space notifications might register more callbacks. Those callbacks will be added to the end
of `modulePostExecUnitJobs` list and will be invoke atomically after the current callback ends.
This raises a concerns of entering an infinite loops, we consider infinite loops as a logical bug
that need to be fixed in the module, an attempt to protect against infinite loops by halting the
execution could result in violation of the feature correctness and so **Redis will make no attempt
to protect the module from infinite loops**

In addition, currently key space notifications are not nested. Some modules might want to allow
nesting key-space notifications. To allow that and keep backward compatibility, we introduce a
new module option called `REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS`.
Setting this option will disable the Redis key-space notifications nesting protection and will
pass this responsibility to the module.

### Redis infrastructure

This PR promotes the existing `propagatePendingCommands` to an "Execution Unit" concept,
which is called after each atomic unit of execution,

Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: Yossi Gottlieb <yossigo@gmail.com>
Co-authored-by: Madelyn Olson <34459052+madolson@users.noreply.github.com>
2022-11-24 19:00:04 +02:00
filipe oliveira
ae1de54900
GEOSEARCH BYBOX: Reduce wastefull computation on geohashGetDistanceIfInRectangle and geohashGetDistance (#11535)
Optimize geohashGetDistanceIfInRectangle when there are many misses.
It calls 3x geohashGetDistance. The first 2 times we call them to produce intermediate results.
This PR focus on optimizing for those 2 intermediate results.

1 Reduce expensive computation on intermediate geohashGetDistance with same long
2 Avoid expensive lon_distance calculation if lat_distance fails beforehand

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-11-24 18:09:56 +02:00
Binbin
ca174e1d47
Fix sanitizer warning, use offsetof instread of member_offset (#11539)
In #11511 we introduced member_offset which has a sanitizer warning:
```
multi.c:390:26: runtime error: member access within null pointer of type 'watchedKey' (aka 'struct watchedKey')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior multi.c:390:26
```

We can use offsetof() from stddef.h. This is part of the standard lib
just to avoid this UB :) Sanitizer should not complain after we change
this.

1. Use offsetof instead of member_offset, so we can delete this now
2. Changed (uint8_t*) cast to (char*).

This does not matter much but according to standard, we are only allowed
to cast pointers to its own type, char* and void*. Let's try to follow
the rules.

This change was suggested by tezc and the comments is also from him.

Co-authored-by: Ozan Tezcan <ozantezcan@gmail.com>
2022-11-24 15:38:09 +02:00
sundb
fd80818552
Ignore -Wstringop-overread warning for SHA1Transform() on GCC 12 (#11538)
Fix compile warning for SHA1Transform() method under alpine with GCC 12.

Warning:
```
In function 'SHA1Update',
    inlined from 'SHA1Final' at sha1.c:187:9:
sha1.c:144:13: error: 'SHA1Transform' reading 64 bytes from a region of size 0 [-Werror=stringop-overread]
  144 |             SHA1Transform(context->state, &data[i]);
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sha1.c:144:13: note: referencing argument 2 of type 'const unsigned char[64]'
sha1.c: In function 'SHA1Final':
sha1.c:56:6: note: in a call to function 'SHA1Transform'
   56 | void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
      |      ^~~~~~~~~~~~~
```

This warning is a false positive because it has been determined in the loop judgment that there must be 64 chars after position `i`
```c
for ( ; i + 63 < len; i += 64) {
    SHA1Transform(context->state, &data[i]);
}
```

Reference: e1d7d3e40a
2022-11-24 15:27:16 +02:00
Wen Hui
75c66fb02c
Update Sentinel Debug command json file and add test case for it (#11513)
Command SENTINEL DEBUG could be no arguments, which display all
configurable arguments and their values.
Update the command arguments in the docs (json file) to indicate that
arguments are optional
2022-11-24 13:10:41 +02:00
Mingyi Kang
3b462ce566
optimize unwatchAllKeys() (#11511)
In unwatchAllKeys() function, we traverse all the keys watched by the client,
and for each key we need to remove the client from the list of clients watching that key.
This is implemented by listSearchKey which traverses the list of clients.

If we can reach the node of the list of clients from watchedKey in O(1) time,
then we do not need to call listSearchKey anymore.

Changes in this PR: put the node of the list of clients of each watched key in the
db inside the watchedKey structure. In this way, for every key watched by the client,
we can get the watchedKey structure and then reach the node in the list of clients in
db->watched_keys to remove it from that list.
From the perspective of the list of clients watching the key, the list node is inside a
watchedKey structure, so we can get to the watchedKey struct from the listnode by
struct member offset math. And because of this, node->value is not used, we can point
node->value to the list itself, so that we don't need to fetch the list of clients from the dict.
2022-11-23 17:39:08 +02:00
Itamar Haber
f36eb5a1ba
Deprecates SETEX, PSETEX and SETNX (#11512)
Technically, these commands were deprecated as of 2.6.12, with the
introduction of the respective arguments to SET.
In reality, the deprecation note will only be added in 7.2.0.
2022-11-22 18:10:21 +02:00
Wen Hui
6e9724cb6a
Add explicit error log message for AOF_TRUNCATED status when server load AOF file (#11484)
Now, according to the comments, if the truncated file is not the last file,
it will be considered as a fatal error.
And the return code will updated to AOF_FAILED, then server will exit
without any error message to the client.

Similar to other error situations, this PR add an explicit error message
for this case and make the client know clearly what happens.
2022-11-22 16:18:36 +02:00
Binbin
3f8756a06a
Fix set with duplicate elements causes sdiff to hang (#11530)
This payload produces a set with duplicate elements (listpack encoding):
```
restore _key 0 "\x14\x25\x25\x00\x00\x00\x0A\x00\x06\x01\x82\x5F\x35\x03\x04\x01\x82\x5F\x31\x03\x82\x5F\x33\x03\x00\x01\x82\x5F\x39\x03\x82\x5F\x33\x03\x08\x01\x02\x01\xFF\x0B\x00\x31\xBE\x7D\x41\x01\x03\x5B\xEC"

smembers key
1) "6"
2) "_5"
3) "4"
4) "_1"
5) "_3"  ---> dup
6) "0"
7) "_9"
8) "_3"  ---> dup
9) "8"
10) "2"
```

This kind of sets will cause SDIFF to hang, SDIFF generated a broken
protocol and left the client hung. (Expected ten elements, but only
got nine elements due to the duplication.)

If we set `sanitize-dump-payload` to yes, we will be able to find
the duplicate elements and report "ERR Bad data format".

Discovered and discussed in #11290.

This PR also improve prints when corrupt-dump-fuzzer hangs, it will
print the cmds and the payload, an example like:
```
Testing integration/corrupt-dump-fuzzer
[TIMEOUT]: clients state report follows.
sock6 => (SPAWNED SERVER) pid:28884
Killing still running Redis server 28884
commands caused test to hang:
SDIFF __key 
payload that caused test to hang: "\x14\balabala"
```

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-11-22 11:20:24 +02:00
Binbin
51887e61b8
sanitize dump payload: fix crash with empty set with listpack encoding (#11519)
The following example will create an empty set (listpack encoding):
```
> RESTORE key 0
"\x14\x25\x25\x00\x00\x00\x00\x00\x02\x01\x82\x5F\x37\x03\x06\x01\x82\x5F\x35\x03\x82\x5F\x33\x03\x00\x01\x82\x5F\x31\x03\x82\x5F\x39\x03\x04\xA9\x08\x01\xFF\x0B\x00\xA3\x26\x49\xB4\x86\xB0\x0F\x41"
OK
> SCARD key
(integer) 0
> SRANDMEMBER key
Error: Server closed the connection
```

In the spirit of #9297, skip empty set when loading RDB_TYPE_SET_LISTPACK.
Introduced in #11290
2022-11-20 12:12:15 +02:00
Wen Hui
2f411770c8
Add CONFIG SET and GET loglevel feature in Sentinel (#11214)
Till now Sentinel allowed modifying the log level in the config file, but not at runtime.
this makes it possible to tune the log level at runtime
2022-11-20 12:03:00 +02:00
Ping Xie
203b12e41f
Introduce Shard IDs to logically group nodes in cluster mode (#10536)
Introduce Shard IDs to logically group nodes in cluster mode.
1. Added a new "shard_id" field to "cluster nodes" output and nodes.conf after "hostname"
2. Added a new PING extension to propagate "shard_id"
3. Handled upgrade from pre-7.2 releases automatically
4. Refactored PING extension assembling/parsing logic

Behavior of Shard IDs:

Replicas will always follow the shards of their reported primaries. If a primary updates its shard ID, the replica will follow. (This need not follow for cluster v2) This is not an expected use case.
2022-11-16 19:24:18 -08:00
sundb
2168ccc661
Add listpack encoding for list (#11303)
Improve memory efficiency of list keys

## Description of the feature
The new listpack encoding uses the old `list-max-listpack-size` config
to perform the conversion, which we can think it of as a node inside a
quicklist, but without 80 bytes overhead (internal fragmentation included)
of quicklist and quicklistNode structs.
For example, a list key with 5 items of 10 chars each, now takes 128 bytes
instead of 208 it used to take.

## Conversion rules
* Convert listpack to quicklist
  When the listpack length or size reaches the `list-max-listpack-size` limit,
  it will be converted to a quicklist.
* Convert quicklist to listpack
  When a quicklist has only one node, and its length or size is reduced to half
  of the `list-max-listpack-size` limit, it will be converted to a listpack.
  This is done to avoid frequent conversions when we add or remove at the bounding size or length.
    
## Interface changes
1. add list entry param to listTypeSetIteratorDirection
    When list encoding is listpack, `listTypeIterator->lpi` points to the next entry of current entry,
    so when changing the direction, we need to use the current node (listTypeEntry->p) to 
    update `listTypeIterator->lpi` to the next node in the reverse direction.

## Benchmark
### Listpack VS Quicklist with one node
* LPUSH - roughly 0.3% improvement
* LRANGE - roughly 13% improvement

### Both are quicklist
* LRANGE - roughly 3% improvement
* LRANGE without pipeline - roughly 3% improvement

From the benchmark, as we can see from the results
1. When list is quicklist encoding, LRANGE improves performance by <5%.
2. When list is listpack encoding, LRANGE improves performance by ~13%,
   the main enhancement is brought by `addListListpackRangeReply()`.

## Memory usage
1M lists(key:0~key:1000000) with 5 items of 10 chars ("hellohello") each.
shows memory usage down by 35.49%, from 214MB to 138MB.

## Note
1. Add conversion callback to support doing some work before conversion
    Since the quicklist iterator decompresses the current node when it is released, we can 
    no longer decompress the quicklist after we convert the list.
2022-11-16 20:29:46 +02:00
Madelyn Olson
d136bf2830
Explicitly send function commands to monitor (#11510)
Both functions and eval are marked as "no-monitor", since we want to explicitly feed in the script command before the commands generated by the script. Note that we want this behavior generally, so that commands can redact arguments before being added to the monitor.
2022-11-15 17:21:27 -08:00
uriyage
e4eb18b303
Module CLIENT_CHANGE, Fix crash on free blocked client with DB!=0 (#11500)
In moduleFireServerEvent we change the real client DB to 0 on freeClient in case the event is REDISMODULE_EVENT_CLIENT_CHANGE.
It results in a crash if the client is blocked on a key on other than DB 0.

The DB change is not necessary even for module-client, as we set its DB to 0 on either createClient or moduleReleaseTempClient.

Co-authored-by: Madelyn Olson <34459052+madolson@users.noreply.github.com>
Co-authored-by: Binbin <binloveplay1314@qq.com>
2022-11-14 14:40:35 -08:00
Oran Agra
4c54528f0f
fixes for fork child exit and test: #11463 (#11499)
Fix a few issues with the recent #11463
* use exitFromChild instead of exit
* test should ignore defunct process since that's what we expect to
  happen for thees child processes when the parent dies.
* fix typo

Co-authored-by: Binbin <binloveplay1314@qq.com>
2022-11-12 20:35:34 +02:00
Binbin
6617f1704b
Add missing lpFree for listpack test, fix valgrind daily (#11492)
Add missing lpFree, introduced in #11290
2022-11-10 10:27:38 +02:00
Viktor Söderqvist
4e472a1a7f
Listpack encoding for sets (#11290)
Small sets with not only integer elements are listpack encoded, by default
up to 128 elements, max 64 bytes per element, new config `set-max-listpack-entries`
and `set-max-listpack-value`. This saves memory for small sets compared to using a hashtable.

Sets with only integers, even very small sets, are still intset encoded (up to 1G
limit, etc.). Larger sets are hashtable encoded.

This PR increments the RDB version, and has an effect on OBJECT ENCODING

Possible conversions when elements are added:

    intset -> listpack
    listpack -> hashtable
    intset -> hashtable

Note: No conversion happens when elements are deleted. If all elements are
deleted and then added again, the set is deleted and recreated, thus implicitly
converted to a smaller encoding.
2022-11-09 19:50:07 +02:00
Viktor Söderqvist
07d187066a
Deprecate QUIT (#11439)
Clients should not use this command.
Instead, clients should simply close the connection when they're not used anymore.
Terminating a connection on the client side is preferable, as it eliminates `TIME_WAIT`
lingering sockets on the server side.
2022-11-09 14:41:00 +02:00
Oran Agra
ccaef5c923
diskless master, avoid bgsave child hung when fork parent crashes (#11463)
During a diskless sync, if the master main process crashes, the child would
have hung in `write`. This fix closes the read fd on the child side, so that if the
parent crashes, the child will get a write error and exit.

This change also fixes disk-based replication, BGSAVE and AOFRW.
In that case the child wouldn't have been hang, it would have just kept
running until done which may be pointless.

There is a certain degree of risk here. in case there's a BGSAVE child that could
maybe succeed and the parent dies for some reason, the old code would have let
the child keep running and maybe succeed and avoid data loss.
On the other hand, if the parent is restarted, it would have loaded an old rdb file
(or none), and then the child could reach the end and rename the rdb file (data
conflicting with what the parent has), or also have a race with another BGSAVE
child that the new parent started.

Note that i removed a comment saying a write error will be ignored in the child
and handled by the parent (this comment was very old and i don't think relevant).
2022-11-09 10:02:18 +02:00
Oran Agra
3e112d4610
Use jemalloc by default also on ARM (#11407)
Till now Redis attempted to avoid using jemalloc on ARM, but didn't do that properly (missing armv8l and aarch64), so in fact we did you jemalloc on these without a problem.

Side notes:

Some ARM platforms, which share instruction set and can share binaries (docker images), may have different page size, and apparently jemalloc uses the page size of the build machine as the maximum page size to be supported by the build.
see https://github.com/redis-stack/redis-stack/issues/187

To work around that, when building for ARM, one can change the maximum page size to 64k (or greater if present on the build machine) In recent versions of jemalloc, this should not have any severe side effects (like VM map fragmentation), see:
https://github.com/jemalloc/jemalloc/issues/467
https://github.com/redis/redis/pull/11170#issuecomment-1236265230

To do that, one can use:
```
JEMALLOC_CONFIGURE_OPTS="--with-lg-page=16" make
```

Besides that, this PR fixes a messy makefile condition that was created
here: f30b18f4de
2022-11-07 19:11:12 +02:00
yancz2000
1f2456389b
Unify repeated code in redis-check-aof (#11456) 2022-11-06 14:49:55 +02:00
Hanif Ariffin
0cbe10e892
Remove redundant calls to update refcount of shared integers (#11479)
Since they're created with makeObjectShared, then incrRefCount on them is a NOP.

Signed-off-by: Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com>
2022-11-06 08:33:28 +02:00
Binbin
fac188b49d
Introduce socket shutdown into connection type, used if a fork is active (#11376)
Introduce socket `shutdown()` into connection type, and use it
on normal socket if a fork is active. This allows us to close
client connections when there are child processes sharing the
file descriptors.

Fixes #10077. The reason is that since the `fork()` child is holding
the file descriptors, the `close` in `unlinkClient -> connClose`
isn't sufficient. The client will not realize that the connection is
disconnected until the child process ends.

Let's try to be conservative and only use shutdown when the fork is active.
2022-11-04 18:46:37 +02:00
Madelyn Olson
c337c0a8a4
Retain ACL categories used to generate ACL for displaying them later (#11224)
Retain ACL categories used to generate ACL for displaying them later
2022-11-03 10:14:56 -07:00
Binbin
8764611c8a
Block some specific characters in module command names (#11434)
Today we don't place any specific restrictions on module command names.
This can cause ambiguous scenarios. For example, someone might name a
command like "module|feature" which would be incorrectly parsed by the
ACL system as a subcommand.

In this PR, we will block some chars that we know can mess things up.
Specifically ones that can appear ok at first and cause problems in some
cases (we rather surface the issue right away).

There are these characters:
 * ` ` (space) - issues with old inline protocol.
 * `\r`, `\n` (newline) - can mess up the protocol on acl error replies.
 * `|` - sub-commands.
 * `@` - ACL categories
 * `=`, `,` - info and client list fields.

note that we decided to leave `:` out as it's handled by `getSafeInfoString`
and is more likely to already been used by existing modules.
2022-11-03 13:19:49 +02:00
Wen Hui
7395e370e6
Fix XSETID with max_deleted_entry_id issue (#11444)
Resolve an edge case where the ID of a stream is updated retroactively
to an ID lower than the already set max_deleted_entry_id.

Currently, if we have command as below:
**xsetid mystream 1-1 MAXDELETEDID 1-2**
Then we will get the following error:
**(error) ERR The ID specified in XSETID is smaller than the provided max_deleted_entry_id**
Becuase the provided MAXDELETEDID 1-2 is greated than input last-id: 1-1

Then we could assume there is a similar situation:
step 1: we add three items in the mystream

**127.0.0.1:6381> xadd mystream 1-1 a 1
"1-1"
127.0.0.1:6381> xadd mystream 1-2 b 2
"1-2"
127.0.0.1:6381> xadd mystream 1-3 c 3
"1-3"**

step 2: we could check the mystream infomation as below:
**127.0.0.1:6381> xinfo stream mystream
 1) "length"
 2) (integer) 3
 7) "last-generated-id"
 8) "1-3"
 9) "max-deleted-entry-id"
10) "0-0"

step 3: we delete the item id 1-2 and 1-3 as below:
**127.0.0.1:6381> xdel mystream 1-2
(integer) 1
127.0.0.1:6381> xdel mystream 1-3
(integer) 1**

step 4: we check the mystream information:
127.0.0.1:6381> xinfo stream mystream
 1) "length"
 2) (integer) 1
 7) "last-generated-id"
 8) "1-3"
 9) "max-deleted-entry-id"
10) "1-3"

we could notice that the **max-deleted-entry-id update to 1-3**, so right now, if we just run:
**xsetid mystream 1-2** 
the above command has the same effect with **xsetid mystream 1-2  MAXDELETEDID 1-3**

So we should return an error to the client that **(error) ERR The ID specified in XSETID is smaller than current max_deleted_entry_id**
2022-11-02 16:16:16 +02:00
Wen Hui
fea9bbbe0f
Fix command BITFIELD_RO and BITFIELD argument json file, add some test cases for them (#11445)
According to the source code, the commands can be executed with only key name,
and no GET/SET/INCR operation arguments.
change the docs to reflect that by marking these arguments as optional.
also add tests.
2022-11-02 15:15:12 +02:00
Binbin
e632e62e68
Print IP and port on cluster bus message sanity check (#11443)
* Print IP and port on cluster bus message sanity check

Add a print statement to indicate which IP/port is sending
the error messages. That way we can at least check to see
if it is a node in the cluster or some other nefarious nodes.

It is proposed in #11339.

Unrelated changes: the return check for connAddrPeerName should
be -1 instead of C_ERR, although the value of C_ERR is also -1.

Co-authored-by: Madelyn Olson <34459052+madolson@users.noreply.github.com>
2022-11-01 19:27:30 -07:00
Brennan
47c493e070
Re-design cluster link send buffer to improve memory management (#11343)
Re-design cluster link send queue to improve memory management
2022-11-01 19:26:44 -07:00
xbasel
5b102e2339
Don't process file events if AE_FILE_EVENTS isn't set. (#11428)
All current usage of the function are correct, but in the future it might change.
2022-10-29 16:24:12 -07:00
Moti Cohen
c0d7226274
Refactor and (internally) rebrand from pause-clients to pause-actions (#11098)
Renamed from "Pause Clients" to "Pause Actions" since the mechanism can pause
several actions in redis, not just clients (e.g. eviction, expiration).

Previously each pause purpose (which has a timeout that's tracked separately from others purposes),
also implicitly dictated what it pauses (reads, writes, eviction, etc). Now it is explicit, and
the actions that are paused (bit flags) are defined separately from the purpose.

- Previously, when using feature pause-client it also implicitly means to make the server static:
  - Pause replica traffic
  - Pauses eviction processing
  - Pauses expire processing

Making the server static is used also for failover and shutdown. This PR internally rebrand
pause-client API to become pause-action API. It also Simplifies pauseClients structure
by replacing pointers array with static array.

The context of this PR is to add another trigger to pause-client which will activated in case
of OOM as throttling mechanism ([see here](https://github.com/redis/redis/issues/10907)).
In this case we want only to pause client, and eviction actions.
2022-10-27 11:57:04 +03:00
Shaya Potter
38028dab8d
RM_Call - only enforce OOM on scripts if 'M' flag is sent (#11425)
RM_Call is designed to let modules call redis commands disregarding the
OOM state (the module is responsible to declare its command flags to redis,
or perform the necessary checks).
The other (new) alternative is to pass the "M" flag to RM_Call so that redis can
OOM reject commands implicitly.

However, Currently, RM_Call enforces OOM on scripts (excluding scripts that
declared `allow-oom`) in all cases, regardless of the RM_Call "M" flag being present.

This PR fixes scripts to be consistent with other commands being executed by RM_Call.
It modifies the flow in effect treats scripts as if they if they have the ALLOW_OOM script
flag, if the "M" flag is not passed (i.e. no OOM checking is being performed by RM_Call,
so no OOM checking should be done on script).

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-10-27 09:29:43 +03:00
AntiTopQuark
af43617122
fix: reducing duplicate header file definitions (#11437)
Reducing duplicate header file definitions <sys/resource.h>
2022-10-26 08:45:19 -07:00
Wen Hui
7c3916ae6e
Fix command GEOHASH and GEOPOS argument doc, mark member as optional (#11417)
These commands take a list of members, which can be empty (i.e. running
the command with just a key name).
this always results in an empty array reply, so it doesn't make much sense,
but changing it is a breaking change.

This PR fixes the documentation, making the member field as optional, just makes
sure the command format documentation is consistent with the command behavior.

The command format will be:

127.0.0.1:6381> GEOPOS key [member [member ...]]
127.0.0.1:6381> GEOHASH key [member [member ...]]
2022-10-25 14:26:08 +03:00
guybe7
f8970fdbfa
Cleanup: Remove redundant arg from moduleCreateArgvFromUserFormat (#11426)
We do not need to return the length of argv because it is equal to argc, which we return anyway.
This change makes the code cleaner and adds a comment to explain something that might not be immediately clear.
2022-10-24 18:30:16 +03:00
guybe7
737a090511
Set errno in case XADD with partial ID fails (#11424)
This is a rare failure mode of a new feature of redis 7 introduced in #9217
(when the incremental part of the ID overflows).
Till now, the outcome of that error was undetermined (could easily result in
`Elements are too large to be stored` wrongly, due to unset `errno`).
2022-10-24 18:27:56 +03:00
Moti Cohen
bd23b15ad7
Fix sentinel function that compares hostnames (if failed resolve) (#11419)
Funcion sentinelAddrEqualsHostname() of sentinel makes DNS resolve
and based on it determines if two IP addresses are equal. Now, If the
DNS resolve command fails, the function simply returns 0, even if the
hostnames are identical.

This might become an issue in case of failover such that sentinel might
receives from Redis instance, response to regular INFO query it sent,
and wrongly decide that the instance is pointing to is different leader
than the one recorded because of this function, yet hostnames are
identical. In turn sentinel disconnects the connection between sentinel
and valid slave which leads to -failover-abort-no-good-slave.
See issue #11241.

I managed to reproduce only part of the flow in which the function
return wrong result and trigger +fix-slave-config.

The fix is even if the function failed to resolve then compare based on
hostnames. That is our best effort as long as the server is unavailable
for some reason. It is fine since Redis instance cannot have multiple
hostnames for a given setup
2022-10-23 16:00:47 +03:00
qetu3790
20df1424a2
Fix wrong tips when the user pass wrong # of arguments to redis.set_repl(). (#11415)
redis.set_repl() needs one arg, but the tips says two.
2022-10-23 15:06:58 +03:00
Binbin
9e1b879f5b
Make PFMERGE source key optional in docs, add tests with one input key, add tests on missing source keys (#11205)
The following two cases will create an empty destkey HLL:
1. called with no source keys, like `pfmerge destkey`
2. called with non-existing source keys, like `pfmerge destkey non-existing-source-key`

In the first case, in `PFMERGE`, the dest key is actually one of the source keys too.
So `PFMERGE k1 k2` is equivalent to `SUNIONSTORE k1 k1 k2`,
and `PFMERGE k1` is equivalent to `SUNIONSTORE k1 k1`.
So the first case is reasonable, the source key is actually optional.

And the second case, `PFMERGE` on missing keys should succeed and create an empty dest.
This is consistent with `PFCOUNT`, and also with `SUNIONSTORE`, no need to change.
2022-10-22 20:41:17 +03:00
sundb
6dd213558b
Fix crash due to to reuse iterator entry after list deletion in module (#11383)
In the module, we will reuse the list iterator entry for RM_ListDelete, but `listTypeDelete` will only update
`quicklistEntry->zi` but not `quicklistEntry->node`, which will result in `quicklistEntry->node` pointing to
a freed memory address if the quicklist node is deleted. 

This PR sync `key->u.list.index` and `key->u.list.entry` to list iterator after `RM_ListDelete`.

This PR also optimizes the release code of the original list iterator.

Co-authored-by: Viktor Söderqvist <viktor@zuiderkwast.se>
2022-10-22 20:36:50 +03:00
FutabaRio
6debeb3779
fix the size of variable merge_sz in quicklist.c (#11285)
11 was the size of header/trailer in the old structure Ziplist,
but now the size of header/trailer in the new structure Listpack should be 7.
2022-10-19 15:11:28 +03:00
guybe7
b57fd01064
Blocked module clients should be aware when a key is deleted (#11310)
The use case is a module that wants to implement a blocking command on a key that
necessarily exists and wants to unblock the client in case the key is deleted (much like
what we implemented for XREADGROUP in #10306)

New module API:
* RedisModule_BlockClientOnKeysWithFlags

Flags:
* REDISMODULE_BLOCK_UNBLOCK_NONE
* REDISMODULE_BLOCK_UNBLOCK_DELETED

### Detailed description of code changes

blocked.c:
1. Both module and stream functions are called whether the key exists or not, regardless of
  its type. We do that in order to allow modules/stream to unblock the client in case the key
  is no longer present or has changed type (the behavior for streams didn't change, just code
  that moved into serveClientsBlockedOnStreamKey)
2. Make sure afterCommand is called in serveClientsBlockedOnKeyByModule, in order to propagate
  actions from moduleTryServeClientBlockedOnKey.
3. handleClientsBlockedOnKeys: call propagatePendingCommands directly after lookupKeyReadWithFlags
  to prevent a possible lazy-expire DEL from being mixed with any command propagated by the
  preceding functions.
4. blockForKeys: Caller can specifiy that it wants to be awakened if key is deleted.
   Minor optimizations (use dictAddRaw).
5. signalKeyAsReady became signalKeyAsReadyLogic which can take a boolean in case the key is deleted.
  It will only signal if there's at least one client that awaits key deletion (to save calls to
  handleClientsBlockedOnKeys).
  Minor optimizations (use dictAddRaw)

db.c:
1. scanDatabaseForDeletedStreams is now scanDatabaseForDeletedKeys and will signalKeyAsReady
  for any key that was removed from the database or changed type. It is the responsibility of the code
  in blocked.c to ignore or act on deleted/type-changed keys.
2. Use the new signalDeletedKeyAsReady where needed

blockedonkey.c + tcl:
1. Added test of new capabilities (FSL.BPOPGT now requires the key to exist in order to work)
2022-10-18 19:50:02 +03:00
Meir Shpilraien (Spielrein)
b43f254813
Avoid saving module aux on RDB if no aux data was saved by the module. (#11374)
### Background

The issue is that when saving an RDB with module AUX data, the module AUX metadata
(moduleid, when, ...) is saved to the RDB even though the module did not saved any actual data.
This prevent loading the RDB in the absence of the module (although there is no actual data in
the RDB that requires the module to be loaded).

### Solution

The solution suggested in this PR is that module AUX will be saved on the RDB only if the module
actually saved something during `aux_save` function.

To support backward compatibility, we introduce `aux_save2` callback that acts the same as
`aux_save` with the tiny change of avoid saving the aux field if no data was actually saved by
the module. Modules can use the new API to make sure that if they have no data to save,
then it will be possible to load the created RDB even without the module.

### Concerns

A module may register for the aux load and save hooks just in order to be notified when
saving or loading starts or completed (there are better ways to do that, but it still possible
that someone used it).

However, if a module didn't save a single field in the save callback, it means it's not allowed
to read in the read callback, since it has no way to distinguish between empty and non-empty
payloads. furthermore, it means that if the module did that, it must never change it, since it'll
break compatibility with it's old RDB files, so this is really not a valid use case.

Since some modules (ones who currently save one field indicating an empty payload), need
to know if saving an empty payload is valid, and if Redis is gonna ignore an empty payload
or store it, we opted to add a new API (rather than change behavior of an existing API and
expect modules to check the redis version)

### Technical Details

To avoid saving AUX data on RDB, we change the code to first save the AUX metadata
(moduleid, when, ...) into a temporary buffer. The buffer is then flushed to the rio at the first
time the module makes a write operation inside the `aux_save` function. If the module saves
nothing (and `aux_save2` was used), the entire temporary buffer is simply dropped and no
data about this AUX field is saved to the RDB. This make it possible to load the RDB even in
the absence of the module.

Test was added to verify the fix.
2022-10-18 19:45:46 +03:00
Shuning
20d286f77e
keyIsExpired checks server.loading before calling getExpire (#11393)
Seems excessive to call getExpire if we don't need it.
This can maybe have some speedup on AOF file loading (saving a dictFind call)

Co-authored-by: lvshuning <lvshuning@meituan.com>
2022-10-18 13:55:49 +03:00
DarrenJiang13
ba1f09d3fe
fix malloc macro in listpack.c (#11398)
fix some malloc macros in `listpack.c`.
listpack has it's own malloc aliases, but in some places normal redis malloc calls have slipped in.
2022-10-18 08:28:25 +03:00
Binbin
a9d561afa5
Bump codespell from 2.2.1 to 2.2.2 in /.codespell (#11399)
And fix a few newly detected typo.
Closes #11394
2022-10-18 08:24:30 +03:00
Shaya Potter
3193f086ca
Unify ACL failure error messaging. (#11160)
Motivation: for applications that use RM ACL verification functions, they would
want to return errors back to the user, in ways that are consistent with Redis.
While investigating how we should return ACL errors to the user, we realized that
Redis isn't consistent, and currently returns ACL error strings in 3 primary ways.

[For the actual implications of this change, see the "Impact" section at the bottom]

1. how it returns an error when calling a command normally
   ACL_DENIED_CMD -> "this user has no permissions to run the '%s' command"
   ACL_DENIED_KEY -> "this user has no permissions to access one of the keys used as arguments"
   ACL_DENIED_CHANNEL -> "this user has no permissions to access one of the channels used as arguments"

2. how it returns an error when calling via 'acl dryrun' command
   ACL_DENIED_CMD ->  "This user has no permissions to run the '%s' command"
   ACL_DENIED_KEY -> "This user has no permissions to access the '%s' key"
   ACL_DENIED_CHANNEL -> "This user has no permissions to access the '%s' channel"

3. how it returns an error via RM_Call (and scripting is similar).
   ACL_DENIED_CMD -> "can't run this command or subcommand";
   ACL_DENIED_KEY -> "can't access at least one of the keys mentioned in the command arguments";
   ACL_DENIED_CHANNEL -> "can't publish to the channel mentioned in the command";
   
   In addition, if one wants to use RM_Call's "dry run" capability instead of the RM ACL
   functions directly, one also sees a different problem than it returns ACL errors with a -ERR,
   not a -PERM, so it can't be returned directly to the caller.

This PR modifies the code to generate a base message in a common manner with the ability
to set verbose flag for acl dry run errors, and keep it unset for normal/rm_call/script cases

```c
sds getAclErrorMessage(int acl_res, user *user, struct redisCommand *cmd, sds errored_val, int verbose) {
    switch (acl_res) {
    case ACL_DENIED_CMD:
        return sdscatfmt(sdsempty(), "User %S has no permissions to run "
                                     "the '%S' command", user->name, cmd->fullname);
    case ACL_DENIED_KEY:
        if (verbose) {
            return sdscatfmt(sdsempty(), "User %S has no permissions to access "
                                         "the '%S' key", user->name, errored_val);
        } else {
            return sdsnew("No permissions to access a key");
        }
    case ACL_DENIED_CHANNEL:
        if (verbose) {
            return sdscatfmt(sdsempty(), "User %S has no permissions to access "
                                         "the '%S' channel", user->name, errored_val);
        } else {
            return sdsnew("No permissions to access a channel");
        }
    }
```

The caller can append/prepend the message (adding NOPERM for normal/RM_Call or indicating it's within a script).

Impact:
- Plain commands, as well as scripts and RM_Call now include the user name.
- ACL DRYRUN remains the only one that's verbose (mentions the offending channel or key name)
- Changes RM_Call ACL errors from being a `-ERR` to being `-NOPERM` (besides for textual changes)
  **This somewhat a breaking change, but it only affects the RM_Call with both `C` and `E`, or `D`**
- Changes ACL errors in scripts textually from being
  `The user executing the script <old non unified text>`
  to
  `ACL failure in script: <new unified text>`
2022-10-16 09:01:37 +03:00
Meir Shpilraien (Spielrein)
56f97bfa5f
Fix wrong replication on cluster slotmap changes with module KSN propagation (#11377)
As discussed on #11084, `propagatePendingCommands` should happened after the del
notification is fired so that the notification effect and the `del` will be replicated inside MULTI EXEC.

Test was added to verify the fix.
2022-10-16 08:30:01 +03:00
David CARLIER
871cc200a0
Fixes build warning when CACHE_LINE_SIZE is already defined. (#11389)
* Fixes build warning when CACHE_LINE_SIZE is already defined
* Fixes wrong CACHE_LINE_SIZE on some FreeBSD systems where it could be set to 128 (e.g. on MIPS)
* Fixes wrong CACHE_LINE_SIZE on Apple M1 (use 128 instead of 64)

Wrong cache line size in that case can some false sharing of array elements between threads, see #10892
2022-10-16 07:51:44 +03:00
filipe oliveira
29380ff77d
optimizing d2string() and addReplyDouble() with grisu2: double to string conversion based on Florian Loitsch's Grisu-algorithm (#10587)
All commands / use cases that heavily rely on double to a string representation conversion,
(e.g. meaning take a double-precision floating-point number like 1.5 and return a string like "1.5" ),
could benefit from a performance boost by swapping snprintf(buf,len,"%.17g",value) by the
equivalent [fpconv_dtoa](https://github.com/night-shift/fpconv) or any other algorithm that ensures
100% coverage of conversion.

This is a well-studied topic and Projects like MongoDB. RedPanda, PyTorch leverage libraries
( fmtlib ) that use the optimized double to string conversion underneath.


The positive impact can be substantial. This PR uses the grisu2 approach ( grisu explained on
https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf section 5 ). 

test suite changes:
Despite being compatible, in some cases it produces a different result from printf, and some tests
had to be adjusted.
one case is that `%.17g` (which means %e or %f which ever is shorter), chose to use `5000000000`
instead of 5e+9, which sounds like a bug?
In other cases, we changed TCL to compare numbers instead of strings to ignore minor rounding
issues (`expr 0.8 == 0.79999999999999999`)
2022-10-15 12:17:41 +03:00
C Charles
9ab873d9d3
MIGTATE with AUTH that contains "keys" is getting wrong key names in migrateGetKeys, leads to ACL errors (#11253)
When using the MIGRATE, with a destination Redis that has the user name or password set to the string "keys",
Redis would have determine the wrong set of key names the command is gonna access.
This lead to ACL returning wrong authentication result.

Destination instance:
```
127.0.0.1:6380> acl setuser default >keys
OK
127.0.0.1:6380> acl setuser keys on nopass ~* &* +@all
OK
```

Source instance:
```
127.0.0.1:6379> set a 123
OK
127.0.0.1:6379> acl setuser cc on nopass ~a* +@all
OK
127.0.0.1:6379> auth cc 1
OK
127.0.0.1:6379> migrate 127.0.0.1 6380 "" 0 1000 auth keys keys a
(error) NOPERM this user has no permissions to access one of the keys used as arguments
127.0.0.1:6379> migrate 127.0.0.1 6380 "" 0 1000 auth2 keys pswd keys a
(error) NOPERM this user has no permissions to access one of the keys used as arguments
```

Using `acl dryrun` we know that the parameters of `auth` and `auth2` are mistaken for the `keys` option.
```
127.0.0.1:6379> acl dryrun cc migrate whatever whatever "" 0 1000 auth keys keys a
"This user has no permissions to access the 'keys' key"
127.0.0.1:6379> acl dryrun cc migrate whatever whatever "" 0 1000 auth2 keys pswd keys a
"This user has no permissions to access the 'pswd' key"
```

Fix the bug by editing db.c/migrateGetKeys function, which finds the `keys` option and all the keys following.
2022-10-13 15:03:54 +03:00
Oran Agra
dd60c6c8d3
Improve linux overcommit check and warning (#11357)
1. show the overcommit warning when overcommit is disabled (2),
   not just when it is set to heuristic (0).
2. improve warning text to mention the issue with jemalloc causing VM
   mapping fragmentation when set to 2.
2022-10-13 13:05:20 +03:00
Meir Shpilraien (Spielrein)
eb6accad40
Fix crash on RM_Call inside module load (#11346)
PR #9320 introduces initialization order changes. Now cluster is initialized after modules.
This changes causes a crash if the module uses RM_Call inside the load function
on cluster mode (the code will try to access `server.cluster` which at this point is NULL).

To solve it, separate cluster initialization into 2 phases:
1. Structure initialization that happened before the modules initialization
2. Listener initialization that happened after.

Test was added to verify the fix.
2022-10-12 13:09:51 +03:00
Nikita Tolkachev
4c53bdc241
Fix typo in scan commands complexity statement (#11370)
remove double period at the end of sentence.
2022-10-11 09:17:55 +03:00
Binbin
1cc511d7cb
Fix TIME command microseconds overflow under 32-bits (#11368)
The old `server.unixtime*1000000` will overflow in 32-bits.
This was introduced in #10300 (not released).
2022-10-09 18:02:37 +03:00
yancz2000
fe0550a4a6
Fix redis-benchmark hang when it fails to connect to redis (#11366)
Forgot to start redis-server when testing performance.
When opening the benchmark for testing, it will always be stuck,
and the process cpu will reach 100%.
2022-10-09 12:17:36 +03:00
Binbin
35b3fbd90c
Freeze time sampling during command execution, and scripts (#10300)
Freeze time during execution of scripts and all other commands.
This means that a key is either expired or not, and doesn't change
state during a script execution. resolves #10182

This PR try to add a new `commandTimeSnapshot` function.
The function logic is extracted from `keyIsExpired`, but the related
calls to `fixed_time_expire` and `mstime()` are removed, see below.

In commands, we will avoid calling `mstime()` multiple times
and just use the one that sampled in call. The background is,
e.g. using `PEXPIRE 1` with valgrind sometimes result in the key
being deleted rather than expired. The reason is that both `PEXPIRE`
command and `checkAlreadyExpired` call `mstime()` separately.

There are other more important changes in this PR:
1. Eliminate `fixed_time_expire`, it is no longer needed. 
   When we want to sample time we should always use a time snapshot. 
   We will use `in_nested_call` instead to update the cached time in `call`.
2. Move the call for `updateCachedTime` from `serverCron` to `afterSleep`.
    Now `commandTimeSnapshot` will always return the sample time, the
    `lookupKeyReadWithFlags` call in `getNodeByQuery` will get a outdated
    cached time (because `processCommand` is out of the `call` context).
    We put the call to `updateCachedTime` in `aftersleep`.
3. Cache the time each time the module lock Redis.
    Call `updateCachedTime` in `moduleGILAfterLock`, affecting `RM_ThreadSafeContextLock`
    and `RM_ThreadSafeContextTryLock`

Currently the commandTimeSnapshot change affects the following TTL commands:
- SET EX / SET PX
- EXPIRE / PEXPIRE
- SETEX / PSETEX
- GETEX EX / GETEX PX
- TTL / PTTL
- EXPIRETIME / PEXPIRETIME
- RESTORE key TTL

And other commands just use the cached mstime (including TIME).

This is considered to be a breaking change since it can break a script
that uses a loop to wait for a key to expire.
2022-10-09 08:18:34 +03:00
Meir Shpilraien (Spielrein)
d2ad01ab3e
RedisModule_ResetDataset should not clear the functions. (#11268)
As mentioned on docs, `RM_ResetDataset` Performs similar operation to FLUSHALL.
As FLUSHALL do not clean the function, `RM_ResetDataset` should not clean the functions
as well.
2022-10-09 07:42:21 +03:00
Oran Agra
34e70c13c9
fix arm build warning due to new compiler optimizations (#11362)
Build fails with warnings in ARM CI after adding more aggressive optimizations (#11350)
probably a result of more aggressive inlining

```
ziplist.c: In function ‘pop.constprop’:
ziplist.c:1770:13: error: ‘vlong’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
             printf("%lld", vlong);
             ^~~~~~~~~~~~~~~~~~~~~
```

```
listpack.c: In function ‘lpInsert.constprop’:
listpack.c:406:9: error: argument 2 null where non-null expected [-Werror=nonnull]
         memcpy(buf+1,s,len);
         ^~~~~~~~~~~~~~~~~~~
```
2022-10-07 21:24:54 +03:00
aradz44
8e19415343
Added authentication failure and access denied metrics (#11288)
Added authentication failure and access denied metrics
2022-10-07 10:19:34 -07:00
Moti Cohen
210ad2e4db
Improve BLMPOP/BZMPOP/WAIT timeout overflow handling and error messages (#11338)
Refine getTimeoutFromObjectOrReply() out-of-range check.

Timeout is parsed (and verifies out of range) as double and
multiplied by 1000, added mstime() and stored in long-long
which might lead to out-of-range value of long-long.

Co-authored-by: moticless <moticless@github.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: Ozan Tezcan <ozantezcan@gmail.com>
2022-10-06 12:12:05 +03:00
Ozan Tezcan
b08ebff31f
Pass -flto flag to the linker (#11350)
Currently, we add -flto to the compile flags only. We are supposed
to add it to the linker flags as well. Clang build fails because of this.

Added a change to add -flto to REDIS_CFLAGS and REDIS_LDFLAGS
if the build optimization flag is -O3. (noopt build will not use -flto)
2022-10-06 11:26:19 +03:00
Madelyn Olson
663fbd3459
Stabilize cluster hostnames tests (#11307)
This PR introduces a couple of changes to improve cluster test stability:
1. Increase the cluster node timeout to 3 seconds, which is similar to the
   normal cluster tests, but introduce a new mechanism to increase the ping
   period so that the tests are still fast. This new config is a debug config.
2. Set `cluster-replica-no-failover yes` on a wider array of tests which are
   sensitive to failovers. This was occurring on the ARM CI.
2022-10-03 09:25:16 +03:00
David CARLIER
ff80809053
register debug support on illumos/solaris. (#11335) 2022-10-02 16:36:31 +03:00
Maria Markova
3469c6509c
Change compiler optimizations to -O3 -flto (#11207)
Optimization update from -O2 to -O3 -flto gives up to 5% performance gain
in 'redis-benchmarks-spec-client-runner' tests geomean where GCC 9.4.0 is used for build

* Fix for false-positive warning in bitops.c
   Warning appeared with O3, on CentOS during inlininig procedure
* Fixed unitialized streamID within streamTrim() (#1)

Co-authored-by: filipe oliveira <filipecosta.90@gmail.com>
2022-10-02 15:15:14 +03:00
Binbin
3c02d1acc4
code, typo and comment cleanups (#11280)
- fix `the the` typo
- `LPOPRPUSH` does not exist, should be `RPOPLPUSH`
- `CLUSTER GETKEYINSLOT` 's time complexity should be O(N)
- `there bytes` should be `three bytes`, this closes #11266
- `slave` word to `replica` in log, modified the front and missed the back
- remove useless aofReadDiffFromParent in server.h
- `trackingHandlePendingKeyInvalidations` method adds a void parameter
2022-10-02 13:56:45 +03:00
Huang Zhw
2804eefc58
fix some commands json file (#11201)
- BITOP: turn argument `operation` from string to oneof
- CLIENT KILL: turn argument `skipme` from string to oneof
- COMMAND GETKEYS / GETKEYSANDFLAGS: change arguments to optional, and change arity to -3 (fixes regression in redis 7.0)
- CLIENT PAUSE: this command was added in v3.0.0
2022-10-02 10:52:13 +03:00
Binbin
ed4c432ec5
Update CLUSTER NODES help message (#11341)
We will always show the bus-port, and if the node hostname exists, it will also show it.
2022-09-30 06:24:44 -07:00
Huang Zhw
f8e2279e3a
Add redis-cli hints to ACL DRYRUN, COMMAND GETKEYS, COMMAND GETKEYSANDFLAGS (#11232)
Better redis-cli hints for commands that take other commands as arguments.

```
command getkeysandflags hello [protover [AUTH username password]]
acl dryrun user hello [protover [AUTH username password]]
```
2022-09-29 09:49:53 +03:00
Wen Hui
e21c059967
Update sentinel-config.json to consistent with Config Get and Set operation (#11334)
The sentinel CONFIG GET command doesn't support multiple arguments, but the json file did.
remove that.
2022-09-29 09:33:37 +03:00
Meir Shpilraien (Spielrein)
0bf90d9443
Avoid crash on crash report when a bad function pointer was called (#11298)
If Redis crashes due to calling an invalid function pointer,
the `backtrace` function will try to dereference this invalid pointer
which will cause a crash inside the crash report and will kill
the processes without having all the crash report information.

Example:

```
=== REDIS BUG REPORT START: Cut & paste starting from here ===
198672:M 19 Sep 2022 18:06:12.936 # Redis 255.255.255 crashed by signal: 11, si_code: 1
198672:M 19 Sep 2022 18:06:12.936 # Accessing address: 0x1
198672:M 19 Sep 2022 18:06:12.936 # Crashed running the instruction at: 0x1
// here the processes is crashing
```

This PR tries to fix this crash be:
1. Identify the issue when it happened.
2. Replace the invalid pointer with a pointer to some dummy function
   so that `backtrace` will not crash.

I identification is done by comparing `eip` to `info->si_addr`, if they
are the same we know that the crash happened on the same address it tries to
accesses and we can conclude that it tries to call and invalid function pointer.

To replace the invalid pointer we introduce a new function, `setMcontextEip`,
which is very similar to `getMcontextEip` and it knows to set the Eip for the
different supported OS's. After printing the trace we retrieve the old `Eip` value.
2022-09-29 08:58:58 +03:00
sundb
f106beebfa
Fix the missing server.dirty increment and redundant signalModifiedKey in serveClientBlockedOnList (#11326)
Mainly fix two minor bug
1. When handle BL*POP/BLMOVE commands with blocked clients, we should increment server.dirty.
2.  `listPopRangeAndReplyWithKey()` in `serveClientBlockedOnList()` should not repeat calling
   `signalModifiedKey()` which has been called when an element was pushed on the list.
   (was skipped in all bpop commands, other than blmpop) 

Other optimization
add `signal` param for `listElementsRemoved` to skip `signalModifiedKey()` to unify all pop operation.

Unifying all pop operations also prepares us for #11303, so that we can avoid having to deal with the
conversion from quicklist to listpack() in various places when the list shrinks.
2022-09-28 21:07:38 +03:00
guybe7
3330ea1864
RM_CreateCommand should not set CMD_KEY_VARIABLE_FLAGS automatically (#11320)
The original idea behind auto-setting the default (first,last,step) spec was to use
the most "open" flags when the user didn't provide any key-spec flags information.

While the above idea is a good approach, it really makes no sense to set
CMD_KEY_VARIABLE_FLAGS if the user didn't provide the getkeys-api flag:
in this case there's not way to retrieve these variable flags, so what's the point?

Internally in redis there was code to ignore this already, so this fix doesn't change
redis's behavior, it only affects the output of COMMAND command.
2022-09-28 14:15:07 +03:00
Phoeniwx
c0725abfbb
fix: redis-cli --memkeys-samples add check lastarg (#11269)
doing redis-cli --memkeys-samples without any additional arguments
would have lead to a crash of the cli.
2022-09-28 13:38:20 +03:00
guybe7
bd40d3158b
Remove redundant arity checks in XINFO (#11331)
The arity in the JSON files of the subcommands reneder this
code unreachable
2022-09-28 12:46:54 +03:00
Steffen Moser
6aab4cb736
Fixing compilation by removing flock() when compiling on Solaris (#11327)
SunOS/Solaris and its relatives don't support the flock() function.
While "redis" has been excluding setting up the lock using flock() on the cluster
configuration file when compiling under Solaris, it was still using flock() in the
unlock call while shutting down. 

This pull request eliminates the flock() call also in the unlocking stage
for Oracle Solaris and its relatives.

Fix compilation regression from #10912
2022-09-27 16:20:13 +03:00
Ozan Tezcan
18920813a9
Ignore RM_Call deny-oom flag if maxmemory is zero (#11319)
If a command gets an OOM response and then if we set maxmemory to zero
to disable the limit, server.pre_command_oom_state never gets updated
and it stays true. As RM_Call() calls with "respect deny-oom" flag checks
server.pre_command_oom_state, all calls will fail with OOM.

Added server.maxmemory check in RM_Call() to process deny-oom flag
only if maxmemory is configured.
2022-09-26 10:03:45 +03:00
Binbin
1de675b3d5
Fix CLUSTER SHARDS showing empty hostname (#11297)
* Fix CLUSTER SHARDS showing empty hostname

In #10290, we changed clusterNode hostname from `char*`
to `sds`, and the old `node->hostname` was changed to
`sdslen(node->hostname)!=0`.

But in `addNodeDetailsToShardReply` it is missing.
It results in the return of an empty string hostname
in CLUSTER SHARDS command if it unavailable.

Like this (note that we listed it as optional in the doc):
```
 9) "hostname"
10) ""
```
2022-09-22 11:39:34 -07:00
Shaya Potter
6e993a5dfa
Add RM_SetContextUser to support acl validation in RM_Call (and scripts) (#10966)
Adds a number of user management/ACL validaiton/command execution functions to improve a
Redis module's ability to enforce ACLs correctly and easily.

* RM_SetContextUser - sets a RedisModuleUser on the context, which RM_Call will use to both
  validate ACLs (if requested and set) as well as assign to the client so that scripts executed via
  RM_Call will have proper ACL validation.
* RM_SetModuleUserACLString - Enables one to pass an entire ACL string, not just a single OP
  and have it applied to the user
* RM_GetModuleUserACLString - returns a stringified version of the user's ACL (same format as dump
  and list).  Contains an optimization to cache the stringified version until the underlying ACL is modified.
* Slightly re-purpose the "C" flag to RM_Call from just being about ACL check before calling the
  command, to actually running the command with the right user, so that it also affects commands
  inside EVAL scripts. see #11231
2022-09-22 16:29:00 +03:00
Oran Agra
6d21560190
Fix heap overflow vulnerability in XAUTOCLAIM (CVE-2022-35951) (#11301)
Executing an XAUTOCLAIM command on a stream key in a specific state, with a
specially crafted COUNT argument may cause an integer overflow, a subsequent
heap overflow, and potentially lead to remote code execution.
The problem affects Redis versions 7.0.0 or newer.
2022-09-22 11:55:53 +03:00
Valentino Geron
e53bf65245
Replica that asks for rdb only should be closed right after the rdb part (#11296)
The bug is that the the server keeps on sending newlines to the client.
As a result, the receiver might not find the EOF marker since it searches
for it only on the end of each payload it reads from the socket.
The but only affects `CLIENT_REPL_RDBONLY`.
This affects `redis-cli --rdb` (depending on timing)

The fixed consist of two steps:
1. The `CLIENT_REPL_RDBONLY` should be closed ASAP (we cannot
   always call to `freeClient` so we use `freeClientAsync`)
2. Add new replication state `SLAVE_STATE_RDB_TRANSMITTED`
2022-09-22 11:22:05 +03:00
Binbin
bb6513cbba
ACL default newly created user set USER_FLAG_SANITIZE_PAYLOAD flag (#11279)
Starting from 6.2, after ACL SETUSER user reset, the user
will carry the sanitize-payload flag. It was added in #7807,
and then ACL SETUSER reset is inconsistent with default
newly created user which missing sanitize-payload flag.

Same as `off` and `on` these two bits are mutually exclusive,
the default created user needs to have sanitize-payload flag.
Adds USER_FLAG_SANITIZE_PAYLOAD flag to ACLCreateUser.

Note that the bug don't have any real implications,
since the code in rdb.c (rdbLoadObject) checks for
`USER_FLAG_SANITIZE_PAYLOAD_SKIP`, so the fact that
`USER_FLAG_SANITIZE_PAYLOAD` is missing doesn't really matters.

Added tests to make sure it won't be broken in the future,
and updated the comment in ACLSetUser and redis.conf
2022-09-22 09:13:39 +03:00
Shay Fadida
eedb8b1724
Fix missing sections for INFO ALL with module (#11291)
When using `INFO ALL <section>`, when `section` is a specific module section. 
Redis will not print the additional section(s).

The fix in this case, will search the modules info sections if the user provided additional sections to `ALL`.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-09-21 08:10:03 +03:00
Binbin
c2b0c13d5c
Fix Invalid node address specified in redis-cli --cluster create/add-node (#11151)
This bug was introduced in #10344 (7.0.3), and it breaks the
redis-cli --cluster create usage in #10436 (7.0 RC3).

At the same time, the cluster-port support introduced in #10344
cannot use the DNS lookup brought by #10436.
2022-09-19 13:59:36 +03:00
sundb
13d25dd95e
Fix crash due to delete entry from compress quicklistNode and wrongly split quicklistNode (#11242)
This PR mainly deals with 2 crashes introduced in #9357,
and fix the QUICKLIST-PACKED-THRESHOLD mess in external test mode.

1. Fix crash due to deleting an entry from a compress quicklistNode
   When inserting a large element, we need to create a new quicklistNode first,
   and then delete its previous element, if the node where the deleted element is
   located is compressed, it will cause a crash.
   Now add `dont_compress` to quicklistNode, if we want to use a quicklistNode
   after some operation, we can use this flag like following:

    ```c
    node->dont_compress = 1; /* Prevent to be compressed */
    some_operation(node); /* This operation might try to compress this node */
    some_other_operation(node); /* We can use this node without decompress it */
    node->dont_compress = 0; /* Re-able compression */
    quicklistCompressNode(node);
    ```

   Perhaps in the future, we could just disable the current entry from being
   compressed during the iterator loop, but that would require more work.

2. Fix crash due to wrongly split quicklist
   before #9357, the offset param of _quicklistSplitNode() will not negative.
   For now, when offset is negative, the split extent will be wrong.
   following example:
    ```c
    int orig_start = after ? offset + 1 : 0;
    int orig_extent = after ? -1 : offset;
    int new_start = after ? 0 : offset;
    int new_extent = after ? offset + 1 : -1;
    # offset: -2, after: 1, node->count: 2
    # current wrong range: [-1,-1] [0,-1]
    # correct range: [1,-1] [0, 1]
    ```

   Because only `_quicklistInsert()` splits the quicklistNode and only
   `quicklistInsertAfter()`, `quicklistInsertBefore()` call _quicklistInsert(), 
   so `quicklistReplaceEntry()` and `listTypeInsert()` might occur this crash.
   But the iterator of `listTypeInsert()` is alway from head to tail(iter->offset is
   always positive), so it is not affected.
   The final conclusion is this crash only occur when we insert a large element
   with negative index into a list, that affects `LSET` command and `RM_ListSet`
   module api.
     
3. In external test mode, we need to restore quicklist packed threshold after
   when the end of test.
4. Show `node->count` in quicklistRepr().
5. Add new tcl proc `config_get_set` to support restoring config in tests.
2022-09-19 09:47:52 +03:00
zhaozhao.zz
464aa04188
fix infinite sleep in performEvictions when have lazyfree jobs (#11237)
This bug is introduced in #7653. (Redis 6.2.0)

When `server.maxmemory_eviction_tenacity` is 100, `eviction_time_limit_us` is
`ULONG_MAX`, and if we cannot find the best key to delete (e.g. maxmemory-policy
is `volatile-lru` and all keys with ttl have been evicted), in `cant_free` redis will sleep
forever if some items are being freed in the lazyfree thread.
2022-09-18 17:46:24 +03:00
Adi Pinsky
d144dc927a
Adds listnode to client struct for clients_pending_write list (#11220) 2022-09-14 22:39:47 -05:00
Viktor Söderqvist
42e4241ece
Avoid crash when a cluster node is a replica of a replica of itself (#11263) 2022-09-13 17:48:48 -07:00
Madelyn Olson
6c03786b66
Prevent use after free for inbound cluster link (#11255) 2022-09-13 16:19:29 -05:00
Wen Hui
5389fa62a6
Update group and consumer description in json file for Unifying Stream command format (#11190)
For the stream data type, some commands, such as **XGROUP CREATE, XGROUP DESTROY, XGROUP CREATECONSUMER, 
XGROUP DELCONSUMER and XINFO CONSUMERS** use groupname and consumername in the command description;

However, for the commands **XREADGROUP GROUP, XPENDING, XACK , XCLAIM  and XAUTOCLAIM**  use term "group and consumer", clients could be confused.

This PR goal is to unify all the commands to groupname and consumername.
2022-09-08 09:37:49 +03:00
Mingyi Kang
e67d06ee6b
Optimize setGenericCommand(): no need to remove the expiration entry when 'expire' is not NULL (#11244) 2022-09-07 22:35:25 -05:00
*caco
89018ff6a7
fix semantic uncorresponding in comment of ziplist example (#11141)
fix semantic uncorresponding in comment of ziplist example
2022-09-07 21:48:11 -05:00
tmoshaiov
fb1d56bc2a
Added API to initialize dictionary iterators without memory allocation (#11245)
* Added api to use dictionary iterators without calling malloc.
2022-09-07 20:57:43 -05:00
Ozan Tezcan
3761fdb048
Use cached value correctly inside connectionTypeTls() (#11236)
When Redis is built without TLS support, connectionTypeTls() function 
keeps searching connection type as cached connection type is NULL. 

Added another variable to track if we cached the connection type to 
prevent search after the first time. 

Noticed a log warning message is printed repeatedly by connectionTypeTls.

Co-authored-by: zhenwei pi <pizhenwei@bytedance.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
2022-09-06 09:04:33 +03:00
Shogo Hayashi
e764e2a627
Fix typo in DEBUG REPLYBUFFER RESIZING comment
This command is related with reply buffer, not replay buffer

Co-authored-by: Shogo Hayashi <hayshogo@amazon.co.jp>
2022-09-06 08:40:37 +03:00
chendianqiang
e42d98ed27
Correctly handle scripts with shebang (not read-only) on a cluster replica (#11223)
EVAL scripts are by default not considered `write` commands, so they were allowed on a replica.
But when adding a shebang, they become `write` command (unless the `no-writes` flag is added).
With this change we'll handle them as write commands, and reply with MOVED instead of
READONLY when executed on a redis cluster replica.

Co-authored-by: chendianqiang <chendianqiang@meituan.com>
2022-09-05 16:59:14 +03:00
Shaya Potter
87e7973c7e
Add a dry run flag to RM_Call execution (#11158)
Add a new "D" flag to RM_Call which runs whatever verification the user requests,
but returns before the actual execution of the command.

It automatically enables returning error messages as CallReply objects to distinguish
success (NULL) from failure (CallReply returned).
2022-09-05 16:19:32 +03:00
David CARLIER
22f763aa10
zmalloc api set malloc attributes for api giving non aliased pointers. (#11196)
micro optimizations, giving the hints that the returned addresses
 are guaranteed to be unique. The alloc_size attribute gives an extra hint
 about the source of the size, useful mostly for calloc-like calls or when there
 are extra arguments.
2022-09-05 16:09:28 +03:00
Shaya Potter
bed6d759bc
Improve cmd_flags for script/functions in RM_Call (#11159)
When RM_Call was used with `M` (reject OOM), `W` (reject writes),
as well as `S` (rejecting stale or write commands in "Script mode"),
it would have only checked the command flags, but not the declared
script flag in case it's a command that runs a script.

Refactoring: extracts out similar code in server.c's processCommand
to be usable in RM_Call as well.
2022-08-28 13:10:10 +03:00
weimeng
8945067544
bugfix:del keys in slot replicate to replica, and trigger other invalidations (#11084)
Bugfix:
with the scenario if we force assigned a slot to other master,
old master will lose the slot ownership, then old master will
call the function delKeysInSlot() to delete all keys which in
the slot. These delete operations should replicate to replicas,
avoid the data divergence issue in master and replicas.

Additionally, in this case, we now call:
* signalModifiedKey (to invalidate WATCH)
* moduleNotifyKeyspaceEvent (key space notification for modules)
* dirty++ (to signal that the persistence file may be outdated)

Co-authored-by: weimeng <weimeng@didiglobal.com>
Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
2022-08-28 11:37:26 +03:00
chendianqiang
bc7fe41e58
fix hincrbyfloat not to create a key if the new value is invalid (#11149)
Check the validity of the value before performing the create operation,
prevents new data from being generated even if the request fails to execute.

Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: chendianqiang <chendianqiang@meituan.com>
Co-authored-by: Binbin <binloveplay1314@qq.com>
2022-08-28 11:33:41 +03:00
Huang Zhw
a7da7473cb
Remove the NONDETERMINISTIC_OUTPUT flag from most CLUSTER sub-commands. (#11157)
TLDR: the CLUSTER command originally had the `random` flag,
so all the sub-commands initially got that new flag, but in fact many
of them don't need it.
The only effect of this change is on the output of COMMAND INFO.
2022-08-28 11:24:47 +03:00
Moti Cohen
246f44d723
Removing old redundant code from bio.c (#11136)
* Remove redundant array bio_pending[]. Value at index i identically reflects the
length of list bio_jobs[i]. Better use listLength() instead and discard this array.
(no critical section issues to concern about).

changed returned value of bioPendingJobsOfType() from "long long" to "long".

Remove unused API. Maybe we will use this API later.
2022-08-26 09:09:23 -07:00
Paul Menzel
14e026e685
Correct grammatical error in for DENIED error message (#11192)
networking: Spell verb *set up* with space in error message
2022-08-26 09:06:55 -07:00
Oran Agra
c789fb0aa7
Fix assertion when a key is lazy expired during cluster key migration (#11176)
Redis 7.0 has #9890 which added an assertion when the propagation queue
was not flushed and we got to beforeSleep.
But it turns out that when processCommands calls getNodeByQuery and
decides to reject the command, it can lead to a key that was lazy
expired and is deleted without later flushing the propagation queue.

This change prevents lazy expiry from deleting the key at this stage
(not as part of a command being processed in `call`)
2022-08-24 19:39:15 +03:00
Binbin
78259826cd
Bump codespell from 2.1.0 to 2.2.1 in /.codespell (#11184)
add a few terms to the white list, and fix a few newly detected typos
2022-08-24 15:07:43 +03:00
Brad Dunbar
c07212372c
Cleanup in GETDEL: Strings are never freed lazily (#11175)
The GETDEL command only operates on strings, and strings are never freed
lazily, so there's no need to use `dbAsyncDelete` or `shared.unlink`.
2022-08-24 14:11:04 +03:00
Meir Shpilraien (Spielrein)
c1bd61a4a5
Reverts most of the changes of #10969 (#11178)
The PR reverts the changes made on #10969.
The reason for revert was trigger because of occasional test failure
that started after the PR was merged.

The issue is that if there is a lazy expire during the command invocation,
the `del` command is added to the replication stream after the command
placeholder. So the logical order on the primary is:

* Delete the key (lazy expiration)
* Command invocation

But the replication stream gets it the other way around:

* Command invocation (because the command is written into the placeholder)
* Delete the key (lazy expiration)

So if the command write to the key that was just lazy expired we will get
inconsistency between primary and replica.

One solution we considered is to add another lazy expire replication stream
and write all the lazy expire there. Then when replicating, we will replicate the
lazy expire replication stream first. This will solve this specific test failure but
we realize that the issues does not ends here and the more we dig the more
problems we find.One of the example we thought about (that can actually
crashes Redis) is as follow:

* User perform SINTERSTORE
* When Redis tries to fetch the second input key it triggers lazy expire
* The lazy expire trigger a module logic that deletes the first input key
* Now Redis hold the robj of the first input key that was actually freed

We believe we took the wrong approach and we will come up with another
PR that solve the problem differently, for now we revert the changes so we
will not have the tests failure.

Notice that not the entire code was revert, some parts of the PR are changes
that we would like to keep. The changes that **was** reverted are:

* Saving a placeholder for replication at the beginning of the command (`call` function)
* Order of the replication stream on active expire and eviction (we will decide how
  to handle it correctly on follow up PR)
* `Spop` changes are no longer needed (because we reverted the placeholder code)

Changes that **was not** reverted:

* On expire/eviction, wrap the `del` and the notification effect in a multi exec.
* `PropagateNow` function can still accept a special dbid, -1, indicating not to replicate select.
* Keep optimisation for reusing the `alsoPropagate` array instead of allocating it each time.

Tests:

* All tests was kept and only few tests was modify to work correctly with the changes
* Test was added to verify that the revert fixes the issues.
2022-08-24 12:51:36 +03:00
Oran Agra
41d9eb0291
Merge: Fully abstract connection and make TLS dynamically loadable (#9320)
There are many commits in this PR, the detailed changes is described
in each commit message.

### Main changes in this PR

* Fully abstract connection type, and hide connection type specified methods.
  Ex, currently TLS class looks like:
```
static ConnectionType CT_TLS = {
    /* connection type */
    .get_type = connTLSGetType,

    /* connection type initialize & finalize & configure */
    .init = tlsInit,
    .cleanup = tlsCleanup,
    .configure = tlsConfigure,

    /* ae & accept & listen & error & address handler */
    .ae_handler = tlsEventHandler,
    .accept_handler = tlsAcceptHandler,
    .addr = connTLSAddr,
    .listen = connTLSListen,

    /* create/close connection */
    .conn_create = connCreateTLS,
    .conn_create_accepted = connCreateAcceptedTLS,
    .close = connTLSClose,

    /* connect & accept */
    .connect = connTLSConnect,
    .blocking_connect = connTLSBlockingConnect,
    .accept = connTLSAccept,

    /* IO */
    .read = connTLSRead,
    .write = connTLSWrite,
    .writev = connTLSWritev,
    .set_write_handler = connTLSSetWriteHandler,
    .set_read_handler = connTLSSetReadHandler,
    .get_last_error = connTLSGetLastError,
    .sync_write = connTLSSyncWrite,
    .sync_read = connTLSSyncRead,
    .sync_readline = connTLSSyncReadLine,

    /* pending data */
    .has_pending_data = tlsHasPendingData,
    .process_pending_data = tlsProcessPendingData,

    /* TLS specified methods */
    .get_peer_cert = connTLSGetPeerCert,
};

int RedisRegisterConnectionTypeTLS()
{
    return connTypeRegister(&CT_TLS);
}
```

* Also abstract Unix socket class. Currently, the connection framework becomes like:
```
                       uplayer
                          |
                   connection layer
                     /    |     \
                   TCP   Unix   TLS
    
```

* It's possible to build TLS as a shared library (`make BUILD_TLS=module`).
  Loading the shared library(redis-tls.so) into Redis by Redis module subsystem,
  and Redis starts to listen TLS port. Ex:
```
    ./src/redis-server --tls-port 6379 --port 0 \
        --tls-cert-file ./tests/tls/redis.crt \
        --tls-key-file ./tests/tls/redis.key \
        --tls-ca-cert-file ./tests/tls/ca.crt \
        --loadmodule src/redis-tls.so
```

### Interface changes
* RM_GetContextFlags supports a new flag: REDISMODULE_CTX_FLAGS_SERVER_STARTUP
* INFO SERVER includes a list of listeners:
```
listener0:name=tcp,bind=127.0.0.1,port=6380
listener1:name=unix,bind=/run/redis.sock
listener2:name=tls,bind=127.0.0.1,port=6379
```

### Other notes

* Fix wrong signature of RedisModuleDefragFunc, this could break
  compilation of a module, but not the ABI
* Some reordering of initialization order in server.c:
  * Move initialization of listeners to be after loading the modules
  * Config TLS after initialization of listeners
  * Init cluster after initialization of listeners
* Sentinel does not support the TLS module or any connection module
  since it uses hiredis for outbound connections, so when TLS is built as
  a module, sentinel lacks TLS support.
2022-08-24 08:35:46 +03:00
Oran Agra
4faddf18ca Build TLS as a loadable module
* Support BUILD_TLS=module to be loaded as a module via config file or
  command line. e.g. redis-server --loadmodule redis-tls.so
* Updates to redismodule.h to allow it to be used side by side with
  server.h by defining REDISMODULE_CORE_MODULE
* Changes to server.h, redismodule.h and module.c to avoid repeated
  type declarations (gcc 4.8 doesn't like these)
* Add a mechanism for non-ABI neutral modules (ones who include
  server.h) to refuse loading if they detect not being built together with
  redis (release.c)
* Fix wrong signature of RedisModuleDefragFunc, this could break
  compilation of a module, but not the ABI
* Move initialization of listeners in server.c to be after loading
  the modules
* Config TLS after initialization of listeners
* Init cluster after initialization of listeners
* Add TLS module to CI
* Fix a test suite race conditions:
  Now that the listeners are initialized later, it's not sufficient to
  wait for the PID message in the log, we need to wait for the "Server
  Initialized" message.
* Fix issues with moduleconfigs test as a result from start_server
  waiting for "Server Initialized"
* Fix issues with modules/infra test as a result of an additional module
  present

Notes about Sentinel:
Sentinel can't really rely on the tls module, since it uses hiredis to
initiate connections and depends on OpenSSL (won't be able to use any
other connection modules for that), so it was decided that when TLS is
built as a module, sentinel does not support TLS at all.
This means that it keeps using redis_tls_ctx and redis_tls_client_ctx directly.

Example code of config in redis-tls.so(may be use in the future):
RedisModuleString *tls_cfg = NULL;

void tlsInfo(RedisModuleInfoCtx *ctx, int for_crash_report) {
    UNUSED(for_crash_report);
    RedisModule_InfoAddSection(ctx, "");
    RedisModule_InfoAddFieldLongLong(ctx, "var", 42);
}

int tlsCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
{
    if (argc != 2) return RedisModule_WrongArity(ctx);
    return RedisModule_ReplyWithString(ctx, argv[1]);
}

RedisModuleString *getStringConfigCommand(const char *name, void *privdata) {
    REDISMODULE_NOT_USED(name);
    REDISMODULE_NOT_USED(privdata);
    return tls_cfg;
}

int setStringConfigCommand(const char *name, RedisModuleString *new, void *privdata, RedisModuleString **err) {
    REDISMODULE_NOT_USED(name);
    REDISMODULE_NOT_USED(err);
    REDISMODULE_NOT_USED(privdata);
    if (tls_cfg) RedisModule_FreeString(NULL, tls_cfg);
    RedisModule_RetainString(NULL, new);
    tls_cfg = new;
    return REDISMODULE_OK;
}

int RedisModule_OnLoad(void *ctx, RedisModuleString **argv, int argc)
{
    ....
    if (RedisModule_CreateCommand(ctx,"tls",tlsCommand,"",0,0,0) == REDISMODULE_ERR)
        return REDISMODULE_ERR;

    if (RedisModule_RegisterStringConfig(ctx, "cfg", "", REDISMODULE_CONFIG_DEFAULT, getStringConfigCommand, setStringConfigCommand, NULL, NULL) == REDISMODULE_ERR)
        return REDISMODULE_ERR;

    if (RedisModule_LoadConfigs(ctx) == REDISMODULE_ERR) {
        if (tls_cfg) {
            RedisModule_FreeString(ctx, tls_cfg);
            tls_cfg = NULL;
        }
        return REDISMODULE_ERR;
    }
    ...
}

Co-authored-by: zhenwei pi <pizhenwei@bytedance.com>
Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-23 12:37:56 +03:00
Ariel Shtul
90223759a3
[PERF] use snprintf once in addReplyDouble (#11093)
The previous implementation calls `snprintf` twice, the second time used to
'memcpy' the output of the first, which could be a very large string.
The new implementation reserves space for the protocol header ahead
of the formatted double, and then prepends the string length ahead of it.

Measured improvement of simple ZADD of some 25%.
2022-08-23 09:37:59 +03:00
Itamar Haber
407b5c912f
Replaces a made-up term with a real one (#11169) 2022-08-22 15:05:01 +03:00
zhenwei pi
89e1148688 Introduce redis module ctx flag 'server startup'
A module may be loaded only during initial stage, a typical case is
connection type shared library.

Introduce REDISMODULE_CTX_FLAGS_SERVER_STARTUP context flag
to tell the module the stage of Redis. Then the module gets the flag
by RedisModule_GetContextFlags(ctx), tests flags and returns error in
onload handler.

Suggested-by: Oran Agra <oran@redislabs.com>
Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 19:44:55 +08:00
zhenwei pi
8a59c19310 Introduce redis module ctx flag 'server startup' & 'sentinel'
A module may be loaded only during initial stage, a typical case is
connection type shared library.

Introduce REDISMODULE_CTX_FLAGS_SERVER_STARTUP context flag
to tell the module the stage of Redis. Then the module gets the flag
by RedisModule_GetContextFlags(ctx), tests flags and returns error in
onload handler.

Also introduce 'REDISMODULE_CTX_FLAGS_SENTINEL' context flag to tell
the module the sentinel mode or not.

Suggested-by: Oran Agra <oran@redislabs.com>
Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:16:42 +08:00
zhenwei pi
0c4d2fcc8e Add listeners info string for 'INFO' command
Suggested by Oran, add necessary listeners information in 'INFO'
command. It would be helpful for debug.

Example of this:
127.0.0.1:6379> INFO SERVER
redis_version:255.255.255
...
listener0:name=tcp,bind=127.0.0.1,port=6380
listener1:name=unix,bind=/run/redis.sock
listener2:name=tls,bind=127.0.0.1,port=6379
...

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:16:26 +08:00
zhenwei pi
0b27cfe37d Introduce .listen into connection type
Introduce listen method into connection type, this allows no hard code
of listen logic. Originally, we initialize server during startup like
this:
    if (server.port)
        listenToPort(server.port,&server.ipfd);
    if (server.tls_port)
        listenToPort(server.port,&server.tlsfd);
    if (server.unixsocket)
        anetUnixServer(...server.unixsocket...);

    ...
    if (createSocketAcceptHandler(&server.ipfd, acceptTcpHandler) != C_OK)
    if (createSocketAcceptHandler(&server.tlsfd, acceptTcpHandler) != C_OK)
    if (createSocketAcceptHandler(&server.sofd, acceptTcpHandler) != C_OK)
    ...

If a new connection type gets supported, we have to add more hard code
to setup listener.

Introduce .listen and refactor listener, and Unix socket supports this.
this allows to setup listener arguments and create listener in a loop.

What's more, '.listen' is defined in connection.h, so we should include
server.h to import 'struct socketFds', but server.h has already include
'connection.h'. To avoid including loop(also to make code reasonable),
define 'struct connListener' in connection.h instead of 'struct socketFds'
in server.h. This leads this commit to get more changes.

There are more fields in 'struct connListener', hence it's possible to
simplify changeBindAddr & applyTLSPort() & updatePort() into a single
logic: update the listener config from the server.xxx, and re-create
the listener.

Because of the new field 'priv' in struct connListener, we expect to pass
this to the accept handler(even it's not used currently), this may be used
in the future.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:16:08 +08:00
zhenwei pi
45617385e7 Use connection name of string
Suggested by Oran, use an array to store all the connection types
instead of a linked list, and use connection name of string. The index
of a connection is dynamically allocated.

Currently we support max 8 connection types, include:
- tcp
- unix socket
- tls

and RDMA is in the plan, then we have another 4 types to support, it
should be enough in a long time.

Introduce 3 functions to get connection type by a fast path:
- connectionTypeTcp()
- connectionTypeTls()
- connectionTypeUnix()

Note that connectionByType() is designed to use only in unlikely code path.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:15:37 +08:00
zhenwei pi
eb94d6d36d Introduce unix socket connection type
Unix socket uses different accept handler/create listener from TCP,
to hide these difference to avoid hard code, use a new unix socket
connection type. Also move 'acceptUnixHandler' into unix.c.

Currently, the connection framework becomes like following:

                   uplayer
                      |
               connection layer
                 /    |     \
               TCP   Unix   TLS

It's possible to build Unix socket support as a shared library, and
load it dynamically. Because TCP and Unix socket don't require any
heavy dependencies or overheads, we build them into Redis statically.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:12:31 +08:00
zhenwei pi
0ae02ce95b Abstract accept handler
Abstract accept handler for socket&TLS, and add helper function
'connAcceptHandler' to get accept handler by specified type.

Also move acceptTcpHandler into socket.c, and move
acceptTLSHandler into tls.c.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:12:18 +08:00
zhenwei pi
41fff55d52 Use socketFds for unix
socketFds is also suitable for Unix socket, then we can use
'createSocketAcceptHandler' to create accept handler.
And then, we can abstract accept handler in the future.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:12:04 +08:00
zhenwei pi
1234e3a562 Fully abstract connection type
Abstract common interface of connection type, so Redis can hide the
implementation and uplayer only calls connection API without macro.

               uplayer
                  |
           connection layer
             /          \
          socket        TLS

Currently, for both socket and TLS, all the methods of connection type
are declared as static functions.

It's possible to build TLS(even socket) as a shared library, and Redis
loads it dynamically in the next step.

Also add helper function connTypeOfCluster() and
connTypeOfReplication() to simplify the code:
link->conn = server.tls_cluster ? connCreateTLS() : connCreateSocket();
-> link->conn = connCreate(connTypeOfCluster());

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:11:44 +08:00
zhenwei pi
c4c02f8036 Introduce TLS specified APIs
Introduce .get_peer_cert, .get_ctx and .get_client_ctx for TLS, also
hide redis_tls_ctx & redis_tls_client_ctx.

Then outside could access the variables by connection API only:
- redis_tls_ctx -> connTypeGetCtx(CONN_TYPE_TLS)
- redis_tls_client_ctx -> connTypeGetClientCtx(CONN_TYPE_TLS)

Also remove connTLSGetPeerCert(), use connGetPeerCert() instead.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:11:25 +08:00
zhenwei pi
709b55b09d Introduce pending data for connection type
Introduce .has_pending_data and .process_pending_data for connection
type, and hide tlsHasPendingData() and tlsProcessPendingData(). Also
set .has_pending_data and .process_pending_data as NULL explicitly in
socket.c.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:11:06 +08:00
zhenwei pi
8234a5123d Introduce connection layer framework
Use connTypeRegister() to register a connection type into redis, and
query connection by connectionByType() via type.

With this change, we can hide TLS specified methods into connection
type:
- void tlsInit(void);
- void tlsCleanup(void);
- int tlsConfigure(redisTLSContextConfig *ctx_config);
- int isTlsConfigured(void);

Merge isTlsConfigured & tlsConfigure, use an argument *reconfigure*
to distinguish:
   tlsConfigure(&server.tls_ctx_config)
-> onnTypeConfigure(CONN_TYPE_TLS, &server.tls_ctx_config, 1)

   isTlsConfigured() && tlsConfigure(&server.tls_ctx_config)
-> connTypeConfigure(CONN_TYPE_TLS, &server.tls_ctx_config, 0)

Finally, we can remove USE_OPENSSL from config.c. If redis is built
without TLS, and still run redis with TLS, then redis reports:
 # Missing implement of connection type 1
 # Failed to configure TLS. Check logs for more info.

The log can be optimised, let's leave it in the future. Maybe we can
use connection type as a string.

Although uninitialized fields of a static struct are zero, we still
set them as NULL explicitly in socket.c, let them clear to read & maintain:
    .init = NULL,
    .cleanup = NULL,
    .configure = NULL,

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:09:59 +08:00
zhenwei pi
bff7ecc786 Introduce connAddr
Originally, connPeerToString is designed to get the address info from
socket only(for both TCP & TLS), and the API 'connPeerToString' is
oriented to operate a FD like:
int connPeerToString(connection *conn, char *ip, size_t ip_len, int *port) {
    return anetFdToString(conn ? conn->fd : -1, ip, ip_len, port, FD_TO_PEER_NAME);
}

Introduce connAddr and implement .addr method for socket and TLS,
thus the API 'connAddr' and 'connFormatAddr' become oriented to a
connection like:
static inline int connAddr(connection *conn, char *ip, size_t ip_len, int *port, int remote) {
    if (conn && conn->type->addr) {
        return conn->type->addr(conn, ip, ip_len, port, remote);
    }

    return -1;
}

Also remove 'FD_TO_PEER_NAME' & 'FD_TO_SOCK_NAME', use a boolean type
'remote' to get local/remote address of a connection.

With these changes, it's possible to support the other connection
types which does not use socket(Ex, RDMA).

Thanks to Oran for suggestions!

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:01:40 +08:00
zhenwei pi
b9d7728824 Reorder methods for ConnectionType
Reorder methods for CT_Socket & CT_TLS, also add comments to make the
methods clear.

Also move the CT_TLS to the end of file, other methods can be static
in the next step.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:01:32 +08:00
zhenwei pi
8045e26efa Move 'connGetSocketError' to 'anetGetError'
getsockopt is part of TCP, rename 'connGetSocketError' to
'anetGetError', and move it into anet.c.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:01:16 +08:00
zhenwei pi
dca5c6ff11 Move several conn functions to connection.h
These functions are really short enough and they are the connection
functions, separate them from the socket source.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:01:01 +08:00
zhenwei pi
22e74e4720 Rename connection.c to socket.c
ConnectionType CT_Socket is implemented in connection.c, so rename
this file to socket.c.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2022-08-22 15:00:26 +08:00
Itamar Haber
a5349832fe
Changes "lower" to "capital" in GEO units history notes (#11164)
A overlooked mistake in the #11162
2022-08-21 18:15:53 +03:00
yourtree
ca6aeadfbe
Support setlocale via CONFIG operation. (#11059)
Till now Redis officially supported tuning it via environment variable see #1074.
But we had other requests to allow changing it at runtime, see #799, and #11041.

Note that `strcoll()` is used as Lua comparison function and also for comparison of
certain string objects in Redis, which leads to a problem that, in different regions,
for some characters, the result may be different. Below is an example.
```
127.0.0.1:6333> SORT test alpha
1) "<"
2) ">"
3) ","
4) "*"
127.0.0.1:6333> CONFIG GET locale-collate
1) "locale-collate"
2) ""
127.0.0.1:6333> CONFIG SET locale-collate 1
(error) ERR CONFIG SET failed (possibly related to argument 'locale')
127.0.0.1:6333> CONFIG SET locale-collate C
OK
127.0.0.1:6333> SORT test alpha
1) "*"
2) ","
3) "<"
4) ">"
```
That will cause accidental code compatibility issues for Lua scripts and some
Redis commands. This commit creates a new config parameter to control the
local environment which only affects `Collate` category. Above shows how it
affects `SORT` command, and below shows the influence on Lua scripts.
```
127.0.0.1:6333> CONFIG GET locale-collate
1) " locale-collate"
2) "C"
127.0.0.1:6333> EVAL "return ',' < '*'" 0
(nil)
127.0.0.1:6333> CONFIG SET locale-collate ""
OK
127.0.0.1:6333> EVAL "return ',' < '*'" 0
(integer) 1
```

Co-authored-by: calvincjli <calvincjli@tencent.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
2022-08-21 17:55:45 +03:00
Itamar Haber
31ef410e88
Adds historical note about lower-case geo units support (#11162)
This change was part of #9656 (Redis 7.0)
2022-08-21 17:01:17 +03:00
Binbin
3a16ad30b7
Fix CLUSTERDOWN issue in cluster reshard unblock test (#11139)
change the cluster-node-timeout from 1 to 1000
2022-08-18 09:18:18 -07:00
guybe7
223046ec9a
Repurpose redisCommandArg's name as the unique ID (#11051)
This PR makes sure that "name" is unique for all arguments in the same
level (i.e. all args of a command and all args within a block/oneof).
This means several argument with identical meaning can be referred to together,
but also if someone needs to refer to a specific one, they can use its full path.

In addition, the "display_text" field has been added, to be used by redis.io
in order to render the syntax of the command (for the vast majority it is
identical to "name" but sometimes we want to use a different string
that is not "name")
The "display" field is exposed via COMMAND DOCS and will be present
for every argument, except "oneof" and "block" (which are container
arguments)

Other changes:
1. Make sure we do not have any container arguments ("oneof" or "block")
   that contain less than two sub-args (otherwise it doesn't make sense)
2. migrate.json: both AUTH and AUTH2 should not be "optional"
3. arg names cannot contain underscores, and force the usage of hyphens
  (most of these were a result of the script that generated the initial json files
  from redis.io commands.json).
2022-08-18 15:09:36 +03:00
Binbin
fc3956e8f4
Fix memory leak in moduleFreeCommand (#11147)
Currently, we call zfree(cmd->args), but the argument array
needs to be freed recursively (there might be sub-args).
Also fixed memory leaks on cmd->tips and cmd->history.

Fixes #11145
2022-08-18 12:36:01 +03:00
Meir Shpilraien (Spielrein)
508a138885
Fix replication inconsistency on modules that uses key space notifications (#10969)
Fix replication inconsistency on modules that uses key space notifications.

### The Problem

In general, key space notifications are invoked after the command logic was
executed (this is not always the case, we will discuss later about specific
command that do not follow this rules). For example, the `set x 1` will trigger
a `set` notification that will be invoked after the `set` logic was performed, so
if the notification logic will try to fetch `x`, it will see the new data that was written.
Consider the scenario on which the notification logic performs some write
commands. for example, the notification logic increase some counter,
`incr x{counter}`, indicating how many times `x` was changed.
The logical order by which the logic was executed is has follow:

```
set x 1
incr x{counter}
```

The issue is that the `set x 1` command is added to the replication buffer
at the end of the command invocation (specifically after the key space
notification logic was invoked and performed the `incr` command).
The replication/aof sees the commands in the wrong order:

```
incr x{counter}
set x 1
```

In this specific example the order is less important.
But if, for example, the notification would have deleted `x` then we would
end up with primary-replica inconsistency.

### The Solution

Put the command that cause the notification in its rightful place. In the
above example, the `set x 1` command logic was executed before the
notification logic, so it should be added to the replication buffer before
the commands that is invoked by the notification logic. To achieve this,
without a major code refactoring, we save a placeholder in the replication
buffer, when finishing invoking the command logic we check if the command
need to be replicated, and if it does, we use the placeholder to add it to the
replication buffer instead of appending it to the end.

To be efficient and not allocating memory on each command to save the
placeholder, the replication buffer array was modified to reuse memory
(instead of allocating it each time we want to replicate commands).
Also, to avoid saving a placeholder when not needed, we do it only for
WRITE or MAY_REPLICATE commands.

#### Additional Fixes

* Expire and Eviction notifications:
  * Expire/Eviction logical order was to first perform the Expire/Eviction
    and then the notification logic. The replication buffer got this in the
    other way around (first notification effect and then the `del` command).
    The PR fixes this issue.
  * The notification effect and the `del` command was not wrap with
    `multi-exec` (if needed). The PR also fix this issue.
* SPOP command:
  * On spop, the `spop` notification was fired before the command logic
    was executed. The change in this PR would have cause the replication
    order to be change (first `spop` command and then notification `logic`)
    although the logical order is first the notification logic and then the
    `spop` logic. The right fix would have been to move the notification to
    be fired after the command was executed (like all the other commands),
    but this can be considered a breaking change. To overcome this, the PR
    keeps the current behavior and changes the `spop` code to keep the right
    logical order when pushing commands to the replication buffer. Another PR
    will follow to fix the SPOP properly and match it to the other command (we
    split it to 2 separate PR's so it will be easy to cherry-pick this PR to 7.0 if
    we chose to).

#### Unhanded Known Limitations

* key miss event:
  * On key miss event, if a module performed some write command on the
    event (using `RM_Call`), the `dirty` counter would increase and the read
    command that cause the key miss event would be replicated to the replication
    and aof. This problem can also happened on a write command that open
    some keys but eventually decides not to perform any action. We decided
    not to handle this problem on this PR because the solution is complex
    and will cause additional risks in case we will want to cherry-pick this PR.
    We should decide if we want to handle it in future PR's. For now, modules
    writers is advice not to perform any write commands on key miss event.

#### Testing

* We already have tests to cover cases where a notification is invoking write
  commands that are also added to the replication buffer, the tests was modified
  to verify that the replica gets the command in the correct logical order.
* Test was added to verify that `spop` behavior was kept unchanged.
* Test was added to verify key miss event behave as expected.
* Test was added to verify the changes do not break lazy expiration.

#### Additional Changes

* `propagateNow` function can accept a special dbid, -1, indicating not
  to replicate `select`. We use this to replicate `multi/exec` on `propagatePendingCommands`
  function. The side effect of this change is that now the `select` command
  will appear inside the `multi/exec` block on the replication stream (instead of
  outside of the `multi/exec` block). Tests was modified to match this new behavior.
2022-08-18 10:16:32 +03:00
Oran Agra
ac1cc5a6e1
Trim rdb loading code for pre-release formats (#11058)
The initial module format introduced in 4.0  RC1 and was changed in RC2
The initial function format introduced in 7.0 RC1 and changed in RC3
2022-08-15 21:41:44 +03:00
kmy2001
eef2d8303d
Optimization in t_hash.c: Avoid looking for a same field twice by using dictAddRaw() instead of dictFind() and dictAdd() (#11110)
Before this change in hashTypeSet() function, we first use dictFind()
to look for the field and if it does not exist, we use dictAdd() to add it.
In dictAdd() function the dictionary will look for the field again and I
think this is meaningless as we already know that the field does not exist.

An optimization is to use dictAddRaw() instead of dictFind() and dictAdd().
If we use dictAddRaw(), a new entry will be added when the field does not
exist, and what we should do then is just set the value of that entry, and set
its key to 'sdsdup(field)' in the case that 'HASH_SET_TAKE_FIELD' flag wasn't set.
2022-08-14 14:53:40 +03:00
sundb
8aad2ac352
Add missing lua_pop in luaGetFromRegistry (#11097)
This pr mainly has the following four changes:

1. Add missing lua_pop in `luaGetFromRegistry`.
    This bug affects `redis.register_function`, where `luaGetFromRegistry` in
    `luaRegisterFunction` will return null when we call `redis.register_function` nested.
    .e.g
    ```
    FUNCTION LOAD "#!lua name=mylib \n local lib=redis \n lib.register_function('f2', function(keys, args) lib.register_function('f1', function () end) end)"
    fcall f2 0
    ````
    But since we exit when luaGetFromRegistry returns null, it does not cause the stack to grow indefinitely.

3. When getting `REGISTRY_RUN_CTX_NAME` from the registry, use `serverAssert`
    instead of error return. Since none of these lua functions are registered at the time
    of function load, scriptRunCtx will never be NULL.
4. Add `serverAssert` for `luaLdbLineHook`, `luaEngineLoadHook`.
5. Remove `luaGetFromRegistry` from `redis_math_random` and
    `redis_math_randomseed`, it looks like they are redundant.
2022-08-14 11:50:18 +03:00
Ozan Tezcan
99ebbee2b2
Fix overflow in redis-benchmark (#11102)
Fix overflow in redis-benchmark affecting latency measurements on 32bit builds.

If `long` is 4 bytes (typical on 32 bit systems), multiplication overflows.
Using `long long` will fix the issue as it is guaranteed to be at least 8 bytes. 

Also, I've added a change to reuse `ustime()` for `mstime()`.
2022-08-11 15:28:16 +03:00
DarrenJiang13
44859a41ee
fix the client type in trackingInvalidateKey() (#11052)
Fix bug with scripts ignoring client tracking NOLOOP and
send an invalidation message anyway.
2022-08-10 11:58:54 +03:00
judeng
91c3c742e7
fix typos around dict funtions of cstring (#11092)
replace "dist" with "dict"
2022-08-09 08:50:26 +03:00
Huang Zhw
ec5034a2e3
acl: bitfield with get and set|incrby can be executed with readonly permission (#11086)
`bitfield` with `get` may not be readonly.

```
127.0.0.1:6384> acl setuser hello on nopass %R~* +@all
OK
127.0.0.1:6384> auth hello 1
OK
127.0.0.1:6384> bitfield hello set i8 0 1
(error) NOPERM this user has no permissions to access one of the keys used as arguments
127.0.0.1:6384> bitfield hello set i8 0 1 get i8 0
1) (integer) 0
2) (integer) 1
```

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-08-07 09:21:19 +03:00
judeng
7d8911d22a
Optimize the performance of multi-key commands in cluster mode (#11044)
* Optimize the performance of multi-key commands in cluster mode

* add note
2022-08-04 20:42:56 -07:00
Binbin
4505eb1821
errno cleanup around rdbLoad (#11042)
This is an addition to #11039, which cleans up rdbLoad* related errno. Remove the
errno print from the outer message (may be invalid since errno may have been overwritten).

Our aim should be the code that detects the error and knows which system call
triggered it, is the one to print errno, and not the code way up above (in some cases
a result of a logical error and not a system one).

Remove the code to update errno in rdbLoadRioWithLoadingCtx, signature check
and the rdb version check, in these cases, we do print the error message.
The caller dose not have the specific logic for handling EINVAL.

Small fix around rdb-preamble AOF: A truncated RDB is considered a failure,
not handled the same as a truncated AOF file.
2022-08-04 10:47:37 +03:00
filipe oliveira
6686c6d774
Avoid the sdslen() on shared.crlf given we know its size beforehand. Improve ~3-4% of cpu cycles to lrange logic (#10987)
* Avoid the sdslen() on shared.crlf given we know its size beforehand
* Removed shared.crlf from sharedObjects
2022-08-04 10:38:20 +03:00
Jie Liang Ang
f3588fbcca
Reuse checkGoodReplicasStatus in script.c (#11078)
Small refactoring done to reuse `checkGoodReplicasStatus` in `script.c` when checking for status of good replicas.
2022-08-04 10:10:42 +03:00
Moti Cohen
1aa6c4ab92
Adding parentheses and do-while(0) to macros (#11080)
Fixing few macros that doesn't follows most basic safety conventions
which is wrapping any usage of passed variable
with parentheses and if written more than one command, then wrap
it with do-while(0) (or parentheses).
2022-08-03 19:38:08 +03:00
sundb
7cd3520424
Return ASAP when lua error is string (#11075)
This is a harmless optimization/bug.
When the top of the lua stack is a string, we should not continue to use lua_getfield to get the table fields.
2022-08-03 08:03:13 +03:00
Wen Hui
beb9746a9f
Fix function load error message (#10964)
Update error messages for function load
2022-08-02 18:19:53 -07:00
Rudi Floren
4ce3fd51b9
Fix wrong commands json docs for CLIENT KILL (#10970)
The docs state that there is a new and an old argument format.
The current state of the arguments allows mixing the old and new format,
thus the need for two additional oneof blocks.
One for differentiating the new from the old format and then one to
allow setting multiple filters using the new format.
2022-08-01 15:52:40 +03:00
Valentino Geron
2029976dc3
Optimization: moduleLoadString should try to create embedded string if not plain (#11050)
Before this change, if the module has an embedded string, then uses RedisModule_SaveString
and RedisModule_LoadString, the result would be a raw string instead of an embedded string.

Now the `RDB_LOAD_ENC` flag to `moduleLoadString` only affects integer encoding, but not
embedded strings (which still hold an sds in the robj ptr, so they're actually still raw strings for
anyone who reads them).

Co-authored-by: Valentino Geron <valentino@redis.com>
2022-07-31 17:29:59 +03:00
Huang Zhw
61451b02cb
tracking pending invalidation message of flushdb sent by (#11068)
trackingHandlePendingKeyInvalidations should use proto.
2022-07-31 16:14:39 +03:00
Binbin
90f35cea81
Avoid false positive out-of-bounds in writeForgottenNodePingExt (#11053)
In clusterMsgPingExtForgottenNode, sizeof(name) is CLUSTER_NAMELEN,
and sizeof(clusterMsgPingExtForgottenNode) is > CLUSTER_NAMELEN.
Doing a (name + sizeof(clusterMsgPingExtForgottenNode)) sanitizer
generates an out-of-bounds error which is a false positive in here
2022-07-28 15:14:18 -07:00
guybe7
45c99d7092
Adds RM_Microseconds and RM_CachedMicroseconds (#11016)
RM_Microseconds
Return the wall-clock Unix time, in microseconds

RM_CachedMicroseconds
Returns a cached copy of the Unix time, in microseconds.
It is updated in the server cron job and before executing a command.
It is useful for complex call stacks, such as a command causing a
key space notification, causing a module to execute a RedisModule_Call,
causing another notification, etc.
It makes sense that all these callbacks would use the same clock.
2022-07-27 14:40:05 +03:00
Binbin
00097bf4aa
Change the return value of rdbLoad function to enums (#11039)
The reason we do this is because in #11036, we added error
log message when failing to open RDB file for reading.
In loadDdataFromDisk we call rdbLoad and also check errno,
now the logging corrupts errno (reported in alpine daily).

It is not safe to rely on errno as we do today, so we change
the return value of rdbLoad function to enums, like we have
when loading an AOF.
2022-07-26 15:13:13 +03:00
Huang Zhw
6f0a27e38e
When client tracking is on, invalidation message of flushdb in a (#11038)
When FLUSHDB / FLUSHALL / SWAPDB is inside MULTI / EXEC, the
client side tracking invalidation message was interleaved with transaction response.
2022-07-26 13:28:37 +03:00
Meir Shpilraien (Spielrein)
020e046b42
Fix #11030, use lua_rawget to avoid triggering metatables and crash. (#11032)
Fix #11030, use lua_rawget to avoid triggering metatables.

#11030 shows how return `_G` from the Lua script (either function or eval), cause the
Lua interpreter to Panic and the Redis processes to exit with error code 1.
Though return `_G` only panic on Redis 7 and 6.2.7, the underline issue exists on older
versions as well (6.0 and 6.2). The underline issue is returning a table with a metatable
such that the metatable raises an error.

The following example demonstrate the issue:
```
127.0.0.1:6379> eval "local a = {}; setmetatable(a,{__index=function() foo() end}) return a" 0
Error: Server closed the connection
```
```
PANIC: unprotected error in call to Lua API (user_script:1: Script attempted to access nonexistent global variable 'foo')
```

The Lua panic happened because when returning the result to the client, Redis needs to
introspect the returning table and transform the table into a resp. In order to scan the table,
Redis uses `lua_gettable` api which might trigger the metatable (if exists) and might raise an error.
This code is not running inside `pcall` (Lua protected call), so raising an error causes the
Lua to panic and exit. Notice that this is not a crash, its a Lua panic that exit with error code 1.

Returning `_G` panics on Redis 7 and 6.2.7 because on those versions `_G` has a metatable
that raises error when trying to fetch a none existing key.

### Solution

Instead of using `lua_gettable` that might raise error and cause the issue, use `lua_rawget`
that simply return the value from the table without triggering any metatable logic.
This is promised not to raise and error.

The downside of this solution is that it might be considered as breaking change, if someone
rely on metatable in the returned value. An alternative solution is to wrap this entire logic
with `pcall` (Lua protected call), this alternative require a much bigger refactoring.

### Back Porting

The same fix will work on older versions as well (6.2, 6.0). Notice that on those version,
the issue can cause Redis to crash if inside the metatable logic there is an attempt to accesses
Redis (`redis.call`). On 7.0, there is not crash and the `redis.call` is executed as if it was done
from inside the script itself.

### Tests

Tests was added the verify the fix
2022-07-26 10:33:50 +03:00
Viktor Söderqvist
5032de50f2
Gossip forgotten nodes on CLUSTER FORGET (#10869)
Gossip the cluster node blacklist in ping and pong messages.
This means that CLUSTER FORGET doesn't need to be sent to all nodes in a cluster.
It can be sent to one or more nodes and then be propagated to the rest of them.

For each blacklisted node, its node id and its remaining blacklist TTL is gossiped in a
cluster bus ping extension (introduced in #9530).
2022-07-26 10:28:13 +03:00
YaacovHazan
33bd8fb981
Add error log message when failing to open RDB file for reading (#11036)
When failing to open the rdb file, there was no specific error printed (unlike a
corrupt file), so it was not clear what failed and why.
2022-07-25 10:09:58 +03:00
Binbin
03fff10ab4
fsync the old aof file when open a new INCR AOF (#11004)
In rewriteAppendOnlyFileBackground, after flushAppendOnlyFile(1),
and before openNewIncrAofForAppend, we should call redis_fsync
to fsync the aof file.

Because we may open a new INCR AOF in openNewIncrAofForAppend,
in the case of using everysec policy, the old AOF file may not
be fsynced in time (or even at all).

When using everysec, we don't want to pay the disk latency from
the main thread, so we will do a background fsync.

Adding a argument for bioCreateCloseJob, a `need_fsync` flag to
indicate that a fsync is required before the file is closed. So we will
fsync the old AOF file before we close it.

A cleanup, we make union become a union, since the free_* args and
the fd / fsync args are never used together.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-07-25 09:16:35 +03:00
chenyang8094
39d216a326
Register abs-expire apis (#11025)
RM_SetAbsExpire and RM_GetAbsExpire were not actually operational since
they were introduced, due to omission in API registration.
2022-07-24 08:50:21 +03:00
Pavel Krush
5879e490b8
fixed complexity of bzmpop and zmpop commands (#11026)
Swap M and N in the complexity formula of [B]ZMPOP

Co-authored-by: Pavel Krush <neon@pushwoosh.com>
2022-07-24 08:38:04 +03:00
Tian
d00b8af892
Don't update node ip when peer fd is closed (#10696) 2022-07-20 16:59:27 -07:00
guybe7
6d6e932fa6
Adds LASTID to XCLAIM docs (#11017)
It seems it was overlooked when we first created the json files
2022-07-20 10:12:06 +03:00
Tian
cc2848132f
Make cluster config file saving atomic and fsync acl (#10924)
As an outstanding part mentioned in #10737, we could just make the cluster config file and
ACL file saving done with a more safe and atomic pattern (write to temp file, fsync, rename, fsync dir).

The cluster config file uses an in-place overwrite and truncation (which was also used by the
main config file before #7824).
The ACL file is using the temp file and rename approach, but was missing an fsync.

Co-authored-by: 朱天 <zhutian03@meituan.com>
2022-07-20 09:11:01 +03:00
Wen Hui
56828bab59
Fix EVALSHA_RO and EVAL_RO command json file (#11015)
these are missing from the RO_ commands, present in the other ones.

Co-authored-by: Ubuntu <lucas.guang.yang1@huawei.com>
2022-07-19 18:54:45 +03:00
Binbin
95b88f672a
Set RM_StringCompare input args as const (#11010)
Following #10996, it forgot to modify RM_StringCompare in module.c

Modified RM_StringCompare, compareStringObjectsWithFlags,
compareStringObjects and collateStringObjects.
2022-07-19 08:59:39 +03:00
Oran Agra
2825b6057b
Fix heap overflow corruption in XAUTOCLAIM (CVE-2022-31144) (#11002)
The temporary array for deleted entries reply of XAUTOCLAIM was
insufficient, but also in fact the COUNT argument should be used to
control the size of the reply, so instead of terminating the loop by
only counting the claimed entries, we'll count deleted entries as well.

Fix #10968
Addresses CVE-2022-31144
2022-07-18 11:36:19 +03:00
ranshid
eacca729a5
Avoid using unsafe C functions (#10932)
replace use of:
sprintf --> snprintf
strcpy/strncpy  --> redis_strlcpy
strcat/strncat  --> redis_strlcat

**why are we making this change?**
Much of the code uses some unsafe variants or deprecated buffer handling
functions.
While most cases are probably not presenting any issue on the known path
programming errors and unterminated strings might lead to potential
buffer overflows which are not covered by tests.

**As part of this PR we change**
1. added implementation for redis_strlcpy and redis_strlcat based on the strl implementation: https://linux.die.net/man/3/strl
2. change all occurrences of use of sprintf with use of snprintf
3. change occurrences of use of  strcpy/strncpy with redis_strlcpy
4. change occurrences of use of strcat/strncat with redis_strlcat
5. change the behavior of ll2string/ull2string/ld2string so that it will always place null
  termination ('\0') on the output buffer in the first index. this was done in order to make
  the use of these functions more safe in cases were the user will not check the output
  returned by them (for example in rdbRemoveTempFile)
6. we added a compiler directive to issue a deprecation error in case a use of
  sprintf/strcpy/strcat is found during compilation which will result in error during compile time.
  However keep in mind that since the deprecation attribute is not supported on all compilers,
  this is expected to fail during push workflows.


**NOTE:** while this is only an initial milestone. We might also consider
using the *_s implementation provided by the C11 Extensions (however not
yet widly supported). I would also suggest to start
looking at static code analyzers to track unsafe use cases.
For example LLVM clang checker supports security.insecureAPI.DeprecatedOrUnsafeBufferHandling
which can help locate unsafe function usage.
https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-deprecatedorunsafebufferhandling-c
The main reason not to onboard it at this stage is that the alternative
excepted by clang is to use the C11 extensions which are not always
supported by stdlib.
2022-07-18 10:56:26 +03:00
Valentino Geron
82b8203555
remove boolean usage and use 0/1 instead (#10997)
If we do not use jemalloc (mostly with valgrind) and use an old compiler that does not support C11
we will get compilation error

Co-authored-by: Valentino Geron <valentino@redis.com>
2022-07-17 18:28:38 +03:00
Guy Korland
587fc9ce76
Set RedisModule_StringCompare input args as const (#10996) 2022-07-17 13:53:48 +03:00
Wen Hui
2d3240f31b
Add optional for FCALL and FCALL_RO command json file (#10988)
According to the Redis functions documentation, FCALL command format could be
FCALL function_name numberOfKeys [key1, key2, key3.....] [arg1, arg2, arg3.....]

So in the json file of fcall and fcall_ro, we should add optional for key and arg part.
Just like EVAL...

Co-authored-by: Binbin <binloveplay1314@qq.com>
2022-07-17 09:40:07 +03:00
Oran Agra
599e59ebc5
Avoid valgrind fishy value warning on corrupt restore payloads (#10937)
The corrupt dump fuzzer uncovered a valgrind warning saying:
```
==76370== Argument 'size' of function malloc has a fishy (possibly negative) value: -3744781444216323815
```
This allocation would have failed (returning NULL) and being handled properly by redis (even before this change), but we also want to silence the valgrind warnings (which are checking that casting to ssize_t produces a non-negative value).

The solution i opted for is to explicitly fail these allocations (returning NULL), before even reaching `malloc` (which would have failed and return NULL too).

The implication is that we will not be able to support a single allocation of more than 2GB on a 32bit system (which i don't think is a realistic scenario).
i.e. i do think we could be facing cases were redis consumes more than 2gb on a 32bit system, but not in a single allocation.

The byproduct of this, is that i dropped the overflow assertions, since these will now lead to the same OOM panic we have for failed allocations.
2022-07-13 09:14:38 +03:00
Binbin
20af95a99f
Add range check for server port in redis-cli/benchmark (#9854)
Validating inputs ahead of time, to give the end user a slightly more useful error.
2022-07-12 20:32:14 -07:00
Wen Hui
8221d48165
Normalize the style of help information with other documentation (#10965) 2022-07-12 09:56:02 -07:00
jimgreen2013
53e7de205f
Simplify arithmetic expression on LP_REPLACE case in lpinsert (#6327)
Remove unnecessary variable name.
2022-07-12 09:24:59 -07:00
Oran Agra
b4568fc78a
update help.h (#10961) 2022-07-11 12:36:03 +03:00
Binbin
35e8ae3eb5
Add cluster-port support to redis-cli --cluster (#10344)
In #9389, we add a new `cluster-port` config and make cluster bus port configurable,
and currently redis-cli --cluster create/add-node doesn't support with a configurable `cluster-port` instance.
Because redis-cli uses the old way (port + 10000) to send the `CLUSTER MEET` command.

Now we add this support on redis-cli `--cluster`, note we don't need to explicitly pass in the
`cluster-port` parameter, we can get the real `cluster-port` of the node in `clusterManagerNodeLoadInfo`,
so the `--cluster create` and `--cluster add-node` interfaces have not changed.

We will use the `cluster-port` when we are doing `CLUSTER MEET`, also note that `CLUSTER MEET` bus-port
parameter was added in 4.0, so if the bus_port (the one in redis-cli) is 0, or equal (port + 10000),
we just call `CLUSTER MEET` with 2 arguments, using the old form.

Co-authored-by: Madelyn Olson <34459052+madolson@users.noreply.github.com>
2022-07-11 11:23:31 +03:00
Binbin
1e85b89aef
Add --check-system in redis-server usage (#10960) 2022-07-11 08:31:39 +03:00
Madelyn Olson
e6a1b2ea95
Fix crash during handshake and cluster shards call (#10942)
* Fix an engine crash when there are nodes in handshaking and a user calls cluster shards
2022-07-10 22:00:44 -07:00
Madelyn Olson
1209dc2277
Only print ACL syntax errors once and include command names in errors (#10922)
* Only print ACL syntax errors once and include command names in errors
2022-07-09 21:02:22 -07:00
Binbin
8203461120
Fix some outdated comments and some typo (#10946)
* Fix some outdated comments and some typo
2022-07-06 20:31:59 -07:00
Binbin
0132ed7544
Add pubsubshard_channels field in INFO STATS (#10929)
We already have `pubsub_channels` and `pubsub_patterns`
in INFO stats, now add `pubsubshard_channels` (symmetry).

Sharded pubsub was added in #8621
2022-07-06 09:50:08 +03:00
Yossi Gottlieb
45ae605332
TLS: Notify clients on connection shutdown. (#10931)
Use SSL_shutdown(), in a best-effort manner, when closing a TLS
connection. This change better supports OpenSSL 3.x clients that will
not silently ignore the socket-level EOF.
2022-07-05 08:41:17 +03:00
Harkrishn Patro
9bcdd1537e
Avoid double multiplication of alloc_count (#10934) 2022-07-04 10:09:27 -07:00
Harkrishn Patro
a3704d4e87
Optimize number of realloc syscall during multi/exec flow (#10921)
## Issue
During the MULTI/EXEC flow, each command gets queued until the `EXEC`
command is received and during this phase on every command queue, a
`realloc` is being invoked. This could be expensive based on the realloc
behavior (if copy to a new memory location). 


## Solution
In order to reduce the no. of syscall, couple of optimization I've used.

1. By default, reserve memory for atleast two commands. `MULTI/EXEC` for a
single command doesn't have any significance. Hence, I believe customer wouldn't use it.
2. For further reservation, increase the memory allocation in exponent growth (power of 2).
This reduces the no. of `realloc` call from `N` to `log(N)` times.

## Other changes:

* Include multi exec queued command array in client memory consumption calculation
(affects client eviction too)
2022-07-04 09:47:34 +03:00
Qu Chen
33b7ff387c
Unlock cluster config file upon server shutdown. (#10912)
Currently in cluster mode, Redis process locks the cluster config file when
starting up and holds the lock for the entire lifetime of the process.
When the server shuts down, it doesn't explicitly release the lock on the
cluster config file. We noticed a problem with restart testing that if you shut down
a very large redis-server process (i.e. with several hundred GB of data stored),
it takes the OS a while to free the resources and unlock the cluster config file.
So if we immediately try to restart the redis server process, it might fail to acquire
the lock on the cluster config file and fail to come up.

This fix explicitly releases the lock on the cluster config file upon a shutdown rather
than relying on the OS to release the lock, which is a cleaner and safer approach to
free up resources acquired.
2022-07-04 09:38:19 +03:00
Harkrishn Patro
0ab885a685
Account sharded pubsub channels memory consumption (#10925)
Account sharded pubsub channels memory consumption in client memory usage
computation to accurately evict client based on the set threshold for `maxmemory-clients`.
2022-07-04 09:18:57 +03:00
Binbin
679344a2b0
Set aof rewrite status in some backgroundRewriteDoneHandler errors (#10923)
We should also set aof_lastbgrewrite_status to C_ERR on these
errors. Because aof rewrite did fail, and we did not finish the
manifest update. Also maintain the stat_aofrw_consecutive_failures.
2022-07-03 15:36:42 +03:00
Yossi Gottlieb
0b645d6319
Fix TLS issues with large replies (#10909)
This problem was introduced by 496375f and seems to more easily reproduce on macOS since OpenSSL writes more frequently return with EAGAIN.
2022-07-03 13:35:58 +03:00
Binbin
2ab6767744
Always set server.aof_last_write_errno in aof write error (#10917)
The `can_log` variable prevents us from outputting too
many error logs. But it should not include the modification
of server.aof_last_write_errno.

We are doing this because:
1. In the short write case, we always set aof_last_write_errno
to ENOSPC, we don't care the `can_log` flag.

2. And we always set aof_last_write_status to C_ERR in aof write
error (except for FSYNC_ALWAYS, we exit). So there may be a chance
that `aof_last_write_errno` is not right.

An innocent bug or just a code cleanup.
2022-07-03 08:34:39 +03:00
Binbin
35e836c26d
Add SENTINEL command flag to CLIENT/COMMANDS subcommands (#10904)
This was harmless because we marked the parent command
with SENTINEL flag. So the populateCommandTable was ok.
And we also don't show the flag (SENTINEL and ONLY-SENTNEL)
in COMMAND INFO.

In this PR, we also add the same CMD_SENTINEL and CMD_ONLY_SENTINEL
flags check when populating the sub-commands.
so that in the future it'll be possible to add some sub-commands to sentinel or sentinel-only but not others.
2022-06-30 16:32:40 +03:00
Wen Hui
51da5c3dde
Fix CLUSTER RESET command argument number issue (#10898)
Fix regression of CLUSTER RESET command in redis 7.0.

cluster reset command format is:
CLUSTER RESET [ HARD | SOFT]

According to the cluster reset command doc and codes, the third argument is optional, so
the arity in json file should be -2 instead of 3.

Add test to verify future regressions with RESET and RESET SOFT that were not covered.

Co-authored-by: Ubuntu <lucas.guang.yang1@huawei.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: Binbin <binloveplay1314@qq.com>
2022-06-29 08:17:00 +03:00
jonnyomerredis
35c2ee8716
Add sharded pubsub keychannel count to client info (#10895)
When calling CLIENT INFO/LIST, and in various debug prints, Redis is printing
the number of pubsub channels / patterns the client is subscribed to.
With the addition of sharded pubsub, it would be useful to print the number of
keychannels the client is subscribed to as well.
2022-06-28 10:11:17 +03:00
Tian
069b30a2b3
A minor refinement to clusterbus extension estlen (#10902) 2022-06-27 20:42:55 -07:00
Viktor Söderqvist
6af021007a
Add missing REDISMODULE_CLIENTINFO_INITIALIZER (#10885)
The module API docs mentions this macro, but it was not defined (so no one could have used it).

Instead of adding it as is, we decided to add a _V1 macro, so that if / when we some day extend this struct,
modules that use this API and don't need the extra fields, will still use the old version
and still be compatible with older redis version (despite being compiled with newer redismodule.h)
2022-06-27 08:29:05 +03:00
RinChanNOW!
2854637385
Support conversion between RedisModuleString and unsigned long long (#10889)
Since the ranges of `unsigned long long` and `long long` are different, we cannot read an
`unsigned long long` integer from a `RedisModuleString` by `RedisModule_StringToLongLong` . 

So I added two new Redis Module APIs to support the conversion between these two types:
* `RedisModule_StringToULongLong`
* `RedisModule_CreateStringFromULongLong`

Signed-off-by: RinChanNOWWW <hzy427@gmail.com>
2022-06-26 15:02:52 +03:00
Binbin
d443e312ad
redis-server command line arguments allow passing config name and value in the same arg (#10866)
This commit has two topics.

## Passing config name and value in the same arg
In #10660 (Redis 7.0.1), when we supported the config values that can start with `--` prefix (one of the two topics of that PR),
we broke another pattern: `redis-server redis.config "name value"`, passing both config name
and it's value in the same arg, see #10865

This wasn't a intended change (i.e we didn't realize this pattern used to work).
Although this is a wrong usage, we still like to fix it.

Now we support something like:
```
src/redis-server redis.conf "--maxmemory '700mb'" "--maxmemory-policy volatile-lru" --proc-title-template --my--title--template --loglevel verbose
```

## Changes around --save
Also in this PR, we undo the breaking change we made in #10660 on purpose.
1. `redis-server redis.conf --save --loglevel verbose` (missing `save` argument before anotehr argument).
    In 7.0.1, it was throwing an wrong arg error.
    Now it will work and reset the save, similar to how it used to be in 7.0.0 and 6.2.x.
3. `redis-server redis.conf --loglevel verbose --save` (missing `save` argument as last argument).
    In 6.2, it did not reset the save, which was a bug (inconsistent with the previous bullet).
    Now we will make it work and reset the save as well (a bug fix).
2022-06-26 14:36:39 +03:00
Viktor Söderqvist
6272ca609e
Add RM_SetClientNameById and RM_GetClientNameById (#10839)
Adding Module APIs to let the module read and set the client name of an arbitrary connection.
2022-06-26 14:34:59 +03:00
Binbin
d96cf3639a
Sync argv_len var back after command call in execCommand (#10900)
This is harmless, we only restore mstate to make sure we
free the right pointer in freeClientMultiState, but it'll
be nicer to also sync that argv_len var back.
2022-06-26 12:32:34 +03:00
Elvina Yakubova
e2cf386765
Replace regular array to array of structs to get rid of false sharing (#10892)
There are a lot of false sharing cache misses in line 4013 inside getIOPendingCount function.
The reason is that elements of io_threads_pending array access the same cache line from different
threads, so it is better to represent it as an array of structures with fields aligned to cache line size.
This change should improve performance (in particular, it affects the latency metric, we saw up to 3% improvement).
2022-06-26 08:39:30 +03:00
Steve Lorello
a64b29485d
changing min,max in ZRANGE -> start stop (#10097)
In 6.2.0 with the introduction of the REV subcommand in ZRANGE, there was a semantic shift in the arguments of ZRANGE when the REV sub-command is executed. Without the sub-command `min` and `max` (the old names of the arguments) are appropriate because if you put the min value and the max value in everything works fine.

```bash
127.0.0.1:6379> ZADD myset 0 foo
(integer) 1
127.0.0.1:6379> ZADD myset 1 bar
(integer) 1
127.0.0.1:6379> ZRANGE myset 0 inf BYSCORE
1) "foo"
2) "bar"
``` 

However - if you add the `REV` subcommand, ordering the arguments `min` `max` breaks the command:

```bash
127.0.0.1:6379> ZRANGE myset 0 inf BYSCORE REV
(empty array)
```

why? because `ZRANGE` with the `REV` sub-command is expecting the `max` first and the `min` second (because it's a reverse range like `ZREVRANGEBYSCORE`):

```bash
127.0.0.1:6379> ZRANGE myset 0 inf BYSCORE REV
(empty array)
```
2022-06-25 19:02:20 +03:00
WuYunlong
64205345bc
migrateGetSocket() cleanup.. (#5546)
I think parameter c is only useful to get client reply.
Besides, other commands' host and port parameters may not be the at index 1 and 2.
2022-06-23 18:41:32 +03:00
Binbin
755b51a42c
When dirCreateIfMissing or openNewIncrAofForAppend fail, set aof_lastbgrewrite_status to err (#10775)
It will be displayed in the `aof_last_bgrewrite_status`
field of the INFO command.
2022-06-23 18:40:20 +03:00
(╯°□°)╯︵ uᴉǝssnH ɐɟɐʇsoW
c52922e1d9
command prompt help: add stdin config usage (#6313)
Signed-off-by: Mostafa Hussein <mostafa.hussein91@gmail.com>
2022-06-23 18:37:42 +03:00
Binbin
aabce8932a
Add bus_port argument in cluster-meet.json (#10304)
In `CLUSTER MEET`, bus-port argument was added in 11436b1.
For cluster announce ip / port implementation, part of the
4.0-RC1.

And in #9389, we add a new cluster-port config and make
cluster bus port configurable, part of the 7.0-RC1.
2022-06-23 07:56:25 +03:00
judeng
49876158cc
fix redis-benchmark's bug: check if clients are created successfully in idle mode (#10891)
my maxclients config:
```
redis-cli config get maxclients
1) "maxclients"
2) "4064"
```

Before this bug was fixed, creating 4065 clients appeared to be successful, but only 4064 were actually created```
```
./redis-benchmark -c 4065 -I
Creating 4065 idle connections and waiting forever (Ctrl+C when done)
cients: 4065
```

now :
```
./redis-benchmark -c 4065 -I
Creating 4065 idle connections and waiting forever (Ctrl+C when done)
Error from server: ERR max number of clients reached

./redis-benchmark -c 4064 -I
Creating 4064 idle connections and waiting forever (Ctrl+C when done)
clients: 4064

```
2022-06-22 19:30:22 +03:00
Viktor Söderqvist
02acb8fd3a
Module API docs corrections (#10890)
* Fix typo `RedisModule_CreatString` -> `RedisModule_CreateString` (multiple occurrences)
* Make the markdown gen script change all `RM_` to `RedisModule_` even in code examples, etc.
2022-06-21 17:00:24 +03:00
Meir Shpilraien (Spielrein)
61baabd8d5
Fix crash on RM_Call with script mode. (#10886)
The PR fixes 2 issues:

### RM_Call crash on script mode

`RM_Call` can potentially be called from a background thread where `server.current_client`
are not set. In such case we get a crash on `NULL` dereference.
The fix is to check first if `server.current_client` is `NULL`, if it does we should
verify disc errors and readonly replica as we do to any normal clients (no masters nor AOF).

### RM_Call block OOM commands when not needed

Again `RM_Call` can be executed on a background thread using a `ThreadSafeCtx`.
In such case `server.pre_command_oom_state` can be irrelevant and should not be
considered when check OOM state. This cause OOM commands to be blocked when
not necessarily needed.

In such case, check the actual used memory (and not the cached value). Notice that in
order to know if the cached value can be used, we check that the ctx that was used on
the `RM_Call` is a ThreadSafeCtx. Module writer can potentially abuse the API and use
ThreadSafeCtx on the main thread. We consider this as a API miss used.
2022-06-21 10:01:13 +03:00
Vlad
a3fdc9cd82
Outdated comments, replace COUNTER_INIT_VAL with LFU_INIT_VAL, fix typo (#10888)
`COUNTER_INIT_VAL` doesn't exist in the code anymore so we can replace it with `LFU_INIT_VAL` entries
2022-06-21 08:14:31 +03:00
Bar Shaul
091701f363
Set replicas' configEpoch to 0 when loaded from cluster configuration file (#10798)
* Changed clusterLoadConfig to set the config epoch of replica nodes to 0 when loaded.
2022-06-20 21:40:48 -07:00
judeng
ff6419658b
Optimize the performance of clusterSendPing for large clusters (#10624)
Optimize the performance of clusterSendPing by improving speed of checking for duplicate items in gossip.
2022-06-20 21:02:22 -07:00
Tian
99a425d0f3
Fsync directory while persisting AOF manifest, RDB file, and config file (#10737)
The current process to persist files is `write` the data, `fsync` and `rename` the file,
but a underlying problem is that the rename may be lost when a sudden crash like
power outage and the directory hasn't been persisted.

The article [Ensuring data reaches disk](https://lwn.net/Articles/457667/) mentions
a safe way to update file should be:

1. create a new temp file (on the same file system!)
2. write data to the temp file
3. fsync() the temp file
4. rename the temp file to the appropriate name
5. fsync() the containing directory

This commit handles CONFIG REWRITE, AOF manifest, and RDB file (both for persistence,
and the one the replica gets from the master).
It doesn't handle (yet), ACL SAVE and Cluster configs, since these don't yet follow this pattern.
2022-06-20 19:17:23 +03:00
Masahiro Ide
f2387daa83
Fix a prototype inconsitency of _serverAssert between redisassert.h and redis.h (#10872)
both redisassert.c and server.h + debug.c use const, but redisassert.h doesn't.
2022-06-19 08:42:12 +03:00
Oran Agra
2189100383
optimize zset conversion on large ZRANGESTORE (#10789)
when we know the size of the zset we're gonna store in advance,
we can check if it's greater than the listpack encoding threshold,
in which case we can create a skiplist from the get go, and avoid
converting the listpack to skiplist later after it was already populated.
2022-06-14 21:12:45 +03:00
Oran Agra
8ef4f1dbad
Script that made modification will not break with unexpected NOREPLICAS error (#10855)
If a script made a modification and then was interrupted for taking too long.
there's a chance redis will detect that a replica dropped and would like to reject
write commands with NOREPLICAS due to insufficient good replicas.
returning an error on a command in this case breaks the script atomicity.

The same could in theory happen with READONLY, MISCONF, but i don't think
these state changes can happen during script execution.
2022-06-14 21:09:50 +03:00
Oran Agra
ffa0077041
Allow ECHO in loading and stale modes (#10853)
I noticed that scripting.tcl uses INFO from within a script and thought it's an
overkill and concluded it's nicer to use another CMD_STALE command,
decided to use ECHO, and then noticed it's not at all allowed in stale mode.
probably overlooked at #6843
2022-06-14 08:48:08 +03:00
hdyztmdqd
c65e5087e8
Fix 2 comments in dict.c & redis-cli.c (#10860)
* fix comment in dict.c

fix comment in dict.c

* Fix comment in redis-cli.c

Fix comment in redis-cli.c
2022-06-14 08:09:08 +03:00
Huang Zhw
78960ad57b
Throw -TRYAGAIN instead of -ASK on migrating nodes for multi-key commands when the node only has some of the keys (#9526)
* In cluster getNodeByQuery when target slot is in migrating state and
the slot lack some keys but have at least one key, should return TRYAGAIN.

Before this commit, when a node is in migrating state and recevies
multiple keys command, if some keys don't exist, the command emits
an `ASK` redirection.

After this commit, if some keys exist and some keys don't exist, the
command emits a TRYAGAIN error. If all keys don't exist, the command
emits an `ASK` redirection.
2022-06-13 21:32:43 -07:00
Binbin
0a2f78837d
redis-check-rdb add when_opcode check for module aux (#10859)
In #9199, we add a `goto eoferr` in when_opcode check,
this means that if the when_opcode check fails, we will
abort the rdb loading, but this not reflected in the
rdb-check tool. So someone can modify when_opcode to make
rdb load fail, but rdb-check will report OK. Just a cleanup
or a code consistency issue.
```
serverLog: # Internal error in RDB reading offset 0, function at rdb.c:3055 -> bad when_opcode
[offset 0] Checking RDB file dump.rdb
[offset 109] \o/ RDB looks OK! \o/
```

Plus a minor memory leak fix like #9860, note that it will
exit immediately after the eoferr, so it is not strictly a
leak, so it is also a small cleanup.
2022-06-13 18:23:53 +03:00
XiongDa
d4595dd94f
Fix typo in replication.c (#10854) 2022-06-13 12:12:46 +03:00
Johannes Truschnigg
9f3b410050
Correctly check for vm.overcommit_memory == 0 (#10841)
A regression caused by #10636 (released in 7.0.1) causes Redis startup warning about overcommit to be missing when needed and printed when not. 

Also, using atoi() to convert the string's value to an integer cannot discern
between an actual 0 (zero) having been read, or a conversion error.
2022-06-12 20:53:11 +03:00
XiongDa
abb2ea7e3c
Fix 3 comments in server.c (#10844) 2022-06-12 08:44:44 +03:00
Binbin
92fb4f4f61
Fixed SET and BITFIELD commands being wrongly marked movablekeys (#10837)
The SET and BITFIELD command were added `get_keys_function` in #10148, causing
them to be wrongly marked movablekeys in `populateCommandMovableKeys`.

This was an unintended side effect introduced in #10148 (7.0 RC1)
which could cause some clients an extra round trip for these commands in cluster mode.

Since we define movablekeys as a way to determine if the legacy range [first, last, step]
doesn't find all keys, then we need a completely different approach.

The right approach should be to check if the legacy range covers all key-specs,
and if none of the key-specs have the INCOMPLETE flag. 
This way, we don't need to look at getkeys_proc of VARIABLE_FLAG at all.
Probably with the exception of modules, who may still not be using key-specs.

In this PR, we removed `populateCommandMovableKeys` and put its logic in
`populateCommandLegacyRangeSpec`.
In order to properly serve both old and new modules, we must probably keep relying
CMD_MODULE_GETKEYS, but do that only for modules that don't declare key-specs. 
For ones that do, we need to take the same approach we take with native redis commands.

This approach was proposed by Oran. Fixes #10833

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-06-12 08:22:18 +03:00
Binbin
62ac1ab007
Fix crash when overcommit_memory is inaccessible (#10848)
When `/proc/sys/vm/overcommit_memory` is inaccessible, fp is NULL.
`checkOvercommit` will return -1 without setting err_msg, and then
the err_msg is used to print the log, crash the server.
Set the err_msg variables to Null when declaring it, seems safer.

And the overcommit_memory error log will print two "WARNING",
like `WARNING WARNING overcommit_memory is set to 0!`, this PR
also removes the second WARNING in `checkOvercommit`.

Reported in #10846. Fixes #10846. Introduced in #10636 (7.0.1)
2022-06-11 22:27:44 +03:00
Wen Hui
6e1c3ff132
Update some comments in stream command docs (#10821)
some small documentation fixes.
2022-06-09 10:16:56 +03:00
Binbin
ae9764ea0a
Increment the stat_rdb_saves counter in SAVE command (#10827)
Currently, we only increment stat_rdb_saves in rdbSaveBackground,
we should also increment it in the SAVE command.

We concluded there's no need to increment when:
1. saving a base file for an AOF
2. when saving an empty rdb file to delete an old one
3. when saving to sockets (not creating a persistence / snapshot file)

The stat counter was introduced in #10178

* fix a wrong comment in startSaving
2022-06-07 17:38:31 +03:00
ls-2018
b8665b879b
fix unused argument warning in ae_select.c (#10824) 2022-06-07 14:47:09 +03:00
Bjorn Svensson
1067cfb34b
Documentation fixes of BITFIELD_RO and XINFO STREAM (#10823)
Correcting the introduction version of the command `BITFIELD_RO`
Command added by commit: b3e4abf06e 

Add history info of the `FULL` modifier in `XINFO STREAM`
Modifier was added by commit: 1e2aee3919

(Includes output from `./utils/generate-command-code.py`)
2022-06-07 13:26:47 +03:00
Binbin
3d56f607b7
Handle multiple_token flag in generate-command-help.rb (#10822)
Currently generate-command.help.rb dose not handle the
multiple_token flag, handle this flag in this PR.
The format is the same as redis-cli rendering.
```diff
- bitfield_ro key GET encoding offset [encoding offset ...]
+ bitfield_ro key GET encoding offset [GET encoding offset ...]
```

Re run generate-command-code.py which was forget in #10820.
Also change the flag value from string to bool, like "true" to true
2022-06-07 10:15:39 +03:00
ranshid
b4772f6381
Fix bitfield_ro documentation (#10820)
Current documentation only states a single GET token is needed which is not true. Marking the command with multiple_token.
2022-06-06 18:11:58 -07:00
Oran Agra
b0272252f7
update help.h (#10818)
before releasing 7.0.1
2022-06-06 11:39:53 +03:00
Oran Agra
475563e2e9
crash report instructions (#10816)
Trying to avoid people opening crash report issues about module crashes and ARM QEMU bugs.
2022-06-06 11:39:23 +03:00
DarrenJiang13
f558583493
Split instantaneous_repl_total_kbps to instantaneous_input_repl_kbps and instantaneous_output_repl_kbps. (#10810)
A supplement to https://github.com/redis/redis/pull/10062
Split `instantaneous_repl_total_kbps` to `instantaneous_input_repl_kbps` and `instantaneous_output_repl_kbps`. 
## Work:
This PR:
- delete 1 info field:
    - `instantaneous_repl_total_kbps`
- add 2 info fields:
    - `instantaneous_input_repl_kbps / instantaneous_output_repl_kbps`
## Result:
- master
```
total_net_input_bytes:26633673
total_net_output_bytes:21716596
total_net_repl_input_bytes:0
total_net_repl_output_bytes:18433052
instantaneous_input_kbps:0.02
instantaneous_output_kbps:0.00
instantaneous_input_repl_kbps:0.00
instantaneous_output_repl_kbps:0.00
```
- slave
```
total_net_input_bytes:18433212
total_net_output_bytes:94790
total_net_repl_input_bytes:18433052
total_net_repl_output_bytes:0
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.05
instantaneous_input_repl_kbps:0.00
instantaneous_output_repl_kbps:0.00
```
2022-06-06 08:29:24 +03:00
Mixficsol
c751d8a686
Update cluster.c (#10773)
On line 4068, redis has a logical nodeIsSlave(myself) on the outer if layer,
which you can delete without having to repeat the decision
2022-06-06 08:17:18 +03:00
Steve Lorello
247e792bde
some minor spelling/grammatical fixes to module.c (#10812) 2022-06-03 15:36:35 -07:00
Madelyn Olson
4ad166235e
Update time independent string compare to use hash length (#9759)
* Update time independent string compare to use hash length
2022-06-03 09:30:28 -07:00
zhaozhao.zz
a18c91d642
rewrite alias config to original name (#10811)
Redis 7 adds some new alias config like `hash-max-listpack-entries` alias `hash-max-ziplist-entries`.

If a config file contains both real name and alias like this:
```
hash-max-listpack-entries 20
hash-max-ziplist-entries 20
```

after set `hash-max-listpack-entries` to 100 and `config rewrite`, the config file becomes to:
```
hash-max-listpack-entries 100
hash-max-ziplist-entries 20
```

we can see that the alias config is not modified, and users will get wrong config after restart.

6.0 and 6.2 doesn't have this bug, since they only have the `slave` word alias.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-06-02 14:03:47 +03:00