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

Code before:
    UNUSED(err);
    server.active_defrag_configuration_changed = 1;
    return 1;
}

static int updateJemallocBgThread(const char **err) {
    UNUSED(err);
    set_jemalloc_bg_thread(server.jemalloc_bg_thread);
    return 1;
}

static int updateReplBacklogSize(const char **err) {
    UNUSED(err);
    resizeReplicationBacklog();
    return 1;
}

static int updateCommandlogRequestLargerThan(const char **err) {
    UNUSED(err);
    int track_bytes = (server.commandlog[COMMANDLOG_TYPE_LARGE_REQUEST].threshold != -1);
    listIter li;
    listNode *ln;
    listRewind(server.clients, &li);
    while ((ln = listNext(&li))) {
        client *c = listNodeValue(ln);
        c->flag.track_net_output_bytes = track_bytes;
    }
    return 1;
}

static int updateMaxmemory(const char **err) {
    UNUSED(err);
    if (server.maxmemory) {
        size_t used = zmalloc_used_memory() - freeMemoryGetNotCountedMemory();
        if (server.maxmemory < used) {
            serverLog(LL_WARNING,
                      "WARNING: the new maxmemory value set via CONFIG SET (%llu) is smaller than the current memory "
                      "usage (%zu). This will result in key eviction and/or the inability to accept new write commands "
                      "depending on the maxmemory-policy.",
                      server.maxmemory, used);
        }
        startEvictionTimeProc();
    }
    return 1;
}

static int updateGoodReplicas(const char **err) {
    UNUSED(err);
    refreshGoodReplicasCount();
    return 1;
}

Review comment (performance):
Traversing all clients can be slightly slow if there are many clients. I hope that we can avoid it. Btw, this seems to be equivalent to simply accessing `server.commandlog[COMMANDLOG_TYPE_LARGE_REQUEST].threshold` directly from the IO threads.

However, neither the global config value nor the client flags are thread safe and there can be IO threads writing to these clients at the same time as this value is being changed. We might account for these bytes twice or zero times depending on timing when the config is changed.

We should instead make the decision per reply, in the addReply functions in the main threads, then in the IO thread we will know exactly if the accounting for this reply has already been done in the main thread or not.

Code after:
    UNUSED(err);
    server.active_defrag_configuration_changed = 1;
    return 1;
}

static int updateJemallocBgThread(const char **err) {
    UNUSED(err);
    set_jemalloc_bg_thread(server.jemalloc_bg_thread);
    return 1;
}

static int updateReplBacklogSize(const char **err) {
    UNUSED(err);
    resizeReplicationBacklog();
    return 1;
}

static int updateMaxmemory(const char **err) {
    UNUSED(err);
    if (server.maxmemory) {
        size_t used = zmalloc_used_memory() - freeMemoryGetNotCountedMemory();
        if (server.maxmemory < used) {
            serverLog(LL_WARNING,
                      "WARNING: the new maxmemory value set via CONFIG SET (%llu) is smaller than the current memory "
                      "usage (%zu). This will result in key eviction and/or the inability to accept new write commands "
                      "depending on the maxmemory-policy.",
                      server.maxmemory, used);
        }
        startEvictionTimeProc();
    }
    return 1;
}

static int updateGoodReplicas(const char **err) {
    UNUSED(err);
    refreshGoodReplicasCount();
    return 1;
}

static int updateWatchdogPeriod(const char **err) {
    UNUSED(err);
    applyWatchdogPeriod();
    return 1;
}

static int updateAppendOnly(const char **err) {
    if (!server.aof_enabled && server.aof_state != AOF_OFF) {
        stopAppendOnly();
    } else if (server.aof_enabled && server.aof_state == AOF_OFF) {
        if (startAppendOnly() == C_ERR) {
            *err = "Unable to turn on AOF. Check server logs.";