Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package valkey for openSUSE:Factory checked in at 2025-12-10 15:30:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/valkey (Old) and /work/SRC/openSUSE:Factory/.valkey.new.1939 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "valkey" Wed Dec 10 15:30:32 2025 rev:17 rq:1321869 version:9.0.1 Changes: -------- --- /work/SRC/openSUSE:Factory/valkey/valkey.changes 2025-11-05 16:19:34.001260819 +0100 +++ /work/SRC/openSUSE:Factory/.valkey.new.1939/valkey.changes 2025-12-10 15:31:17.492178118 +0100 @@ -1,0 +2,23 @@ +Tue Dec 9 20:31:50 UTC 2025 - Andreas Stieger <[email protected]> + +- Update to 9.0.1: + * Authenticate slot migration client on source node to internal user + * Bug fix: reset io_last_written on c->buf resize to prevent stale pointers + * Sentinel: fix regression requiring "+failover" ACL in failover path + * Cluster: Avoid usage of light weight messages to nodes with not ready bidirectional links + * Send duplicate multi meet packet only for node which supports it in mixed clusters + * Fix: LTRIM should not call signalModifiedKey when no elements are removed + * Fix build on some 32-bit ARM by only using NEON on AArch64 + * Fix deadlock in IO-thread shutdown during panic + * Fix COMMANDLOG large-reply when using reply copy avoidance + * Fix CLUSTER SLOTS crash when called from module timer callback + +------------------------------------------------------------------- +Sat Nov 29 02:18:38 UTC 2025 - Marcus Rueckert <[email protected]> + +- update valkey-conf.patch + instead of copying the whole default example config we can also + have it as include file and start out with a very minimal + configuration for each instance. + +------------------------------------------------------------------- Old: ---- valkey-9.0.0.tar.gz New: ---- valkey-9.0.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ valkey.spec ++++++ --- /var/tmp/diff_new_pack.RvKK9e/_old 2025-12-10 15:31:18.216208645 +0100 +++ /var/tmp/diff_new_pack.RvKK9e/_new 2025-12-10 15:31:18.220208813 +0100 @@ -26,7 +26,7 @@ %global make_flags CFLAGS="%{build_cflags}" DEBUG="" V="echo" PREFIX=%{buildroot}%{_prefix} BUILD_WITH_SYSTEMD=yes BUILD_TLS=yes Name: valkey -Version: 9.0.0 +Version: 9.0.1 Release: 0 Summary: Persistent key-value database License: BSD-3-Clause @@ -117,9 +117,11 @@ %{buildroot}%{_data_dir}/default install -pDm644 src/%{name}module.h %{buildroot}%{_includedir}/%{name}module.h +install -Dpm0640 valkey.conf %{buildroot}%{_conf_dir}/includes/valkey.defaults.conf +install -Dpm0640 sentinel.conf %{buildroot}%{_conf_dir}/includes/sentinel.defaults.conf -install -Dpm0640 valkey.conf %{buildroot}%{_conf_dir}/default.conf.example -install -Dpm0660 sentinel.conf %{buildroot}%{_conf_dir}/sentinel.conf.example +install -Dpm0640 valkey.default.conf %{buildroot}%{_conf_dir}/valkey.default.conf.template +install -Dpm0660 sentinel.default.conf %{buildroot}%{_conf_dir}/sentinel.default.conf.template # some sysctl stuff install -Dpm0644 %{SOURCE6} %{buildroot}/%{_prefix}/lib/sysctl.d/00-%{name}.conf ++++++ valkey-9.0.0.tar.gz -> valkey-9.0.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/.github/workflows/daily.yml new/valkey-9.0.1/.github/workflows/daily.yml --- old/valkey-9.0.0/.github/workflows/daily.yml 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/.github/workflows/daily.yml 2025-12-09 19:03:34.000000000 +0100 @@ -1255,7 +1255,7 @@ version: 13.2 shell: bash run: | - sudo pkg install -y bash gmake lang/tcl86 lang/tclx + sudo pkg install -y bash gmake lang/tcl86 lang/tclX gmake ./runtest --single unit/keyspace --single unit/auth --single unit/networking --single unit/protocol diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/00-RELEASENOTES new/valkey-9.0.1/00-RELEASENOTES --- old/valkey-9.0.0/00-RELEASENOTES 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/00-RELEASENOTES 2025-12-09 19:03:34.000000000 +0100 @@ -11,6 +11,23 @@ | CRITICAL | There is a critical bug affecting MOST USERS. Upgrade ASAP. | | SECURITY | There are security fixes in the release. | +Valkey 9.0.1 - December 9, 2025 +------------------------------- + +Upgrade urgency MODERATE: Program an upgrade of the server, but it's not urgent. + +### Bug fixes +* Authenticate slot migration client on source node to internal user (#2785) +* Bug fix: reset io_last_written on c->buf resize to prevent stale pointers (#2786) +* Sentinel: fix regression requiring "+failover" ACL in failover path (#2780) +* Cluster: Avoid usage of light weight messages to nodes with not ready bidirectional links (#2817) +* Send duplicate multi meet packet only for node which supports it in mixed clusters (#2840) +* Fix: LTRIM should not call signalModifiedKey when no elements are removed (#2787) +* Fix build on some 32-bit ARM by only using NEON on AArch64 (#2873) +* Fix deadlock in IO-thread shutdown during panic (#2898) +* Fix COMMANDLOG large-reply when using reply copy avoidance (#2652) +* Fix CLUSTER SLOTS crash when called from module timer callback (#2915) + Valkey 9.0.0 GA - October 21, 2025 ------------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/sentinel.conf new/valkey-9.0.1/sentinel.conf --- old/valkey-9.0.0/sentinel.conf 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/sentinel.conf 2025-12-09 19:03:34.000000000 +0100 @@ -119,8 +119,11 @@ # In the Valkey servers side, the ACL to provide just minimal access to # Sentinel instances, should be configured along the following lines: # -# user sentinel-user >somepassword +client +subscribe +publish \ +# user sentinel-user >somepassword +subscribe +publish +failover +script|kill \ # +ping +info +multi +slaveof +config +client +exec &__sentinel__:hello on +# +# Since Valkey Sentinel 9.0, the sentinel user requires the +failover permission +# on all monitored Valkey instances for proper operation. # sentinel down-after-milliseconds <master-name> <milliseconds> # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/Makefile new/valkey-9.0.1/src/Makefile --- old/valkey-9.0.0/src/Makefile 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/Makefile 2025-12-09 19:03:34.000000000 +0100 @@ -469,10 +469,12 @@ echo STD=$(STD) >> .make-settings echo WARN=$(WARN) >> .make-settings echo OPT=$(OPT) >> .make-settings + echo PROG_SUFFIX=$(PROG_SUFFIX) >> .make-settings echo MALLOC=$(MALLOC) >> .make-settings echo BUILD_TLS=$(BUILD_TLS) >> .make-settings echo BUILD_RDMA=$(BUILD_RDMA) >> .make-settings echo USE_SYSTEMD=$(USE_SYSTEMD) >> .make-settings + echo USE_FAST_FLOAT=$(USE_FAST_FLOAT) >> .make-settings echo CFLAGS=$(CFLAGS) >> .make-settings echo LDFLAGS=$(LDFLAGS) >> .make-settings echo SERVER_CFLAGS=$(SERVER_CFLAGS) >> .make-settings diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/cli_common.c new/valkey-9.0.1/src/cli_common.c --- old/valkey-9.0.0/src/cli_common.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/cli_common.c 2025-12-09 19:03:34.000000000 +0100 @@ -331,7 +331,7 @@ !strncasecmp(redisTlsscheme, curr, strlen(redisTlsscheme))) { #ifdef USE_OPENSSL *tls_flag = 1; - char *del = strstr(curr, "://"); + const char *del = strstr(curr, "://"); curr += (del - curr) + 3; #else char *copy = strdup(curr); @@ -341,7 +341,7 @@ exit(1); #endif } else if (!strncasecmp(scheme, curr, strlen(scheme)) || !strncasecmp(redisScheme, curr, strlen(redisScheme))) { - char *del = strstr(curr, "://"); + const char *del = strstr(curr, "://"); curr += (del - curr) + 3; } else { fprintf(stderr, "Invalid URI scheme\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/cluster_legacy.c new/valkey-9.0.1/src/cluster_legacy.c --- old/valkey-9.0.0/src/cluster_legacy.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/cluster_legacy.c 2025-12-09 19:03:34.000000000 +0100 @@ -1145,7 +1145,8 @@ myself->flags |= nofailover; myself->flags |= CLUSTER_NODE_EXTENSIONS_SUPPORTED | CLUSTER_NODE_LIGHT_HDR_PUBLISH_SUPPORTED | - CLUSTER_NODE_LIGHT_HDR_MODULE_SUPPORTED; + CLUSTER_NODE_LIGHT_HDR_MODULE_SUPPORTED | + CLUSTER_NODE_MULTI_MEET_SUPPORTED; if (myself->flags != oldflags) { clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG | CLUSTER_TODO_UPDATE_STATE); } @@ -3675,6 +3676,13 @@ } else { sender->flags &= ~CLUSTER_NODE_LIGHT_HDR_MODULE_SUPPORTED; } + + /* Check if the node can handle multi meet packet. */ + if (flags & CLUSTER_NODE_MULTI_MEET_SUPPORTED) { + sender->flags |= CLUSTER_NODE_MULTI_MEET_SUPPORTED; + } else { + sender->flags &= ~CLUSTER_NODE_MULTI_MEET_SUPPORTED; + } } /* Update the last time we saw any data from this node. We @@ -4828,6 +4836,18 @@ clusterMsgSendBlockDecrRefCount(msgblock); } +/* Inline functions that check support of light weight messages by node + * and avoid using light weight messages until the bidirectional + * link(s) have been established. */ +static inline bool nodeSupportsLightMsgHdrForPubSub(clusterNode *n) { + return n->link && n->pong_received >= n->link->ctime && + (n->flags & CLUSTER_NODE_LIGHT_HDR_PUBLISH_SUPPORTED); +} +static inline bool nodeSupportsLightMsgHdrForModule(clusterNode *n) { + return n->link && n->pong_received >= n->link->ctime && + (n->flags & CLUSTER_NODE_LIGHT_HDR_MODULE_SUPPORTED); +} + /* Create a MODULE message block. * * If is_light is 1, then build a message block with `clusterMsgLight` struct else `clusterMsg`. */ @@ -5715,7 +5735,8 @@ } if (nodeInNormalState(node) && node->link != NULL && node->inbound_link == NULL && now - node->inbound_link_freed_time > getHandshakeTimeout() && - now - node->meet_sent > getHandshakeTimeout()) { + now - node->meet_sent > getHandshakeTimeout() && + nodeSupportsMultiMeet(node)) { /* Node has an outbound link, but no inbound link for more than the handshake timeout. * This probably means this node does not know us yet, whereas we know it. * So we send it a MEET packet to do a handshake with it and correct the inconsistent cluster view. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/cluster_legacy.h new/valkey-9.0.1/src/cluster_legacy.h --- old/valkey-9.0.0/src/cluster_legacy.h 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/cluster_legacy.h 2025-12-09 19:03:34.000000000 +0100 @@ -49,19 +49,22 @@ #define linkSupportsExtension(link) ((link)->flags & CLUSTER_LINK_EXTENSIONS_SUPPORTED) /* Cluster node flags and macros. */ -#define CLUSTER_NODE_PRIMARY (1 << 0) /* The node is a primary */ -#define CLUSTER_NODE_REPLICA (1 << 1) /* The node is a replica */ -#define CLUSTER_NODE_PFAIL (1 << 2) /* Failure? Need acknowledge */ -#define CLUSTER_NODE_FAIL (1 << 3) /* The node is believed to be malfunctioning */ -#define CLUSTER_NODE_MYSELF (1 << 4) /* This node is myself */ -#define CLUSTER_NODE_HANDSHAKE (1 << 5) /* We have still to exchange the first ping */ -#define CLUSTER_NODE_NOADDR (1 << 6) /* We don't know the address of this node */ -#define CLUSTER_NODE_MEET (1 << 7) /* Send a MEET message to this node */ -#define CLUSTER_NODE_MIGRATE_TO (1 << 8) /* Primary eligible for replica migration. */ -#define CLUSTER_NODE_NOFAILOVER (1 << 9) /* Replica will not try to failover. */ -#define CLUSTER_NODE_EXTENSIONS_SUPPORTED (1 << 10) /* This node supports extensions. */ -#define CLUSTER_NODE_LIGHT_HDR_PUBLISH_SUPPORTED (1 << 11) /* This node supports light message header for publish type. */ -#define CLUSTER_NODE_LIGHT_HDR_MODULE_SUPPORTED (1 << 12) /* This node supports light message header for module type. */ +#define CLUSTER_NODE_PRIMARY (1 << 0) /* The node is a primary */ +#define CLUSTER_NODE_REPLICA (1 << 1) /* The node is a replica */ +#define CLUSTER_NODE_PFAIL (1 << 2) /* Failure? Need acknowledge */ +#define CLUSTER_NODE_FAIL (1 << 3) /* The node is believed to be malfunctioning */ +#define CLUSTER_NODE_MYSELF (1 << 4) /* This node is myself */ +#define CLUSTER_NODE_HANDSHAKE (1 << 5) /* We have still to exchange the first ping */ +#define CLUSTER_NODE_NOADDR (1 << 6) /* We don't know the address of this node */ +#define CLUSTER_NODE_MEET (1 << 7) /* Send a MEET message to this node */ +#define CLUSTER_NODE_MIGRATE_TO (1 << 8) /* Primary eligible for replica migration. */ +#define CLUSTER_NODE_NOFAILOVER (1 << 9) /* Replica will not try to failover. */ +#define CLUSTER_NODE_EXTENSIONS_SUPPORTED (1 << 10) /* This node supports extensions. */ +#define CLUSTER_NODE_LIGHT_HDR_PUBLISH_SUPPORTED (1 << 11) /* This node supports light message header for publish type. */ +#define CLUSTER_NODE_LIGHT_HDR_MODULE_SUPPORTED (1 << 12) /* This node supports light message header for module type. */ +#define CLUSTER_NODE_MULTI_MEET_SUPPORTED CLUSTER_NODE_LIGHT_HDR_MODULE_SUPPORTED /* This node handles multi meet packet. \ + Light hdr for module and multi meet were both introduced in 8.1, \ + so we could reduce the same flag value. */ #define CLUSTER_NODE_NULL_NAME \ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \ "\000\000\000\000\000\000\000\000\000\000\000\000" @@ -75,8 +78,7 @@ #define nodeFailed(n) ((n)->flags & CLUSTER_NODE_FAIL) #define nodeCantFailover(n) ((n)->flags & CLUSTER_NODE_NOFAILOVER) #define nodeSupportsExtensions(n) ((n)->flags & CLUSTER_NODE_EXTENSIONS_SUPPORTED) -#define nodeSupportsLightMsgHdrForPubSub(n) ((n)->flags & CLUSTER_NODE_LIGHT_HDR_PUBLISH_SUPPORTED) -#define nodeSupportsLightMsgHdrForModule(n) ((n)->flags & CLUSTER_NODE_LIGHT_HDR_MODULE_SUPPORTED) +#define nodeSupportsMultiMeet(n) ((n)->flags & CLUSTER_NODE_MULTI_MEET_SUPPORTED) #define nodeInNormalState(n) (!((n)->flags & (CLUSTER_NODE_HANDSHAKE | CLUSTER_NODE_MEET | CLUSTER_NODE_PFAIL | CLUSTER_NODE_FAIL))) /* Cluster messages header */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/cluster_migrateslots.c new/valkey-9.0.1/src/cluster_migrateslots.c --- old/valkey-9.0.0/src/cluster_migrateslots.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/cluster_migrateslots.c 2025-12-09 19:03:34.000000000 +0100 @@ -1385,7 +1385,7 @@ serverAssert(job->type == SLOT_MIGRATION_EXPORT); job->client = createClient(job->conn); job->conn = NULL; - job->client->flag.authenticated = 1; + clientSetUser(job->client, NULL, 1); job->client->slot_migration_job = job; initClientReplicationData(job->client); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/commands/hexpiretime.json new/valkey-9.0.1/src/commands/hexpiretime.json --- old/valkey-9.0.0/src/commands/hexpiretime.json 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/commands/hexpiretime.json 2025-12-09 19:03:34.000000000 +0100 @@ -1,7 +1,7 @@ { "HEXPIRETIME": { "summary": "Returns Unix timestamps in seconds since the epoch at which the given key's field(s) will expire", - "complexity": "O(1) for each field, so O(N) for N items when the command is called with multiple fields.", + "complexity": "O(N) where N is the number of specified fields.", "group": "hash", "since": "9.0.0", "arity": -5, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/commands/hgetex.json new/valkey-9.0.1/src/commands/hgetex.json --- old/valkey-9.0.0/src/commands/hgetex.json 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/commands/hgetex.json 2025-12-09 19:03:34.000000000 +0100 @@ -1,7 +1,7 @@ { "HGETEX": { "summary": "Get the value of one or more fields of a given hash key, and optionally set their expiration time or time-to-live (TTL).", - "complexity": "O(1)", + "complexity": "O(N) where N is the number of specified fields.", "group": "hash", "since": "9.0.0", "arity": -5, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/commands/hpersist.json new/valkey-9.0.1/src/commands/hpersist.json --- old/valkey-9.0.0/src/commands/hpersist.json 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/commands/hpersist.json 2025-12-09 19:03:34.000000000 +0100 @@ -1,7 +1,7 @@ { "HPERSIST": { "summary": "Remove the existing expiration on a hash key's field(s).", - "complexity": "O(1) for each field assigned with TTL, so O(N) to persist N items when the command is called with multiple fields.", + "complexity": "O(N) where N is the number of specified fields.", "group": "hash", "since": "9.0.0", "arity": -5, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/commands/hpexpiretime.json new/valkey-9.0.1/src/commands/hpexpiretime.json --- old/valkey-9.0.0/src/commands/hpexpiretime.json 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/commands/hpexpiretime.json 2025-12-09 19:03:34.000000000 +0100 @@ -1,7 +1,7 @@ { "HPEXPIRETIME": { "summary": "Returns the Unix timestamp in milliseconds since Unix epoch at which the given key's field(s) will expire", - "complexity": "O(1) for each field, so O(N) for N items when the command is called with multiple fields.", + "complexity": "O(N) where N is the number of specified fields.", "group": "hash", "since": "9.0.0", "arity": -5, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/commands/hpttl.json new/valkey-9.0.1/src/commands/hpttl.json --- old/valkey-9.0.0/src/commands/hpttl.json 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/commands/hpttl.json 2025-12-09 19:03:34.000000000 +0100 @@ -1,7 +1,7 @@ { "HPTTL": { "summary": "Returns the remaining time to live in milliseconds of a hash key's field(s) that have an associated expiration.", - "complexity": "O(1) for each field assigned with TTL, so O(N) for N items when the command is called with multiple fields.", + "complexity": "O(N) where N is the number of specified fields.", "group": "hash", "since": "9.0.0", "arity": -5, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/commands/hsetex.json new/valkey-9.0.1/src/commands/hsetex.json --- old/valkey-9.0.0/src/commands/hsetex.json 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/commands/hsetex.json 2025-12-09 19:03:34.000000000 +0100 @@ -1,7 +1,7 @@ { "HSETEX": { "summary": "Set the value of one or more fields of a given hash key, and optionally set their expiration time.", - "complexity": "O(1)", + "complexity": "O(N) where N is the number of specified fields.", "group": "hash", "since": "9.0.0", "arity": -6, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/commands/httl.json new/valkey-9.0.1/src/commands/httl.json --- old/valkey-9.0.0/src/commands/httl.json 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/commands/httl.json 2025-12-09 19:03:34.000000000 +0100 @@ -1,7 +1,7 @@ { "HTTL": { "summary": "Returns the remaining time to live (in seconds) of a hash key's field(s) that have an associated expiration.", - "complexity": "O(1) for each field, so O(N) for N items when the command is called with multiple fields.", + "complexity": "O(N) where N is the number of specified fields.", "group": "hash", "since": "9.0.0", "arity": -5, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/commands.def new/valkey-9.0.1/src/commands.def --- old/valkey-9.0.0/src/commands.def 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/commands.def 2025-12-09 19:03:34.000000000 +0100 @@ -11787,28 +11787,28 @@ {MAKE_CMD("hexists","Determines whether a field exists in a hash.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXISTS_History,0,HEXISTS_Tips,0,hexistsCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HEXISTS_Keyspecs,1,NULL,2),.args=HEXISTS_Args}, {MAKE_CMD("hexpire","Set expiry time on hash fields.","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIRE_History,0,HEXPIRE_Tips,0,hexpireCommand,-6,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HEXPIRE_Keyspecs,1,NULL,4),.args=HEXPIRE_Args}, {MAKE_CMD("hexpireat","Set expiry time on hash fields.","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIREAT_History,0,HEXPIREAT_Tips,0,hexpireatCommand,-6,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HEXPIREAT_Keyspecs,1,NULL,4),.args=HEXPIREAT_Args}, -{MAKE_CMD("hexpiretime","Returns Unix timestamps in seconds since the epoch at which the given key's field(s) will expire","O(1) for each field, so O(N) for N items when the command is called with multiple fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIRETIME_History,0,HEXPIRETIME_Tips,0,hexpiretimeCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HEXPIRETIME_Keyspecs,1,NULL,2),.args=HEXPIRETIME_Args}, +{MAKE_CMD("hexpiretime","Returns Unix timestamps in seconds since the epoch at which the given key's field(s) will expire","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HEXPIRETIME_History,0,HEXPIRETIME_Tips,0,hexpiretimeCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HEXPIRETIME_Keyspecs,1,NULL,2),.args=HEXPIRETIME_Args}, {MAKE_CMD("hget","Returns the value of a field in a hash.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HGET_History,0,HGET_Tips,0,hgetCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HGET_Keyspecs,1,NULL,2),.args=HGET_Args}, {MAKE_CMD("hgetall","Returns all fields and values in a hash.","O(N) where N is the size of the hash.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HGETALL_History,0,HGETALL_Tips,1,hgetallCommand,2,CMD_READONLY,ACL_CATEGORY_HASH,HGETALL_Keyspecs,1,NULL,1),.args=HGETALL_Args}, -{MAKE_CMD("hgetex","Get the value of one or more fields of a given hash key, and optionally set their expiration time or time-to-live (TTL).","O(1)","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HGETEX_History,0,HGETEX_Tips,0,hgetexCommand,-5,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HGETEX_Keyspecs,1,NULL,3),.args=HGETEX_Args}, +{MAKE_CMD("hgetex","Get the value of one or more fields of a given hash key, and optionally set their expiration time or time-to-live (TTL).","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HGETEX_History,0,HGETEX_Tips,0,hgetexCommand,-5,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HGETEX_Keyspecs,1,NULL,3),.args=HGETEX_Args}, {MAKE_CMD("hincrby","Increments the integer value of a field in a hash by a number. Uses 0 as initial value if the field doesn't exist.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HINCRBY_History,0,HINCRBY_Tips,0,hincrbyCommand,4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HINCRBY_Keyspecs,1,NULL,3),.args=HINCRBY_Args}, {MAKE_CMD("hincrbyfloat","Increments the floating point value of a field by a number. Uses 0 as initial value if the field doesn't exist.","O(1)","2.6.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HINCRBYFLOAT_History,0,HINCRBYFLOAT_Tips,0,hincrbyfloatCommand,4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HINCRBYFLOAT_Keyspecs,1,NULL,3),.args=HINCRBYFLOAT_Args}, {MAKE_CMD("hkeys","Returns all fields in a hash.","O(N) where N is the size of the hash.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HKEYS_History,0,HKEYS_Tips,1,hkeysCommand,2,CMD_READONLY,ACL_CATEGORY_HASH,HKEYS_Keyspecs,1,NULL,1),.args=HKEYS_Args}, {MAKE_CMD("hlen","Returns the number of fields in a hash.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HLEN_History,0,HLEN_Tips,0,hlenCommand,2,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HLEN_Keyspecs,1,NULL,1),.args=HLEN_Args}, {MAKE_CMD("hmget","Returns the values of all fields in a hash.","O(N) where N is the number of fields being requested.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HMGET_History,0,HMGET_Tips,0,hmgetCommand,-3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HMGET_Keyspecs,1,NULL,2),.args=HMGET_Args}, {MAKE_CMD("hmset","Sets the values of multiple fields.","O(N) where N is the number of fields being set.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HMSET_History,0,HMSET_Tips,0,hsetCommand,-4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HMSET_Keyspecs,1,NULL,2),.args=HMSET_Args}, -{MAKE_CMD("hpersist","Remove the existing expiration on a hash key's field(s).","O(1) for each field assigned with TTL, so O(N) to persist N items when the command is called with multiple fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPERSIST_History,0,HPERSIST_Tips,0,hpersistCommand,-5,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HPERSIST_Keyspecs,1,NULL,2),.args=HPERSIST_Args}, +{MAKE_CMD("hpersist","Remove the existing expiration on a hash key's field(s).","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPERSIST_History,0,HPERSIST_Tips,0,hpersistCommand,-5,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HPERSIST_Keyspecs,1,NULL,2),.args=HPERSIST_Args}, {MAKE_CMD("hpexpire","Set expiry time on hash object.","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIRE_History,0,HPEXPIRE_Tips,0,hpexpireCommand,-6,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIRE_Keyspecs,1,NULL,4),.args=HPEXPIRE_Args}, {MAKE_CMD("hpexpireat","Set expiration time on hash field.","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIREAT_History,0,HPEXPIREAT_Tips,0,hpexpireatCommand,-6,CMD_WRITE|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIREAT_Keyspecs,1,NULL,4),.args=HPEXPIREAT_Args}, -{MAKE_CMD("hpexpiretime","Returns the Unix timestamp in milliseconds since Unix epoch at which the given key's field(s) will expire","O(1) for each field, so O(N) for N items when the command is called with multiple fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIRETIME_History,0,HPEXPIRETIME_Tips,0,hpexpiretimeCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIRETIME_Keyspecs,1,NULL,2),.args=HPEXPIRETIME_Args}, -{MAKE_CMD("hpttl","Returns the remaining time to live in milliseconds of a hash key's field(s) that have an associated expiration.","O(1) for each field assigned with TTL, so O(N) for N items when the command is called with multiple fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPTTL_History,0,HPTTL_Tips,0,hpttlCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HPTTL_Keyspecs,1,NULL,2),.args=HPTTL_Args}, +{MAKE_CMD("hpexpiretime","Returns the Unix timestamp in milliseconds since Unix epoch at which the given key's field(s) will expire","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPEXPIRETIME_History,0,HPEXPIRETIME_Tips,0,hpexpiretimeCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HPEXPIRETIME_Keyspecs,1,NULL,2),.args=HPEXPIRETIME_Args}, +{MAKE_CMD("hpttl","Returns the remaining time to live in milliseconds of a hash key's field(s) that have an associated expiration.","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HPTTL_History,0,HPTTL_Tips,0,hpttlCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HPTTL_Keyspecs,1,NULL,2),.args=HPTTL_Args}, {MAKE_CMD("hrandfield","Returns one or more random fields from a hash.","O(N) where N is the number of fields returned","6.2.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HRANDFIELD_History,0,HRANDFIELD_Tips,1,hrandfieldCommand,-2,CMD_READONLY,ACL_CATEGORY_HASH,HRANDFIELD_Keyspecs,1,NULL,2),.args=HRANDFIELD_Args}, {MAKE_CMD("hscan","Iterates over fields and values of a hash.","O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection.","2.8.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSCAN_History,0,HSCAN_Tips,1,hscanCommand,-3,CMD_READONLY,ACL_CATEGORY_HASH,HSCAN_Keyspecs,1,NULL,5),.args=HSCAN_Args}, {MAKE_CMD("hset","Creates or modifies the value of a field in a hash.","O(1) for each field/value pair added, so O(N) to add N field/value pairs when the command is called with multiple field/value pairs.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSET_History,1,HSET_Tips,0,hsetCommand,-4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HSET_Keyspecs,1,NULL,2),.args=HSET_Args}, -{MAKE_CMD("hsetex","Set the value of one or more fields of a given hash key, and optionally set their expiration time.","O(1)","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSETEX_History,0,HSETEX_Tips,0,hsetexCommand,-6,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HSETEX_Keyspecs,1,NULL,4),.args=HSETEX_Args}, +{MAKE_CMD("hsetex","Set the value of one or more fields of a given hash key, and optionally set their expiration time.","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSETEX_History,0,HSETEX_Tips,0,hsetexCommand,-6,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HSETEX_Keyspecs,1,NULL,4),.args=HSETEX_Args}, {MAKE_CMD("hsetnx","Sets the value of a field in a hash only when the field doesn't exist.","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSETNX_History,0,HSETNX_Tips,0,hsetnxCommand,4,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HASH,HSETNX_Keyspecs,1,NULL,3),.args=HSETNX_Args}, {MAKE_CMD("hstrlen","Returns the length of the value of a field.","O(1)","3.2.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HSTRLEN_History,0,HSTRLEN_Tips,0,hstrlenCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HSTRLEN_Keyspecs,1,NULL,2),.args=HSTRLEN_Args}, -{MAKE_CMD("httl","Returns the remaining time to live (in seconds) of a hash key's field(s) that have an associated expiration.","O(1) for each field, so O(N) for N items when the command is called with multiple fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HTTL_History,0,HTTL_Tips,0,httlCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HTTL_Keyspecs,1,NULL,2),.args=HTTL_Args}, +{MAKE_CMD("httl","Returns the remaining time to live (in seconds) of a hash key's field(s) that have an associated expiration.","O(N) where N is the number of specified fields.","9.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HTTL_History,0,HTTL_Tips,0,httlCommand,-5,CMD_READONLY|CMD_FAST,ACL_CATEGORY_HASH,HTTL_Keyspecs,1,NULL,2),.args=HTTL_Args}, {MAKE_CMD("hvals","Returns all values in a hash.","O(N) where N is the size of the hash.","2.0.0",CMD_DOC_NONE,NULL,NULL,"hash",COMMAND_GROUP_HASH,HVALS_History,0,HVALS_Tips,1,hvalsCommand,2,CMD_READONLY,ACL_CATEGORY_HASH,HVALS_Keyspecs,1,NULL,1),.args=HVALS_Args}, /* hyperloglog */ {MAKE_CMD("pfadd","Adds elements to a HyperLogLog key. Creates the key if it doesn't exist.","O(1) to add every element.","2.8.9",CMD_DOC_NONE,NULL,NULL,"hyperloglog",COMMAND_GROUP_HYPERLOGLOG,PFADD_History,0,PFADD_Tips,0,pfaddCommand,-2,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_HYPERLOGLOG,PFADD_Keyspecs,1,NULL,2),.args=PFADD_Args}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/config.h new/valkey-9.0.1/src/config.h --- old/valkey-9.0.0/src/config.h 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/config.h 2025-12-09 19:03:34.000000000 +0100 @@ -392,7 +392,7 @@ #endif /* Check if we can compile ARM SIMD code */ -#if defined(__ARM_NEON) || defined(__ARM_NEON__) +#if defined(__aarch64__) && (defined(__ARM_NEON) || defined(__ARM_NEON__)) #define HAVE_ARM_NEON 1 #else #define HAVE_ARM_NEON 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/io_threads.c new/valkey-9.0.1/src/io_threads.c --- old/valkey-9.0.0/src/io_threads.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/io_threads.c 2025-12-09 19:03:34.000000000 +0100 @@ -285,6 +285,10 @@ if (tid == pthread_self()) return; if (tid == 0) return; + /* Only unlock mutex for inactive threads. Active threads are already unlocked. */ + if (id >= server.active_io_threads_num) { + pthread_mutex_unlock(&io_threads_mutex[id]); + } pthread_cancel(tid); if ((err = pthread_join(tid, NULL)) != 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/module.c new/valkey-9.0.1/src/module.c --- old/valkey-9.0.0/src/module.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/module.c 2025-12-09 19:03:34.000000000 +0100 @@ -6733,7 +6733,7 @@ uint64_t id = 0; for (int j = 0; j < 9; j++) { - char *p = strchr(cset, name[j]); + const char *p = strchr(cset, name[j]); if (!p) return 0; unsigned long pos = p - cset; id = (id << 6) | pos; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/networking.c new/valkey-9.0.1/src/networking.c --- old/valkey-9.0.0/src/networking.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/networking.c 2025-12-09 19:03:34.000000000 +0100 @@ -811,7 +811,7 @@ char *err_prefix = "ERR"; size_t prefix_len = 3; if (s[0] == '-') { - char *spaceloc = memchr(s, ' ', len < 32 ? len : 32); + const char *spaceloc = memchr(s, ' ', len < 32 ? len : 32); /* If we cannot retrieve the error prefix, use the default: "ERR". */ if (spaceloc) { const size_t errEndPos = (size_t)(spaceloc - s); @@ -1391,7 +1391,17 @@ /* Add an Object as a bulk reply */ void addReplyBulk(client *c, robj *obj) { - if (tryAvoidBulkStrCopyToReply(c, obj) == C_OK) return; + if (tryAvoidBulkStrCopyToReply(c, obj) == C_OK) { + /* If copy avoidance allowed, then we explicitly maintain net_output_bytes_curr_cmd. */ + serverAssert(obj->encoding == OBJ_ENCODING_RAW); + size_t str_len = sdslen(obj->ptr); + uint32_t num_len = digits10(str_len); + /* RESP encodes bulk strings as $<length>\r\n<data>\r\n */ + c->net_output_bytes_curr_cmd += (num_len + 3); /* $<length>\r\n */ + c->net_output_bytes_curr_cmd += str_len; /* <data> */ + c->net_output_bytes_curr_cmd += 2; /* \r\n */ + return; + } addReplyBulkLen(c, obj); addReply(c, obj); addReplyProto(c, "\r\n", 2); @@ -4177,11 +4187,17 @@ /* The cached client peer id is on the form "[IPv6]:port" for IPv6 * addresses, so we just check for '[' here. */ if (c->flag.fake && server.current_client) { - /* Fake client? Use current client instead. - * Noted that in here we are assuming server.current_client is set - * and real (aof has already violated this in loadSingleAppendOnlyFil). */ + /* Fake client? Use current client instead, if we have one. */ c = server.current_client; } + + if (c->flag.fake || !c->conn) { + /* If we still don't have a client with a real connection (e.g., called + * from module timer with no real current client), default to IPv4 to + * avoid crashing. */ + return 0; + } + return getClientPeerId(c)[0] == '['; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/resp_parser.c new/valkey-9.0.1/src/resp_parser.c --- old/valkey-9.0.0/src/resp_parser.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/resp_parser.c 2025-12-09 19:03:34.000000000 +0100 @@ -62,7 +62,7 @@ static int parseBulk(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); long long bulklen; parser->curr_location = p + 2; /* for \r\n */ @@ -81,7 +81,7 @@ static int parseSimpleString(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); parser->curr_location = p + 2; /* for \r\n */ parser->callbacks.simple_str_callback(p_ctx, proto + 1, p - proto - 1, proto, parser->curr_location - proto); return C_OK; @@ -89,7 +89,7 @@ static int parseError(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); parser->curr_location = p + 2; // for \r\n parser->callbacks.error_callback(p_ctx, proto + 1, p - proto - 1, proto, parser->curr_location - proto); return C_OK; @@ -97,7 +97,7 @@ static int parseLong(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); parser->curr_location = p + 2; /* for \r\n */ long long val; string2ll(proto + 1, p - proto - 1, &val); @@ -107,7 +107,7 @@ static int parseAttributes(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); long long len; string2ll(proto + 1, p - proto - 1, &len); p += 2; @@ -118,7 +118,7 @@ static int parseVerbatimString(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); long long bulklen; parser->curr_location = p + 2; /* for \r\n */ string2ll(proto + 1, p - proto - 1, &bulklen); @@ -132,7 +132,7 @@ static int parseBigNumber(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); parser->curr_location = p + 2; /* for \r\n */ parser->callbacks.big_number_callback(p_ctx, proto + 1, p - proto - 1, proto, parser->curr_location - proto); return C_OK; @@ -140,7 +140,7 @@ static int parseNull(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); parser->curr_location = p + 2; /* for \r\n */ parser->callbacks.null_callback(p_ctx, proto, parser->curr_location - proto); return C_OK; @@ -148,7 +148,7 @@ static int parseDouble(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); parser->curr_location = p + 2; /* for \r\n */ char buf[MAX_LONG_DOUBLE_CHARS + 1]; size_t len = p - proto - 1; @@ -164,7 +164,7 @@ static int parseBool(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); parser->curr_location = p + 2; /* for \r\n */ parser->callbacks.bool_callback(p_ctx, proto[1] == 't', proto, parser->curr_location - proto); return C_OK; @@ -172,7 +172,7 @@ static int parseArray(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); long long len; string2ll(proto + 1, p - proto - 1, &len); p += 2; @@ -187,7 +187,7 @@ static int parseSet(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); long long len; string2ll(proto + 1, p - proto - 1, &len); p += 2; @@ -198,7 +198,7 @@ static int parseMap(ReplyParser *parser, void *p_ctx) { const char *proto = parser->curr_location; - char *p = strchr(proto + 1, '\r'); + const char *p = strchr(proto + 1, '\r'); long long len; string2ll(proto + 1, p - proto - 1, &len); p += 2; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/sentinel.c new/valkey-9.0.1/src/sentinel.c --- old/valkey-9.0.0/src/sentinel.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/sentinel.c 2025-12-09 19:03:34.000000000 +0100 @@ -4856,7 +4856,7 @@ if (retval == C_ERR) return retval; ri->link->pending_commands++; - if (ri->monitored_instance_failover_state != SENTINEL_MONITORED_INSTANCE_FAILOVER_NS) { + if (ri->monitored_instance_failover_state == SENTINEL_MONITORED_INSTANCE_FAILOVER) { retval = valkeyAsyncCommand(ri->link->cc, sentinelDiscardReplyCallback, ri, "%s ABORT", sentinelInstanceMapCommand(ri, "FAILOVER")); if (retval == C_ERR) return retval; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/server.c new/valkey-9.0.1/src/server.c --- old/valkey-9.0.0/src/server.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/server.c 2025-12-09 19:03:34.000000000 +0100 @@ -988,6 +988,9 @@ size_t oldbuf_size = c->buf_usable_size; c->buf = zmalloc_usable(new_buffer_size, &c->buf_usable_size); memcpy(c->buf, oldbuf, c->bufpos); + if (c->io_last_written.buf == oldbuf) { + c->io_last_written.buf = c->buf; + } zfree_with_size(oldbuf, oldbuf_size); } return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/t_list.c new/valkey-9.0.1/src/t_list.c --- old/valkey-9.0.0/src/t_list.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/t_list.c 2025-12-09 19:03:34.000000000 +0100 @@ -909,8 +909,9 @@ } else { listTypeTryConversion(o, LIST_CONV_SHRINKING, NULL, NULL); } - signalModifiedKey(c, c->db, c->argv[1]); - server.dirty += (ltrim + rtrim); + long long total_trim = ltrim + rtrim; + if (total_trim) signalModifiedKey(c, c->db, c->argv[1]); + server.dirty += total_trim; addReply(c, shared.ok); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/src/version.h new/valkey-9.0.1/src/version.h --- old/valkey-9.0.0/src/version.h 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/src/version.h 2025-12-09 19:03:34.000000000 +0100 @@ -4,8 +4,8 @@ * similar. */ #define SERVER_NAME "valkey" #define SERVER_TITLE "Valkey" -#define VALKEY_VERSION "9.0.0" -#define VALKEY_VERSION_NUM 0x00090000 +#define VALKEY_VERSION "9.0.1" +#define VALKEY_VERSION_NUM 0x00090001 /* The release stage is used in order to provide release status information. * In unstable branch the status is always "dev". * During release process the status will be set to rc1,rc2...rcN. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/modules/cluster.c new/valkey-9.0.1/tests/modules/cluster.c --- old/valkey-9.0.0/tests/modules/cluster.c 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/modules/cluster.c 2025-12-09 19:03:34.000000000 +0100 @@ -3,6 +3,35 @@ #define UNUSED(x) (void)(x) +void cluster_timer_handler(ValkeyModuleCtx *ctx, void *data) { + VALKEYMODULE_NOT_USED(data); + + ValkeyModuleCallReply *rep = ValkeyModule_Call(ctx, "CLUSTER", "c", "SLOTS"); + + if (rep) { + if (ValkeyModule_CallReplyType(rep) == VALKEYMODULE_REPLY_ARRAY) { + ValkeyModule_Log(ctx, "notice", "Timer: CLUSTER SLOTS success"); + } else { + ValkeyModule_Log(ctx, "notice", + "Timer: CLUSTER SLOTS unexpected reply type %d", + ValkeyModule_CallReplyType(rep)); + } + ValkeyModule_FreeCallReply(rep); + } else { + ValkeyModule_Log(ctx, "warning", "Timer: CLUSTER SLOTS failed"); + } +} + +int test_start_cluster_timer(ValkeyModuleCtx *ctx, ValkeyModuleString **argv, int argc) { + VALKEYMODULE_NOT_USED(argv); + VALKEYMODULE_NOT_USED(argc); + + ValkeyModule_CreateTimer(ctx, 1, cluster_timer_handler, NULL); + + return ValkeyModule_ReplyWithSimpleString(ctx, "OK"); +} + + int test_cluster_slots(ValkeyModuleCtx *ctx, ValkeyModuleString **argv, int argc) { UNUSED(argv); @@ -77,8 +106,12 @@ if (ValkeyModule_CreateCommand(ctx, "test.cluster_shards", test_cluster_shards, "", 0, 0, 0) == VALKEYMODULE_ERR) return VALKEYMODULE_ERR; + if (ValkeyModule_CreateCommand(ctx, "test.start_cluster_timer", test_start_cluster_timer, "", 0, 0, 0) == VALKEYMODULE_ERR) + return VALKEYMODULE_ERR; + /* Register our handlers for different message types. */ ValkeyModule_RegisterClusterMessageReceiver(ctx, MSGTYPE_DING, DingReceiver); ValkeyModule_RegisterClusterMessageReceiver(ctx, MSGTYPE_DONG, DongReceiver); + return VALKEYMODULE_OK; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/sentinel/tests/00-base.tcl new/valkey-9.0.1/tests/sentinel/tests/00-base.tcl --- old/valkey-9.0.0/tests/sentinel/tests/00-base.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/sentinel/tests/00-base.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -6,6 +6,9 @@ S $id sentinel debug default-down-after 1000 } +set ::user "sentinel-user" +set ::password "sentinel-password" + if {$::simulate_error} { test "This test will fail" { fail "Simulated error" @@ -76,6 +79,10 @@ } test "Basic failover works if the primary is down" { + # Explicitly forbid the FAILOVER command to ensure backward compatibility with + # ACLs that were documented for Valkey < 9.0 + configure_sentinel_user_acl $::user $::password 0 + set old_port [RPort $master_id] set addr [S 0 SENTINEL GET-PRIMARY-ADDR-BY-NAME mymaster] assert {[lindex $addr 1] == $old_port} @@ -116,6 +123,7 @@ } else { fail "Old master not reconfigured as slave of new master" } + reset_sentinel_user_acl $::user } test "ODOWN is not possible without N (quorum) Sentinels reports" { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/sentinel/tests/03-runtime-reconf.tcl new/valkey-9.0.1/tests/sentinel/tests/03-runtime-reconf.tcl --- old/valkey-9.0.0/tests/sentinel/tests/03-runtime-reconf.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/sentinel/tests/03-runtime-reconf.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -38,31 +38,6 @@ assert_equal {OK} [R $id CONFIG SET primaryauth ""] } -proc verify_sentinel_connect_replicas {id} { - foreach replica [S $id SENTINEL REPLICAS mymaster] { - if {[string match "*disconnected*" [dict get $replica flags]]} { - return 0 - } - } - return 1 -} - -proc wait_for_sentinels_connect_servers { {is_connect 1} } { - foreach_sentinel_id id { - wait_for_condition 1000 50 { - [string match "*disconnected*" [dict get [S $id SENTINEL PRIMARY mymaster] flags]] != $is_connect - } else { - fail "At least some sentinel can't connect to master" - } - - wait_for_condition 1000 50 { - [verify_sentinel_connect_replicas $id] == $is_connect - } else { - fail "At least some sentinel can't connect to replica" - } - } -} - test "Sentinels (re)connection following SENTINEL SET myprimary auth-pass" { # 3 types of sentinels to test: # (re)started while primary changed pwd. Manage to connect only after setting pwd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/sentinel/tests/05-manual.tcl new/valkey-9.0.1/tests/sentinel/tests/05-manual.tcl --- old/valkey-9.0.0/tests/sentinel/tests/05-manual.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/sentinel/tests/05-manual.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -8,7 +8,13 @@ S $id sentinel debug publish-period 1000 } +set ::user "sentinel-user" +set ::password "sentinel-password" + + test "Manual failover works" { + configure_sentinel_user_acl $::user $::password + set old_port [RPort $master_id] set addr [S 0 SENTINEL GET-PRIMARY-ADDR-BY-NAME mymaster] assert {[lindex $addr 1] == $old_port} @@ -60,6 +66,7 @@ } else { fail "Old master not reconfigured as slave of new master" } + reset_sentinel_user_acl $::user } foreach flag {crash-after-election crash-after-promotion} { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/sentinel/tests/17-manual-coordinated.tcl new/valkey-9.0.1/tests/sentinel/tests/17-manual-coordinated.tcl --- old/valkey-9.0.0/tests/sentinel/tests/17-manual-coordinated.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/sentinel/tests/17-manual-coordinated.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -2,12 +2,17 @@ source "../tests/includes/init-tests.tcl" +set ::user "sentinel-user" +set ::password "sentinel-password" + foreach_sentinel_id id { S $id sentinel debug info-period 2000 S $id sentinel debug publish-period 1000 } test "Manual coordinated failover works" { + configure_sentinel_user_acl $::user $::password + set old_port [RPort $master_id] set addr [S 0 SENTINEL GET-PRIMARY-ADDR-BY-NAME mymaster] assert {[lindex $addr 1] == $old_port} @@ -133,6 +138,7 @@ foreach_sentinel_id id { assert {[lindex [S $id SENTINEL GET-PRIMARY-ADDR-BY-NAME mymaster] 1] == [lindex $addr 1]} } + reset_sentinel_user_acl $::user } foreach flag {crash-after-election crash-after-promotion} { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/sentinel/tests/includes/utils.tcl new/valkey-9.0.1/tests/sentinel/tests/includes/utils.tcl --- old/valkey-9.0.0/tests/sentinel/tests/includes/utils.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/sentinel/tests/includes/utils.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -34,3 +34,60 @@ } } } + +proc verify_sentinel_connect_replicas {id} { + foreach replica [S $id SENTINEL REPLICAS mymaster] { + if {[string match "*disconnected*" [dict get $replica flags]]} { + return 0 + } + } + return 1 +} + +proc wait_for_sentinels_connect_servers { {is_connect 1} } { + foreach_sentinel_id id { + wait_for_condition 1000 50 { + [string match "*disconnected*" [dict get [S $id SENTINEL PRIMARY mymaster] flags]] != $is_connect + } else { + fail "At least some sentinel can't connect to master" + } + + wait_for_condition 1000 50 { + [verify_sentinel_connect_replicas $id] == $is_connect + } else { + fail "At least some sentinel can't connect to replica" + } + } +} + +proc configure_sentinel_user_acl {user password {allow_failover 1}} { + foreach_valkey_id id { + R $id ACL SETUSER $user >$password +subscribe +publish [expr {$allow_failover ? "+failover" : "-failover"}] +script|kill +ping +info +multi +slaveof +config +client +exec &__sentinel__:hello ON + # Ensure default user cannot be used for failover + R $id ACL SETUSER default -failover -slaveof + } + foreach_sentinel_id id { + S $id SENTINEL SET mymaster auth-user $user + S $id SENTINEL SET mymaster auth-pass $password + S $id SENTINEL FLUSHCONFIG + } + foreach_valkey_id id { + R $id CLIENT KILL USER default SKIPME yes + } + wait_for_sentinels_connect_servers +} + +proc reset_sentinel_user_acl {user} { + foreach_sentinel_id id { + S $id SENTINEL SET mymaster auth-user "" + S $id SENTINEL SET mymaster auth-pass "" + S $id SENTINEL FLUSHCONFIG + } + foreach_valkey_id id { + R $id ACL SETUSER default +failover +slaveof + R $id ACL DELUSER $user + R $id CONFIG REWRITE + } + wait_for_sentinels_connect_servers +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/unit/cluster/cluster-migrateslots.tcl new/valkey-9.0.1/tests/unit/cluster/cluster-migrateslots.tcl --- old/valkey-9.0.0/tests/unit/cluster/cluster-migrateslots.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/unit/cluster/cluster-migrateslots.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -803,6 +803,13 @@ assert_match "1" [R $target_idx DEL $slot_to_test_tag:my_key] wait_for_countkeysinslot $node_idx $slot_to_test 0 } + test "Let nodes converge after importing key containment tests" { + wait_for_condition 50 100 { + [R $target_idx debug digest] eq [R $target_repl_idx debug digest] + } else { + fail "Target and its replica have different digests: [R $target_idx debug digest] VS [R $target_repl_idx debug digest]" + } + } } foreach eviction_policy { @@ -2116,6 +2123,42 @@ } } +start_cluster 3 0 {tags {logreqres:skip external:skip cluster}} { + set 16383_slot_tag "{6ZJ}" + set node0_id [R 0 CLUSTER MYID] + + test "Import with default user having no permission" { + # Configure ACLs on both source and target nodes + R 2 ACL SETUSER admin on >S3cureAdmin! ~* &* +@all + R 2 ACL SETUSER default off -@all + R 2 AUTH admin S3cureAdmin! + + R 0 ACL SETUSER admin on >S3cureAdmin! ~* &* +@all + R 0 ACL SETUSER default off -@all + R 0 AUTH admin S3cureAdmin! + + # Set primaryuser and primaryauth on the source node + R 2 CONFIG SET primaryuser admin + R 2 CONFIG SET primaryauth S3cureAdmin! + + # Populate data before migration + populate 1000 "$16383_slot_tag:" 1000 -2 + + # Perform one-shot import + assert_match "OK" [R 2 CLUSTER MIGRATESLOTS SLOTSRANGE 16383 16383 NODE $node0_id] + set jobname [get_job_name 2 16383] + wait_for_migration 0 16383 + + # Keys successfully migrated + assert_match "1000" [R 0 CLUSTER COUNTKEYSINSLOT 16383] + assert_match "0" [R 2 CLUSTER COUNTKEYSINSLOT 16383] + + # Migration log shows success on both ends + assert {[dict get [get_migration_by_name 0 $jobname] state] eq "success"} + assert {[dict get [get_migration_by_name 2 $jobname] state] eq "success"} + } +} + start_cluster 3 6 {tags {logreqres:skip external:skip cluster}} { set node0_id [R 0 CLUSTER MYID] set node1_id [R 1 CLUSTER MYID] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/unit/cluster/failover2.tcl new/valkey-9.0.1/tests/unit/cluster/failover2.tcl --- old/valkey-9.0.0/tests/unit/cluster/failover2.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/unit/cluster/failover2.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -64,7 +64,7 @@ } } ;# start_cluster -start_cluster 7 3 {tags {external:skip cluster} overrides {cluster-ping-interval 1000 cluster-node-timeout 5000}} { +start_cluster 7 3 {tags {external:skip cluster} overrides {cluster-ping-interval 1000}} { test "Primaries will not time out then they are elected in the same epoch" { # Since we have the delay time, so these node may not initiate the # election at the same time (same epoch). But if they do, we make diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/unit/commandlog.tcl new/valkey-9.0.1/tests/unit/commandlog.tcl --- old/valkey-9.0.0/tests/unit/commandlog.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/unit/commandlog.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -118,10 +118,11 @@ assert_equal [lindex $e 3] {set testkey {AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... (896 more bytes)}} assert_equal {foobar} [lindex $e 5] - # for large-reply - set copy_avoid [lindex [r config get min-io-threads-avoid-copy-reply] 1] - r config set min-io-threads-avoid-copy-reply 0 - + # for large-reply - without reply copy avoidance + set copy_avoid [lindex [r config get min-string-size-avoid-copy-reply] 1] + if {!$::external} { + assert_morethan $copy_avoid 1024 + } r get testkey set e [lindex [r commandlog get -1 large-reply] 0] assert_equal [llength $e] 6 @@ -132,8 +133,20 @@ assert_equal [lindex $e 3] {get testkey} assert_equal {foobar} [lindex $e 5] - # Restore min-io-threads-avoid-copy-reply value - r config set min-io-threads-avoid-copy-reply $copy_avoid + # for large-reply - with reply copy avoidance + # set min-string-size-avoid-copy-reply to 1 so wo will use reply copy avoidance + r config set min-string-size-avoid-copy-reply 1 + r get testkey + set e [lindex [r commandlog get -1 large-reply] 0] + assert_equal [llength $e] 6 + if {!$::external} { + assert_equal [lindex $e 0] 118 + } + assert_equal [expr {[lindex $e 2] > 1024}] 1 + assert_equal [lindex $e 3] {get testkey} + assert_equal {foobar} [lindex $e 5] + # Restore min-string-size-avoid-copy-reply value + r config set min-string-size-avoid-copy-reply $copy_avoid } {OK} {needs:debug} test {COMMANDLOG slow - Certain commands are omitted that contain sensitive information} { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/unit/hashexpire.tcl new/valkey-9.0.1/tests/unit/hashexpire.tcl --- old/valkey-9.0.0/tests/unit/hashexpire.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/unit/hashexpire.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -3947,7 +3947,7 @@ test {Hash field TTL and active expiry propagates correctly through chain replication} { $replica replicaof $primary_host $primary_port - # Wait for R2 to connect to R1 + # Wait for R1 to connect to Primary wait_for_condition 100 100 { [info_field [$replica info replication] master_link_status] eq "up" } else { @@ -3957,7 +3957,7 @@ $replica_2 replicaof $replica_host $replica_port # Wait for R2 to connect to R1 wait_for_condition 100 100 { - [info_field [$replica info replication] master_link_status] eq "up" + [info_field [$replica_2 info replication] master_link_status] eq "up" } else { fail "Second replica <-> First replica connection not established" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-9.0.0/tests/unit/moduleapi/cluster.tcl new/valkey-9.0.1/tests/unit/moduleapi/cluster.tcl --- old/valkey-9.0.0/tests/unit/moduleapi/cluster.tcl 2025-10-21 18:05:42.000000000 +0200 +++ new/valkey-9.0.1/tests/unit/moduleapi/cluster.tcl 2025-12-09 19:03:34.000000000 +0100 @@ -285,6 +285,18 @@ assert_equal [lsort [$node2 cluster shards]] [lsort [$node2 test.cluster_shards]] assert_equal [lsort [$node3 cluster shards]] [lsort [$node3 test.cluster_shards]] } + + test "VM_CALL CLUSTER SLOTS from Module Timer" { + assert_equal {OK} [$node1 test.start_cluster_timer] + assert_equal {OK} [$node2 test.start_cluster_timer] + assert_equal {OK} [$node3 test.start_cluster_timer] + + wait_for_condition 50 100 { + [count_log_message 0 "* <cluster> Timer: CLUSTER SLOTS success*"] >= 1 + } else { + fail "Timer did not execute CLUSTER SLOTS or server crashed" + } + } } } ;# end tag ++++++ valkey-conf.patch ++++++ --- /var/tmp/diff_new_pack.RvKK9e/_old 2025-12-10 15:31:19.756273576 +0100 +++ /var/tmp/diff_new_pack.RvKK9e/_new 2025-12-10 15:31:19.764273914 +0100 @@ -1,7 +1,7 @@ -Index: valkey-8.1.1/sentinel.conf +Index: valkey-9.0.0/sentinel.conf =================================================================== ---- valkey-8.1.1.orig/sentinel.conf -+++ valkey-8.1.1/sentinel.conf +--- valkey-9.0.0.orig/sentinel.conf ++++ valkey-9.0.0/sentinel.conf @@ -13,11 +13,12 @@ port 26379 # Note that Valkey will write a pid file in /var/run/valkey-sentinel.pid when # daemonized. @@ -25,11 +25,11 @@ # To enable logging to the system logger, just set 'syslog-enabled' to yes, # and optionally update the other syslog parameters to suit your needs. -Index: valkey-8.1.1/valkey.conf +Index: valkey-9.0.0/valkey.conf =================================================================== ---- valkey-8.1.1.orig/valkey.conf -+++ valkey-8.1.1/valkey.conf -@@ -371,7 +371,7 @@ daemonize no +--- valkey-9.0.0.orig/valkey.conf ++++ valkey-9.0.0/valkey.conf +@@ -395,7 +395,7 @@ daemonize no # The default is "no". To run under upstart/systemd, you can simply uncomment # the line below: # @@ -38,7 +38,7 @@ # If a pid file is specified, the server writes it where specified at startup # and removes it at exit. -@@ -385,7 +385,7 @@ daemonize no +@@ -409,7 +409,7 @@ daemonize no # # Note that on modern Linux systems "/run/valkey.pid" is more conforming # and should be used instead. @@ -47,7 +47,7 @@ # Specify the server verbosity level. # This can be one of: -@@ -416,7 +416,8 @@ loglevel notice +@@ -440,7 +440,8 @@ loglevel notice # Specify the log file name. Also the empty string can be used to force # the server to log on the standard output. Note that if you use standard # output for logging but daemonize, logs will be sent to /dev/null @@ -57,7 +57,7 @@ # To enable logging to the system logger, just set 'syslog-enabled' to yes, # and optionally update the other syslog parameters to suit your needs. -@@ -606,7 +607,7 @@ rdb-del-sync-files no +@@ -631,7 +632,7 @@ rdb-del-sync-files no # Note that modifying 'dir' during runtime may have unexpected behavior, # for example when a child process is running, related file operations may # have unexpected effects. @@ -66,4 +66,27 @@ ################################# REPLICATION ################################# +Index: valkey-9.0.0/valkey.default.conf +=================================================================== +--- /dev/null ++++ valkey-9.0.0/valkey.default.conf +@@ -0,0 +1,7 @@ ++include /etc/valkey/includes/valkey.defaults.conf ++ ++port 6379 ++dir /var/lib/valkey/default/ ++pidfile /run/valkey/default.pid ++logfile /var/log/valkey/default.log ++ +Index: valkey-9.0.0/sentinel.default.conf +=================================================================== +--- /dev/null ++++ valkey-9.0.0/sentinel.default.conf +@@ -0,0 +1,6 @@ ++include /etc/valkey/includes/sentinel.defaults.conf ++ ++port 26379 ++pidfile /run/valkey/sentinel-default.pid ++logfile /var/log/valkey/sentinel-default.log ++
