Commit Graph

8306 Commits

Author SHA1 Message Date
Harkrishn Patro
4065b4f27e
Sharded pubsub publish messagebulk as smessage (#10792)
To easily distinguish between sharded channel message and a global
channel message, introducing `smessage` (instead of `message`) as
message bulk for sharded channel publish message.

This is gonna be a breaking change in 7.0.1!

Background:
Sharded pubsub introduced in redis 7.0, but after the release we quickly
realized that the fact that it's problematic that the client can't distinguish
between normal (global) pubsub messages and sharded ones.
This is important because the same connection can subscribe to both,
but messages sent to one pubsub system are not propagated to the
other (they're completely separate), so if one connection is used to
subscribe to both, we need to assist the client library to know which
message it got so it can forward it to the correct callback.
2022-05-31 08:03:59 +03:00
Wen Hui
d7ae858745
Fix streamParseAddOrTrimArgsOrReply function minor comment issue (#10783)
When I read the source codes, I have no idea where the option "age" come from.


Co-authored-by: Ubuntu <lucas.guang.yang1@huawei.com>
Co-authored-by: guybe7 <guy.benoish@redislabs.com>
2022-05-31 07:57:59 +03:00
Madelyn Olson
ed29d634b3
Add readonly flag to EVAL_RO, EVALSHA_RO and FCALL_RO (#10728)
* Add readonly flag to EVAL_RO, EVALSHA_RO and FCALL_RO
* Require users to explicitly declare @scripting to get access to lua scripting.
2022-05-29 23:42:56 -07:00
skygragon
7a550c8bbb
fixes function cache_memory accounting stats bug (#10791)
This bug resulted in wrong memory usage statistics after a redis function library is removed.

Signed-off-by: skygragon <skygragon@gmail.com>
2022-05-29 22:45:56 +03:00
Binbin
f18c9da3e1
loadAppendOnlyFiles and loadSingleAppendOnlyFile ret should be AOF_OK, not C_OK (#10790)
The ret value should be AOF_OK instead of C_OK.
AOF_OK and C_OK are both 0, so this is just a cleanup.
Also updated some outdated comments.
2022-05-29 13:33:16 +03:00
Lu JJ
2f5edd03e6
fix typo in quicklist.c (#10785)
fix typo ` the largest possible limit is 16k` -> ` the largest possible limit is 64k`.
The count field is 16 bits so the largest possible limit is 64k(2**16).
2022-05-29 08:51:33 +03:00
Vitaly
6461f09f43
Fix ZRANGESTORE crash when zset_max_listpack_entries is 0 (#10767)
When `zrangestore` is called container destination object is created. 
Before this PR we used to create a listpack based object even if `zset-max-ziplist-entries`
or equivalent`zset-max-listpack-entries` was set to 0.
This triggered immediate conversion of the listpack into a skiplist in `zrangestore`, which hits
an assertion resulting in an engine crash.

Added a TCL test that reproduces this issue.
2022-05-27 22:34:00 +03:00
Binbin
2a099d49d4
Fix some commands key spec in json files (#10779)
There are some commands that has the wrong key specs.
This PR adds a key-spec related check in generate-command-code.py.
Check if the index is valid, or if there is an unused index.

The check result will look like:
```
[root]# python utils/generate-command-code.py
Processing json files...
Linking container command to subcommands...
Checking all commands...
command: RESTORE_ASKING may have unused key_spec
command: RENAME may have unused key_spec
command: PFDEBUG may have unused key_spec
command: WATCH key_specs missing flags
command: LCS arg: key2 key_spec_index error
command: RENAMENX may have unused key_spec
Error: There are errors in the commands check, please check the above logs.
```

The following commands have been fixed according to the check results:
- RESTORE ASKING: add missing arguments section (and history section)
- RENAME: newkey's key_spec_index should be 1
- PFDEBUG: add missing arguments (and change the arity from -3 to 3)
- WATCH: add missing key_specs flags: RO, like EXIST (it allow you to know the key exists, or is modified, but doesn't "leak" the data)
- LCS: key2 key_spec_index error, there is only one key-spec
- RENAMENX: newkey's key_spec_index should be 1
2022-05-27 12:58:00 +03:00
Binbin
6f7c1a8ce6
Fix outdated comment about flags in moduleCreateArgvFromUserFormat (#10781)
Clearly more than one flag exists, also fixed some typos.
Fixes #10776
2022-05-26 17:34:17 +03:00
chenyang8094
f28e2ce7a4
improve logging around AOF file creation and loading (#10763)
instead of printing a log when a folder or a manifest is missing (level reduced), we print:

total time it took to load all the aof files
when creating a new base or incr file
starting to write to an existing incr file on startup
2022-05-26 17:23:05 +03:00
Meir Shpilraien (Spielrein)
ad25716a75
Added the function name/script sha to the script timeout log message. (#10780)
Added the function name/script sha to the script timeout log message.
This info existed in the log in redis 6.2, was removed in the function refactoring
since was initially complicated, but later made simple.
2022-05-26 16:11:24 +03:00
Binbin
450c88f368
Fix BZMPOP gets unblocked by non-key args and returns them (#10764)
This bug was introduced in #9484 (7.0.0).
It result that BZMPOP blocked on non-key arguments.

Like `bzmpop 0 1 myzset min count 10`, this command will additionally
block in these keys (except for the first and the last argument) and can return their values:
- 0: timeout value
- 1: numkeys value
- min: min/max token
- count: count token
2022-05-23 14:15:54 +03:00
yoav-steinberg
843a4cdc07
Add warning for suspected slow system clocksource setting (#10636)
This PR does 2 main things:
1) Add warning for suspected slow system clocksource setting. This is Linux specific.
2) Add a `--check-system` argument to redis which runs all system checks and prints a report.

## System checks
Add a command line option `--check-system` which runs all known system checks and provides
a report to stdout of which systems checks have failed with details on how to reconfigure the
system for optimized redis performance.
The `--system-check` mode exists with an appropriate error code after running all the checks.

## Slow clocksource details
We check the system's clocksource performance by running `clock_gettime()` in a loop and then
checking how much time was spent in a system call (via `getrusage()`). If we spend more than
10% of the time in the kernel then we print a warning. I verified that using the slow clock sources:
`acpi_pm` (~90% in the kernel on my laptop) and `xen` (~30% in the kernel on an ec2 `m4.large`)
we get this warning.

The check runs 5 system ticks so we can detect time spent in kernel at 20% jumps (0%,20%,40%...).
Anything more accurate will require the test to run longer. Typically 5 ticks are 50ms. This means
running the test on startup will delay startup by 50ms. To avoid this we make sure the test is only
executed in the `--check-system` mode.

For a quick startup check, we specifically warn if the we see the system is using the `xen` clocksource
which we know has bad performance and isn't recommended (at least on ec2). In such a case the
user should manually rung redis with `--check-system` to force the slower clocksource test described
above.

## Other changes in the PR

* All the system checks are now implemented as functions in _syscheck.c_.
  They are implemented using a standard interface (see details in _syscheck.c_).
  To do this I moved the checking functions `linuxOvercommitMemoryValue()`,
  `THPIsEnabled()`, `linuxMadvFreeForkBugCheck()` out of _server.c_ and _latency.c_
  and into the new _syscheck.c_. When moving these functions I made sure they don't
  depend on other functionality provided in _server.c_ and made them use a standard
  "check functions" interface. Specifically:
  * I removed all logging out of `linuxMadvFreeForkBugCheck()`. In case there's some
    unexpected error during the check aborts as before, but without any logging.
    It returns an error code 0 meaning the check didn't not complete.
  * All these functions now return 1 on success, -1 on failure, 0 in case the check itself
    cannot be completed.
  * The `linuxMadvFreeForkBugCheck()` function now internally calls `exit()` and not
    `exitFromChild()` because the latter is only available in _server.c_ and I wanted to
    remove that dependency. This isn't an because we don't need to worry about the
    child process created by the test doing anything related to the rdb/aof files which
    is why `exitFromChild()` was created.

* This also fixes parsing of other /proc/\<pid\>/stat fields to correctly handle spaces
  in the process name and be more robust in general. Not that before this fix the rss
  info in `INFO memory` was corrupt in case of spaces in the process name. To
  recreate just rename `redis-server` to `redis server`, start it, and run `INFO memory`.
2022-05-22 17:10:31 +03:00
Oran Agra
b0e18f804d
Scripts that declare the no-writes flag are implicitly allow-oom too. (#10699)
Scripts that have the `no-writes` flag, cannot execute write commands,
and since all `deny-oom` commands are write commands, we now act
as if the `allow-oom` flag is implicitly set for scripts that set the `no-writes` flag.
this also implicitly means that the EVAL*_RO and FCALL_RO commands can
never fails with OOM error.

Note about a bug that's no longer relevant:
There was an issue with EVAL*_RO using shebang not being blocked correctly
in OOM state:
When an EVAL script declares a shebang, it was by default not allowed to run in
OOM state.
but this depends on a flag that is updated before the command is executed, which
was not updated in case of the `_RO` variants.
the result is that if the previous cached state was outdated (either true or false),
the script will either unjustly fail with OOM, or unjustly allowed to run despite
the OOM state.
It doesn't affect scripts without a shebang since these depend on the actual
commands they run, and since these are only read commands, they don't care
for that cached oom state flag.
it did affect scripts with shebang and no allow-oom flag, bug after the change in
this PR, scripts that are run with eval_ro would implicitly have that flag so again
the cached state doesn't matter.

p.s. this isn't a breaking change since all it does is allow scripts to run when they
should / could rather than blocking them.
2022-05-22 16:02:59 +03:00
Binbin
18cb4a7d93
Remove ziplist dead code in object.c (#10751)
Remove some dead code in object.c, ziplist is no longer used in 7.0

Some backgrounds:
zipmap - hash: replaced by ziplist in #285
ziplist - hash: replaced by listpack in #8887
ziplist - zset: replaced by listpack in #9366
ziplist - list: replaced by quicklist (listpack) in #2143 / #9740

Moved the location of ziplist.h in the server.c
2022-05-22 12:27:54 +03:00
Yuuoniy
4a7a4e42db
Fix memory leak in streamGetEdgeID (#10753)
si is initialized by streamIteratorStart(), we should call
streamIteratorStop() on it when done.

regression introduced in #9127 (redis 7.0)
2022-05-22 12:15:26 +03:00
Ofir Luzon
00a9d6b314
Add SIGINT handler to redis-cli --bigkeys, --memkeys, --hotkeys, --scan (#10736)
Finish current loop and display the scanned keys summery on SIGINT (Ctrl-C) signal.
It will also prepend the current scanned percentage to the scanned keys summery 1st line.

In this commit I've renamed and relocated `intrinsicLatencyModeStop` function as I'm using the exact same logic.
2022-05-22 10:55:26 +03:00
Binbin
60250f50c2
Fix typos in module comment / documentation (#10740)
minor cleanup in redismodule.h and module.c
2022-05-18 08:29:39 +03:00
Ozan Tezcan
f62d52a5ad
Add const qualifier to config name parameter in RM_RegisterBoolConfig() (#10733)
was present in the C file and missing in the header.
2022-05-16 14:53:38 +03:00
Qu Chen
837c063baf
Replica fail and retry the PSYNC if the master is unresponsive (#10726)
We observed from our replication testing that when the master becomes unresponsive,
or the replication connection is broken during PSYNC so the replica doesn't get a
response from the master, it was not able to recognize that condition as a failure
and instead moved into the full-sync code path. This fix makes the replica fail and
retry the PSYNC with the master in such scenarios.
2022-05-16 12:08:19 +03:00
Qu Chen
a7d6ca9770
Make the check for if script is running or not consistent (#10725)
sometimes it is using `scriptIsRunning()` and other times it is using `server.in_script`.
We should use the `scriptIsRunning()` method consistently throughout the code base.
Removed server.in_script sine it's no longer used / needed.
2022-05-15 14:07:45 +03:00
Tian
4b262182d9
Remove a redundant free in freeClient (#10721) 2022-05-14 19:38:26 -07:00
Stephen Sullivan
acd517c883
re-add SENTINEL SLAVES command, missing in redis 7.0 (#10723)
Alias was mistakenly forgotten when the sub commands introduced as json files.
2022-05-13 19:47:58 +03:00
Wen Hui
135998ed8d
Update comments on command args, and a misleading error reply (#10645)
Updated the comments for:
info command
lmpopCommand and blmpopCommand
sinterGenericCommand 

Fix the missing "key" words in the srandmemberCommand function
For LPOS command, when rank is 0, prompt user that rank could be
positive number or negative number, and add a test for it
2022-05-13 17:55:49 +03:00
yoav-steinberg
b16d1c2713
Fix possible regression around TLS config changes. Add VOLATILE_CONFIG flag for volatile configurations. (#10713)
This fixes a possible regression in Redis 7.0.0, in which doing CONFIG SET
on a TLS config would not reload the configuration in case the new config is
the same file as before.

A volatile configuration is a configuration value which is a reference to the
configuration data and not the configuration data itself. In such a case Redis
doesn't know if the config data changed under the hood and can't assume a
change happens only when the config value changes. Therefore it needs to
be applied even when setting a config value to the same value as it was before.
2022-05-12 17:06:26 +03:00
Yossi Gottlieb
8bdd2d5ddd
Fix Makefile.dep generation with ICC. (#10708)
Before this commit, all source files including those that are not going
to be compiled were used. Some of these files are platform specific and
won't even pre-process on another platform. With GCC/Clang, that's not
an issue and they'll simply ignore them, but ICC aborts in this case.

This commit only attempts to generate Makefile.dep from the actual set
of C source files that will be compiled.
2022-05-11 12:06:33 +03:00
Binbin
bfbb15f75d
redis-server command line arguments support take one bulk string with spaces for MULTI_ARG configs parsing. And allow options value to use the -- prefix (#10660)
## Take one bulk string with spaces for MULTI_ARG configs parsing
Currently redis-server looks for arguments that start with `--`,
and anything in between them is considered arguments for the config.
like: `src/redis-server --shutdown-on-sigint nosave force now --port 6380`

MULTI_ARG configs behave differently for CONFIG command, vs the command
line argument for redis-server.
i.e. CONFIG command takes one bulk string with spaces in it, while the
command line takes an argv array with multiple values.

In this PR, in config.c, if `argc > 1` we can take them as is,
and if the config is a `MULTI_ARG` and `argc == 1`, we will split it by spaces.

So both of these will be the same:
```
redis-server --shutdown-on-sigint nosave force now --shutdown-on-sigterm nosave force
redis-server --shutdown-on-sigint nosave "force now" --shutdown-on-sigterm nosave force
redis-server --shutdown-on-sigint nosave "force now" --shutdown-on-sigterm "nosave force"
```

## Allow options value to use the `--` prefix
Currently it decides to switch to the next config, as soon as it sees `--`, 
even if there was not a single value provided yet to the last config,
this makes it impossible to define a config value that has `--` prefix in it.

For instance, if we want to set the logfile to `--my--log--file`,
like `redis-server --logfile --my--log--file --loglevel verbose`,
current code will handle that incorrectly.

In this PR, now we allow a config value that has `--` prefix in it.
**But note that** something like `redis-server --some-config --config-value1 --config-value2 --loglevel debug`
would not work, because if you want to pass a value to a config starting with `--`, it can only be a single value.
like: `redis-server --some-config "--config-value1 --config-value2" --loglevel debug`

An example (using `--` prefix config value):
```
redis-server --logfile --my--log--file --loglevel verbose
redis-cli config get logfile loglevel
1) "loglevel"
2) "verbose"
3) "logfile"
4) "--my--log--file"
```

### Potentially breaking change
`redis-server --save --loglevel verbose` used to work the same as `redis-server --save "" --loglevel verbose`
now, it'll error!
2022-05-11 11:33:35 +03:00
Binbin
783b210db4
FLUSHDB and FLUSHALL add call forceCommandPropagation / FLUSHALL reset dirty counter to 0 if we enable save (#10691)
## FLUSHALL
We used to restore the dirty counter after `rdbSave` zeroed it if we enable save.
Otherwise FLUSHALL will not be replicated nor put into the AOF.

And then we do increment it again below.
Without that extra dirty++, when db was already empty, FLUSHALL
will not be replicated nor put into the AOF.

We now gonna replace all that dirty counter magic with a call
to forceCommandPropagation (REPL and AOF), instead of all the
messing around with the dirty counter.
Added tests to cover three part (dirty counter, REPL, AOF).

One benefit other than cleaner code is that the `rdb_changes_since_last_save` is correct in this case.

## FLUSHDB
FLUSHDB was not replicated nor put into the AOF when db was already empty.
Unlike DEL on a non-existing key, FLUSHDB always does something, and that's to call the module hook. 
So basically FLUSHDB is never a NOP, and thus it should always be propagated.
Not doing that, could mean that if a module does something in that hook, and wants to
avoid issues of that hook being missing on the replica if the db is empty, it'll need to do complicated things.

So now FLUSHDB add call forceCommandPropagation, we will always propagate FLUSHDB.
Always propagating FLUSHDB seems like a safe approach that shouldn't have any drawbacks (other than looking odd)

This was mentioned in #8972

## Test section:
We actually found it while solving a race condition in the BGSAVE test (other.tcl).
It was found in extra_ci Daily Arm64 (test-libc-malloc).
```
[exception]: Executing test client: ERR Background save already in progress.
ERR Background save already in progress
```

It look like `r flushdb` trigger (schedule) a bgsave right after `waitForBgsave r` and before `r save`.
Changing flushdb to flushall, FLUSHALL will do a foreground save and then set the dirty counter to 0.
2022-05-11 11:21:16 +03:00
guybe7
815a6f846a
Dediacted member to hold RedisModuleCommand (#10681)
Fix #10552

We no longer piggyback getkeys_proc to hold the RedisModuleCommand struct, when exists

Others:
Use `doesCommandHaveKeys` in `RM_GetCommandKeysWithFlags` and `getKeysSubcommandImpl`.
It causes a very minor behavioral change in commands that don't have actual keys, but have a spec
with `CMD_KEY_NOT_KEY`.
For example, before this command `COMMAND GETKEYS SPUBLISH` would return
`Invalid arguments specified for command` but not it returns `The command has no key arguments`
2022-05-10 14:56:12 +03:00
Mariya Markova
c2d8d4e648
Replace float zero comparison to FP_ZERO comparison (#10675)
I suggest to use "[fpclassify](https://en.cppreference.com/w/cpp/numeric/math/fpclassify)" for float
comparison with zero, because of expression "value == 0" with value very close to zero can be
considered as true with some performance compiler optimizations.

Note: this code was introduced by 9d520a7f to accept zset scores that get ERANGE in conversion
due to precision loss near 0.
But with Intel compilers, ICC and ICX, where optimizations for 0 check are more aggressive, "==0" is
true for mentioned functions, however should not be. Behavior is seen starting from O2.
This leads to a failure in the ZSCAN test in scan.tcl
2022-05-10 14:55:09 +03:00
Binbin
2a1ea8c7d8
CLUSTER SHARDS should returns slots as integers, not strings (#10683)
It used to returns slots as strings, like:
```
redis> cluster shards
1) 1) "slots"
   2) 1) "10923"
      2) "16383"
```

CLUSTER SHARDS docs and the top comment of #10293 says that it returns integers.
Note other commands like CLUSTER SLOTS, it returns slots as integers.
Use addReplyLongLong instead of addReplyBulkLongLong, now it returns slots as integers:
```
redis> cluster shards
1) 1) "slots"
   2) 1) (integer) 10923
      2) (integer) 16383
```

This is a small breaking change, introduced in 7.0.0 (7.0 RC3, #10293)

Fixes #10680
2022-05-10 14:22:01 +03:00
Meir Shpilraien (Spielrein)
442e73ea09
Fix #10705, avoid relinking the same library twice. (#10706)
Set `old_li` to NULL to avoid linking it again on error.
Before the fix, loading an already existing library will cause the existing library to be added again. This cause not harm other then wrong statistics. The statistics that are effected  by the issue are:
* `libraries_count` and `functions_count` returned by `function stats` command
* `used_memory_functions` returned on `info memory` command
* `functions.caches` returned on `memory stats` command
2022-05-10 11:47:45 +03:00
Ozan Tezcan
a3df2777e8
Fix cursor type in RedisModuleScanCursor (#10698)
Changed cursor's type from `int` to `unsigned long`
allows handling database or key with more than 2^31 elements
2022-05-09 18:45:51 +03:00
Lu JJ
6b44e4ea92
fix some typos in "t_zset.c" (#10670)
fix some typo in "t_zset.c".
1. `zzlisinlexrange` the function name mentioned in the comment is misspelled.
2. fix typo in function name`zarndmemberReplyWithListpack` -> `zrandmemberReplyWithListpack`
2022-05-09 15:04:39 +03:00
Oran Agra
2bcd890d8a
Fix --save command line regression in redis 7.0.0 (#10690)
Unintentional change in #9644 (since RC1) meant that an empty `--save ""` config
from command line, wouldn't have clear any setting from the config file

Added tests to cover that, and improved test infra to take additional
command line args for redis-server
2022-05-09 13:37:49 +03:00
Oran Agra
eb915a82a5
Bug fixes for enum configs with overlapping bit flags (module API) (#10661)
If we want to support bits that can be overlapping, we need to make sure
that:
1. we don't use the same bit for two return values.
2. values should be sorted so that prefer ones (matching more
   bits) come first.
2022-05-09 13:36:53 +03:00
Ozan Tezcan
8fc959216c
Fix RM_Scan() documentation (#10693)
Fixed RM_Scan() usage example: `RedisModuleCursor` -> `RedisModuleScanCursor`
2022-05-09 12:38:45 +03:00
David CARLIER
bdcd4b3df8
zmalloc_get_rss implementation for haiku. (#10687)
also fixing already defined constants build warning while at it.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-05-08 15:12:17 +03:00
Shaya Potter
4e761eb7e2
update redismodule notify defines to be in sync with server (#10688)
this seems to have been an oversight. syncing the flags so that NOTIFY_NEW is available to modules.
missing in #10512
2022-05-08 15:05:24 +03:00
Meir Shpilraien (Spielrein)
f44c343292
Expose Lua error in case of string error. (#10677)
In general, our error handler make sure the error
object is always a table. In some rare cases (such
as OOM error), the error handler will not be called
and the error object will be a string. The PR expose
the error even if its a string and not a table.

Currently there is no way to test it but if it'll ever happen,
it is better to propagate this string upwards than just
generate a generic error without any specific info.
2022-05-03 10:24:05 +03:00
Lu JJ
87131a5fa6
fast path when SDIFF command has the same key as the first key (#10663)
When user uses the same input key for SDIFF as the first one, the result must be empty, so we don't need to process the elements to test.

This method is like the one done in zset‘s `zsetChooseDiffAlgorithm`

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-05-02 16:18:11 +03:00
wutao_water
9c39256a28
cleanup: use ZIPLIST_ENTRY_END macro instead of 1 (#3672)
update macros ZIPLIST_ENTRY_END i think the right definition is ((zl)+intrev32ifbe(ZIPLIST_BYTES(zl))-ZIPLIST_END_SIZE)
2022-05-02 12:46:48 +03:00
David CARLIER
ef68deb3c2
support tcp-keepalive config interval on macOs (#10667)
Till now, on MacOS we only used to enable SO_KEEPALIVE,
but we didn't set the interval which is configurable via the `tcp-keepalive` config.
This adds support for that on MacOS, to match what we already do on Linux.
2022-05-02 09:37:14 +03:00
Lu JJ
1666ffbe1f
fix typo in 'setTypeRandomElement' (#10662)
`the redis object pointer was populated.` -> `the sds pointer was populated.`
We don't populate the redis object pointer in this function.
2022-05-01 12:09:44 +03:00
Lu JJ
02080f2686
add comment to 'container' in 'quicklist.h' (#10656)
add a comment to `container` in `quicklist.h`.
Because `PLAIN` and `PACKED` are not as easy to understand as `NONE`
and `LISTPACK` and we don't have a detailed comment on it.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-04-28 08:36:40 +03:00
Wen Hui
f36eac9f68
Update the comments of commands introduced or updated in redis 7.0 (#10659) 2022-04-28 08:13:04 +03:00
Oran Agra
89772ed827
Merge pull request #10651 from oranagra/meir_lua_readonly_tables
# Lua readonly tables
The PR adds support for readonly tables on Lua to prevent security vulnerabilities:
* (CVE-2022-24736) An attacker attempting to load a specially crafted Lua script
  can cause NULL pointer dereference which will result with a crash of the
  redis-server process. This issue affects all versions of Redis.
* (CVE-2022-24735) By exploiting weaknesses in the Lua script execution
  environment, an attacker with access to Redis can inject Lua code that will
  execute with the (potentially higher) privileges of another Redis user.

The PR is spitted into 4 commits.

### Change Lua to support readonly tables

This PR modifies the Lua interpreter code to support a new flag on tables. The new flag indicating that the table is readonly and any attempt to perform any writes on such a table will result in an error. The new feature can be turned off and on using the new `lua_enablereadonlytable` Lua API. The new API can be used **only** from C code. Changes to support this feature was taken from https://luau-lang.org/

### Change eval script to set user code on Lua registry

Today, Redis wrap the user Lua code with a Lua function. For example, assuming the user code is:

```
return redis.call('ping')
```

The actual code that would have sent to the Lua interpreter was:

```
f_b3a02c833904802db9c34a3cf1292eee3246df3c() return redis.call('ping') end
```

The warped code would have been saved on the global dictionary with the following name: `f_<script sha>` (in our example `f_b3a02c833904802db9c34a3cf1292eee3246df3c`). This approach allows one user to easily override the implementation of another user code, example:

```
f_b3a02c833904802db9c34a3cf1292eee3246df3c = function() return 'hacked' end
```

Running the above code will cause `evalsha b3a02c833904802db9c34a3cf1292eee3246df3c 0` to return `hacked` although it should have returned `pong`. Another disadvantage is that Redis basically runs code on the loading (compiling) phase without been aware of it. User can do code injection like this:

```
return 1 end <run code on compling phase> function() return 1
```

The warped code will look like this and the entire `<run code on compiling phase>` block will run outside of eval or evalsha context:

```
f_<sha>() return 1 end <run code on compling phase> function() return 1 end
```

The commits puts the user code on a special Lua table called the registry. This table is not accessible to the user so it can not be manipulated by him. Also there is no longer a need to warp the user code so there is no risk in code injection which will cause running code in the wrong context.

### Use `lua_enablereadonlytable` to protect global tables on eval and function

The commit uses the new `lua_enablereadonlytable` Lua API to protect the global tables of both evals scripts and functions. For eval scripts, the implementation is easy, We simply call `lua_enablereadonlytable` on the global table to turn it into a readonly table.

On functions its more complected, we want to be able to switch globals between load run and function run. To achieve this, we create a new empty table that acts as the globals table for function, we control the actual globals using metatable manipulations. Notice that even if the user gets a pointer to the original tables, all the tables are set to be readonly (using `lua_enablereadonlytable` Lua API) so he can not change them. The following better explains the solution:

```
Global table {} <- global table metatable {.__index = __real_globals__}
```

The `__real_globals__` is depends on the run context (function load or function call).

Why is this solution needed and its not enough to simply switch globals? When we run in the context of function load and create our functions, our function gets the current globals that was set when they were created. Replacing the globals after the creation will not effect them. This is why this trick it mandatory.

### Protect the rest of the global API and add an allowed list to the provided API

The allowed list is done by setting a metatable on the global table before initialising any library. The metatable set the `__newindex` field to a function that check the allowed list before adding the field to the table. Fields which is not on the
allowed list are simply ignored.

After initialisation phase is done we protect the global table and each table that might be reachable from the global table. For each table we also protect the table metatable if exists.

### Performance

Performance tests was done on a private computer and its only purpose is to show that this fix is not causing any performance regression.

case 1: `return redis.call('ping')`
case 2: `for i=1,10000000 do redis.call('ping') end`

|                             | Unstable eval | Unstable function | lua_readonly_tables eval | lua_readonly_tables function |
|-----------------------------|---------------|-------------------|--------------------------|------------------------------|
| case1 ops/sec               | 235904.70     | 236406.62         | 232180.16               | 230574.14                   |
| case1 avg latency ms        | 0.175         | 0.164             | 0.178                    | 0.149                        |
| case2 total time in seconds | 3.373         | 3.444s            | 3.268                   | 3.278                        |

### Breaking changes

* `print` function was removed from Lua because it can potentially cause the Redis processes to get stuck (if no one reads from stdout). Users should use redis.log. An alternative is to override the `print` implementation and print the message to the log file.

All the work by @MeirShpilraien, i'm just publishing it.
2022-04-27 12:48:51 +03:00
chenyang8094
e24d46004b
Delete renamed new incr when write manifest failed (#10649)
Followup fix for #10616
2022-04-27 08:07:52 +03:00
meir
efa162bcd7 Protect any table which is reachable from globals and added globals white list.
The white list is done by setting a metatable on the global table before initializing
any library. The metatable set the `__newindex` field to a function that check
the white list before adding the field to the table. Fields which is not on the
white list are simply ignored.

After initialization phase is done we protect the global table and each table
that might be reachable from the global table. For each table we also protect
the table metatable if exists.
2022-04-27 00:37:40 +03:00
meir
3731580b6b Protect globals of both evals scripts and functions.
Use the new `lua_enablereadonlytable` Lua API to protect the global tables of
both evals scripts and functions. For eval scripts, the implemetation is easy,
We simply call `lua_enablereadonlytable` on the global table to turn it into
a readonly table.

On functions its more complecated, we want to be able to switch globals between
load run and function run. To achieve this, we create a new empty table that
acts as the globals table for function, we control the actual globals using metatable
manipulation. Notice that even if the user gets a pointer to the original tables, all
the tables are set to be readonly (using `lua_enablereadonlytable` Lua API) so he can
not change them. The following inlustration better explain the solution:

```
Global table {} <- global table metatable {.__index = __real_globals__}
```

The `__real_globals__` is set depends on the run context (function load or function call).

Why this solution is needed and its not enough to simply switch globals?
When we run in the context of function load and create our functions, our function gets
the current globals that was set when they were created. Replacing the globals after
the creation will not effect them. This is why this trick it mandatory.
2022-04-27 00:37:40 +03:00
meir
992f9e23c7 Move user eval function to be located on Lua registry.
Today, Redis wrap the user Lua code with a Lua function.
For example, assuming the user code is:

```
return redis.call('ping')
```

The actual code that would have sent to the Lua interpreter was:

```
f_b3a02c833904802db9c34a3cf1292eee3246df3c() return redis.call('ping') end
```

The wraped code would have been saved on the global dictionary with the
following name: `f_<script sha>` (in our example `f_b3a02c833904802db9c34a3cf1292eee3246df3c`).

This approach allows one user to easily override the implementation a another user code, example:

```
f_b3a02c833904802db9c34a3cf1292eee3246df3c = function() return 'hacked' end
```

Running the above code will cause `evalsha b3a02c833904802db9c34a3cf1292eee3246df3c 0` to return
hacked although it should have returned `pong`.

Another disadventage is that Redis basically runs code on the loading (compiling) phase without been
aware of it. User can do code injection like this:

```
return 1 end <run code on compling phase> function() return 1
```

The wraped code will look like this and the entire `<run code on compling phase>` block will run outside
of eval or evalsha context:

```
f_<sha>() return 1 end <run code on compling phase> function() return 1 end
```
2022-04-27 00:20:54 +03:00
Oran Agra
8192625458
Add module API flag for using enum configs as bit flags (#10643)
Enables registration of an enum config that'll let the user pass multiple keywords that
will be combined with `|` as flags into the integer config value.

```
    const char *enum_vals[] = {"none", "one", "two", "three"};
    const int int_vals[] = {0, 1, 2, 4};

    if (RedisModule_RegisterEnumConfig(ctx, "flags", 3, REDISMODULE_CONFIG_DEFAULT | REDISMODULE_CONFIG_BITFLAGS, enum_vals, int_vals, 4, getFlagsConfigCommand, setFlagsConfigCommand, NULL, NULL) == REDISMODULE_ERR) {
        return REDISMODULE_ERR;
    }
```
doing:
`config set moduleconfigs.flags "two three"` will result in 6 being passed to`setFlagsConfigCommand`.
2022-04-26 20:29:20 +03:00
chenyang8094
46ec6ad98e
Fix bug when AOF enabled after startup. put the new incr file in the manifest only when AOFRW is done. (#10616)
Changes:

- When AOF is enabled **after** startup, the data accumulated during `AOF_WAIT_REWRITE`
  will only be stored in a temp INCR AOF file. Only after the first AOFRW is successful, we will
  add it to manifest file.
  Before this fix, the manifest referred to the temp file which could cause a restart during that
  time to load it without it's base.
- Add `aof_rewrites_consecutive_failures` info field for  aofrw limiting implementation.

Now we can guarantee that these behaviors of MP-AOF are the same as before (past redis releases):
- When AOF is enabled after startup, the data accumulated during `AOF_WAIT_REWRITE` will only
  be stored in a visible place. Only after the first AOFRW is successful, we will add it to manifest file.
- When disable AOF, we did not delete the AOF file in the past so there's no need to change that
  behavior now (yet).
- When toggling AOF off and then on (could be as part of a full-sync), a crash or restart before the
  first rewrite is completed, would result with the previous version being loaded (might not be right thing,
  but that's what we always had).
2022-04-26 16:31:19 +03:00
Eduardo Semprebon
3a1d14259d
Allow configuring signaled shutdown flags (#10594)
The SHUTDOWN command has various flags to change it's default behavior,
but in some cases establishing a connection to redis is complicated and it's easier
for the management software to use signals. however, so far the signals could only
trigger the default shutdown behavior.
Here we introduce the option to control shutdown arguments for SIGTERM and SIGINT.

New config options:
`shutdown-on-sigint [nosave | save] [now] [force]` 
`shutdown-on-sigterm [nosave | save] [now] [force]`

Implementation:
Support MULTI_ARG_CONFIG on createEnumConfig to support multiple enums to be applied as bit flags.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-04-26 14:34:04 +03:00
Binbin
156836bfe5
Fix syntax error in replicationErrorBehavior enum (#10642)
Missing a typeof, we will get errors like this:
- multiple definition of `replicationErrorBehavior'
- ld: error: duplicate symbol: replicationErrorBehavior

Introduced in #10504
2022-04-26 14:29:05 +03:00
Madelyn Olson
6fa8e4f7af
Set replicas to panic on disk errors, and optionally panic on replication errors (#10504)
* Till now, replicas that were unable to persist, would still execute the commands
  they got from the master, now they'll panic by default, and we add a new
  `replica-ignore-disk-errors` config to change that.
* Till now, when a command failed on a replica or AOF-loading, it only logged a
  warning and a stat, we add a new `propagation-error-behavior` config to allow
  panicking in that state (may become the default one day)

Note that commands that fail on the replica can either indicate a bug that could
cause data inconsistency between the replica and the master, or they could be
in some cases (specifically in previous versions), a result of a command (e.g. EVAL)
that failed on the master, but still had to be propagated to fail on the replica as well.
2022-04-26 13:25:33 +03:00
Madelyn Olson
efcd1bf394
By default prevent cross slot operations in functions and scripts with # (#10615)
Adds the `allow-cross-slot-keys` flag to Eval scripts and Functions to allow
scripts to access keys from multiple slots.
The default behavior is now that they are not allowed to do that (unlike before).
This is a breaking change for 7.0 release candidates (to be part of 7.0.0), but
not for previous redis releases since EVAL without shebang isn't doing this check.

Note that the check is done on both the keys declared by the EVAL / FCALL command
arguments, and also the ones used by the script when making a `redis.call`.

A note about the implementation, there seems to have been some confusion
about allowing access to non local keys. I thought I missed something in our
wider conversation, but Redis scripts do block access to non-local keys.
So the issue was just about cross slots being accessed.
2022-04-26 12:09:21 +03:00
Oran Agra
79ffc3524d
fix broken protocol regression from #10612 (#10639)
A change in #10612 introduced a regression.
when replying with garbage bytes to the caller, we must make sure it
doesn't include any newlines.

in the past it called rejectCommandFormat which did that trick.
but now it calls rejectCommandSds, which doesn't, so we need to make sure
to sanitize the sds.
2022-04-26 00:34:01 +03:00
Binbin
119ec91a5a
Fix typos and limit unknown command error message (#10634)
minor cleanup for recent changes.
2022-04-25 17:59:39 +03:00
Lu JJ
0c35f54f0a
fix an unclear comment and add a comment to 'zi' in 'quicklist.h' (#10633)
fix an unclear comment quicklist container formats to quicklist node container formats
Add a comment to 'zi' in quicklistIter (Where it first appeared)
Why do I add a comment to zi:
Because it is not a variable name with a clear meaning, and its name seems to be from the deprecated ziplist.
2022-04-25 17:47:45 +03:00
guybe7
df787764e3
Fix regression not aborting transaction on error, and re-edit some error responses (#10612)
1. Disk error and slave count checks didn't flag the transactions or counted correctly in command stats (regression from #10372  , 7.0 RC3)
2. RM_Call will reply the same way Redis does, in case of non-exisitng command or arity error
3. RM_WrongArtiy will consider the full command name
4. Use lowercase 'u' in "unknonw subcommand" (to align with "unknown command")

Followup work of #10127
2022-04-25 13:08:13 +03:00
guybe7
8ad0cfa56c
isSafeToPerformEvictions: Remove redundant condition (#10610)
If was first added in #9890 to solve the problem of
CONFIG SET maxmemory causing eviction inside MULTI/EXEC,
but that problem is already fixed (CONFIG SET doesn't evict
directly, it just schedules a later eviction)

Keep that condition may hide bugs (i.e. performEvictions
should always expect to have an empty server.also_propagate)
2022-04-24 16:12:00 +03:00
Lu JJ
698e7cbba6
Fix typo in function name "harndfieldReplyWithListpack" to "hrandfieldReplyWithListpack" (#10623) 2022-04-24 10:21:04 +03:00
Lu JJ
719b766586
fix typo in "lcsCommand" doc comment (#10622)
fix typo. `LCS[j+(blen+1)*j]` -> `LCS[j+(blen+1)*i]`
2022-04-24 10:19:46 +03:00
filipe oliveira
3cd8baf616
Optimization: Use either monotonic or wall-clock to measure command execution time, to regain up to 4% execution time (#10502)
In #7491 (part of redis 6.2), we started using the monotonic timer instead of mstime to measure
command execution time for stats, apparently this meant sampling the clock 3 times per command
rather than two (wince we also need the wall-clock time).
In some cases this causes a significant overhead.

This PR fixes that by avoiding the use of monotonic timer, except for the cases were we know it
should be extremely fast.
This PR also adds a new INFO field called `monotonic_clock` that shows which clock redis is using.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-04-20 14:00:30 +03:00
Oran Agra
ee220599b0
Fixes around clients that must be obeyed. Replica report disk errors in PING. (#10603)
This PR unifies all the places that test if the current client is the
master client or AOF client, and uses a method to test that on all of
these.

Other than some refactoring, these are the actual implications:
- Replicas **don't** ignore disk error when processing commands not
  coming from their master.
  **This is important for PING to be used for health check of replicas**
- SETRANGE, APPEND, SETBIT, BITFIELD don't do proto_max_bulk_len check for AOF
- RM_Call in SCRIPT_MODE ignores disk error when coming from master /
  AOF
- RM_Call in cluster mode ignores slot check when processing AOF
- Scripts ignore disk error when processing AOF
- Scripts **don't** ignore disk error on a replica, if the command comes
  from clients other than the master
- SCRIPT KILL won't kill script coming from AOF
- Scripts **don't** skip OOM check on replica if the command comes from
  clients other than the master

Note that Script, AOF, and module clients don't reach processCommand,
which is why some of the changes don't actually have any implications.

Note, reverting the change done to processCommand in 2f4240b9d9
should be dead code due to the above mentioned fact.
2022-04-20 11:11:21 +03:00
menwen
046654a70e
Stop RDB child before flushing and parsing the RDB in Diskless replication too (#10602)
We should stop RDB child in advance before flushing to reduce COW in diskless replication too.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-04-20 09:54:55 +03:00
yoav-steinberg
5075e74366
Optimized hdr_value_at_percentile (#10606)
`hdr_value_at_percentile()` is part of the Hdr_Histogram library
used when generating `latencystats` report. 

There's a pending optimization for this function which greatly
affects the performance of `info latencystats`.
https://github.com/HdrHistogram/HdrHistogram_c/pull/107

This PR:
1. Upgrades the sources in _deps/hdr_histogram_ to the latest Hdr_Histogram
  version 0.11.5
2. Applies the referenced optimization.
3. Adds minor documentation about the hdr_histogram dependency which was
  missing under _deps/README.md_.

benchmark on my machine:
running: `redis-benchmark -n 100000 info latencystats` on a clean build with no data.

| benchmark | RPS |
| ---- | ---- |
| before upgrade to v0.11.05  | 7,681 |
| before optimization | 12,474 |
| after optimization | 52,606 |

Co-authored-by: filipe oliveira <filipecosta.90@gmail.com>
2022-04-20 09:38:20 +03:00
David CARLIER
aba2865c86
Add socket-mark-id support for marking sockets. (#10349)
Add a configuration option to attach an operating system-specific identifier to Redis sockets, supporting advanced network configurations using iptables (Linux) or ipfw (FreeBSD).
2022-04-20 09:29:37 +03:00
Moti Cohen
295cbf297f
Add comment to sdsConfigSet() (#10605)
Improve comments to explain the code

Co-authored-by: moticless <moticless@github.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
2022-04-19 14:22:16 +03:00
judeng
d4cbd8140b
Fixes around AOF failed rewrite rate limiting (#10582)
Changes:
1. Check the failed rewrite time threshold only when we actually consider triggering a rewrite.
  i.e. this should be the last condition tested, since the test has side effects (increasing time threshold)
  Could have happened in some rare scenarios 
2. no limit in startup state (e.g. after restarting redis that previously failed and had many incr files)
3. the “triggered the limit” log would be recorded only when the limit status is returned
4. remove failure count in log (could be misleading in some cases)

Co-authored-by: chenyang8094 <chenyang8094@users.noreply.github.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
2022-04-19 12:06:39 +03:00
sundb
1a93804645
Return 0 when config set out-of-range oom-score-adj-values (#10601)
When oom-score-adj-values is out of range, setConfigOOMScoreAdjValuesOption
should return 0, not -1, otherwise it will be considered as success.
2022-04-19 11:31:15 +03:00
Moti Cohen
85899e359e
Fix sdsConfigRewrite() to prevent freeing invalid memory(#10598) 2022-04-18 20:04:10 -07:00
Oran Agra
7d1ad6ca96
Fix RM_Yield bug processing future commands of the current client. (#10573)
RM_Yield was missing a call to protectClient to prevent redis from
processing future commands of the yielding client.

Adding tests that fail without this fix.

This would be complicated to solve since nested calls to RM_Call used to
replace the current_client variable with the module temp client.

It looks like it's no longer necessary to do that, since it was added
back in #9890 to solve two issues, both already gone:
1. call to CONFIG SET maxmemory could trigger a module hook calling
   RM_Call. although this specific issue is gone, arguably other hooks
   like keyspace notification, can do the same.
2. an assertion in lookupKey that checks the current command of the
   current client, introduced in #9572 and removed in #10248
2022-04-18 14:56:00 +03:00
Binbin
fe4b4806b3
Fix long long to double implicit conversion warning (#10595)
There is a implicit conversion warning in clang:
```
util.c:574:23: error: implicit conversion from 'long long' to 'double'
changes value from -4611686018427387903 to -4611686018427387904
[-Werror,-Wimplicit-const-int-float-conversion]
    if (d < -LLONG_MAX/2 || d > LLONG_MAX/2)
```

introduced in #10486

Co-authored-by: sundb <sundbcn@gmail.com>
2022-04-18 08:34:22 +03:00
Oran Agra
0c4733c8d7
Optimize integer zset scores in listpack (converting to string and back) (#10486)
When the score doesn't have fractional part, and can be stored as an integer,
we use the integer capabilities of listpack to store it, rather than convert it to string.
This already existed before this PR (lpInsert dose that conversion implicitly).

But to do that, we would have first converted the score from double to string (calling `d2string`),
then pass the string to `lpAppend` which identified it as being an integer and convert it back to an int.
Now, instead of converting it to a string, we store it using lpAppendInteger`.

Unrelated:
---
* Fix the double2ll range check (negative and positive ranges, and also the comparison operands
  were slightly off. but also, the range could be made much larger, see comment).
* Unify the double to string conversion code in rdb.c with the one in util.c
* Small optimization in lpStringToInt64, don't attempt to convert strings that are obviously too long.

Benchmark;
---
Up to 20% improvement in certain tight loops doing zzlInsert with large integers.
(if listpack is pre-allocated to avoid realloc, and insertion is sorted from largest to smaller)
2022-04-17 17:16:46 +03:00
guybe7
f49ff156ec
Add RM_PublishMessageShard (#10543)
since PUBLISH and SPUBLISH use different dictionaries for channels and clients,
and we already have an API for PUBLISH, it only makes sense to have one for SPUBLISH

Add test coverage and unifying some test infrastructure.
2022-04-17 15:43:22 +03:00
Wang Yuan
a9d5cfa99b
Optimize the call of prepareReplicasToWrite (#10588)
From #9166, we call several times of prepareReplicasToWrite when propagating
one write command to replication stream (once per argument, same as we do for
normal clients), that is not necessary. Now we only call it one time per command
at the begin of feeding replication stream.

This results in reducing CPU consumption and slightly better performance,
specifically when there are many replicas.
2022-04-17 09:41:46 +03:00
guybe7
fe1c096b18
Add RM_MallocSizeString, RM_MallocSizeDict (#10542)
Add APIs to allow modules to compute the memory consumption of opaque objects owned by redis.
Without these, the mem_usage callbacks of module data types are useless in many cases.

Other changes:
Fix streamRadixTreeMemoryUsage to include the size of the rax structure itself
2022-04-17 08:31:57 +03:00
Madelyn Olson
effa707e9d
Fix incorrect error code for eval scripts and fix test error checking (#10575)
By the convention of errors, there is supposed to be a space between the code and the name.
While looking at some lua stuff I noticed that interpreter errors were not adding the space,
so some clients will try to map the detailed error message into the error.

We have tests that hit this condition, but they were just checking that the string "starts" with ERR.
I updated some other tests with similar incorrect string checking. This isn't complete though, as
there are other ways we check for ERR I didn't fix.

Produces some fun output like:
```
# Errorstats
errorstat_ERR:count=1
errorstat_ERRuser_script_1_:count=1
```
2022-04-14 11:18:32 +03:00
Oran Agra
95050f2683
solve corrupt dump fuzzer crash in streams (#10579)
we had a panic in streamLastValidID when the stream metadata
said it's not empty, but the rax is empty.
2022-04-14 08:29:35 +03:00
Wen Hui
ca913a5de0
Fix several document error and function comments (#10580)
This PR fix the following minor errors before Redis 7 release:

ZRANGEBYLEX command in deprecated in 6.2.0, and could be replaced by ZRANGE with the
BYLEX argument, but in the document, the words is written incorrect in " by ZRANGE with the BYSCORE argument"

Fix function zpopmaxCommand incorrect comment

The comments of function zmpopCommand and bzmpopCommand are not consistent with document description, fix them

Co-authored-by: Ubuntu <lucas.guang.yang1@huawei.com>
2022-04-13 21:18:37 +03:00
filipe oliveira
a642947e04
Optimize stream id sds creation on XADD key * (~20% saved cpu cycles) (#10574)
we can observe that when adding to a stream without ID there is a duplicate work
on sds creation/freeing/sdslen that costs ~11% of the CPU cycles. 

This PR avoids it by not freeing the sds after the first reply. 
The expected reduction in CPU cycles is around 9-10% 

Additionally, we now pre-allocate the sds to the right size, to avoid realloc.
this brought another ~10% improvement

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-04-13 12:29:24 +03:00
Luke Palmer
bb7891f080
Keyspace event for new keys (#10512)
Add an optional keyspace event when new keys are added to the db.

This is useful for applications where clients need to be aware of the redis keyspace.
Such an application can SCAN once at startup and then listen for "new" events (plus
others associated with DEL, RENAME, etc).
2022-04-13 11:36:38 +03:00
guybe7
e875ff89ec
Add the deprecated_since field in command args of COMMAND DOCS (#10545)
Apparently, some modules can afford deprecating command arguments
(something that was never done in Redis, AFAIK), so in order to represent
this piece of information, we added the `deprecated_since` field to redisCommandArg
(in symmetry to the already existing `since` field).

This commit adds `const char *deprecated_since` to `RedisModuleCommandArg`,
which is technically a breaking change, but since 7.0 was not released yet, we decided to let it slide
2022-04-13 11:33:36 +03:00
Yossi Gottlieb
bd8da0ca29
Fix error/warning on Arm due to unsigned char. (#10572) 2022-04-12 18:55:11 +03:00
Madelyn Olson
8bd01a07ae
Allow specifying ACL reason for module log entry (#10559)
Allow specifying an ACL log reason, which is shown in the log. Right now it always shows "unknown", which is a little bit cryptic. This is a breaking change, but this API was added as part of 7 so it seems ok to stabilize it still.
2022-04-11 22:16:17 -07:00
Ernesto Rodriguez Reina
4c6d9bbd62
Extending the use of hashTypeGetValue. (#10567)
* Extending the use of hashTypeGetValue.

Functions hashTypeExists, hashTypeGetValueLength and addHashFieldToReply
have a similar pattern on calling hashTypeGetFromHashTable or
hashTypeGetFromZipList depending on the underlying data structure. What
does functions are duing is exactly what hashTypeGetValue does. Those
functions were changed to use existing function hashTypeGetValue making
the code more consistent.

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
2022-04-11 16:05:45 -07:00
zhaozhao.zz
1a7765cb7c
Durability enhancement for appendfsync=always policy (#9678)
Durability of database is a big and old topic, in this regard Redis use AOF to
support it, and `appendfsync=alwasys` policy is the most strict level, guarantee
all data is both written and synced on disk before reply success to client.

But there are some cases have been overlooked, and could lead to durability broken.

1. The most clear one is about threaded-io mode
   we should also set client's write handler with `ae_barrier` in
   `handleClientsWithPendingWritesUsingThreads`, or the write handler would be
   called after read handler in the next event loop, it means the write command result
   could be replied to client before flush to AOF.
2. About blocked client (mostly by module)
   in `beforeSleep()`, `handleClientsBlockedOnKeys()` should be called before
   `flushAppendOnlyFile()`, in case the unblocked clients modify data without persistence
   but send reply.
3. When handling `ProcessingEventsWhileBlocked`
   normally it takes place when lua/function/module timeout, and we give a chance to users
   to kill the slow operation, but we should call `flushAppendOnlyFile()` before
   `handleClientsWithPendingWrites()`, in case the other clients in the last event loop get
   acknowledge before data persistence.
   for a instance:
   ```
   in the same event loop
   client A executes set foo bar
   client B executes eval "for var=1,10000000,1 do end" 0
   ```
   after the script timeout, client A will get `OK` but lose data after restart (kill redis when
   timeout) if we don't flush the write command to AOF.
4. A more complex case about `ProcessingEventsWhileBlocked`
   it is lua timeout in transaction, for example
   `MULTI; set foo bar; eval "for var=1,10000000,1 do end" 0; EXEC`, then client will get set
   command's result before the whole transaction done, that breaks atomicity too.
   fortunately, it's already fixed by #5428 (although it's not the original purpose just a side
   effect : )), but module timeout should be fixed too.

case 1, 2, 3 are fixed in this commit, the module issue in case 4 needs a followup PR.
2022-04-11 11:08:39 +03:00
Evan
574ed6b0ce
modules: add RedisModuleKey* return type to RM_OpenKey (#3719)
Change `RM_OpenKey` to return `RedisModuleKey*` instead of `void*`.
Which is the input type of other APIs that take the value from RM_OpenKey.
2022-04-11 08:34:43 +03:00
guybe7
eeb0f1426c
Add RM_TryAlloc (#10541)
Similarly to LCS, some modules would want to try to allocate memory, and
fail gracefully if the allocation fails
2022-04-10 11:43:59 +03:00
guybe7
719db14ec7
COMMAND DOCS shows module name, where applicable (#10544)
Add field to COMMAND DOCS response to denote the name of the module
that added that command.
COMMAND LIST can filter by module, but if you get the full commands list,
you may still wanna know which command belongs to which module.
The alternative would be to do MODULE LIST, and then multiple calls to COMMAND LIST
2022-04-10 11:41:31 +03:00
cyhone
6cb5cbb28f
fix indent space (#10562) 2022-04-10 10:38:57 +03:00
zhl49
dd3b545d89
Fix an mistake in comment (#10560)
copy paste error..

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-04-10 09:29:50 +03:00
王恒
ee17e7af8d
improve malloc efficiency: reduce call times of zrealloc (#10533)
* improve malloc efficiency: reduce call times of zrealloc

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
2022-04-09 19:52:36 -07:00
chenyang8094
625bdaf3d1
Fix auto-aof-rewrite-percentage based AOFRW trigger after restart (#10550)
The `auto-aof-rewrite-percentage` config defines at what growth percentage
an automatic AOF rewrite is triggered.
This normally works OK since the size of the AOF file at the end of a rewrite
is stored in `server.aof_rewrite_base_size`.
However, on startup, redis used to store the entire size of the AOF file into that
variable, resulting in a wrong automatic AOF rewrite trigger (could have been
triggered much later than desired).
This issue would only affect the first AOFRW after startup, after that future AOFRW
would have been triggered correctly.
This bug existed in all previous versions of Redis.

This PR unifies the meaning of `server.aof_rewrite_base_size`, which only represents
the size of BASE AOF.
Note that after an AOFRW this size includes the size of the incremental file (all the
commands that executed during rewrite), so that auto-aof-rewrite-percentage is the
ratio from the size of the AOF after rewrite.
However, on startup, it is complicated to know that size, and we compromised on
taking just the size of the base file, this means that the first rewrite after startup can
happen a little bit too soon.

Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: yoav-steinberg <yoav@redislabs.com>
2022-04-07 14:47:07 +03:00
Oran Agra
451531f1c8
Fix RM_Yield bug (#10548)
The bug was when using REDISMODULE_YIELD_FLAG_CLIENTS.
in that case we would have only set the CLIENTS type flag in
server.busy_module_yield_flags and then clear that flag when exiting
RM_Yield, so we would never call unblockPostponedClients when the
context is destroyed.

This didn't really have any actual implication, which is why the tests
couldn't (and still can't) find that since the bug only happens when
using CLIENT, but in this case we won't have any clients to un-postpone
i.e. clients will get rejected with BUSY error, rather than being
postponed.

Unrelated:
* Adding tests for nested contexts, just in case.
* Avoid nested RM_Yield calls
2022-04-07 11:52:28 +03:00
Itamar Haber
3e09a8c097
Fixes commands' syntices (#10534)
Fixes in command argument in json files
* Fixes BITFIELD's syntax ("sub-commands" can be repeated, and OVERFLOW is only valid for SET and INCR)
* Improves readability of SET (reordered)
* Fixes GEOSEARCH and GEOSEARCH_RO syntices (use `oneof` for mutually exclusive group instead of `optional`)
* Fixes MIGRATE syntax (use `oneof` for mutually exclusive group instead of `optional`)
* Fixes MODULE LOADEX syntax (the `CONFIG` token should be repeated too when using multiple configs)

other:
* make generate-command-help.rb accept a path to commands.json, or read it from stdin (e.g. `generate-commands-json.py | generate-command-help.rb -`)
2022-04-06 09:33:33 +03:00
Lu JJ
f110de4b23
Fix the bug that caused hash encoding errors when using hincrbyfloat or hincrby commands (#10479)
Fixed a bug that used the `hincrbyfloat` or `hincrby` commands to make the field or value exceed the
`hash_max_listpack_value` but did not change the object encoding of the hash structure.

Add a length check for field and value, check the length of value first, if the length of value does not
exceed `hash_max_listpack_value` then check the length of field.

If the length of field or value is too long, it will reduce the efficiency of listpack, and the object encoding
will become hashtable after AOF restart, so this is also to keep the same before and after AOF restart.
2022-04-05 21:45:45 +03:00
judeng
8a7049d363
use $^ instead of $< for linker in module makefile (#10530) 2022-04-05 17:08:27 +03:00
Oran Agra
acfb4f7a44
update static help.h from redis.io commands.json (#10529) 2022-04-05 12:09:51 +03:00
Madelyn Olson
4ffcec29af
Update json command files so they only include syntax related information (#10398)
The command json documents should just include information about the "arguments" and the "outputs".
I removed all of the 'functional wording' so it's clear.
2022-04-05 10:36:06 +03:00
Meir Shpilraien (Spielrein)
ae020e3d56
Functions: Move library meta data to be part of the library payload. (#10500)
## Move library meta data to be part of the library payload.

Following the discussion on https://github.com/redis/redis/issues/10429 and the intention to add (in the future) library versioning support, we believe that the entire library metadata (like name and engine) should be part of the library payload and not provided by the `FUNCTION LOAD` command. The reasoning behind this is that the programmer who developed the library should be the one who set those values (name, engine, and in the future also version). **It is not the responsibility of the admin who load the library into the database.**

The PR moves all the library metadata (engine and function name) to be part of the library payload. The metadata needs to be provided on the first line of the payload using the shebang format (`#!<engine> name=<name>`), example:

```lua
#!lua name=test
redis.register_function('foo', function() return 1 end)
```

The above script will run on the Lua engine and will create a library called `test`.

## API Changes (compare to 7.0 rc2)

* `FUNCTION LOAD` command was change and now it simply gets the library payload and extract the engine and name from the payload. In addition, the command will now return the function name which can later be used on `FUNCTION DELETE` and `FUNCTION LIST`.
* The description field was completely removed from`FUNCTION LOAD`, and `FUNCTION LIST`


## Breaking Changes (compare to 7.0 rc2)

* Library description was removed (we can re-add it in the future either as part of the shebang line or an additional line).
* Loading an AOF file that was generated by either 7.0 rc1 or 7.0 rc2 will fail because the old command syntax is invalid.

## Notes

* Loading an RDB file that was generated by rc1 / rc2 **is** supported, Redis will automatically add the shebang to the libraries payloads (we can probably delete that code after 7.0.3 or so since there's no need to keep supporting upgrades from an RC build).
2022-04-05 10:27:24 +03:00
bugwz
2db0d898f8
Cluster node name sanity check (#10391)
* Limit cluster node id length for CLUSTER commands loading
* Cluster node name sanity check for length and values

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
2022-04-04 22:51:51 -07:00
judeng
9578b67e0e
delete obsolete REDISMODULE_EXPERIMENTAL_API define in module demos (#10527)
This macro was recently removed from redismodule.h, so no longer needed.
2022-04-05 08:21:41 +03:00
chenyang8094
cb625844bf
Fix null pointer subtraction warning (#10498)
The warning:
```
pqsort.c:106:7: warning: performing pointer subtraction with a null pointer has undefined behavior [-Wnull-pointer-subtraction]
loop:   SWAPINIT(a, es);
        ^~~~~~~~~~~~~~~
pqsort.c:65:47: note: expanded from macro 'SWAPINIT'
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)NULL) % sizeof(long) || \
```
Clang version:
```
Apple clang version 13.1.6 (clang-1316.0.21.2)
Target: x86_64-apple-darwin21.3.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
```
2022-04-04 18:38:18 +03:00
Bofang Liu
8500ca4ae8
Fix mistake / outdated doc comment (#10521)
Unlike original reference code, Redis uses 64bit variable, so half the bits make it 32bit, not 16
2022-04-04 15:35:49 +03:00
Meir Shpilraien (Spielrein)
047b609335
Fix #10508, on error, pop function and error handler from Lua stack. (#10519)
If, for some reason, Redis decides not to execute the script, we need
to pop the function and error handler from Lua stack. Otherwise, eventually
the Lua stack will explode.

Relevant only for 7.0-rc1 and 7.0-rc2.
2022-04-04 10:58:59 +03:00
judeng
6cdaa27703
fix typos in aof.c (#10513)
function aofRewriteLimited in aof.c, deley->delay and NAX->MAX

Co-authored-by: judeng <judeng@didiglobal.com>
2022-04-04 08:38:41 +03:00
Viktor Söderqvist
b53c7f2c0b
Turn into replica on SETSLOT (#10489)
* Fix race condition where node loses its last slot and turns into replica

When a node has lost its last slot and finds out from the SETSLOT command
before the cluster bus PONG from the new owner arrives. In this case, the
node didn't turn itself into a replica of the new slot owner.

This commit adds the same logic to the SETSLOT command as already exists
for the cluster bus PONG processing.

* Revert "Fix new / failing cluster slot migration test (#10482)"

This reverts commit 0b21ef8d49.

In this test, the old slot owner finds out that it has lost its last
slot in a nondeterministic way. Either the cluster bus PONG from the
new slot owner and sometimes in a SETSLOT command from redis-cli. In
both cases, the result should be the same and the old owner should
turn itself into a replica of the new slot owner.
2022-04-02 14:58:07 -07:00
Ozan Tezcan
7da1cc3e90
Use exit code 1 on error in redis-cli (#10468)
On error, redis-cli was returning `REDIS_ERR` on some cases by mistake. `REDIS_ERR` is `-1` which becomes `255` as exit code. This commit changes it and returns `1` on errors to be consistent.
2022-03-30 21:16:02 +03:00
Nick Chun
bda9d74dad
Module Configurations (#10285)
This feature adds the ability to add four different types (Bool, Numeric,
String, Enum) of configurations to a module to be accessed via the redis
config file, and the CONFIG command.

**Configuration Names**:

We impose a restriction that a module configuration always starts with the
module name and contains a '.' followed by the config name. If a module passes
"config1" as the name to a register function, it will be registered as MODULENAME.config1.

**Configuration Persistence**:

Module Configurations exist only as long as a module is loaded. If a module is
unloaded, the configurations are removed.
There is now also a minimal core API for removal of standardConfig objects
from configs by name.

**Get and Set Callbacks**:

Storage of config values is owned by the module that registers them, and provides
callbacks for Redis to access and manipulate the values.
This is exposed through a GET and SET callback.

The get callback returns a typed value of the config to redis. The callback takes
the name of the configuration, and also a privdata pointer. Note that these only
take the CONFIGNAME portion of the config, not the entire MODULENAME.CONFIGNAME.

```
 typedef RedisModuleString * (*RedisModuleConfigGetStringFunc)(const char *name, void *privdata);
 typedef long long (*RedisModuleConfigGetNumericFunc)(const char *name, void *privdata);
 typedef int (*RedisModuleConfigGetBoolFunc)(const char *name, void *privdata);
 typedef int (*RedisModuleConfigGetEnumFunc)(const char *name, void *privdata);
```

Configs must also must specify a set callback, i.e. what to do on a CONFIG SET XYZ 123
or when loading configurations from cli/.conf file matching these typedefs. *name* is
again just the CONFIGNAME portion, *val* is the parsed value from the core,
*privdata* is the registration time privdata pointer, and *err* is for providing errors to a client.

```
typedef int (*RedisModuleConfigSetStringFunc)(const char *name, RedisModuleString *val, void *privdata, RedisModuleString **err);
typedef int (*RedisModuleConfigSetNumericFunc)(const char *name, long long val, void *privdata, RedisModuleString **err);
typedef int (*RedisModuleConfigSetBoolFunc)(const char *name, int val, void *privdata, RedisModuleString **err);
typedef int (*RedisModuleConfigSetEnumFunc)(const char *name, int val, void *privdata, RedisModuleString **err);
```

Modules can also specify an optional apply callback that will be called after
value(s) have been set via CONFIG SET:

```
typedef int (*RedisModuleConfigApplyFunc)(RedisModuleCtx *ctx, void *privdata, RedisModuleString **err);
```

**Flags:**
We expose 7 new flags to the module, which are used as part of the config registration.

```
#define REDISMODULE_CONFIG_MODIFIABLE 0 /* This is the default for a module config. */
#define REDISMODULE_CONFIG_IMMUTABLE (1ULL<<0) /* Can this value only be set at startup? */
#define REDISMODULE_CONFIG_SENSITIVE (1ULL<<1) /* Does this value contain sensitive information */
#define REDISMODULE_CONFIG_HIDDEN (1ULL<<4) /* This config is hidden in `config get <pattern>` (used for tests/debugging) */
#define REDISMODULE_CONFIG_PROTECTED (1ULL<<5) /* Becomes immutable if enable-protected-configs is enabled. */
#define REDISMODULE_CONFIG_DENY_LOADING (1ULL<<6) /* This config is forbidden during loading. */
/* Numeric Specific Configs */
#define REDISMODULE_CONFIG_MEMORY (1ULL<<7) /* Indicates if this value can be set as a memory value */
```

**Module Registration APIs**:

```
int (*RedisModule_RegisterBoolConfig)(RedisModuleCtx *ctx, char *name, int default_val, unsigned int flags, RedisModuleConfigGetBoolFunc getfn, RedisModuleConfigSetBoolFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata);
int (*RedisModule_RegisterNumericConfig)(RedisModuleCtx *ctx, const char *name, long long default_val, unsigned int flags, long long min, long long max, RedisModuleConfigGetNumericFunc getfn, RedisModuleConfigSetNumericFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata);
int (*RedisModule_RegisterStringConfig)(RedisModuleCtx *ctx, const char *name, const char *default_val, unsigned int flags, RedisModuleConfigGetStringFunc getfn, RedisModuleConfigSetStringFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata);
int (*RedisModule_RegisterEnumConfig)(RedisModuleCtx *ctx, const char *name, int default_val, unsigned int flags, const char **enum_values, const int *int_values, int num_enum_vals, RedisModuleConfigGetEnumFunc getfn, RedisModuleConfigSetEnumFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata);
int (*RedisModule_LoadConfigs)(RedisModuleCtx *ctx);
```

The module name will be auto appended along with a "." to the front of the name of the config.

**What RM_Register[...]Config does**:

A RedisModule struct now keeps a list of ModuleConfig objects which look like:
```
typedef struct ModuleConfig {
    sds name; /* Name of config without the module name appended to the front */
    void *privdata; /* Optional data passed into the module config callbacks */
    union get_fn { /* The get callback specificed by the module */
        RedisModuleConfigGetStringFunc get_string;
        RedisModuleConfigGetNumericFunc get_numeric;
        RedisModuleConfigGetBoolFunc get_bool;
        RedisModuleConfigGetEnumFunc get_enum;
    } get_fn;
    union set_fn { /* The set callback specified by the module */
        RedisModuleConfigSetStringFunc set_string;
        RedisModuleConfigSetNumericFunc set_numeric;
        RedisModuleConfigSetBoolFunc set_bool;
        RedisModuleConfigSetEnumFunc set_enum;
    } set_fn;
    RedisModuleConfigApplyFunc apply_fn;
    RedisModule *module;
} ModuleConfig;
```
It also registers a standardConfig in the configs array, with a pointer to the
ModuleConfig object associated with it.

**What happens on a CONFIG GET/SET MODULENAME.MODULECONFIG:**

For CONFIG SET, we do the same parsing as is done in config.c and pass that
as the argument to the module set callback. For CONFIG GET, we call the
module get callback and return that value to config.c to return to a client.

**CONFIG REWRITE**:

Starting up a server with module configurations in a .conf file but no module load
directive will fail. The flip side is also true, specifying a module load and a bunch
of module configurations will load those configurations in using the module defined
set callbacks on a RM_LoadConfigs call. Configs being rewritten works the same
way as it does for standard configs, as the module has the ability to specify a
default value. If a module is unloaded with configurations specified in the .conf file
those configurations will be commented out from the .conf file on the next config rewrite.

**RM_LoadConfigs:**

`RedisModule_LoadConfigs(RedisModuleCtx *ctx);`

This last API is used to make configs available within the onLoad() after they have
been registered. The expected usage is that a module will register all of its configs,
then call LoadConfigs to trigger all of the set callbacks, and then can error out if any
of them were malformed. LoadConfigs will attempt to set all configs registered to
either a .conf file argument/loadex argument or their default value if an argument is
not specified. **LoadConfigs is a required function if configs are registered.
** Also note that LoadConfigs **does not** call the apply callbacks, but a module
can do that directly after the LoadConfigs call.

**New Command: MODULE LOADEX [CONFIG NAME VALUE] [ARGS ...]:**

This command provides the ability to provide startup context information to a module.
LOADEX stands for "load extended" similar to GETEX. Note that provided config
names need the full MODULENAME.MODULECONFIG name. Any additional
arguments a module might want are intended to be specified after ARGS.
Everything after ARGS is passed to onLoad as RedisModuleString **argv.

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
Co-authored-by: Madelyn Olson <matolson@amazon.com>
Co-authored-by: sundb <sundbcn@gmail.com>
Co-authored-by: Madelyn Olson <34459052+madolson@users.noreply.github.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: Yossi Gottlieb <yossigo@gmail.com>
2022-03-30 15:47:06 +03:00
Binbin
e2fa6aa158
command json files cleanups (#10473)
This PR do some command json files cleanups:

1. Add COMMAND TIPS to some commands
- command-docs: add `NONDETERMINISTIC_OUTPUT_ORDER`
- command-info: add `NONDETERMINISTIC_OUTPUT_ORDER`
- command-list: add `NONDETERMINISTIC_OUTPUT_ORDER`
- command: change `NONDETERMINISTIC_OUTPUT` to `NONDETERMINISTIC_OUTPUT_ORDER`
- function-list: add `NONDETERMINISTIC_OUTPUT_ORDER`
- latency-doctor: add `NONDETERMINISTIC_OUTPUT`, `REQUEST_POLICY:ALL_NODES` and `RESPONSE_POLICY:SPECIAL`
- latency-graph: add `NONDETERMINISTIC_OUTPUT`, `REQUEST_POLICY:ALL_NODES` and `RESPONSE_POLICY:SPECIAL`
- memory-doctor: add `REQUEST_POLICY:ALL_SHARDS` and `RESPONSE_POLICY:SPECIAL`
- memory-malloc-stats: add `REQUEST_POLICY:ALL_SHARDS` and `RESPONSE_POLICY:SPECIAL`
- memory-purge: add `REQUEST_POLICY:ALL_SHARDS` and `RESPONSE_POLICY:ALL_SUCCEEDED`
- module-list: add `NONDETERMINISTIC_OUTPUT_ORDER`
- msetnx: add `REQUEST_POLICY:MULTI_SHARD` and `RESPONSE_POLICY:AGG_MIN`
- object-refcount: add `NONDETERMINISTIC_OUTPUT`
3. Only (mostly) indentation and formatting changes:
- cluster-shards
- latency-history
- pubsub-shardchannels
- pubsub-shardnumsub
- spublish
- ssubscribe
- sunsubscribe
4. add doc_flags (DEPRECATED) to cluster-slots,  replaced_by `CLUSTER SHARDS` in 7.0
5. command-getkeysandflags: a better summary (the old one is copy from command-getkeys)
6. adjustment of command parameter types
- `port` is integer, not string (`MIGRATE`, `REPLICAOF`, `SLAVEOF`)
- `replicationid` is string, not integer (`PSYNC`)
- `pattern` is pattern, not string (`PUBSUB CHANNELS`, `SENTINEL RESET`, `SORT`, `SORT_RO`)
2022-03-30 09:39:26 +03:00
Viktor Söderqvist
35bb021254
redis-cli: Do DNS lookup before sending CLUSTER MEET (#10436)
Affects `--cluster create` and `--cluster add-node`.
2022-03-29 15:45:14 +03:00
zhaozhao.zz
001e192575
show cluster.links in MEMORY STATS (#10302) 2022-03-29 16:54:45 +08:00
Oran Agra
3b1e65a32b
improve malloc efficiency for cluster slots_info_pairs (#10488)
This commit improve malloc efficiency of the slots_info_pairs mechanism in cluster.c
by changing adlist into an array being realloced with greedy growth mechanism

Recently the cluster tests are consistently failing when executed with ASAN in the CI.
I tried to track down the commit that started it, and it appears to be #10293.
Looking at the commit, i realize it didn't affect this test / flow, other than the
replacement of the slots_info_pairs from sds to list.

I concluded that what could be happening is that the slot range is very fragmented,
and that results in many allocations.
with sds, it results in one allocation and also, we have a greedy growth mechanism,
but with adlist, we just have many many small allocations.
this probably causes stress on ASAN, and causes it to be slow at termination.
2022-03-29 10:05:06 +03:00
Oran Agra
14b198868f
introduce MAX_D2STRING_CHARS instead of 128 const (#10487)
There are a few places that use a hard coded const of 128 to allocate a buffer for d2string.
Replace these with a clear macro.
Note that In theory, converting double into string could take as much as nearly 400 chars,
but since d2string uses `%g` and not `%f`, it won't pass some 40 chars.

unrelated:
restore some changes to auto generated commands.c that got accidentally reverted in #10293
2022-03-28 18:35:56 +03:00
Binbin
3f28d7d712
Make redis-cli --cluster help output to stdout (#10485)
redis-cli --cluster help currently outputs the help on stderr.
This is similar to #9124
2022-03-28 14:47:36 +03:00
DarrenJiang13
ae771ea77b
fix crash in debug protocol push (#10483)
a missing of resp3 judgement which may lead to the crash using `debug protocol push`
introduced in #9235
Similar improvement in RM_ReplySetAttributeLength in case the module ignored the
error that returned from RM_ReplyWithAttribute.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-03-28 11:54:34 +03:00
zhaozhao.zz
78bef6e1fe
optimize(remove) usage of client's pending_querybuf (#10413)
To remove `pending_querybuf`, the key point is reusing `querybuf`, it means master client's `querybuf` is not only used to parse command, but also proxy to sub-replicas.

1. add a new variable `repl_applied` for master client to record how many data applied (propagated via `replicationFeedStreamFromMasterStream()`) but not trimmed in `querybuf`.

2. don't sdsrange `querybuf` in `commandProcessed()`, we trim it to `repl_applied` after the whole replication pipeline processed to avoid fragmented `sdsrange`. And here are some scenarios we cannot trim to `qb_pos`:
    * we don't receive complete command from master
    * master client blocked because of client pause
    * IO threads operate read, master client flagged with CLIENT_PENDING_COMMAND

    In these scenarios, `qb_pos` points to the part of the current command or the beginning of next command, and the current command is not applied yet, so the `repl_applied` is not equal to `qb_pos`.

Some other notes:
* Do not do big arg optimization on master client, since we can only sdsrange `querybuf` after data sent to replicas.
* Set `qb_pos` and `repl_applied` to 0 when `freeClient` in `replicationCacheMaster`.
* Rewrite `processPendingCommandsAndResetClient` to `processPendingCommandAndInputBuffer`, let `processInputBuffer` to be called successively after `processCommandAndResetClient`.
2022-03-25 10:45:40 +08:00
Oran Agra
6761d10cc3
crash log, print killer pid only when si_code is SI_USER (#10454)
Avoid printing "Killed by PID" when si_code != SI_USER.
Apparently SI_USER isn't always set to 0. e.g. on Mac it's 0x10001 and the check that did <= was wrong.
2022-03-22 17:37:34 +02:00
Meir Shpilraien (Spielrein)
f3855a0930
Add new RM_Call flags for script mode, no writes, and error replies. (#10372)
The PR extends RM_Call with 3 new capabilities using new flags that
are given to RM_Call as part of the `fmt` argument.
It aims to assist modules that are getting a list of commands to be
executed from the user (not hard coded as part of the module logic),
think of a module that implements a new scripting language...

* `S` - Run the command in a script mode, this means that it will raise an
  error if a command which are not allowed inside a script (flaged with the
  `deny-script` flag) is invoked (like SHUTDOWN). In addition, on script mode,
  write commands are not allowed if there is not enough good replicas (as
  configured with `min-replicas-to-write`) and/or a disk error happened.

* `W` - no writes mode, Redis will reject any command that is marked with `write`
  flag. Again can be useful to modules that implement a new scripting language
  and wants to prevent any write commands.

* `E` - Return errors as RedisModuleCallReply. Today the errors that happened
  before the command was invoked (like unknown commands or acl error) return
  a NULL reply and set errno. This might be missing important information about
  the failure and it is also impossible to just pass the error to the user using
  RM_ReplyWithCallReply. This new flag allows you to get a RedisModuleCallReply
  object with the relevant error message and treat it as if it was an error that was
  raised by the command invocation.

Tests were added to verify the new code paths.

In addition small refactoring was done to share some code between modules,
scripts, and `processCommand` function:
1. `getAclErrorMessage` was added to `acl.c` to unified to log message extraction
  from the acl result
2. `checkGoodReplicasStatus` was added to `replication.c` to check the status of
  good replicas. It is used on `scriptVerifyWriteCommandAllow`, `RM_Call`, and
  `processCommand`.
3. `writeCommandsGetDiskErrorMessage` was added to `server.c` to get the error
  message on persistence failure. Again it is used on `scriptVerifyWriteCommandAllow`,
  `RM_Call`, and `processCommand`.
2022-03-22 14:13:28 +02:00
yiyuaner
08aed7e7dd
Fix an off by one error in zzlStrtod (#10465)
When vlen = sizeof(buf), the statement buf[vlen] = '\0' accessing the buffer buf is an off by one error.
2022-03-22 10:46:16 +02:00
zhaozhao.zz
79db037a4f
config rewrite enhancement, in case of line longer than 1024 (#8009)
When rewrite the config file, we need read the old config file first,
but the CONFIG_MAX_LEN is 1024, so if some lines are longer than it,
it will generate a wrong config file, and redis cannot reboot from
the new config file.

Rename CONFIG_MAX_LINE to CONFIG_READ_LEN
2022-03-22 16:34:01 +08:00
郭伟光
93dda65354
config rewrite failed save errno in case of being tainted (#10461)
errno would be potentially tainted during the serverLog() by the file io functions, such as fopen and fflush.
2022-03-21 14:20:23 +02:00
Ozan Tezcan
4517fadb59
Use exit code 1 if redis-cli fails to connect (#10438)
Use exit code 1 if redis-cli fails to connect.

Before https://github.com/redis/redis/pull/10382/, on a connection failure,
exit code would be 1.  After this PR, whether connection is established or not,
`noninteractive()` return value is used as the exit code. On a failure, this function
returns `REDIS_ERR` which is `-1`. It becomes `255` as exit codes are between `0-255`.

There is nothing wrong by returning 1 or 255 on failure as far as I know but it'll break
things that expect to see 1 as exit code on a connection failure. This is also how we
realized the issue. With this PR, changing behavior back to using 1 as exit code to
preserve backward compatibility.
2022-03-21 13:40:02 +02:00
guybe7
e82c1aedea
BITSET and BITFIELD SET should propagate even if just length changed (#10459)
Bug introduced in #9403, caused inconsistency between master and
replica in case just the length (i.e. set a high-index bit to 0)
changed.
2022-03-21 11:33:27 +02:00
Madelyn Olson
557222d1e0
Fix timing issue in shards test and fix displayed TLS port (#10450) 2022-03-20 22:08:40 -07:00
郭伟光
fae5b1a19d
unblockClient: avoid to reset client when the client was shutdown-blocked (#10440)
fix #10439. see https://github.com/redis/redis/pull/9872
When executing SHUTDOWN we pause the client so we can un-pause it
if the shutdown fails.
this could happen during the timeout, if the shutdown is aborted, but could
also happen from withing the initial `call()` to shutdown, if the rdb save fails.
in that case when we return to `call()`, we'll crash if `c->cmd` has been set to NULL.

The call stack is:
```
unblockClient(c)
replyToClientsBlockedOnShutdown()
cancelShutdown()
finishShutdown()
prepareForShutdown()
shutdownCommand()
```

what's special about SHUTDOWN in that respect is that it can be paused,
and then un-paused before the original `call()` returns.
tests where added for both failed shutdown, and a followup successful one.
2022-03-20 15:18:53 +02:00
carlosfu
b69636d377
fix wrong comment about cluster_announce_hostname (#10274) 2022-03-16 20:26:30 -07:00
Madelyn Olson
e8771efda9
Fixed incorrect parsing of hostname information from nodes.conf (#10435) 2022-03-16 14:07:24 -07:00
Viktor Söderqvist
69017fa232
Fix redis-cli CLUSTER SETSLOT race conditions (#10381)
After migrating a slot, send CLUSTER SETSLOT NODE to the destination
node first to make sure the slot isn't left without an owner in case
the destination node crashes before it is set as new owner.

When informing the source node, it can happen that the destination
node has already informed it and if the source node has lost its
last slot, it has already turned itself into a replica. Redis-cli
should ignore this error in this case.
2022-03-16 10:11:38 -07:00
Harkrishn Patro
45ccae89bb
Add new cluster shards command (#10293)
Implement a new cluster shards command, which provides a flexible and extensible API for topology discovery.

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
2022-03-15 18:24:40 -07:00
Madelyn Olson
416c9ac2ef
Add module API for redacting command arguments (#10425)
Add module API for redacting client commands
2022-03-15 18:21:13 -07:00
Wen Hui
c30de7073c
Sentinel: update command json files (#10374) 2022-03-15 18:38:07 +02:00
ranshid
1078e30c5f
make sort/ro commands validate external keys access patterns (#10106) (#10340)
Currently the sort and sort_ro can access external keys via `GET` and `BY`
in order to make sure the user cannot violate the authorization ACL
rules, the decision is to reject external keys access patterns unless ACL allows
SORT full access to all keys.
I.e. for backwards compatibility, SORT with GET/BY keeps working, but
if ACL has restrictions to certain keys, these features get permission denied.

### Implemented solution
We have discussed several potential solutions and decided to only allow the GET and BY
arguments when the user has all key permissions with the SORT command. The reasons
being that SORT with GET or BY is problematic anyway, for instance it is not supported in
cluster mode since it doesn't declare keys, and we're not sure the combination of that feature
with ACL key restriction is really required.
**HOWEVER** If in the fullness of time we will identify a real need for fine grain access
support for SORT, we would implement the complete solution which is the alternative
described below.

### Alternative (Completion solution):
Check sort ACL rules after executing it and before committing output (either via store or
to COB). it would require making several changes to the sort command itself. and would
potentially cause performance degradation since we will have to collect all the get keys
instead of just applying them to a temp array and then scan the access keys against the
ACL selectors. This solution can include an optimization to avoid the overheads of collecting
the key names, in case the ACL rules grant SORT full key-access, or if the ACL key pattern
literal matches the one used in GET/BY. It would also mean that authorization would be
O(nlogn) since we will have to complete most of the command execution before we can
perform verification

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
2022-03-15 17:14:53 +02:00
yoav-steinberg
cf6dcb7bf1
Optimization: remove updateClientMemUsage from i/o threads. (#10401)
In a benchmark we noticed we spend a relatively long time updating the client
memory usage leading to performance degradation.
Before #8687 this was performed in the client's cron and didn't affect performance.
But since introducing client eviction we need to perform this after filling the input
buffers and after processing commands. This also lead me to write this code to be
thread safe and perform it in the i/o threads.

It turns out that the main performance issue here is related to atomic operations
being performed while updating the total clients memory usage stats used for client
eviction (`server.stat_clients_type_memory[]`). This update needed to be atomic
because `updateClientMemUsage()` was called from the IO threads.

In this commit I make sure to call `updateClientMemUsage()` only from the main thread.
In case of threaded IO I call it for each client during the "fan-in" phase of the read/write
operation. This also means I could chuck the `updateClientMemUsageBucket()` function
which was called during this phase and embed it into `updateClientMemUsage()`.

Profiling shows this makes `updateClientMemUsage()` (on my x86_64 linux) roughly x4 faster.
2022-03-15 14:18:23 +02:00
DarrenJiang13
38ed6c6007
improve string2ll() to avoid extra conversion for long integer string. (#10408)
For an integer string like "123456789012345678901" which could cause
overflow-failure in string2ll() conversion, we could compare its length at
the beginning to avoid extra work.

* move LONG_STR_SIZE to be in declared in util.h, next to MAX_LONG_DOUBLE_CHARS
2022-03-14 08:22:57 +02:00
郭伟光
dc7a9d3a31
Cleanup: replicationFeedMonitors use the monitor list arg it got (#10417)
Better check the monitors list argument instead of server.monitors in the function,
although they are basically the same in the context, so this doesn't have any
impact on the current code.
2022-03-13 16:19:42 +02:00
Moti Cohen
a6bf509810
Sentinel: fix no reconnect after auth-pass is changed (#10400)
When updating SENTINEL with master’s new password (command:
`SENTINEL SET mymaster auth-pass some-new-password`), 
sentinel might still keep the old connection and avoid reconnecting 
with the new password. This is because of wrong logic that traces 
the last ping (pong) time to servers. In fact it worked fine until 8631e64 
changed the condition to send ping. To resolve it with minimal risk, 
let’s disconnect master and replicas once changing password/user. 

Based on earlier work of yz1509.
2022-03-13 10:13:47 +02:00
Wen Hui
b576fbc474
Remove redundancy GETNAME in client help command message (#10418)
probably a copy paste error.
2022-03-13 08:27:41 +02:00
Binbin
1797330e2e
Initialize help when using redis-cli help or redis-cli ? (#10382)
The following usage will output an empty newline:
```
> redis-cli help set
empty line
```

The reason is that in interactive mode, we have called
`cliInitHelp`, which initializes help.

When using `redis-cli help xxx` or `redis-cli help ? xxx`,
we can't match the command due to empty `helpEntries`,
so we output an empty newline.

In this commit, we will call `cliInitHelp` to init the help.
Note that in this case, we need to call `cliInitHelp` (COMMAND DOCS)
every time, which i think is acceptable.

So now the output will look like:
```
[redis]# src/redis-cli help get

  GET key
  summary: Get the value of a key
  since: 1.0.0
  group: string

[redis]#
```

Fixes #10378

This PR also fix a redis-cli crash when using `--ldb --eval`:
```
[root]# src/redis-cli --ldb --eval test.lua test 1
Lua debugging session started, please use:
quit    -- End the session.
restart -- Restart the script in debug mode again.
help    -- Show Lua script debugging commands.

* Stopped at 1, stop reason = step over
-> 1   local num = redis.call('GET', KEYS[1]);
redis-cli: redis-cli.c:718: cliCountCommands: Assertion
`commandTable->element[i]->type == 1' failed.
Aborted
```
Because in ldb mode, `COMMAND DOCS` or `COMMAND` will
return an array, only with one element, and the type
is `REDIS_REPLY_STATUS`, the result is `<error> Unknown
Redis Lua debugger command or wrong number of arguments`.

So if we are in the ldb mode, and init the Redis HELP, we
will get the wrong response and crash the redis-cli.
In ldb mode we don't initialize HELP, help is only initialized
after the lua debugging session ends.

It was broken in #10043
2022-03-10 18:20:01 +02:00
ranshid
11b071a22b
ACL DRYRUN does not validate the verified command args. (#10405)
As a result we segfault when parsing and matching the command keys.
2022-03-10 10:08:41 +02:00
zhugezy
a26cab9dd6
set "disable-thp" config immutable (#10409)
It's confusing for this config to be modifiable since it only takes effect on startup
2022-03-10 09:52:49 +02:00
rangerzhang
4e012daee9
Fix outdated comments on updateSlavesWaitingBgsave (#10394)
* fix-replication-comments

The described capacity
 `and to schedule a new BGSAVE if there are slaves that attached while a BGSAVE was in progress`
was moved to `checkChildrenDone()`  named by `replicationStartPendingFork`

But the comment was not changed, may misleading others.

* remove-misleading-comments

The described capacity
 `to schedule a new BGSAVE if there are slaves that attached while a BGSAVE was in progress` 
and 
`or when the replication RDB transfer strategy is modified from disk to socket or the other way around` 
were not correct now.
2022-03-10 09:51:55 +02:00
Oran Agra
311a757cb1
Some adjustments to command hints. (#10375)
* stats and latency commands have non-deterministic output.
* the ones about latency should be sent to ALL_NODES (considering
  reads from replicas)
* the ones about running scripts and memory usage only to masters.
* stats aggregation is SPECIAL (like in INFO)
2022-03-09 16:40:27 +02:00
a2tt
86ca9b25e2
fix typos (#10402) 2022-03-09 13:58:23 +02:00
蔡相跃
24da71e507
Fix typo "the the" (#10399) 2022-03-09 13:55:17 +02:00
sundb
adc5a3217c
Use dismissMemory to dismiss COW of client output buffer (#10403)
c->buf is not sds, so we should use dismissMemory instead of dismissSds to dismiss it.
This is a recent regression from #10371
2022-03-09 13:32:03 +02:00
guybe7
2a2954086a
XREADGROUP: Unblock client if stream is deleted (#10306)
Deleting a stream while a client is blocked XREADGROUP should unblock the client.

The idea is that if a client is blocked via XREADGROUP is different from
any other blocking type in the sense that it depends on the existence of both
the key and the group. Even if the key is deleted and then revived with XADD
it won't help any clients blocked on XREADGROUP because the group no longer
exist, so they would fail with -NOGROUP anyway.
The conclusion is that it's better to unblock these clients (with error) upon
the deletion of the key, rather than waiting for the first XADD. 

Other changes:
1. Slightly optimize all `serveClientsBlockedOn*` functions by checking `server.blocked_clients_by_type`
2. All `serveClientsBlockedOn*` functions now use a list iterator rather than looking at `listFirst`, relying
  on `unblockClient` to delete the head of the list. Before this commit, only `serveClientsBlockedOnStreams`
  used to work like that.
3. bugfix: CLIENT UNBLOCK ERROR should work even if the command doesn't have a timeout_callback
  (only relevant to module commands)
2022-03-08 17:10:36 +02:00
zhaozhao.zz
728e62523e
script should not allow may-replicate commands when client pause write (#10364)
In some special commands like eval_ro / fcall_ro we allow no-writes commands.
But may-replicate commands are no-writes too, that leads crash when client pause write:
2022-03-08 16:53:11 +02:00
Oran Agra
b3fe4f31a2
dismiss COW of client output buffer now that it's dynamic (#10371)
since #9822, the static reply buffer is no longer part of the client structure, so we need to dismiss it.
2022-03-08 15:17:15 +02:00
zhugezy
4f19b4d0c1
remove a piece of redundant comment (#10392)
introduced in #10147 since we blocked the first-arg mechanism on subcommands
2022-03-08 13:35:37 +02:00
Yossi Gottlieb
38052fd702
Fix redis-benchmark --cluster with IPv6. (#10393)
Currently, CLUSTER NODES is parsed and was not done correctly for IPv6
addresses.
2022-03-08 13:10:24 +02:00
Binbin
7ef68cd5ec
Add missing doc_flags to cluster-slaves (#10387)
Add `DEPRECATED` doc_flag.
2022-03-07 17:59:51 +02:00
Shaya Potter
23f03e7965
Modules: Add REDISMODULE_EVENT_CONFIG (#10311)
Add a new REDISMODULE_EVENT_CONFIG event type for notifying modules when Redis configuration changes.
2022-03-07 17:37:57 +02:00
Yuta Hongo
e3ef73dc2a
redis-cli: Better --json Unicode support and --quoted-json (#10286)
Normally, `redis-cli` escapes non-printable data received from Redis, using a custom scheme (which is also used to handle quoted input). When using `--json` this is not desired as it is not compatible with RFC 7159, which specifies JSON strings are assumed to be Unicode and how they should be escaped.

This commit changes `--json` to follow RFC 7159, which means that properly encoded Unicode strings in Redis will result with a valid Unicode JSON.

However, this introduces a new problem with `--json` and data that is not valid Unicode (e.g., random binary data, text that follows other encoding, etc.). To address this, we add `--quoted-json` which produces JSON strings that follow the original redis-cli quoting scheme.

For example, a value that consists of only null (0x00) bytes will show up as:
* `"\u0000\u0000\u0000"` when using `--json`
* `"\\x00\\x00\\x00"` when using `--quoted-json`
2022-03-05 21:25:52 +02:00
Binbin
af6d5c5932
Constrain cluster node name logging (#10376)
Cluster node name is not null terminated, so need to be constrained.
2022-03-02 22:41:31 -08:00
Henry
feb032fd42
A faster and more robust code of zslRandomLevel using RAND_MAX (#5539)
1. since ZSKIPLIST_P is float, using it directly inside the condition used to causes floating point code to be used (gcc/x86)
2. In some operating system(eg.Windows), the largest value returned from random() is 0x7FFF(15bit), so after bitwise AND with 0xFFFF, the probability of the less operation returning true in the while loop's condition is no more equal to ZSKIPLIST_P.
3. In case some library has random() returning int in range [0~ZSKIPLIST_P*65535], the while loop will be an infinite loop.
4. on Linux where RAND_MAX is higher than 0xFFFF, this change actually improves precision (despite not matching the result against a float value)
2022-03-02 10:40:39 +02:00
ranshid
9b15dd288e
Introduce debug command to disable reply buffer resizing (#10360)
In order to resolve some flaky tests which hard rely on examine memory footprint.
we introduce the following fixes:

# Fix in client-eviction test - by @yoav-steinberg 
Sometime the libc allocator can use different size client struct allocations.
this may cause unexpected memory calculations to fail the test.

# Introduce new DEBUG command for disabling reply buffer resizing
In order to eliminate reply buffer resizing during specific tests.
we introduced the ability to disable (and enable) the resizing cron job

Co-authored-by: yoav-steinberg yoav@redislabs.com
2022-03-01 14:40:29 +02:00
Madelyn Olson
4a45386e3c
Move most of the configuration to a hashtable (#10323)
* Moved configuration storage from a list to a hash table
* Configs are returned in a non-deterministic order. It's possible that a client was relying on order (hopefully not).
* Fixed an esoteric bug where if you did a set with an alias with an error, it would throw an error indicating a bug with the preferred name for that config.
2022-02-28 23:02:47 -08:00
Harkrishn Patro
21aabab401
Fix acl dryrun to return the tested common permission error. (#10359) 2022-02-28 20:26:58 -08:00
Vitah Lin
dff153ff24
Fix memory leak in RM_StreamIteratorStop and moduleFreeKeyIterator (#10353)
* Fix memory leak in RM_StreamIteratorStop
* Fix memory leak in moduleFreeKeyIterator
2022-02-28 17:06:39 +02:00
Oran Agra
fa5d90069f
update redis-cli help.h (#10352)
re-generate help.h from commands.json
2022-02-28 10:59:16 +02:00
Binbin
ad7a6275ff
Fix node-id type in cluster-setslot (#10348)
* The type of node-id should be string, not integer.
* Also improve the CLUSTER SETSLOT help message.
2022-02-27 23:46:57 -08:00
Meir Shpilraien (Spielrein)
aa856b39f2
Sort out the mess around Lua error messages and error stats (#10329)
This PR fix 2 issues on Lua scripting:
* Server error reply statistics (some errors were counted twice).
* Error code and error strings returning from scripts (error code was missing / misplaced).

## Statistics
a Lua script user is considered part of the user application, a sophisticated transaction,
so we want to count an error even if handled silently by the script, but when it is
propagated outwards from the script we don't wanna count it twice. on the other hand,
if the script decides to throw an error on its own (using `redis.error_reply`), we wanna
count that too.
Besides, we do count the `calls` in command statistics for the commands the script calls,
we we should certainly also count `failed_calls`.
So when a simple `eval "return redis.call('set','x','y')" 0` fails, it should count the failed call
to both SET and EVAL, but the `errorstats` and `total_error_replies` should be counted only once.

The PR changes the error object that is raised on errors. Instead of raising a simple Lua
string, Redis will raise a Lua table in the following format:

```
{
    err='<error message (including error code)>',
    source='<User source file name>',
    line='<line where the error happned>',
    ignore_error_stats_update=true/false,
}
```

The `luaPushError` function was modified to construct the new error table as describe above.
The `luaRaiseError` was renamed to `luaError` and is now simply called `lua_error` to raise
the table on the top of the Lua stack as the error object.
The reason is that since its functionality is changed, in case some Redis branch / fork uses it,
it's better to have a compilation error than a bug.

The `source` and `line` fields are enriched by the error handler (if possible) and the
`ignore_error_stats_update` is optional and if its not present then the default value is `false`.
If `ignore_error_stats_update` is true, the error will not be counted on the error stats.

When parsing Redis call reply, each error is translated to a Lua table on the format describe
above and the `ignore_error_stats_update` field is set to `true` so we will not count errors
twice (we counted this error when we invoke the command).

The changes in this PR might have been considered as a breaking change for users that used
Lua `pcall` function. Before, the error was a string and now its a table. To keep backward
comparability the PR override the `pcall` implementation and extract the error message from
the error table and return it.

Example of the error stats update:

```
127.0.0.1:6379> lpush l 1
(integer) 2
127.0.0.1:6379> eval "return redis.call('get', 'l')" 0
(error) WRONGTYPE Operation against a key holding the wrong kind of value. script: e471b73f1ef44774987ab00bdf51f21fd9f7974a, on @user_script:1.

127.0.0.1:6379> info Errorstats
# Errorstats
errorstat_WRONGTYPE:count=1

127.0.0.1:6379> info commandstats
# Commandstats
cmdstat_eval:calls=1,usec=341,usec_per_call=341.00,rejected_calls=0,failed_calls=1
cmdstat_info:calls=1,usec=35,usec_per_call=35.00,rejected_calls=0,failed_calls=0
cmdstat_lpush:calls=1,usec=14,usec_per_call=14.00,rejected_calls=0,failed_calls=0
cmdstat_get:calls=1,usec=10,usec_per_call=10.00,rejected_calls=0,failed_calls=1
```

## error message
We can now construct the error message (sent as a reply to the user) from the error table,
so this solves issues where the error message was malformed and the error code appeared
in the middle of the error message:

```diff
127.0.0.1:6379> eval "return redis.call('set','x','y')" 0
-(error) ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: OOM command not allowed when used memory > 'maxmemory'.
+(error) OOM command not allowed when used memory > 'maxmemory' @user_script:1. Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479)
```

```diff
127.0.0.1:6379> eval "redis.call('get', 'l')" 0
-(error) ERR Error running script (call to f_8a705cfb9fb09515bfe57ca2bd84a5caee2cbbd1): @user_script:1: WRONGTYPE Operation against a key holding the wrong kind of value
+(error) WRONGTYPE Operation against a key holding the wrong kind of value script: 8a705cfb9fb09515bfe57ca2bd84a5caee2cbbd1, on @user_script:1.
```

Notica that `redis.pcall` was not change:
```
127.0.0.1:6379> eval "return redis.pcall('get', 'l')" 0
(error) WRONGTYPE Operation against a key holding the wrong kind of value
```


## other notes
Notice that Some commands (like GEOADD) changes the cmd variable on the client stats so we
can not count on it to update the command stats. In order to be able to update those stats correctly
we needed to promote `realcmd` variable to be located on the client struct.

Tests was added and modified to verify the changes.

Related PR's: #10279, #10218, #10278, #10309

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-27 13:40:57 +02:00
filipe oliveira
9f30dd03cd
Enable redis-benchmark to use RESP3 protocol mode (#10335)
Adds `-3` option to cause redis-benchmark to send a `HELLO 3`
to it can benchmark the effects of RESP3 on the server.
2022-02-27 10:30:39 +02:00
Madelyn Olson
35fccd875a
Fixed typo in variable name (#10347) 2022-02-26 19:52:09 -08:00
filipe oliveira
1dc89e2d02
Optimization: Avoid deferred array reply on ZRANGE commands BYRANK (#10337)
Avoid deferred array reply on genericZrangebyrankCommand() when consumer type is client.
I.e. any ZRANGE / ZREVRNGE (when tank is used).
This was a performance regression introduced in #7844 (v 6.2) mainly affecting pipelined workloads.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-24 14:20:00 +02:00
Binbin
b4079abed4
Fix XGROUP HELP message missing a newline (#10339)
Add a comma, this would have resulted in missing newline in the message.
Forgot to add in #9127
2022-02-24 08:31:39 +02:00
Itamar Haber
c81c7f51c3
Add stream consumer group lag tracking and reporting (#9127)
Adds the ability to track the lag of a consumer group (CG), that is, the number
of entries yet-to-be-delivered from the stream.

The proposed constant-time solution is in the spirit of "best-effort."

Partially addresses #8737.

## Description of approach

We add a new "entries_added" property to the stream. This starts at 0 for a new
stream and is incremented by 1 with every `XADD`.  It is essentially an all-time
counter of the entries added to the stream.

Given the stream's length and this counter value, we can trivially find the logical
"entries_added" counter of the first ID if and only if the stream is contiguous.
A fragmented stream contains one or more tombstones generated by `XDEL`s.
The new "xdel_max_id" stream property tracks the latest tombstone.

The CG also tracks its last delivered ID's as an "entries_read" counter and
increments it independently when delivering new messages, unless the this
read counter is invalid (-1 means invalid offset). When the CG's counter is
available, the reported lag is the difference between added and read counters.

Lastly, this also adds a "first_id" field to the stream structure in order to make
looking it up cheaper in most cases.

## Limitations

There are two cases in which the mechanism isn't able to track the lag.
In these cases, `XINFO` replies with `null` in the "lag" field.

The first case is when a CG is created with an arbitrary last delivered ID,
that isn't "0-0", nor the first or the last entries of the stream. In this case,
it is impossible to obtain a valid read counter (short of an O(N) operation).
The second case is when there are one or more tombstones fragmenting
the stream's entries range.

In both cases, given enough time and assuming that the consumers are
active (reading and lacking) and advancing, the CG should be able to
catch up with the tip of the stream and report zero lag.
Once that's achieved, lag tracking would resume as normal (until the
next tombstone is set).

## API changes

* `XGROUP CREATE` added with the optional named argument `[ENTRIESREAD entries-read]`
  for explicitly specifying the new CG's counter.
* `XGROUP SETID` added with an optional positional argument `[ENTRIESREAD entries-read]`
  for specifying the CG's counter.
* `XINFO` reports the maximal tombstone ID, the recorded first entry ID, and total
  number of entries added to the stream.
* `XINFO` reports the current lag and logical read counter of CGs.
* `XSETID` is an internal command that's used in replication/aof. It has been added with
  the optional positional arguments `[ENTRIESADDED entries-added] [MAXDELETEDID max-deleted-entry-id]`
  for propagating the CG's offset and maximal tombstone ID of the stream.

## The generic unsolved problem

The current stream implementation doesn't provide an efficient way to obtain the
approximate/exact size of a range of entries. While it could've been nice to have
that ability (#5813) in general, let alone specifically in the context of CGs, the risk
and complexities involved in such implementation are in all likelihood prohibitive.

## A refactoring note

The `streamGetEdgeID` has been refactored to accommodate both the existing seek
of any entry as well as seeking non-deleted entries (the addition of the `skip_tombstones`
argument). Furthermore, this refactoring also migrated the seek logic to use the
`streamIterator` (rather than `raxIterator`) that was, in turn, extended with the
`skip_tombstones` Boolean struct field to control the emission of these.

Co-authored-by: Guy Benoish <guy.benoish@redislabs.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-23 22:34:58 +02:00
filipe oliveira
b857928ba7
Optimize deferred replies to use shared objects instead of sprintf (#10334)
Avoid sprintf/ll2string on setDeferredAggregateLen()/addReplyLongLongWithPrefix() when we can used shared objects.
In some pipelined workloads this achieves about 10% improvement.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-23 18:15:12 +02:00
Moti Cohen
a7179e7570
Sentinel: fix a free-after-use issue re-registering Sentinels. (#10333)
In case HELLO message received from another sentinel, with same address like another instance registered in the past but with different runid. Then there was cumbersome logic to modify the instance the port to 0 to in order to mark as invalid and later on to delete it. But the deletion is happening during update of instances in such a way that we might end up accessing an instance that was deleted just before.

Didn't find a good reason why to postpone the deletion action of an obsolete instance (deletion is taking place instantly, for other cases ) -> Lets delete at once
There is a mixture of logic of Sentinel address update with the logic of deletion of Sentinels that match a given Address -> Split to two!
2022-02-23 17:59:22 +02:00
Wen Hui
de6be8850f
Fix PUBSUB SHARDNUMSUB command json file (#10331)
argument was missing, affecting redis.io docs
2022-02-22 23:29:29 +02:00
Andy Pan
496375fc36
Reduce system calls of write for client->reply by introducing writev (#9934)
There are scenarios where it results in many small objects in the reply list,
such as commands heavily using deferred array replies (`addReplyDeferredLen`).
E.g. what COMMAND command and CLUSTER SLOTS used to do (see #10056, #7123),
but also in case of a transaction or a pipeline of commands that use just one differed array reply.

We used to have to run multiple loops along with multiple calls to `write()` to send data back to
peer based on the current code, but by means of `writev()`, we can gather those scattered
objects in reply list and include the static reply buffer as well, then send it by one system call,
that ought to achieve higher performance.

In the case of TLS,  we simply check and concatenate buffers into one big buffer and send it
away by one call to `connTLSWrite()`, if the amount of all buffers exceeds `NET_MAX_WRITES_PER_EVENT`,
then invoke `connTLSWrite()` multiple times to avoid a huge massive of memory copies.

Note that aside of reducing system calls, this change will also reduce the amount of
small TCP packets sent.
2022-02-22 14:00:37 +02:00
Viktor Söderqvist
e9ae03787e
Delete key doesn't dirty client who watched stale key (#10256)
When WATCH is called on a key that's already logically expired, avoid discarding the
transaction when the keys is actually deleted.

When WATCH is called, a flag is stored if the key is already expired
at the time of watch. The expired key is not deleted, only checked.

When a key is "touched", if it is deleted and it was already expired
when a client watched it, the client is not marked as dirty.

Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: zhaozhao.zz <zhaozhao.zz@alibaba-inc.com>
2022-02-22 12:09:46 +02:00
ranshid
47c51d0c78
introduce dynamic client reply buffer size - save memory on idle clients (#9822)
Current implementation simple idle client which serves no traffic still
use ~17Kb of memory. this is mainly due to a fixed size reply buffer
currently set to 16kb.

We have encountered some cases in which the server operates in a low memory environments.
In such cases a user who wishes to create large connection pools to support potential burst period,
will exhaust a large amount of memory  to maintain connected Idle clients.
Some users may choose to "sacrifice" performance in order to save memory.

This commit introduce a dynamic mechanism to shrink and expend the client reply buffer based on
periodic observed peak.
the algorithm works as follows:
1. each time a client reply buffer has been fully written, the last recorded peak is updated: 
new peak = MAX( last peak, current written size)
2. during clients cron we check for each client if the last observed peak was:
     a. matching the current buffer size - in which case we expend (resize) the buffer size by 100%
     b. less than half the buffer size - in which case we shrink the buffer size by 50%
3. In any case we will **not** resize the buffer in case:
    a. the current buffer peak is less then the current buffer usable size and higher than 1/2 the
      current buffer usable size
    b. the value of (current buffer usable size/2) is less than 1Kib
    c. the value of  (current buffer usable size*2) is larger than 16Kib
4. the peak value is reset to the current buffer position once every **5** seconds. we maintain a new
   field in the client structure (buf_peak_last_reset_time) which is used to keep track of how long it
   passed since the last buffer peak reset.

### **Interface changes:**
**CIENT LIST** - now contains 2 new extra fields:
rbs= < the current size in bytes of the client reply buffer >
rbp=< the current value in bytes of the last observed buffer peak position >

**INFO STATS** - now contains 2 new statistics:
reply_buffer_shrinks = < total number of buffer shrinks performed >
reply_buffer_expends = < total number of buffer expends performed >

Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: Yoav Steinberg <yoav@redislabs.com>
2022-02-22 11:19:38 +02:00
Madelyn Olson
71204f9632
Implemented module getchannels api and renamed channel keyspec (#10299)
This implements the following main pieces of functionality:
* Renames key spec "CHANNEL" to be "NOT_KEY", and update the documentation to
  indicate it's for cluster routing and not for any other key related purpose.
* Add the getchannels-api, so that modules can now define commands that are subject to
  ACL channel permission checks. 
* Add 4 new flags that describe how a module interacts with a command (SUBSCRIBE, PUBLISH,
  UNSUBSCRIBE, and PATTERN). They are all technically composable, however not sure how a
  command could both subscribe and unsubscribe from a command at once, but didn't see
  a reason to add explicit validation there.
* Add two new module apis RM_ChannelAtPosWithFlags and RM_IsChannelsPositionRequest to
  duplicate the functionality provided by the keys position APIs.
* The RM_ACLCheckChannelPermissions (only released in 7.0 RC1) was changed to take flags
  rather than a boolean literal.
* The RM_ACLCheckKeyPermissions (only released in 7.0 RC1) was changed to take flags
  corresponding to keyspecs instead of custom permission flags. These keyspec flags mimic
  the flags for ACLCheckChannelPermissions.
2022-02-22 11:00:03 +02:00
Binbin
c4c68f5d41
Remove ALLOW_BUSY from REPLICAOF and add it to REPLCONF. Add DEPRECATED doc flag to SLAVEOF, mark it as deprecated. (#10315)
* Remove ALLOW_BUSY from REPLICAOF and add it to REPLCONF
* mark SLAVEOF as deprecated
2022-02-22 10:55:54 +02:00
chenyang8094
4916d79fbd
Fix path copy error and add more logs. (#10324)
Since we didn't copy the null terminator to temp_filepath, dirname could return the wrong result.
2022-02-22 10:09:34 +02:00
YaacovHazan
65e4bce0e7
fix return value of loadAppendOnlyFiles (#10295)
Make sure the status return from loading multiple AOF files reflects the overall
result, not just the one of the last file.

When one of the AOF files succeeded to load, but the last AOF file
was empty, the loadAppendOnlyFiles will return AOF_EMPTY.
This commit changes this behavior, and return AOF_OK in that case.

This can happen for example, when loading old AOF file, and no more commands processed,
the manifest file will include base AOF file with data, and empty incr AOF file.

Co-authored-by: chenyang8094 <chenyang8094@users.noreply.github.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-22 08:59:23 +02:00
Oran Agra
fad0b0d2a6
Fix error stats and failed command stats for blocked clients (#10309)
This is a followup work for #10278, and a discussion about #10279

The changes:
- fix failed_calls in command stats for blocked clients that got error.
  including CLIENT UNBLOCK, and module replying an error from a thread.
- fix latency stats for XREADGROUP that filed with -NOGROUP

Theory behind which errors should be counted:
- error stats represents errors returned to the user, so an error handled by a
  module should not be counted.
- total error counter should be the same.
- command stats represents execution of commands (even with RM_Call, and if
  they fail or get rejected it counts these calls in commandstats, so it should
  also count failed_calls)

Some thoughts about Scripts:
for scripts it could be different since they're part of user code, not the infra (not an extension to redis)
we certainly want commandstats to contain all calls and errors
a simple script is like mult-exec transaction so an error inside it should be counted in error stats
a script that replies with an error to the user (using redis.error_reply) should also be counted in error stats
but then the problem is that a plain `return redis.call("SET")` should not be counted twice (once for the SET
and once for EVAL)
so that's something left to be resolved in #10279
2022-02-21 11:20:41 +02:00
yoav-steinberg
b59bb9b476
Fix script active defrag test (#10318)
This includes two fixes:
* We forgot to count non-key reallocs in defragmentation stats.
* Fix the script defrag tests so to make dict entries less signigicant in fragmentation by making the scripts larger.
This assures active defrage will complete and reach desired results.
Some inherent fragmentation might exists in dict entries which we need to ignore.
This lead to occasional CI failures.
2022-02-21 09:37:25 +02:00
qetu3790
b2d393b990
Fix geo search bounding box check causing missing results (#10018)
Consider the following example:
1. geoadd k1 -0.15307903289794921875 85 n1 0.3515625 85.00019260486917005437 n2.
2. geodist k1 n1 n2 returns  "4891.9380"
3. but GEORADIUSBYMEMBER k1 n1 4891.94 m only returns n1.
n2 is in the  boundingbox but out of search areas.So we let  search areas contain boundingbox to get n2.

Co-authored-by: Binbin <binloveplay1314@qq.com>
2022-02-21 08:06:58 +02:00
rangerzhang
9b0fd9f4d0
Fix a mistake in comments (#10312)
There is no variable named by REPL_STATE_RECEIVE_PSYNC_REPLY, it should be REPL_STATE_RECEIVE_PSYNC_REPLY according to the contexts.
2022-02-20 08:09:19 +02:00
Binbin
c0ea77f0e1
Show publishshard_sent stat in cluster info (#10314)
publishshard was added in #8621 (7.0 RC1), but the publishshard_sent
stat is not shown in CLUSTER INFO command.

Other changes:
1. Remove useless `needhelp` statements, it was removed in 3dad819.
2. Use `LL_WARNING` log level for some error logs (I/O error, Connection failed).
3. Fix typos that saw by the way.
2022-02-19 21:11:20 -08:00
yoav-steinberg
56fa48ffc1
aof rewrite and rdb save counters in info (#10178)
Add aof_rewrites and rdb_snapshots counters to info.
This is useful to figure our if a rewrite or snapshot happened since last check.
This was part of the (ongoing) effort to provide a safe backup solution for multipart-aof backups.
2022-02-17 14:32:48 +02:00
chenyang8094
a50aa29bde
Adapt redis-check-aof tool for Multi Part Aof (#10061)
Modifications of this PR:
1. Support the verification of `Multi Part AOF`, while still maintaining support for the
  old-style `AOF/RDB-preamble`. `redis-check-aof` will automatically choose which
  mode to use according to the incoming file format.
   
`Usage: redis-check-aof [--fix|--truncate-to-timestamp $timestamp] <AOF/manifest>`
 
2. Refactor part of the code to make it easier to understand
3. Currently only supports truncate  (`--fix` or `--truncate-to-timestamp`) the last AOF
  file (may be `BASE` or `INCR`)

The reasons for 3 above:
- for `--fix`: Only the last AOF may be truncated, this is guaranteed by redis
- for `--truncate-to-timestamp`:  Normally, we only have `BASE` + `INCR` files
  at most, and `BASE` cannot be truncated(It only contains a timestamp annotation
  at the beginning of the file), so only `INCR` can be truncated. If we have a
  `BASE+INCR1+INCR2` file (meaning we have an interrupted AOFRW), Only `INCR2`
  files can be truncated at this time. If we still insist on truncate `INCR1`, we need to
  manually delete `INCR2` and update the manifest file, then re-run `redis-check-aof`
- If we want to support truncate any file, we need to add very complicated code to support
  the atomic modification of multiple file deletion and update manifest, I think this is unnecessary
2022-02-17 08:13:28 +02:00
Ping Xie
f7f68c654a
Use sds for clusterNode.hostname (#10290)
* Provide a fallback static_assert implementation
* Use sds for clusterNode.hostname
2022-02-16 13:35:49 -08:00
Matteo Baccan
cca3577503
Removed double semicolon at the end of line (#10305) 2022-02-16 16:42:04 +02:00
Yossi Gottlieb
3881f7850f
Fix OpenSSL 3.0.x related issues. (#10291)
* Drop obsolete initialization calls.
* Use decoder API for DH parameters.
* Enable auto DH parameters if not explicitly used, which should be the
  preferred configuration going forward.
2022-02-15 08:37:06 +02:00
Oran Agra
b099889a3a
Fix and improve module error reply statistics (#10278)
This PR handles several aspects
1. Calls to RM_ReplyWithError from thread safe contexts don't violate thread safety.
2. Errors returning from RM_Call to the module aren't counted in the statistics (they
  might be handled silently by the module)
3. When a module propagates a reply it got from RM_Call to it's client, then the error
  statistics are counted.

This is done by:
1. When appending an error reply to the output buffer, we avoid updating the global
  error statistics, instead we cache that error in a deferred list in the client struct.
2. When creating a RedisModuleCallReply object, the deferred error list is moved from
  the client into that object.
3. when a module calls RM_ReplyWithCallReply we copy the deferred replies to the dest
  client (if that's a real client, then that's when the error statistics are updated to the server)

Note about RM_ReplyWithCallReply: if the original reply had an array with errors, and the module
replied with just a portion of the original reply, and not the entire reply, the errors are currently not
propagated and the errors stats will not get propagated.

Fix #10180
2022-02-13 18:37:32 +02:00
yoav-steinberg
2eb9b19612
Fix Eval scripts defrag (broken 7.0 in RC1) (#10271)
Remove scripts defragger since it was broken since #10126 (released in 7.0 RC1).
would crash the server if defragger starts in a server that contains eval scripts.

In #10126 the global `lua_script` dict became a dict to a custom `luaScript` struct with an internal `robj`
in it instead of a generic `sds` -> `robj` dict. This means we need custom code to defrag it and since scripts
should never really cause much fragmentation it makes more sense to simply remove the defrag code for scripts.
2022-02-11 21:58:05 +02:00
sundb
5f0119ca91
Fix duplicate module options define (#10284)
The bug is introduced by #9323. (released in 7.0 RC1)
The define of `REDISMODULE_OPTIONS_HANDLE_IO_ERRORS` and `REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED` have the same value.

This will result in skipping `signalModifiedKey()` after `RM_CloseKey()` if the module has set
`REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD` option.
The implication is missing WATCH and client side tracking invalidations.

Other changes:
- add `no-implicit-signal-modified` to the options in INFO modules

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-11 20:15:52 +02:00
chenyang8094
a2f2b6f5b1
Modify AOF preamble related logs, and change the RDB aux field (#10283)
In multi-part aof,  We no longer have the concept of `RDB-preamble`, so the related logs should be removed.
However, in order to print compatible logs when loading old-style AOFs, we also have to keep the relevant code.
Additionally, when saving an RDB, change the RDB aux field from "aof-preamble" to "aof-base".
2022-02-11 18:47:03 +02:00
Harkrishn Patro
a5d17f0b6c
Check target node is a primary during cluster setslot. (#10277) 2022-02-10 23:14:27 -08:00
Omer Shadmi
5bdd72bea7
Use binary representation for key values dumped to crash log (#10275)
Use binary representation for key values dumped crash to log,
so that if they contain null chars they're still printed correctly.
Additionally limit their length to 128 chars

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-10 13:22:57 +02:00
chenyang8094
ceeff6bf86
Remove unused code - leftover from script replication mechanisms (#10272)
append for PR #9812
2022-02-09 15:44:09 +02:00
Binbin
beb94c901e
Fix INFO SENTINEL memory leak (#10268)
* Fix INFO SENTINEL memory leak

Introduced in #6891

* remove the copy-paste sentence
2022-02-09 07:33:24 +02:00
mowenliunian
051cc3d2e6
fix grammar issue in a comment (#10269)
Fixed some syntax errors in the comments
2022-02-09 07:32:40 +02:00
Oran Agra
aa9beaca77
Attempt to fix a rare crash in cluster tests. (#10265)
The theory is that a replica gets disconnected from within REPLCONF ACK,
so when we go up the stack, we'll crash when attempting to access
c->cmd->flags
2022-02-08 19:10:13 +02:00
gms
0990dec3f5
Fix SENTINEL DEBUG with wrong arguments (#10258)
There are two issues in SENTINEL DEBUG:
1. The error message should mention SENTINEL DEBUG
2. Add missing reuturn in args parse.

```
redis> sentinel debug INFO-PERIOD aaa
(error) ERR Invalid argument 'aaa' for SENTINEL SET 'INFO-PERIOD'

redis> sentinel debug a b c d
(error) ERR Unknown option or number of arguments for SENTINEL SET 'a'
redis> ping
(error) ERR Unknown option or number of arguments for SENTINEL SET 'b'
```

Introduced in #9291. Also do some cleanups in the code.
2022-02-08 18:45:47 +02:00
weiguo
34c288fe11
Remove duplicate header file include (#10264) 2022-02-08 16:49:47 +02:00
Viktor Söderqvist
b571c9609d
Remove assert and refuse delete expired on ro replicas (#10248)
There's an assertion added recently to make sure that non-write commands don't use lookupKeyWrite,
It was initially meant to be used only on read-only replicas, but we thought it'll not have enough coverage,
so used it on the masters too.
We now realize that in some cases this can cause issues for modules, so we remove the assert.

Other than that, we also make sure not to force expireIfNeeded on read-only replicas.
even if they somehow run a write command.

See https://github.com/redis/redis/pull/9572#discussion_r800179373
2022-02-08 13:19:27 +02:00
Wen Hui
2e1bc942aa
Make INFO command variadic (#6891)
This is an enhancement for INFO command, previously INFO only support one argument
for different info section , if user want to get more categories information, either perform
INFO all / default or calling INFO for multiple times.

**Description of the feature**

The goal of adding this feature is to let the user retrieve multiple categories via the INFO
command, and still avoid emitting the same section twice.

A use case for this is like Redis Sentinel, which periodically calling INFO command to refresh
info from monitored Master/Slaves, only Server and Replication part categories are used for
parsing information. If the INFO command can return just enough categories that client side
needs, it can save a lot of time for client side parsing it as well as network bandwidth.

**Implementation**
To share code between redis, sentinel, and other users of INFO (DEBUG and modules),
we have a new `genInfoSectionDict` function that returns a dict and some boolean flags
(e.g. `all`) to the caller (built from user input).
Sentinel is later purging unwanted sections from that, and then it is forwarded to the info `genRedisInfoString`.

**Usage Examples**
INFO Server Replication   
INFO CPU Memory
INFO default commandstats

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-08 13:14:42 +02:00
yoav-steinberg
b76016a948
Consistent erros returned from EVAL scripts (#10218)
This PR handles inconsistencies in errors returned from lua scripts.
Details of the problem can be found in #10165.

### Changes

- Remove double stack trace. It's enough that a stack trace is automatically added by the engine's error handler
  see d0bc4fff18/src/function_lua.c (L472-L485)
  and d0bc4fff18/src/eval.c (L243-L255)
- Make sure all errors a preceded with an error code. Passing a simple string to `luaPushError()` will prepend it
  with a generic `ERR` error code.
- Make sure lua error table doesn't include a RESP `-` error status. Lua stores redis error's as a lua table with a
  single `err` field and a string. When the string is translated back to RESP we add a `-` to it.
  See d0bc4fff18/src/script_lua.c (L510-L517)
  So there's no need to store it in the lua table.

### Before & After
```diff
--- <unnamed>
+++ <unnamed>
@@ -1,14 +1,14 @@
  1: config set maxmemory 1
  2: +OK
  3: eval "return redis.call('set','x','y')" 0
- 4: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: @user_script: 1: -OOM command not allowed when used memory > 'maxmemory'.
+ 4: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: OOM command not allowed when used memory > 'maxmemory'.
  5: eval "return redis.pcall('set','x','y')" 0
- 6: -@user_script: 1: -OOM command not allowed when used memory > 'maxmemory'.
+ 6: -OOM command not allowed when used memory > 'maxmemory'.
  7: eval "return redis.call('select',99)" 0
  8: -ERR Error running script (call to 4ad5abfc50bbccb484223905f9a16f09cd043ba8): @user_script:1: ERR DB index is out of range
  9: eval "return redis.pcall('select',99)" 0
 10: -ERR DB index is out of range
 11: eval_ro "return redis.call('set','x','y')" 0
-12: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: @user_script: 1: Write commands are not allowed from read-only scripts.
+12: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: ERR Write commands are not allowed from read-only scripts.
 13: eval_ro "return redis.pcall('set','x','y')" 0
-14: -@user_script: 1: Write commands are not allowed from read-only scripts.
+14: -ERR Write commands are not allowed from read-only scripts.
```
2022-02-08 11:44:40 +02:00
guybe7
3c3e6cc1c7
X[AUTO]CLAIM should skip deleted entries (#10227)
Fix #7021 #8924 #10198

# Intro
Before this commit X[AUTO]CLAIM used to transfer deleted entries from one
PEL to another, but reply with "nil" for every such entry (instead of the entry id).
The idea (for XCLAIM) was that the caller could see this "nil", realize the entry
no longer exists, and XACK it in order to remove it from PEL.
The main problem with that approach is that it assumes there's a correlation
between the index of the "id" arguments and the array indices, which there
isn't (in case some of the input IDs to XCLAIM never existed/read):

```
127.0.0.1:6379> XADD x 1 f1 v1
"1-0"
127.0.0.1:6379> XADD x 2 f1 v1
"2-0"
127.0.0.1:6379> XADD x 3 f1 v1
"3-0"
127.0.0.1:6379> XGROUP CREATE x grp 0
OK
127.0.0.1:6379> XREADGROUP GROUP grp Alice COUNT 2 STREAMS x >
1) 1) "x"
   2) 1) 1) "1-0"
         2) 1) "f1"
            2) "v1"
      2) 1) "2-0"
         2) 1) "f1"
            2) "v1"
127.0.0.1:6379> XDEL x 1 2
(integer) 2
127.0.0.1:6379> XCLAIM x grp Bob 0 0-99 1-0 1-99 2-0
1) (nil)
2) (nil)
```

# Changes
Now,  X[AUTO]CLAIM acts in the following way:
1. If one tries to claim a deleted entry, we delete it from the PEL we found it in
  (and the group PEL too). So de facto, such entry is not claimed, just cleared
  from PEL (since anyway it doesn't exist in the stream)
2. since we never claim deleted entries, X[AUTO]CLAIM will never return "nil"
  instead of an entry.
3. add a new element to XAUTOCLAIM's response (see below)

# Knowing which entries were cleared from the PEL
The caller may want to log any entries that were found in a PEL but deleted from
the stream itself (it would suggest that there might be a bug in the application:
trimming the stream while some entries were still no processed by the consumers)

## XCLAIM
the set {XCLAIM input ids} - {XCLAIM returned ids} contains all the entry ids that were
not claimed which means they were deleted (assuming the input contains only entries
from some PEL). The user doesn't need to XACK them because XCLAIM had already
deleted them from the source PEL.

## XAUTOCLAIM
XAUTOCLAIM has a new element added to its reply: it's an array of all the deleted
stream IDs it stumbled upon.

This is somewhat of a breaking change since X[AUTO]CLAIM used to be able to reply
with "nil" and now it can't... But since it was undocumented (and generally a bad idea
to rely on it, as explained above) the breakage is not that bad.
2022-02-08 10:20:09 +02:00
Oran Agra
66be30f7fc
Handle key-spec flags with modules (#10237)
- add COMMAND GETKEYSANDFLAGS sub-command
- add RM_KeyAtPosWithFlags and GetCommandKeysWithFlags
- RM_KeyAtPos and RM_CreateCommand set flags requiring full access for keys
- RM_CreateCommand set VARIABLE_FLAGS
- expose `variable_flags` flag in COMMAND INFO key-specs
- getKeysFromCommandWithSpecs prefers key-specs over getkeys-api
- add tests for all of these
2022-02-08 10:01:35 +02:00
ivanstosic-janea
bb875603fb
Fix protocol error caused by redis-benchmark (#10236)
The protocol error was caused by the buggy `writeHandler` in `redis-benchmark.c`,
which didn't handle one of the cases, thereby repeating data, leading to protocol errors
when the values being sent are very long.

This PR fixes #10233, issue introduced by #7959
2022-02-07 22:57:11 +02:00
Avital-Fine
9a0ab2fbbf
Update function-delete.json - argument is library name, not function name (#10253) 2022-02-07 20:01:34 +02:00
Binbin
7f4cca11dc
COMMAND DOCS avoid adding summary/since if they don't exist (#10252)
If summary or since is empty, we used to return NULL in
COMMAND DOCS. Currently all redis commands will have these
two fields.

But not for module command, summary and since are optional
for RM_SetCommandInfo. With the change in #10043, if a module
command doesn't have the summary or since, redis-cli will
crash (see #10250).

In this commit, COMMAND DOCS avoid adding summary or since
when they are missing.
2022-02-07 19:57:50 +02:00
Binbin
b95beeb595
Fix redis-cli with sentinel crash due to SENTINEL DEBUG missing summary (#10250)
Fix redis-cli with sentinel crash due to SENTINEL DEBUG missing summary

Because SENTINEL DEBUG missing summary in its json file,
with the change in #10043, the following assertion will fail.
```
[redis]# src/redis-cli -p 26379
redis-cli: redis-cli.c:678: cliInitCommandHelpEntry: Assertion `reply->type == 1' failed.
```

This commit add the summary and complexity for SENTINEL DEBUG,
which introduced in #9291, and also improved the help message.
2022-02-07 13:27:33 +02:00
yoav-steinberg
9dfeda58ed
acl check api for functions and eval (#10220)
Changes:
1. Adds the `redis.acl_check_cmd()` api to lua scripts. It can be used to check if the
  current user has permissions to execute a given command. The new function receives
  the command to check as an argument exactly like `redis.call()` receives the command
  to execute as an argument.
2. In the PR I unified the code used to convert lua arguments to redis argv arguments from
  both the new `redis.acl_check_cmd()` API and the `redis.[p]call()` API. This cleans up
  potential duplicate code.
3. While doing the refactoring in 2 I noticed there's an optimization to reduce allocation calls
  when parsing lua arguments into an `argv` array in the `redis.[p]call()` implementation.
  These optimizations were introduced years ago in 48c49c4851
  and 4f686555ce. It is unclear why this was added.
  The original commit message claims a 4% performance increase which I couldn't recreate
  and might not be worth it even if it did recreate. This PR removes that optimization.
  Following are details of the benchmark I did that couldn't reveal any performance
  improvements due to this optimization:

```
benchmark 1: src/redis-benchmark -P 500 -n 10000000 eval 'return redis.call("ping")' 0
benchmark 2: src/redis-benchmark -P 500 -r 1000 -n 1000000 eval 'return redis.call("mset","k1__rand_int__","v1__rand_int__","k2__rand_int__","v2__rand_int__","k3__rand_int__","v3__rand_int__","k4__rand_int__","v4__rand_int__")' 0
benchmark 3: src/redis-benchmark -P 500 -r 1000 -n 100000 eval "for i=1,100,1 do redis.call('set','kk'..i,'vv'..__rand_int__) end return redis.call('get','kk5')" 0
benchmark 4: src/redis-benchmark -P 500 -r 1000 -n 1000000 eval 'return redis.call("mset","k1__rand_int__","v1__rand_int__","k2__rand_int__","v2__rand_int__","k3__rand_int__","v3__rand_int__","k4__rand_int__","v4__rand_int__xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")'
```
I ran the benchmark on this branch with and without commit 68b71680a4d3bb8f0509e06578a9f15d05b92a47
Results in requests per second:
cmd | without optimization | without optimization 2nd run | with original optimization | with original optimization 2nd run
-- | -- | -- | -- | --
1 | 461233.34 | 477395.31 | 471098.16 | 469946.91
2 | 34774.14 | 35469.8 | 35149.38 | 34464.93
3 | 6390.59 | 6281.41 | 6146.28 | 6464.12
4 | 28005.71 |   | 27965.77 |  

As you can see, different use cases showed identical or negligible performance differences.
So finally I decided to chuck the original optimization and simplify the code.
2022-02-07 08:04:01 +02:00
weiguo
d6e9cde595
Supplement define guards to prevent multiple inclusion (#10246) 2022-02-06 20:13:34 -08:00
footpatch
91cc2059f5
Fix file descriptor leak in memtest_test_linux_anonymous_maps (#4241)
when we fail opening `/proc`, we need to close the log file fd.
2022-02-06 13:17:38 +02:00
Binbin
344e41c922
Fix PSYNC crash with wrong offset (#10243)
`PSYNC replicationid str_offset` will crash the server.

The reason is in `masterTryPartialResynchronization`,
we will call `getLongLongFromObjectOrReply` check the
offset. With a wrong offset, it will add a reply and
then trigger a full SYNC and the client become a replica.

So crash in `c->bufpos == 0 && listLength(c->reply) == 0`.
In this commit, we check the psync_offset before entering
function `masterTryPartialResynchronization`, and return.

Regardless of that crash, accepting the sync, but also replying
with an error would have corrupt the replication stream.
2022-02-06 13:13:56 +02:00
Jason Elbaum
5b17909c4f
redis-cli generates command help tables from the results of COMMAND (#10043)
This is a followup to #9656 and implements the following step mentioned in that PR:

* When possible, extract all the help and completion tips from COMMAND DOCS (Redis 7.0 and up)
* If COMMAND DOCS fails, use the static help.h compiled into redis-cli.
* Supplement additional command names from COMMAND (pre-Redis 7.0)

The last step is needed to add module command and other non-standard commands.

This PR does not change the interactive hinting mechanism, which still uses only the param
strings to provide somewhat unreliable and inconsistent command hints (see #8084).
That task is left for a future PR. 

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-02-05 16:54:16 +02:00
Binbin
e662f6835e
Update FCALL/FCALL_RO summary and complexity (#10240)
1. Update fcall.json and fcall_ro.json
2. Update command.c
3. Update help.h
2022-02-05 10:35:07 +02:00
Viktor Söderqvist
0a82fe8447
Command info module API (#10108)
Adds RM_SetCommandInfo, allowing modules to provide the following command info:

* summary
* complexity
* since
* history
* hints
* arity
* key specs
* args

This information affects the output of `COMMAND`, `COMMAND INFO` and `COMMAND DOCS`,
Cluster, ACL and is used to filter commands with the wrong number of arguments before
the call reaches the module code.

The recently added API functions for key specs (never released) are removed.

A minimalist example would look like so:
```c
    RedisModuleCommand *mycmd = RedisModule_GetCommand(ctx,"mymodule.mycommand");
    RedisModuleCommandInfo mycmd_info = {
        .version = REDISMODULE_COMMAND_INFO_VERSION,
        .arity = -5,
        .summary = "some description",
    };
    if (RedisModule_SetCommandInfo(mycmd, &mycmd_info) == REDISMODULE_ERR)
        return REDISMODULE_ERR;
````

Notes:
* All the provided information (including strings) is copied, not keeping references to the API input data.
* The version field is actually a static struct that contains the sizes of the the structs used in arrays,
  so we can extend these in the future and old version will still be able to take the part they can support.
2022-02-04 21:09:36 +02:00
Binbin
d7fcb3c5a1
Fix SENTINEL SET config rewrite test (#10232)
Change the sentinel config file to a directory in SENTINEL SET test.
So it will now fail on the `rename` in `rewriteConfigOverwriteFile`.

The test used to set the sentinel config file permissions to `000` to
simulate failure. But it fails on centos7 / freebsd / alpine. (introduced in #10151)

Other changes:
1. More error messages after the config rewrite failure.
2. Modify arg name `force_all` in `rewriteConfig` to `force_write`. (was rename in #9304)
3. Fix a typo in debug quicklist-packed-threshold, then -> than. (#9357)
2022-02-04 11:39:51 +02:00
Wen Hui
65ef543f8c
Sentinel: return an error if configuration save fails (#10151)
When performing `SENTINEL SET`, Sentinel updates the local configuration file. Before this commit, failure to update the file would still result with an `+OK` reply. Now, a `-ERR Failed to save config file` error will be returned.

Co-authored-by: Yossi Gottlieb <yossigo@gmail.com>
2022-02-03 13:20:35 +02:00
Vo Trong Phuc
53c43fcc84
Add check min-slave-* feature when evaluating Lua scripts and Functions (#10160)
Add check enough good slaves for write command when evaluating scripts.
This check is made before the script is executed, if we have function flags, and per redis command if we don't.

Co-authored-by: Phuc. Vo Trong <phucvt@vng.com.vn>
Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: Meir Shpilraien (Spielrein) <meir@redis.com>
2022-02-03 11:57:51 +02:00
Viktor Söderqvist
f4ecc799c8
Add 'Available since' to module API function docs (#10229)
The script which generates the markdown docs from module.c is updated to include
the version in which each module API function was introduced.

The script uses git tags to find this information. If git is not available or if we're not in
a git repo, the 'since' is silently skipped.

The line `**Available since:** (version)` is added after the function prototype

Rename to utils/generate-module-api-doc.rb
2022-02-03 10:25:37 +02:00
Meir Shpilraien (Spielrein)
8eb19cc251
update function help message, changed DESC->DESCRIPTION. (#10228)
update function help message, changed DESC->DESCRIPTION (doc was outdated)
2022-02-02 15:50:41 +02:00
sundb
948285de39
Fix src/modules build issue on OS X 11 (#10224) 2022-02-01 21:39:10 +02:00
郭伟光
6b5b3ca414
forbid module to unload when it holds ongoing timer (#10187)
This is done to avoid a crash when the timer fires after the module was unloaded.
Or memory leaks in case we wanted to just ignore the timer.
It'll cause the MODULE UNLOAD command to return with an error

Co-authored-by: sundb <sundbcn@gmail.com>
2022-02-01 14:54:11 +02:00
Madelyn Olson
d0bc4fff18
Added history for cluster-slots changes for hostnames(#10216)
* The first field was previously only an IP address, it can now be a hostname or NULL.
* There is now a fourth field, which has more information.
2022-01-30 23:57:10 -08:00
Oran Agra
ef93125988
update help.h before release (#10210) 2022-01-30 22:53:13 +02:00
Ping Xie
8013af6f3d
Fix cluster bus extensions backwards compatibility (#10206)
Before this commit, notused1 was incorrectly resized resulting with a clusterMsg that is not backwards compatible as expected.
2022-01-30 19:43:37 +02:00
Moti Cohen
52b2fbe970
Improve srand entropy (and fix Sentinel failures) (#10197)
As Sentinel relies upon consensus algorithm, all sentinel instances,
randomize a time to initiate their next attempt to become the
leader of the group. But time after time, all raffled the same value.

The problem is in the line `srand(time(NULL)^getpid())` such that
all spinned up containers get same time (in seconds) and same pid
which is always 1. Added material `tv_usec` and verify that even
consecutive calls brings different values and makes the difference.
2022-01-30 16:39:23 +02:00
Tobias Nießen
4e17154060
Fix typo in function_load local variable (#10209)
Refs: https://github.com/redis/redis/pull/10141
2022-01-30 14:38:58 +02:00
Harkrishn Patro
a43b6922d1
Set default channel permission to resetchannels for 7.0 (#10181)
For backwards compatibility in 6.x, channels default permission was set to `allchannels` however with 7.0,
we should modify it and the default value should be `resetchannels` for better security posture.
Also, with selectors in ACL, a client doesn't have to set channel rules everytime and by default
the value will be `resetchannels`.

Before this change
```
127.0.0.1:6379> acl list
1) "user default on nopass ~* &* +@all"
127.0.0.1:6379>  acl setuser hp on nopass +@all ~*
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* &* +@all"
2) "user hp on nopass ~* &* +@all"
127.0.0.1:6379>  acl setuser hp1 on nopass -@all (%R~sales*)
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* &* +@all"
2) "user hp on nopass ~* &* +@all"
3) "user hp1 on nopass &* -@all (%R~sales* &* -@all)"
```

After this change
```
127.0.0.1:6379> acl list
1) "user default on nopass ~* &* +@all"
127.0.0.1:6379> acl setuser hp on nopass +@all ~*
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* &* +@all"
2) "user hp on nopass ~* resetchannels +@all"
127.0.0.1:6379> acl setuser hp1 on nopass -@all (%R~sales*)
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* &* +@all"
2) "user hp on nopass ~* resetchannels +@all"
3) "user hp1 on nopass resetchannels -@all (%R~sales* resetchannels -@all)"
```
2022-01-30 12:02:55 +02:00
guybe7
eedec155ac
Add key-specs notes (#10193)
Add optional `notes` to keyspecs.

Other changes:

1. Remove the "incomplete" flag from SORT and SORT_RO: it is misleading since "incomplete" means "this spec may not return all the keys it describes" but SORT and SORT_RO's specs (except the input key) do not return any keys at all.
So basically:
If a spec's begin_search is "unknown" you should not use it at all, you must use COMMAND KEYS;
if a spec itself is "incomplete", you can use it to get a partial list of keys, but if you want all of them you must use COMMAND GETKEYS;
otherwise, the spec will return all the keys

2. `getKeysUsingKeySpecs` handles incomplete specs internally
2022-01-30 12:00:03 +02:00
Oran Agra
be0d293354
fix cluster rebalance test race (#10207)
Try to fix the rebalance cluster test that's failing with ASAN daily:

Looks like `redis-cli --cluster rebalance` gets `ERR Please use SETSLOT only with masters` in `clusterManagerMoveSlot()`.
it happens when `12-replica-migration-2.tcl` is run with ASAN in GH Actions.
in `Resharding all the master #0 slots away from it`

So the fix (assuming i got it right) is to call `redis-cli --cluster check` before `--cluster rebalance`.
p.s. it looks like a few other checks in these tests needed that wait, added them too.

Other changes:
* in instances.tcl, make sure to catch tcl test crashes and let the rest of the code proceed, so that if there was
  a redis crash, we'll find it and print it too.
* redis-cli, try to make sure it prints an error instead of silently exiting.

specifically about redis-cli:
1. clusterManagerMoveSlot used to print an error, only if the caller also asked for it (should be the other way around).
2. clusterManagerCommandReshard asked for an error, but didn't use it (probably tried to avoid the double print).
3. clusterManagerCommandRebalance didn't ask for the error, now it does.
4. making sure that other places in clusterManagerCommandRebalance print something before exiting with an error.
2022-01-30 11:30:19 +02:00
Binbin
21135471a6
Fix some wrong commands arguments since (#10208)
ZADD NX and XX was introduced in 3.0.2, not 6.2.0
ZADD GT and LT was introduced in 6.2.0, not 3.0.2

Add missing `COUNT ANY` history in georadius_ro
Add missing `SHUTDOWN [NOW] [FORCE] [ABORT]` since in shutdown.json
2022-01-30 08:45:12 +02:00
Moti Cohen
79f089bdd9
Fixed Sentinel support for hostnames (#10146)
Sentinel tries to resolve instances hostname to IP only during registration. 
It might be that the instance is unavailable during that time, such as 
leader crashed and failover took place. Yet, promoted replica must support:

 - Register leader, even if it fails to resolve its hostname during failover
 - Try later to resolve it, if instance is disconnected. Note that
   this condition also support ip-change of an instance.
2022-01-29 21:00:29 +02:00
Binbin
93d951556b
commands arguments improvement about unix-time type (#10203)
Change the name to unix-time-seconds or unix-time-milliseconds
to be consistent. Change the type from INTEGER to UNIX_TIME.

SET (EXAT and PXAT) was already ok.
and naming aside, both PXAT and EXAT everywhere used unit-time (for both milliseconds and seconds).
the only ones that where wrong are GETEX and XCLAIM (using "integer" for both seconds and milliseconds)
2022-01-29 15:21:59 +02:00
weiguo
76784e4ece
Use object size then pointer size when malloc (#10201) (#10202)
By a happy coincidence, sizeof(sds *) is equal to sizeof(sds) here,
while it's logically consistent to use sizeof(sds) instead.
2022-01-29 14:43:16 +02:00
Madelyn Olson
7a89e49859
Added missing documentation about the ACL GETUSER changes in acl-v2 (#10200) 2022-01-28 12:13:44 -08:00
Yossi Gottlieb
068190a802
Update generate-command-help.rb and help.h. (#10196)
There are some inevitable changes between the old and new output, as a
result of the different `commands.json` semantics.
2022-01-27 21:48:06 +02:00
Binbin
d616925835
Allow SET without GET arg on write-only ACL. Allow BITFIELD GET on read-only ACL (#10148)
SET is a R+W command, because it can also do `GET` on the data.
SET without GET is a write-only command.
SET with GET is a read+write command.

In #9974, we added ACL to let users define write-only access.
So when the user uses SET with GET option, and the user doesn't
have the READ permission on the key, we need to reject it,
but we rather not reject users with write-only permissions from using
the SET command when they don't use GET.

In this commit, we add a `getkeys_proc` function to control key
flags in SET command. We also add a new key spec flag (VARIABLE_FLAGS)
means that some keys might have different flags depending on arguments.

We also handle BITFIELD command, add a `bitfieldGetKeys` function.
BITFIELD GET is a READ ONLY command.
BITFIELD SET or BITFIELD INCR are READ WRITE commands.

Other changes:
1. SET GET was added in 6.2, add the missing since in set.json
2. Added tests to cover the changes in acl-v2.tcl
3. Fix some typos in server.h and cleanups in acl-v2.tcl

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
2022-01-26 21:03:21 +02:00
guybe7
c79389f032
Reply for command args should be an array, not a set (#10188) 2022-01-26 12:49:24 +02:00
Viktor Söderqvist
4491ee1805
redis-cli: Aligned RESP3 maps with multiline value in TTY (#10170)
Before:

```
127.0.0.1:6379> command info get
1)  1) "get"
    2) (integer) 2
    3) 1~ readonly
       2~ fast
    4) (integer) 1
    5) (integer) 1
    6) (integer) 1
    7) 1~ @read
       2~ @string
       3~ @fast
    8) (empty set)
    9) 1~ 1# "flags" => 1~ RO
             2~ access
          2# "begin_search" => 1# "type" => "index"
             2# "spec" => 1# "index" => (integer) 1
          3# "find_keys" => 1# "type" => "range"
             2# "spec" => 1# "lastkey" => (integer) 0
                2# "keystep" => (integer) 1
                3# "limit" => (integer) 0
   10) (empty set)
```

After:

```
127.0.0.1:6379> command info get
1)  1) "get"
    2) (integer) 2
    3) 1~ readonly
       2~ fast
    4) (integer) 1
    5) (integer) 1
    6) (integer) 1
    7) 1~ @read
       2~ @string
       3~ @fast
    8) (empty set)
    9) 1~ 1# "flags" =>
             1~ RO
             2~ access
          2# "begin_search" =>
             1# "type" => "index"
             2# "spec" => 1# "index" => (integer) 1
          3# "find_keys" =>
             1# "type" => "range"
             2# "spec" =>
                1# "lastkey" => (integer) 0
                2# "keystep" => (integer) 1
                3# "limit" => (integer) 0
   10) (empty set)
```
2022-01-25 17:15:57 +02:00
Meir Shpilraien (Spielrein)
5a38ccc253
Added engine stats to FUNCTION STATS command. (#10179)
Added the following statistics (per engine) to FUNCTION STATS command:
* number of functions
* number of libraries

Output example:
```
> FUNCTION stats
1) "running_script"
2) (nil)
3) "engines"
4) 1) "LUA"
   2) 1) "libraries_count"
      2) (integer) 1
      3) "functions_count"
      4) (integer) 1
```

To collect the stats, added a new dictionary to libraries_ctx that contains
for each engine, the engine statistics representing the current libraries_ctx.
Update the stats on:
1. Link library to libraries_ctx
2. Unlink library from libraries_ctx
3. Flushing libraries_ctx
2022-01-25 15:50:14 +02:00
chenyang8094
ac011ebd7f
Delete the residual code related to aof rewrite buf (#10176) 2022-01-25 11:37:18 +02:00
Madelyn Olson
823da54361
Improve testing and update flags around commands without ACL keyspec flags (#10167)
This PR aims to improve the flags associated with some commands and adds various tests around
these cases. Specifically, it's concerned with commands which declare keys but have no ACL
flags (think `EXISTS`), the user needs either read or write permission to access this type of key.

This change is primarily concerned around commands in three categories:

# General keyspace commands
These commands are agnostic to the underlying data outside of side channel attacks, so they are not
marked as ACCESS.
* TOUCH
* EXISTS
* TYPE
* OBJECT 'all subcommands'

Note that TOUCH is not a write command, it could be a side effect of either a read or a write command.

# Length and cardinality commands
These commands are marked as NOT marked as ACCESS since they don't return actual user strings,
just metadata.
* LLEN
* STRLEN
* SCARD
* HSTRLEN

# Container has member commands
These commands return information about the existence or metadata about the key. These commands
are NOT marked as ACCESS since the check of membership is used widely in write commands
e.g. the response of HSET. 
* SISMEMBER
* HEXISTS

# Intersection cardinality commands
These commands are marked as ACCESS since they process data to compute the result.
* PFCOUNT
* ZCOUNT
* ZINTERCARD
* SINTERCARD
2022-01-25 09:55:30 +02:00
Madelyn Olson
c275010fff
Correctly handle minimum arity checks in scripts (#10171)
Correctly handle variable arity checks in scripts
2022-01-24 22:08:57 -08:00
yoav-steinberg
7eadc5ee70
Support function flags in script EVAL via shebang header (#10126)
In #10025 we added a mechanism for flagging certain properties for Redis Functions.
This lead us to think we'd like to "port" this mechanism to Redis Scripts (`EVAL`) as well. 

One good reason for this, other than the added functionality is because it addresses the
poor behavior we currently have in `EVAL` in case the script performs a (non DENY_OOM) write operation
during OOM state. See #8478 (And a previous attempt to handle it via #10093) for details.
Note that in Redis Functions **all** write operations (including DEL) will return an error during OOM state
unless the function is flagged as `allow-oom` in which case no OOM checking is performed at all.

This PR:
- Enables setting `EVAL` (and `SCRIPT LOAD`) script flags as defined in #10025.
- Provides a syntactical framework via [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) for
  additional script annotations and even engine selection (instead of just lua) for scripts.
- Provides backwards compatibility so scripts without the new annotations will behave as they did before.
- Appropriate tests.
- Changes `EVAL[SHA]/_RO` to be flagged as `STALE` commands. This makes it possible to flag individual
  scripts as `allow-stale` or not flag them as such. In backwards compatibility mode these commands will
  return the `MASTERDOWN` error as before.
- Changes `SCRIPT LOAD` to be flagged as a `STALE` command. This is mainly to make it logically
  compatible with the change to `EVAL` in the previous point. It enables loading a script on a stale server
  which is technically okay it doesn't relate directly to the server's dataset. Running the script does, but that
  won't work unless the script is explicitly marked as `allow-stale`.

Note that even though the LUA syntax doesn't support hash tag comments `.lua` files do support a shebang
tag on the top so they can be executed on Unix systems like any shell script. LUA's `luaL_loadfile` handles
this as part of the LUA library. In the case of `luaL_loadbuffer`, which is what Redis uses, I needed to fix the
input script in case of a shebang manually. I did this the same way `luaL_loadfile` does, by replacing the
first line with a single line feed character.
2022-01-24 16:50:02 +02:00
Viktor Söderqvist
857dc5bacd
Disable keyspec module API in 7.0 RC1 (#10135)
The keyspec API is not yet released and there is a plan to change it
in #10108, which is going to be included in RC2. Therefore, we hide
it in RC1 to avoid introducing a breaking change in RC2.

Co-authored-by: Oran Agra <oran@redislabs.com>
2022-01-24 15:02:07 +02:00
Binbin
23325c135f
sub-command support for ACL CAT and COMMAND LIST. redisCommand always stores fullname (#10127)
Summary of changes:
1. Rename `redisCommand->name` to `redisCommand->declared_name`, it is a
  const char * for native commands and SDS for module commands.
2. Store the [sub]command fullname in `redisCommand->fullname` (sds).
3. List subcommands in `ACL CAT`
4. List subcommands in `COMMAND LIST`
5. `moduleUnregisterCommands` now will also free the module subcommands.
6. RM_GetCurrentCommandName returns full command name

Other changes:
1. Add `addReplyErrorArity` and `addReplyErrorExpireTime`
2. Remove `getFullCommandName` function that now is useless.
3. Some cleanups about `fullname` since now it is SDS.
4. Delete `populateSingleCommand` function from server.h that is useless.
5. Added tests to cover this change.
6. Add some module unload tests and fix the leaks
7. Make error messages uniform, make sure they always contain the full command
  name and that it's quoted.
7. Fixes some typos

see the history in #9504, fixes #10124

Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: guybe7 <guy.benoish@redislabs.com>
2022-01-23 10:05:06 +02:00