Repository: valkey-io/valkey
File: src/rdb.c (C)

Code before:
                serverLog(LL_NOTICE, "Loading RDB produced by Valkey version %s", (char *)auxval->ptr);
            } else if (!strcasecmp(auxkey->ptr, "ctime")) {
                time_t age = time(NULL) - strtol(auxval->ptr, NULL, 10);
                if (age < 0) age = 0;
                serverLog(LL_NOTICE, "RDB age %ld seconds", (unsigned long)age);
            } else if (!strcasecmp(auxkey->ptr, "used-mem")) {
                long long usedmem = strtoll(auxval->ptr, NULL, 10);
                serverLog(LL_NOTICE, "RDB memory usage when created %.2f Mb", (double)usedmem / (1024 * 1024));
                server.loading_rdb_used_mem = usedmem;
            } else if (!strcasecmp(auxkey->ptr, "aof-preamble")) {
                long long haspreamble = strtoll(auxval->ptr, NULL, 10);
                if (haspreamble) serverLog(LL_NOTICE, "RDB has an AOF tail");
            } else if (!strcasecmp(auxkey->ptr, "aof-base")) {
                long long isbase = strtoll(auxval->ptr, NULL, 10);
                if (isbase) serverLog(LL_NOTICE, "RDB is base AOF");
            } else if (!strcasecmp(auxkey->ptr, "redis-bits")) {
                /* Just ignored. */
            } else if (!strcasecmp(auxkey->ptr, "slot-info")) {
                int slot_id;
                unsigned long slot_size = 0, expires_slot_size = 0, keys_with_volatile_items_slot_size = 0;
                /* Try to parse the slot information. In case the number of parsed arguments is smaller than expected
                 * we'll fail the RDB load. The use of sscanf was originally introduced in 8.0 to allow extending
                 * the optional saved slot information in future versions without having to bump the rdb version.
                 * This implementation should work in both upgrade and downgrade scenarios.
                 * In case of upgrade, missing data will just be ignored an untouched by sscanf.
                 * In case of relaxed rdb downgrade, the missing data will simply be ignored.
                 * The verification only verifies we read the fields known to exist when we first introduced the slot-ino AUX field,
                 * which are the slot number, number of keys in slot and the number of volatile keys. */
                if (sscanf(auxval->ptr, "%i,%lu,%lu,%lu", &slot_id, &slot_size, &expires_slot_size, &keys_with_volatile_items_slot_size) < 3) {
                    decrRefCount(auxkey);
                    decrRefCount(auxval);
                    goto eoferr;
                }

                if (server.cluster_enabled) {
                    /* In cluster mode we resize individual slot specific dictionaries based on the number of keys that
                     * slot holds. */
                    if (slot_size) kvstoreHashtableExpand(db->keys, slot_id, slot_size);
                    if (expires_slot_size) kvstoreHashtableExpand(db->expires, slot_id, expires_slot_size);
                    if (keys_with_volatile_items_slot_size) kvstoreHashtableExpand(db->keys_with_volatile_items, slot_id, keys_with_volatile_items_slot_size);
                    should_expand_db = 0;
                }
            } else {
                /* Check if this is a dynamic aux field */
                int handled = 0;
                if (rdbAuxFields != NULL) {
                    dictEntry *de = dictFind(rdbAuxFields, auxkey->ptr);
                    if (de != NULL) {
                        handled = 1;
                        rdbAuxFieldCodec *codec = (rdbAuxFieldCodec *)dictGetVal(de);
                        if (codec->decoder(rdbflags, auxval->ptr) == C_ERR) {

Review comment (suggestion):
Good documentation! Just one nit:

```suggestion
                 * In case of relaxed rdb downgrade, trailing unknown data will simply be ignored.
```

Code after:
                serverLog(LL_NOTICE, "Loading RDB produced by Redis version %s", (char *)auxval->ptr);
            } else if (!strcasecmp(auxkey->ptr, "valkey-ver")) {
                serverLog(LL_NOTICE, "Loading RDB produced by Valkey version %s", (char *)auxval->ptr);
            } else if (!strcasecmp(auxkey->ptr, "ctime")) {
                time_t age = time(NULL) - strtol(auxval->ptr, NULL, 10);
                if (age < 0) age = 0;
                serverLog(LL_NOTICE, "RDB age %ld seconds", (unsigned long)age);
            } else if (!strcasecmp(auxkey->ptr, "used-mem")) {
                long long usedmem = strtoll(auxval->ptr, NULL, 10);
                serverLog(LL_NOTICE, "RDB memory usage when created %.2f Mb", (double)usedmem / (1024 * 1024));
                server.loading_rdb_used_mem = usedmem;
            } else if (!strcasecmp(auxkey->ptr, "aof-preamble")) {
                long long haspreamble = strtoll(auxval->ptr, NULL, 10);
                if (haspreamble) serverLog(LL_NOTICE, "RDB has an AOF tail");
            } else if (!strcasecmp(auxkey->ptr, "aof-base")) {
                long long isbase = strtoll(auxval->ptr, NULL, 10);
                if (isbase) serverLog(LL_NOTICE, "RDB is base AOF");
            } else if (!strcasecmp(auxkey->ptr, "redis-bits")) {
                /* Just ignored. */
            } else if (!strcasecmp(auxkey->ptr, "slot-info")) {
                int slot_id;
                unsigned long slot_size = 0, expires_slot_size = 0, keys_with_volatile_items_slot_size = 0;
                /* Try to parse the slot information. In case the number of parsed arguments is smaller than expected
                 * we'll fail the RDB load. The use of sscanf was originally introduced in 8.0 to allow extending
                 * the optional saved slot information in future versions without having to bump the rdb version.
                 * This implementation should work in both upgrade and downgrade scenarios.
                 * In case of upgrade, missing data will just be ignored an untouched by sscanf.
                 * In case of relaxed rdb downgrade, trailing unknown data will simply be ignored.
                 * The verification only verifies we read the fields known to exist when we first introduced the slot-info AUX field,
                 * which are the slot number, number of keys in slot and the number of volatile keys. */
                if (sscanf(auxval->ptr, "%i,%lu,%lu,%lu",
                           &slot_id, &slot_size, &expires_slot_size,
                           &keys_with_volatile_items_slot_size) < 3) {
                    decrRefCount(auxkey);
                    decrRefCount(auxval);
                    goto eoferr;
                }

                if (server.cluster_enabled) {
                    /* In cluster mode we resize individual slot specific dictionaries based on the number of keys that
                     * slot holds. */
                    if (slot_size) kvstoreHashtableExpand(db->keys, slot_id, slot_size);
                    if (expires_slot_size) kvstoreHashtableExpand(db->expires, slot_id, expires_slot_size);
                    if (keys_with_volatile_items_slot_size) {
                        kvstoreHashtableExpand(db->keys_with_volatile_items,
                                               slot_id,
                                               keys_with_volatile_items_slot_size);
                    }
                    should_expand_db = 0;
                }
            } else {