Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
994bc96bb1 | ||
|
|
643b5db235 | ||
|
|
7f9212ec22 | ||
|
|
00cfa6ebbc | ||
|
|
bc71e8fe2d | ||
|
|
ad9575dd6d | ||
|
|
63b87554f0 | ||
|
|
7bc6ff3442 | ||
|
|
e91a340e24 | ||
|
|
4ec6d54426 | ||
|
|
b319f21df1 | ||
|
|
7cd656a0c3 | ||
|
|
b0403f1fa2 | ||
|
|
ce8c3993c5 | ||
|
|
385823ea49 | ||
|
|
c6e5d1d5fe | ||
|
|
5d887c58ae | ||
|
|
452b5b8a3b | ||
|
|
095c131fbb | ||
|
|
89eef40ca2 | ||
|
|
84471e238e | ||
|
|
d1df881ec5 | ||
|
|
53949521de | ||
|
|
a39ffc1fe9 | ||
|
|
cb261828bd | ||
|
|
9265234299 | ||
|
|
1cddd0d3ba | ||
|
|
1d5e13e121 | ||
|
|
c2d3e28540 | ||
|
|
0c1a764074 | ||
|
|
d88611d36f | ||
|
|
4c5a9076d7 | ||
|
|
8aab7ca84c | ||
|
|
9c81f8bd61 | ||
|
|
0a24bfec13 | ||
|
|
14c48cc5ed | ||
|
|
b08fd9f989 | ||
|
|
dd20aa5160 | ||
|
|
30eb6c3210 | ||
|
|
80458d0490 | ||
|
|
5fe3e74a38 | ||
|
|
4955375ec7 | ||
|
|
406a365f44 |
+422
-11
@@ -1,16 +1,427 @@
|
||||
Hello! This file is just a placeholder, since this is the "unstable" branch
|
||||
of Redis, the place where all the development happens.
|
||||
Redis Open Source 8.0 release notes
|
||||
===================================
|
||||
|
||||
There is no release notes for this branch, it gets forked into another branch
|
||||
every time there is a partial feature freeze in order to eventually create
|
||||
a new stable release.
|
||||
--------------------------------------------------------------------------------
|
||||
Upgrade urgency levels:
|
||||
|
||||
Usually "unstable" is stable enough for you to use it in development environments
|
||||
however you should never use it in production environments. It is possible
|
||||
to download the latest stable release here:
|
||||
LOW: No need to upgrade unless there are new features you want to use.
|
||||
MODERATE: Program an upgrade of the server, but it's not urgent.
|
||||
HIGH: There is a critical bug that may affect a subset of users. Upgrade!
|
||||
CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
|
||||
SECURITY: There are security fixes in the release.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
https://download.redis.io/redis-stable.tar.gz
|
||||
Starting with v8.0.1, the release notes contain PRs from multiple repositories:
|
||||
|
||||
More information is available at https://redis.io
|
||||
#n - Redis (https://github.com/redis/redis)
|
||||
#QEn = Query Engine (https://github.com/RediSearch/RediSearch)
|
||||
#JSn = JSON (https://github.com/RedisJSON/RedisJSON)
|
||||
#TSn = Time Series (https://github.com/RedisTimeSeries/RedisTimeSeries)
|
||||
#PRn = Probabilistic (https://github.com/RedisBloom/RedisBloom)
|
||||
|
||||
|
||||
================================================================================
|
||||
Redis 8.0.2 Released Tue 27 May 2025 12:00:00 IST
|
||||
================================================================================
|
||||
|
||||
Update urgency: `SECURITY`: There are security fixes in the release.
|
||||
|
||||
### Security fixes
|
||||
|
||||
- (CVE-2025-27151) redis-check-aof may lead to stack overflow and potential RCE
|
||||
|
||||
### Other general improvements
|
||||
|
||||
- #14048 `LOLWUT` for Redis 8
|
||||
|
||||
|
||||
================================================================================
|
||||
Redis 8.0.1 Released Sun 13 May 2025 16:00:00 IST
|
||||
================================================================================
|
||||
|
||||
Update urgency: `MODERATE`: No need to upgrade unless there are new features you want to use.
|
||||
|
||||
### Performance and resource utilization improvements
|
||||
|
||||
- #13959 Vector set - faster `VSIM` `FILTER` parsing
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- #QE6083 Query Engine - revert default policy `search-on-timeout` to `RETURN`
|
||||
- #QE6050 Query Engine - `@__key` on `FT.AGGREGATE` used as reserved field name preventing access to Redis keyspace
|
||||
- #QE6077 Query Engine - crash when calling `FT.CURSOR DEL` while retrieving from the CURSOR
|
||||
|
||||
### Notes
|
||||
|
||||
- Fixed wrong text in the license files
|
||||
|
||||
|
||||
=======================================================
|
||||
8.0 GA (v8.0.0) Released Fri 2 May 2025 12:00:00 IST
|
||||
=======================================================
|
||||
|
||||
This is the General Availability release of Redis Open Source 8.0.
|
||||
|
||||
Redis 8.0 deprecates previous Redis and Redis Stack versions.
|
||||
|
||||
Stand alone RediSearch, RedisJSON, RedisTimeSeries, and RedisBloom are no longer needed as they are now part of Redis.
|
||||
|
||||
|
||||
### Major changes compared to 7.4.2
|
||||
|
||||
- Name change: Redis Community Edition is now Redis Open Source
|
||||
- License change: licensed under your choice of
|
||||
- (a) the Redis Source Available License 2.0 (RSALv2); or
|
||||
- (b) the Server Side Public License v1 (SSPLv1); or
|
||||
- (c) the GNU Affero General Public License (AGPLv3)
|
||||
- Redis Query engine and 8 new data structures are now an integral part of Redis 8
|
||||
- (1) Redis Query Engine, which now supports both horizontal and vertical scaling for search, query and vector workloads
|
||||
- (2) JSON - a queryable JSON document
|
||||
- (3) Time series
|
||||
- (4-8) Five probabilistic data structures: Bloom filter, Cuckoo filter, Count-min sketch, Top-k, and t-digest
|
||||
- (9) Vector set [beta] - a data structure designed for Vector Similarity Search, inspired by Sorted set
|
||||
- These nine components are included in all binary distributions
|
||||
|
||||
- See instructions in the README.md file on how to build from source with all these components
|
||||
- New configuration file: redis-full.conf - loads Redis with all these components,
|
||||
and contains new configuration parameters for Redis Query engine and the new data structures
|
||||
- New ACL categories: @search, @json, @timeseries, @bloom, @cuckoo, @cms, @topk, @tdigest
|
||||
- Commands are also included in the existing ACL categories (@read, @write, etc.)
|
||||
|
||||
- More than 30 performance and resource utilization improvements
|
||||
- A new I/O threading implementation which enables throughput increase on multi-core environments
|
||||
(set with `io-threads` configuration parameter)
|
||||
- An improved replication mechanism which is more performant and robust
|
||||
- New hash commands - `HGETDEL`, `HGETEX`, `HSETEX`
|
||||
|
||||
For more details, see the release notes of 8.0-M01, 8.0-M02, 8.0-M03,8.0-M04, and 8.0-RC1
|
||||
|
||||
### Binary distributions
|
||||
|
||||
- Alpine and Debian Docker images - https://hub.docker.com/_/redis
|
||||
- Install using snap - see https://github.com/redis/redis-snap
|
||||
- Install using brew - see https://github.com/redis/homebrew-redis
|
||||
- Install using RPM - see https://github.com/redis/redis-rpm
|
||||
- Install using Debian APT - see https://github.com/redis/redis-debian
|
||||
|
||||
### Operating systems we test Redis 8.0 on
|
||||
|
||||
- Ubuntu 20.04 (Focal Fossa), 22.04 (Jammy Jellyfish), 24.04 (Noble Numbat)
|
||||
- Rocky Linux 8.10, 9.5
|
||||
- AlmaLinux 8.10, 9.5
|
||||
- Debian 11 (Bullseye), 12 (Bookworm)
|
||||
- macOS 13 (Ventura), 14 (Sonoma), 15 (Sequoia)
|
||||
|
||||
### Supported upgrade paths (by replication or persistence)
|
||||
|
||||
- From previous Redis versions, without modules
|
||||
- From previous Redis versions with modules (RediSearch, RedisJSON, RedisTimeSeries, RedisBloom)
|
||||
- From Redis Stack 7.2 or 7.4
|
||||
|
||||
### Security fixes (compared to 8.0-RC1)
|
||||
|
||||
|
||||
* (CVE-2025-21605) An unauthenticated client can cause an unlimited growth of output buffers
|
||||
|
||||
### Bug fixes (compared to 8.0-RC1)
|
||||
|
||||
- #13966, #13932 `CLUSTER SLOTS` - TLS port update not reflected in CLUSTER SLOTS
|
||||
- #13958 `XTRIM`, `XADD` - incorrect lag due to trimming stream
|
||||
- #13931 `HGETEX` - wrong order of keyspace notifications
|
||||
|
||||
|
||||
==========================================================
|
||||
8.0-RC1 (v7.9.240) Released Mon 7 Apr 2025 10:00:00 IST
|
||||
==========================================================
|
||||
|
||||
This is the first Release Candidate of Redis Community Edition 8.0.
|
||||
|
||||
Release Candidates are feature-complete pre-releases. Pre-releases are not suitable for production use.
|
||||
|
||||
|
||||
### Headlines
|
||||
|
||||
8.0-RC1 includes a new beta data structure - vector set.
|
||||
|
||||
### Distributions
|
||||
|
||||
- Alpine and Debian Docker images - https://hub.docker.com/_/redis
|
||||
- Install using snap - see https://github.com/redis/redis-snap
|
||||
- Install using brew - see https://github.com/redis/homebrew-redis
|
||||
- Install using RPM and Debian APT - will be added on the GA release
|
||||
|
||||
### New Features
|
||||
|
||||
- #13915 Vector set - a new data structure [beta]:
|
||||
Vector set extends the concept of sorted sets to allow the storage and querying of
|
||||
high-dimensional vector embeddings, enhancing Redis for AI use cases that involve
|
||||
semantic search and recommendation systems. Vector sets complement the existing
|
||||
vector search capability in the Redis Query Engine. The vector set data type is
|
||||
available in beta. We may change, or even break, the features and the API in
|
||||
future versions. We are open to your feedback as you try out this new data type.
|
||||
- #13846 Allow detecting incompatibility risks before switching to cluster mode
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- #13895 RDB Channel replication - replica is online after BGSAVE is done
|
||||
- #13877 Inconsistency for ShardID in case both master and replica support it
|
||||
- #13883 Defrag scan may return nothing when type/encoding changes during it
|
||||
- #13863 `RANDOMKEY` - infinite loop during client pause
|
||||
- #13853 `SLAVEOF` - crash when clients are blocked on lazy free
|
||||
- #13632 `XREAD` returns nil while stream is not empty
|
||||
|
||||
### Metrics
|
||||
|
||||
- #13846 `INFO`: `cluster_incompatible_ops` - number of cluster-incompatible commands
|
||||
|
||||
### Configuration parameters
|
||||
|
||||
- #13846 `cluster-compatibility-sample-ratio` - sampling ratio (0-100) for checking command compatibility with cluster mode
|
||||
|
||||
|
||||
============================================================
|
||||
8.0-M04 (v7.9.227) Committed Sun 16 Mar 2025 11:00:00 IST
|
||||
============================================================
|
||||
|
||||
This is the fourth Milestone of Redis Community Edition 8.0.
|
||||
|
||||
Milestones are non-feature-complete pre-releases. Pre-releases are not suitable for production use.
|
||||
Once we reach feature-completeness we will release RC1.
|
||||
|
||||
### Headlines
|
||||
|
||||
8.0-M04 includes 3 new hash commands, performance improvements, and memory defragmentation improvements.
|
||||
|
||||
### Distributions
|
||||
|
||||
- Alpine and Debian Docker images - https://hub.docker.com/_/redis
|
||||
- Install using snap - see https://github.com/redis/redis-snap
|
||||
- Install using brew - see https://github.com/redis/homebrew-redis
|
||||
- Install using RPM and Debian APT - will be added on the GA release
|
||||
|
||||
### New Features
|
||||
|
||||
- #13798 Hash - new commands:
|
||||
- `HGETDEL` Get and delete the value of one or more fields of a given hash key
|
||||
- `HGETEX` Get the value of one or more fields of a given hash key, and optionally set their expiration
|
||||
- `HSETEX` Set the value of one or more fields of a given hash key, and optionally set their expiration
|
||||
- #13773 Add replication offset to AOF, allowing more robust way to determine which AOF has a more up-to-date data during recovery
|
||||
- #13740, #13763 shared secret - new mechanism to allow sending internal commands between nodes
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- #13804 Overflow on 32-bit systems when calculating idle time for eviction
|
||||
- #13793 `WAITAOF` returns prematurely
|
||||
- #13800 Remove `DENYOOM` from `HEXPIRE`, `HEXPIREAT`, `HPEXPIRE`, and `HPEXPIREAT`
|
||||
- #13632 Streams - wrong behavior of `XREAD +` after last entry
|
||||
|
||||
### Modules API
|
||||
|
||||
- #13788 `RedisModule_LoadDefaultConfigs` - load module configuration values from redis.conf
|
||||
- #13815 `RM_RegisterDefragFunc2` - support for incremental defragmentation of global module data
|
||||
- #13816 `RM_DefragRedisModuleDict` - allow modules to defrag `RedisModuleDict`
|
||||
- #13774 `RM_GetContextFlags` - add a `REDISMODULE_CTX_FLAGS_DEBUG_ENABLED` flag to execute debug commands
|
||||
|
||||
|
||||
### Performance and resource utilization improvements
|
||||
|
||||
- #13752 Reduce defrag CPU usage when defragmentation is ineffective
|
||||
- #13764 Reduce latency when a command is called consecutively
|
||||
- #13787 Optimize parsing data from clients, specifically multi-bulk (array) data
|
||||
- #13792 Optimize dictionary lookup by avoiding duplicate key length calculation during comparisons
|
||||
- #13796 Optimize expiration checks
|
||||
|
||||
|
||||
============================================================
|
||||
8.0-M03 (v7.9.226) Committed Mon 20 Jan 2025 15:00:00 IST
|
||||
============================================================
|
||||
|
||||
This is the third Milestone of Redis Community Edition 8.0.
|
||||
|
||||
Milestones are non-feature-complete pre-releases. Pre-releases are not suitable for production use.
|
||||
Once we reach feature-completeness we will release RC1.
|
||||
|
||||
### Headlines:
|
||||
|
||||
8.0-M03 introduces an improved replication mechanism which is more performant and robust, a new I/O threading implementation which enables throughput increase on multi-core environments, and many additional performance improvements. Both Alpine and Debian Docker images are now available on [Docker Hub](https://hub.docker.com/_/redis). A snap and Homebrew distributions are available as well.
|
||||
|
||||
|
||||
### Security fixes
|
||||
|
||||
- (CVE-2024-46981) Lua script may lead to remote code execution
|
||||
- (CVE-2024-51741) Denial-of-service due to malformed ACL selectors
|
||||
|
||||
### New Features
|
||||
|
||||
- #13695 New I/O threading implementation
|
||||
- #13732 New replication mechanism
|
||||
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- #13653 `MODULE LOADEX` - crash on nonexistent parameter name
|
||||
- #13661 `FUNCTION FLUSH` - memory leak when using jemalloc
|
||||
- #13626 Memory leak on failed RDB loading
|
||||
|
||||
### Other general improvements
|
||||
|
||||
- #13639 When `hide-user-data-from-log` is enabled - also print command tokens on crash
|
||||
- #13660 Add the Lua VM memory to memory overhead
|
||||
|
||||
### New metrics
|
||||
|
||||
- #13592 `INFO` - new `KEYSIZES` section includes key size distributions for basic data types
|
||||
- #13695 `INFO` - new `Threads` section includes I/O threading metrics
|
||||
|
||||
### Modules API
|
||||
|
||||
- #13666 `RedisModule_ACLCheckKeyPrefixPermissions` - check access permissions to any key matching a given prefix
|
||||
- #13676 `RedisModule_HashFieldMinExpire` - query the minimum expiration time over all the hash’s fields
|
||||
- #13676 `RedisModule_HashGet` - new `REDISMODULE_HASH_EXPIRE_TIME` flag - query the field expiration time
|
||||
- #13656 `RedisModule_RegisterXXXConfig` - allow registering unprefixed configuration parameters
|
||||
|
||||
### Configuration parameters
|
||||
|
||||
|
||||
- `replica-full-sync-buffer-limit` - maximum size of accumulated replication stream data on the replica side
|
||||
- `io-threads-do-reads` is no longer effective. The new I/O threading implementation always use threads for both reads and writes
|
||||
|
||||
### Performance and resource utilization improvements
|
||||
|
||||
- #13638 Optimize CRC64 performance
|
||||
- #13521 Optimize commands with large argument count - reuse c->argv after command execution
|
||||
- #13558 Optimize `PFCOUNT` and `PFMERGE` - SIMD acceleration
|
||||
- #13644 Optimize `GET` on high pipeline use-cases
|
||||
- #13646 Optimize `EXISTS` - prefetching and branch prediction hints
|
||||
- #13652 Optimize `LRANGE` - improve listpack handling and decoding efficiency
|
||||
- #13655 Optimize `HSET` - avoid unnecessary hash field creation or deletion
|
||||
- #13721 Optimize `LRANGE` and `HGETALL` - refactor client write preparation and handling
|
||||
|
||||
|
||||
============================================================
|
||||
8.0-M02 (v7.9.225) Committed Mon 28 Oct 2024 14:00:00 IST
|
||||
============================================================
|
||||
|
||||
This is the second Milestone of Redis Community Edition 8.0.
|
||||
|
||||
Milestones are non-feature-complete pre-releases. Pre-releases are not suitable for production use.
|
||||
Once we reach feature-completeness we will release RC1.
|
||||
|
||||
### Headlines:
|
||||
|
||||
8.0-M02 introduces significant performance improvements. Both Alpine and Debian Docker images are now available on [Docker Hub](https://hub.docker.com/_/redis). Additional distributions will be introduced in upcoming pre-releases.
|
||||
|
||||
### Supported upgrade paths (by replication or persistence) to 8.0-M02
|
||||
|
||||
- From previous Redis versions, without modules
|
||||
|
||||
The following upgrade paths (by replication or persistence) to 8.0-M02 are not yet tested and will be introduced in upcoming pre-releases:
|
||||
- From previous Redis versions with modules (RediSearch, RedisJSON, RedisTimeSeries, RedisBloom)
|
||||
- From Redis Stack 7.2 or 7.4
|
||||
|
||||
### Security fixes
|
||||
|
||||
- (CVE-2024-31449) Lua library commands may lead to stack overflow and potential RCE.
|
||||
- (CVE-2024-31227) Potential Denial-of-service due to malformed ACL selectors.
|
||||
- (CVE-2024-31228) Potential Denial-of-service due to unbounded pattern matching.
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- #13539 Hash: Fix key ref for a hash that no longer has fields with expiration on `RENAME`/`MOVE`/`SWAPDB`/`RESTORE`
|
||||
- #13512 Fix `TOUCH` command from a script in no-touch mode
|
||||
- #13468 Cluster: Fix cluster node config corruption caused by mixing shard-id and non-shard-id versions
|
||||
- #13608 Cluster: Fix `GET #` option in `SORT` command
|
||||
|
||||
### Modules API
|
||||
|
||||
- #13526 Extend `RedisModule_OpenKey` to read also expired keys and subkeys
|
||||
|
||||
### Performance and resource utilization improvements
|
||||
|
||||
- #11884 Optimize `ZADD` and `ZRANGE*` commands
|
||||
- #13530 Optimize `SSCAN` command in case of listpack or intset encoding
|
||||
- #13531 Optimize `HSCAN`/`ZSCAN` command in case of listpack encoding
|
||||
- #13520 Optimize commands that heavily rely on bulk/mbulk replies (example of `LRANGE`)
|
||||
- #13566 Optimize `ZUNION[STORE]` by avoiding redundant temporary dict usage
|
||||
- #13567 Optimize `SUNION`/`SDIFF` commands by avoiding redundant temporary dict usage
|
||||
- #11533 Avoid redundant `lpGet` to boost `quicklistCompare`
|
||||
- #13412 Reduce redundant call of `prepareClientToWrite` when call `addReply*` continuously
|
||||
|
||||
|
||||
===========================================================
|
||||
8.0-M01 (v7.9.224) Released Thu 12 Sep 2024 10:00:00 IST
|
||||
===========================================================
|
||||
|
||||
This is the first Milestone of Redis Community Edition 8.0.
|
||||
|
||||
Milestones are non-feature-complete pre-releases. Pre-releases are not suitable for production use.
|
||||
Once we reach feature-completeness we will release RC1.
|
||||
|
||||
### Headlines:
|
||||
|
||||
Redis 8.0 introduces new data structures: JSON, time series, and 5 probabilistic data structures (previously available as separate Redis modules) and incorporates the enhanced Redis Query Enginer (with vector search).
|
||||
|
||||
8.0-M01 is available as a Docker image and can be downloaded from [Docker Hub](https://hub.docker.com/_/redis). Additional distributions will be introduced in upcoming pre-releases.
|
||||
|
||||
### Supported upgrade paths (by replication or persistence) to 8.0-M01
|
||||
|
||||
|
||||
- From previous Redis versions, without modules
|
||||
|
||||
The following upgrade paths (by replication or persistence) to 8.0-M01 are not yet tested and will be introduced in upcoming pre-releases:
|
||||
- From previous Redis versions with modules (RediSearch, RedisJSON, RedisTimeSeries, RedisBloom)
|
||||
- From Redis Stack 7.2 or 7.4
|
||||
|
||||
### New Features in binary distributions
|
||||
|
||||
- 7 new data structures: JSON, Time series, Bloom filter, Cuckoo filter, Count-min sketch, Top-k, t-digest
|
||||
- The enhanced Redis Query Engine (with vector search)
|
||||
|
||||
### Potentially breaking changes
|
||||
|
||||
- #12272 `GETRANGE` returns an empty bulk when the negative end index is out of range
|
||||
- #12395 Optimize `SCAN` command when matching data type
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- #13510 Fix `RM_RdbLoad` to enable AOF after RDB loading is completed
|
||||
- #13489 `ACL CAT` - return module commands
|
||||
- #13476 Fix a race condition in the `cache_memory` of `functionsLibCtx`
|
||||
- #13473 Fix incorrect lag due to trimming stream via `XTRIM` command
|
||||
- #13338 Fix incorrect lag field in `XINFO` when tombstone is after the `last_id` of the consume group
|
||||
- #13470 On `HDEL` of last field - update the global hash field expiration data structure
|
||||
- #13465 Cluster: Pass extensions to node if extension processing is handled by it
|
||||
- #13443 Cluster: Ensure validity of myself when loading cluster config
|
||||
- #13422 Cluster: Fix `CLUSTER SHARDS` command returns empty array
|
||||
|
||||
### Modules API
|
||||
|
||||
- #13509 New API calls: `RM_DefragAllocRaw`, `RM_DefragFreeRaw`, and `RM_RegisterDefragCallbacks` - defrag API to allocate and free raw memory
|
||||
|
||||
### Performance and resource utilization improvements
|
||||
|
||||
- #13503 Avoid overhead of comparison function pointer calls in listpack `lpFind`
|
||||
- #13505 Optimize `STRING` datatype write commands
|
||||
- #13499 Optimize `SMEMBERS` command
|
||||
- #13494 Optimize `GEO*` commands reply
|
||||
- #13490 Optimize `HELLO` command
|
||||
- #13488 Optimize client query buffer
|
||||
- #12395 Optimize `SCAN` command when matching data type
|
||||
- #13529 Optimize `LREM`, `LPOS`, `LINSERT`, and `LINDEX` commands
|
||||
- #13516 Optimize `LRANGE` and other commands that perform several writes to client buffers per call
|
||||
- #13431 Avoid `used_memory` contention when updating from multiple threads
|
||||
|
||||
### Other general improvements
|
||||
|
||||
- #13495 Reply `-LOADING` on replica while flushing the db
|
||||
|
||||
### CLI tools
|
||||
|
||||
- #13411 redis-cli: Fix wrong `dbnum` showed after the client reconnected
|
||||
|
||||
### Notes
|
||||
|
||||
- No backward compatibility for replication or persistence.
|
||||
- Additional distributions, upgrade paths, features, and improvements will be introduced in upcoming pre-releases.
|
||||
- With the GA release of 8.0 we will deprecate Redis Stack.
|
||||
|
||||
Happy hacking!
|
||||
|
||||
+55
-12
@@ -1734,18 +1734,24 @@ void VectorSetRdbSave(RedisModuleIO *rdb, void *value) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Load object from RDB. Please note that we don't do any cleanup
|
||||
* on errors, and just return NULL, as Redis will abort completely
|
||||
* not just the module but the server itself in this case. */
|
||||
/* Load object from RDB. Recover from recoverable errors (read errors)
|
||||
* by performing cleanup. */
|
||||
void *VectorSetRdbLoad(RedisModuleIO *rdb, int encver) {
|
||||
if (encver != 0) return NULL; // Invalid version
|
||||
|
||||
uint32_t dim = RedisModule_LoadUnsigned(rdb);
|
||||
uint64_t elements = RedisModule_LoadUnsigned(rdb);
|
||||
uint32_t hnsw_config = RedisModule_LoadUnsigned(rdb);
|
||||
if (RedisModule_IsIOError(rdb)) return NULL;
|
||||
uint32_t quant_type = hnsw_config & 0xff;
|
||||
uint32_t hnsw_m = (hnsw_config >> 8) & 0xffff;
|
||||
|
||||
/* Check that the quantization type is correct. Otherwise
|
||||
* return ASAP signaling the error. */
|
||||
if (quant_type != HNSW_QUANT_NONE &&
|
||||
quant_type != HNSW_QUANT_Q8 &&
|
||||
quant_type != HNSW_QUANT_BIN) return NULL;
|
||||
|
||||
if (hnsw_m == 0) hnsw_m = 16; // Default, useful for RDB files predating
|
||||
// this configuration parameter: it was fixed
|
||||
// to 16.
|
||||
@@ -1754,22 +1760,21 @@ void *VectorSetRdbLoad(RedisModuleIO *rdb, int encver) {
|
||||
|
||||
/* Load projection matrix if present */
|
||||
uint32_t save_flags = RedisModule_LoadUnsigned(rdb);
|
||||
if (RedisModule_IsIOError(rdb)) goto ioerr;
|
||||
int has_projection = save_flags & SAVE_FLAG_HAS_PROJMATRIX;
|
||||
int has_attribs = save_flags & SAVE_FLAG_HAS_ATTRIBS;
|
||||
if (has_projection) {
|
||||
uint32_t input_dim = RedisModule_LoadUnsigned(rdb);
|
||||
if (RedisModule_IsIOError(rdb)) goto ioerr;
|
||||
uint32_t output_dim = dim;
|
||||
size_t matrix_size = sizeof(float) * input_dim * output_dim;
|
||||
|
||||
vset->proj_matrix = RedisModule_Alloc(matrix_size);
|
||||
if (!vset->proj_matrix) {
|
||||
vectorSetReleaseObject(vset);
|
||||
return NULL;
|
||||
}
|
||||
vset->proj_input_size = input_dim;
|
||||
|
||||
// Load projection matrix as a binary blob
|
||||
char *matrix_blob = RedisModule_LoadStringBuffer(rdb, NULL);
|
||||
if (matrix_blob == NULL) goto ioerr;
|
||||
memcpy(vset->proj_matrix, matrix_blob, matrix_size);
|
||||
RedisModule_Free(matrix_blob);
|
||||
}
|
||||
@@ -1777,9 +1782,14 @@ void *VectorSetRdbLoad(RedisModuleIO *rdb, int encver) {
|
||||
while(elements--) {
|
||||
// Load associated string element.
|
||||
RedisModuleString *ele = RedisModule_LoadString(rdb);
|
||||
if (RedisModule_IsIOError(rdb)) goto ioerr;
|
||||
RedisModuleString *attrib = NULL;
|
||||
if (has_attribs) {
|
||||
attrib = RedisModule_LoadString(rdb);
|
||||
if (RedisModule_IsIOError(rdb)) {
|
||||
RedisModule_FreeString(NULL,ele);
|
||||
goto ioerr;
|
||||
}
|
||||
size_t attrlen;
|
||||
RedisModule_StringPtrLen(attrib,&attrlen);
|
||||
if (attrlen == 0) {
|
||||
@@ -1789,18 +1799,42 @@ void *VectorSetRdbLoad(RedisModuleIO *rdb, int encver) {
|
||||
}
|
||||
size_t vector_len;
|
||||
void *vector = RedisModule_LoadStringBuffer(rdb, &vector_len);
|
||||
if (RedisModule_IsIOError(rdb)) {
|
||||
RedisModule_FreeString(NULL,ele);
|
||||
if (attrib) RedisModule_FreeString(NULL,attrib);
|
||||
goto ioerr;
|
||||
}
|
||||
uint32_t vector_bytes = hnsw_quants_bytes(vset->hnsw);
|
||||
if (vector_len != vector_bytes) {
|
||||
RedisModule_LogIOError(rdb,"warning",
|
||||
"Mismatching vector dimension");
|
||||
return NULL; // Loading error.
|
||||
RedisModule_FreeString(NULL,ele);
|
||||
if (attrib) RedisModule_FreeString(NULL,attrib);
|
||||
RedisModule_Free(vector);
|
||||
goto ioerr;
|
||||
}
|
||||
|
||||
// Load node parameters back.
|
||||
uint32_t params_count = RedisModule_LoadUnsigned(rdb);
|
||||
if (RedisModule_IsIOError(rdb)) {
|
||||
RedisModule_FreeString(NULL,ele);
|
||||
if (attrib) RedisModule_FreeString(NULL,attrib);
|
||||
RedisModule_Free(vector);
|
||||
goto ioerr;
|
||||
}
|
||||
|
||||
uint64_t *params = RedisModule_Alloc(params_count*sizeof(uint64_t));
|
||||
for (uint32_t j = 0; j < params_count; j++)
|
||||
for (uint32_t j = 0; j < params_count; j++) {
|
||||
// Ignore loading errors here: handled at the end of the loop.
|
||||
params[j] = RedisModule_LoadUnsigned(rdb);
|
||||
}
|
||||
if (RedisModule_IsIOError(rdb)) {
|
||||
RedisModule_FreeString(NULL,ele);
|
||||
if (attrib) RedisModule_FreeString(NULL,attrib);
|
||||
RedisModule_Free(vector);
|
||||
RedisModule_Free(params);
|
||||
goto ioerr;
|
||||
}
|
||||
|
||||
struct vsetNodeVal *nv = RedisModule_Alloc(sizeof(*nv));
|
||||
nv->item = ele;
|
||||
@@ -1809,15 +1843,25 @@ void *VectorSetRdbLoad(RedisModuleIO *rdb, int encver) {
|
||||
if (node == NULL) {
|
||||
RedisModule_LogIOError(rdb,"warning",
|
||||
"Vector set node index loading error");
|
||||
return NULL; // Loading error.
|
||||
vectorSetReleaseNodeValue(nv);
|
||||
RedisModule_Free(vector);
|
||||
RedisModule_Free(params);
|
||||
goto ioerr;
|
||||
}
|
||||
if (nv->attrib) vset->numattribs++;
|
||||
RedisModule_DictSet(vset->dict,ele,node);
|
||||
RedisModule_Free(vector);
|
||||
RedisModule_Free(params);
|
||||
}
|
||||
hnsw_deserialize_index(vset->hnsw);
|
||||
if (!hnsw_deserialize_index(vset->hnsw)) goto ioerr;
|
||||
|
||||
return vset;
|
||||
|
||||
ioerr:
|
||||
/* We want to recover from I/O errors and free the partially allocated
|
||||
* data structure to support diskless replication. */
|
||||
vectorSetReleaseObject(vset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Calculate memory usage */
|
||||
@@ -1944,7 +1988,6 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
if (RedisModule_Init(ctx,"vectorset",1,REDISMODULE_APIVER_1)
|
||||
== REDISMODULE_ERR) return REDISMODULE_ERR;
|
||||
|
||||
/* TODO: Added to pass CI, need to make changes in order to support these options */
|
||||
RedisModule_SetModuleOptions(ctx, REDISMODULE_OPTIONS_HANDLE_IO_ERRORS|REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD);
|
||||
|
||||
RedisModuleTypeMethods tm = {
|
||||
|
||||
+1
-1
@@ -363,7 +363,7 @@ endif
|
||||
|
||||
REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX)
|
||||
REDIS_SENTINEL_NAME=redis-sentinel$(PROG_SUFFIX)
|
||||
REDIS_SERVER_OBJ=threads_mngr.o adlist.o quicklist.o ae.o anet.o dict.o ebuckets.o eventnotifier.o iothread.o mstr.o kvstore.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o cluster_legacy.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crccombine.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o strl.o connection.o unix.o logreqres.o
|
||||
REDIS_SERVER_OBJ=threads_mngr.o adlist.o quicklist.o ae.o anet.o dict.o ebuckets.o eventnotifier.o iothread.o mstr.o kvstore.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o cluster_legacy.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crccombine.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o lolwut8.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o strl.o connection.o unix.o logreqres.o
|
||||
REDIS_CLI_NAME=redis-cli$(PROG_SUFFIX)
|
||||
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o redisassert.o crcspeed.o crccombine.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o strl.o cli_commands.o
|
||||
REDIS_BENCHMARK_NAME=redis-benchmark$(PROG_SUFFIX)
|
||||
|
||||
@@ -1445,12 +1445,6 @@ static int activeDefragTimeProc(struct aeEventLoop *eventLoop, long long id, voi
|
||||
monotime endtime = starttime + dutyCycleUs;
|
||||
int haveMoreWork = 1;
|
||||
|
||||
/* Increment server.cronloops so that run_with_period works. */
|
||||
long hz_ms = 1000 / server.hz;
|
||||
int cronloops = (server.mstime - server.blocked_last_cron + (hz_ms - 1)) / hz_ms; /* rounding up */
|
||||
server.blocked_last_cron += cronloops * hz_ms;
|
||||
server.cronloops += cronloops;
|
||||
|
||||
mstime_t latency;
|
||||
latencyStartMonitor(latency);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
void lolwut5Command(client *c);
|
||||
void lolwut6Command(client *c);
|
||||
void lolwut8Command(client *c);
|
||||
|
||||
/* The default target for LOLWUT if no matching version was found.
|
||||
* This is what unstable versions of Redis will display. */
|
||||
@@ -54,6 +55,9 @@ void lolwutCommand(client *c) {
|
||||
else if ((v[0] == '6' && v[1] == '.' && v[2] != '9') ||
|
||||
(v[0] == '5' && v[1] == '.' && v[2] == '9'))
|
||||
lolwut6Command(c);
|
||||
else if ((v[0] == '8' && v[1] == '.' && v[2] != '9') ||
|
||||
(v[0] == '7' && v[1] == '.' && v[2] == '9'))
|
||||
lolwut8Command(c);
|
||||
else
|
||||
lolwutUnstableCommand(c);
|
||||
|
||||
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2025-Present, Redis Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under your choice of (a) the Redis Source Available License 2.0
|
||||
* (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the
|
||||
* GNU Affero General Public License v3 (AGPLv3).
|
||||
*
|
||||
* Originally authored by: Salvatore Sanfilippo.
|
||||
* Algorithm based on the Almanacco Bompiani description and the Python
|
||||
* code written by Emiliano Russo.
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* The LOLWUT 8 command:
|
||||
*
|
||||
* LOLWUT [EN|IT]
|
||||
*
|
||||
* By default the command produces verses in English language, in order for
|
||||
* the output to be more universally accessible. However, passing IT as argument
|
||||
* it is possible to reproduce the original output, exactly like done by
|
||||
* Nanni Balestrini in TAPE MARK I, and described in the Almanacco Letterario
|
||||
* Bompiani, 1962.
|
||||
*/
|
||||
|
||||
// Structure to represent a verse with its metrical characteristics.
|
||||
typedef struct {
|
||||
char text_en[100]; // English verse text.
|
||||
char text_it[100]; // Italian verse text.
|
||||
char fraction1[5]; // First fraction (rhythm/meter indicator).
|
||||
char fraction2[5]; // Second fraction (rhythm/meter indicator).
|
||||
char group[2]; // Group number (1-3 representing different
|
||||
// literary sources).
|
||||
} Verse;
|
||||
|
||||
// Fisher-Yates shuffle algorithm to randomize verse order.
|
||||
static void shuffle(Verse *array, int size) {
|
||||
for (int i = size - 1; i > 0; i--) {
|
||||
int j = rand() % (i + 1);
|
||||
Verse temp = array[j];
|
||||
array[j] = array[i];
|
||||
array[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void lolwut8Command(client *c) {
|
||||
int en_lang = 1; // Default to English.
|
||||
|
||||
/* Parse the optional arguments if any. */
|
||||
if (c->argc > 1 && !strcasecmp(c->argv[1]->ptr,"IT"))
|
||||
en_lang = 0;
|
||||
|
||||
// Define verses from three literary sources with their metrical fractions:
|
||||
// Group 1: Diary of Hiroshima by Michihito Hachiya.
|
||||
// Group 2: The Mystery of the Elevator by Paul Goldwin.
|
||||
// Group 3: Tao Te Ching by Lao Tse.
|
||||
Verse verses[] = {
|
||||
// Group 1: Hiroshima verses.
|
||||
{" The blinding / globe / of fire ",
|
||||
" l accecante / globo / di fuoco ", "1/4", "2/3", "1"},
|
||||
{" It expands / rapidly ",
|
||||
" si espande / rapidamente ", "1/2", "3/4", "1"},
|
||||
{" Thirty times / brighter / than the sun ",
|
||||
" trenta volte / piu luminoso / del sole ", "2/3", "2/4", "1"},
|
||||
{" When it reaches / the stratosphere ",
|
||||
" quando raggiunge / la stratosfera ", "3/4", "1/2", "1"},
|
||||
{" The summit / of the cloud ",
|
||||
" la sommita / della nuvola ", "1/3", "2/3", "1"},
|
||||
{" Assumes / the well-known shape / of a mushroom ",
|
||||
" assume / la ben nota forma / di fungo ", "2/4", "3/4", "1"},
|
||||
|
||||
// Group 2: Elevator mystery verses.
|
||||
{" The head / pressed / upon the shoulder ",
|
||||
" la testa / premuta / sulla spalla ", "1/4", "2/4", "2"},
|
||||
{" The hair / between the lips ",
|
||||
" i capelli / tra le labbra ", "1/4", "2/4", "2"},
|
||||
{" They lay / motionless / without speaking ",
|
||||
" giacquero / immobili / senza parlare ", "2/3", "2/3", "2"},
|
||||
{" Till he moved / his fingers / slowly ",
|
||||
" finche non mosse / le dita / lentamente ", "3/4", "1/3", "2"},
|
||||
{" Trying / to grasp ",
|
||||
" cercando / di afferrare ", "3/4", "1/2", "2"},
|
||||
|
||||
// Group 3: Tao Te Ching verses.
|
||||
{" While the multitude / of things / comes into being ",
|
||||
" mentre la moltitudine / delle cose / accade ", "1/2", "1/2", "3"},
|
||||
{" I envisage / their return ",
|
||||
" io contemplo / il loro ritorno ", "2/3", "3/4", "3"},
|
||||
{" Although / things / flourish ",
|
||||
" malgrado / che le cose / fioriscano ", "1/2", "2/3", "3"},
|
||||
{" They all return / to / their roots ",
|
||||
" esse tornano / tutte / alla loro radice ", "2/3", "1/4", "3"}
|
||||
};
|
||||
|
||||
// Calculate the total number of verses.
|
||||
int num_verses = sizeof(verses) / sizeof(verses[0]);
|
||||
|
||||
// Create a working copy of verses for manipulation.
|
||||
Verse *working_verses = zmalloc(num_verses * sizeof(Verse));
|
||||
memcpy(working_verses, verses, num_verses * sizeof(Verse));
|
||||
|
||||
// Step 1: Shuffle the verses randomly.
|
||||
shuffle(working_verses, num_verses);
|
||||
|
||||
// Step 2: Build stanza by finding compatible verses
|
||||
// Each subsequent verse must:
|
||||
// - Have compatible metrical fractions (connecting criteria).
|
||||
// - Belong to a different group than the previous verse.
|
||||
Verse stanza[10];
|
||||
|
||||
int j; // At the end, it will contain the number of added stanzas.
|
||||
for (j = 0; j < 10; j++) {
|
||||
int i = 0;
|
||||
int found = 0;
|
||||
|
||||
// Search for compatible verse among remaining verses.
|
||||
while (i < num_verses) {
|
||||
// Metrical compatibility check: this is used to select verses
|
||||
// that go somewhat well together, if their fractions match.
|
||||
// The algorithm checks if current verse's first fraction matches
|
||||
// with previous verse's second fraction in various ways, and
|
||||
// force successive verses to be of different groups.
|
||||
if (j == 0 || // First stanza is always accepted.
|
||||
((working_verses[i].fraction1[0] == stanza[j-1].fraction2[0] ||
|
||||
working_verses[i].fraction1[2] == stanza[j-1].fraction2[0] ||
|
||||
working_verses[i].fraction1[2] == stanza[j-1].fraction2[2]) &&
|
||||
strcmp(working_verses[i].group, stanza[j-1].group) != 0))
|
||||
{
|
||||
|
||||
// Add compatible verse to stanza.
|
||||
stanza[j] = working_verses[i];
|
||||
|
||||
// Remove selected verse from working set, to avoid reuse.
|
||||
for (int k = i; k < num_verses - 1; k++)
|
||||
working_verses[k] = working_verses[k + 1];
|
||||
num_verses--;
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Exit if there are no longer matching verses.
|
||||
if (!found) break;
|
||||
}
|
||||
zfree(working_verses);
|
||||
|
||||
// Step 3: Combine all stanza verses into single SDS string.
|
||||
sds combined = sdsempty();
|
||||
for (int i = 0; i < j; i++) {
|
||||
if (en_lang) {
|
||||
combined = sdscat(combined, stanza[i].text_en);
|
||||
} else {
|
||||
combined = sdscat(combined, stanza[i].text_it);
|
||||
}
|
||||
combined = sdscat(combined, "\n");
|
||||
}
|
||||
|
||||
// Step 4: Make uppercase, and strip the "/".
|
||||
for (size_t j = 0; j < sdslen(combined); j++) {
|
||||
combined[j] = toupper(combined[j]);
|
||||
if (combined[j] == '/') combined[j] = ' ';
|
||||
}
|
||||
|
||||
// Step 5: Add background info about what the user just saw.
|
||||
combined = sdscat(combined,
|
||||
"\nIn 1961, Nanni Balestrini created one of the first computer-generated poems, TAPE MARK I, using an IBM 7090 mainframe. Each execution combined verses from three literary sources following algorithmic rules based on metrical compatibility and group constraints. This LOLWUT command reproduces Balestrini's original algorithm, generating new stanzas through the same computational poetry process described in Almanacco Letterario Bompiani, 1962.\n\n"
|
||||
"https://en.wikipedia.org/wiki/Digital_poetry\n"
|
||||
"https://www.youtube.com/watch?v=8i7uFCK7G0o (English subs)\n\n"
|
||||
"Use: LOLWUT IT for the original Italian output.\n\n");
|
||||
|
||||
addReplyVerbatim(c,combined,sdslen(combined),"txt");
|
||||
sdsfree(combined);
|
||||
}
|
||||
@@ -556,6 +556,12 @@ int redis_check_aof_main(int argc, char **argv) {
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
/* Check if filepath is longer than PATH_MAX */
|
||||
if (strlen(filepath) > PATH_MAX) {
|
||||
printf("Error: filepath is too long (exceeds PATH_MAX)\n");
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
/* In the glibc implementation dirname may modify their argument. */
|
||||
memcpy(temp_filepath, filepath, strlen(filepath) + 1);
|
||||
dirpath = dirname(temp_filepath);
|
||||
|
||||
@@ -1663,6 +1663,12 @@ void whileBlockedCron(void) {
|
||||
if (server.blocked_last_cron >= server.mstime)
|
||||
return;
|
||||
|
||||
/* Increment server.cronloops so that run_with_period works. */
|
||||
long hz_ms = 1000 / server.hz;
|
||||
int cronloops = (server.mstime - server.blocked_last_cron + (hz_ms - 1)) / hz_ms; /* rounding up */
|
||||
server.blocked_last_cron += cronloops * hz_ms;
|
||||
server.cronloops += cronloops;
|
||||
|
||||
mstime_t latency;
|
||||
latencyStartMonitor(latency);
|
||||
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
#define REDIS_VERSION "255.255.255"
|
||||
#define REDIS_VERSION_NUM 0x00ffffff
|
||||
#define REDIS_VERSION "8.0.2"
|
||||
#define REDIS_VERSION_NUM 0x00080002
|
||||
|
||||
@@ -15,6 +15,10 @@ if { ! [ catch {
|
||||
|
||||
proc generate_collections {suffix elements} {
|
||||
set rd [redis_deferring_client]
|
||||
set numcmd 7
|
||||
set has_vsets [server_has_command vadd]
|
||||
if {$has_vsets} {incr numcmd}
|
||||
|
||||
for {set j 0} {$j < $elements} {incr j} {
|
||||
# add both string values and integers
|
||||
if {$j % 2 == 0} {set val $j} else {set val "_$j"}
|
||||
@@ -25,8 +29,11 @@ proc generate_collections {suffix elements} {
|
||||
$rd zadd zset$suffix $j $val
|
||||
$rd sadd set$suffix $val
|
||||
$rd xadd stream$suffix * item 1 value $val
|
||||
if {$has_vsets} {
|
||||
$rd vadd vset$suffix VALUES 3 1 1 1 $j
|
||||
}
|
||||
}
|
||||
for {set j 0} {$j < $elements * 7} {incr j} {
|
||||
for {set j 0} {$j < $elements * $numcmd} {incr j} {
|
||||
$rd read ; # Discard replies
|
||||
}
|
||||
$rd close
|
||||
|
||||
@@ -931,5 +931,16 @@ test {corrupt payload: hash listpack encoded with invalid length causes hscan to
|
||||
}
|
||||
}
|
||||
|
||||
test {corrupt payload: fuzzer findings - vector sets with wrong encoding} {
|
||||
start_server [list overrides [list loglevel verbose use-exit-on-panic yes crash-memcheck-enabled no] ] {
|
||||
r config set sanitize-dump-payload yes
|
||||
r debug set-skip-checksum-validation 1
|
||||
catch {r restore _key 0 "\x07\x81\xBD\xE7\x2D\xA2\xBB\x1E\xB4\x00\x02\x03\x02\x03\x02\x50\x8F\x02\x00\x05\xC0\x02\x05\x03\x7F\x7F\x7F\x02\x07\x02\x03\x02\x00\x02\x02\x02\x20\x02\x01\x02\x02\x02\x81\x3F\x13\xCD\x3A\x3F\xDD\xB3\xD7\x05\xC0\x01\x05\x03\x7F\x7F\x7F\x02\x0B\x02\x02\x02\x02\x02\x02\x02\x20\x02\x01\x02\x03\x02\x06\x02\x10\x02\x00\x02\x10\x02\x81\x3F\x13\xCD\x3A\x3F\xDD\xB3\xD7\x05\xC0\x00\x05\x03\x7F\x7F\x7F\x02\x07\x02\x01\x02\x00\x02\x02\x02\x20\x02\x02\x02\x03\x02\x81\x3F\x13\xCD\x3A\x3F\xDD\xB3\xD7\x00\x0C\x00\xC6\xA3\x70\x40\x02\x26\xE8\x9B"} err
|
||||
assert_match "*Bad data format*" $err
|
||||
r ping
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} ;# tags
|
||||
|
||||
|
||||
@@ -756,6 +756,8 @@ test {diskless loading short read} {
|
||||
redis.register_function('test', function() return 'hello1' end)
|
||||
}
|
||||
|
||||
set has_vector_sets [server_has_command vadd]
|
||||
|
||||
for {set k 0} {$k < 3} {incr k} {
|
||||
for {set i 0} {$i < 10} {incr i} {
|
||||
r set "$k int_$i" [expr {int(rand()*10000)}]
|
||||
@@ -769,6 +771,11 @@ test {diskless loading short read} {
|
||||
r zadd "$k zset_large" [expr {rand()}] [string repeat A [expr {int(rand()*1000000)}]]
|
||||
r lpush "$k list_small" [string repeat A [expr {int(rand()*10)}]]
|
||||
r lpush "$k list_large" [string repeat A [expr {int(rand()*1000000)}]]
|
||||
|
||||
if {$has_vector_sets} {
|
||||
r vadd "$k vector_set" VALUES 3 [expr {rand()}] [expr {rand()}] [expr {rand()}] [string repeat A [expr {int(rand()*1000)}]]
|
||||
}
|
||||
|
||||
for {set j 0} {$j < 10} {incr j} {
|
||||
r xadd "$k stream" * foo "asdf" bar "1234"
|
||||
}
|
||||
|
||||
+23
-1
@@ -738,7 +738,8 @@ proc generate_fuzzy_traffic_on_key {key type duration} {
|
||||
set list_commands {LINDEX LINSERT LLEN LPOP LPOS LPUSH LPUSHX LRANGE LREM LSET LTRIM RPOP RPOPLPUSH RPUSH RPUSHX}
|
||||
set set_commands {SADD SCARD SDIFF SDIFFSTORE SINTER SINTERSTORE SISMEMBER SMEMBERS SMOVE SPOP SRANDMEMBER SREM SSCAN SUNION SUNIONSTORE}
|
||||
set stream_commands {XACK XADD XCLAIM XDEL XGROUP XINFO XLEN XPENDING XRANGE XREAD XREADGROUP XREVRANGE XTRIM}
|
||||
set commands [dict create string $string_commands hash $hash_commands zset $zset_commands list $list_commands set $set_commands stream $stream_commands]
|
||||
set vset_commands {VADD VREM}
|
||||
set commands [dict create string $string_commands hash $hash_commands zset $zset_commands list $list_commands set $set_commands stream $stream_commands vectorset $vset_commands]
|
||||
|
||||
set cmds [dict get $commands $type]
|
||||
set start_time [clock seconds]
|
||||
@@ -788,6 +789,18 @@ proc generate_fuzzy_traffic_on_key {key type duration} {
|
||||
lappend cmd [randomValue]
|
||||
incr i 4
|
||||
}
|
||||
if {$cmd == "VADD"} {
|
||||
lappend cmd $key
|
||||
lappend cmd VALUES 3 1 1 1
|
||||
lappend cmd [randomValue]
|
||||
incr i 7
|
||||
}
|
||||
if {$cmd == "VREM"} {
|
||||
lappend cmd $key
|
||||
lappend cmd [randomValue]
|
||||
incr i 2
|
||||
}
|
||||
|
||||
for {} {$i < $arity} {incr i} {
|
||||
if {$i == $firstkey || $i == $lastkey} {
|
||||
lappend cmd $key
|
||||
@@ -1144,6 +1157,15 @@ proc memory_usage {key} {
|
||||
return $usage
|
||||
}
|
||||
|
||||
# Test if the server supports the specified command.
|
||||
proc server_has_command {cmd_wanted} {
|
||||
set lowercase_commands {}
|
||||
foreach cmd [r command list] {
|
||||
lappend lowercase_commands [string tolower $cmd]
|
||||
}
|
||||
expr {[lsearch $lowercase_commands [string tolower $cmd_wanted]] != -1}
|
||||
}
|
||||
|
||||
# forward compatibility, lmap missing in TCL 8.5
|
||||
proc lmap args {
|
||||
set body [lindex $args end]
|
||||
|
||||
Reference in New Issue
Block a user