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

Code before:
serverDb *createDatabase(int id) {
    int slot_count_bits = 0;
    int flags = KVSTORE_ALLOCATE_HASHTABLES_ON_DEMAND;
    if (server.cluster_enabled) {
        flags |= KVSTORE_FREE_EMPTY_HASHTABLES;
        slot_count_bits = CLUSTER_SLOT_MASK_BITS;
    }

    serverDb *db = zmalloc(sizeof(serverDb));
    db->keys = kvstoreCreate(&kvstoreKeysHashtableType, slot_count_bits, flags);
    db->expires = kvstoreCreate(&kvstoreExpiresHashtableType, slot_count_bits, flags);
    db->expires_cursor = 0;
    db->blocking_keys = dictCreate(&keylistDictType);
    db->blocking_keys_unblock_on_nokey = dictCreate(&objectKeyPointerValueDictType);
    db->ready_keys = dictCreate(&objectKeyPointerValueDictType);
    db->watched_keys = dictCreate(&keylistDictType);
    db->id = id;
    db->avg_ttl = 0;
    return db;
}

void initDatabase(int id) {
    if (server.db[id] == NULL) {
        server.db[id] = createDatabase(id);
    }
}

void initServer(void) {
    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    setupSignalHandlers();
    ThreadsManager_init();
    makeThreadKillable();

    if (server.syslog_enabled) {
        openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT, server.syslog_facility);
    }

    /* Initialization after setting defaults from the config system. */
    server.aof_state = server.aof_enabled ? AOF_ON : AOF_OFF;
    server.fsynced_reploff = server.aof_enabled ? 0 : -1;
    server.hz = server.config_hz;
    server.in_fork_child = CHILD_TYPE_NONE;
    server.rdb_pipe_read = -1;
    server.rdb_child_exit_pipe = -1;
    server.main_thread_id = pthread_self();
    server.current_client = NULL;
    server.errors = raxNew();
    server.execution_nesting = 0;
    server.clients = listCreate();
    server.clients_index = raxNew();

Review comment (suggestion):

In `kvstore.c` there is lazy creation of hashtables. It is similar to lazy creation of databases. In kvstore, a function called createHashtableIfNeeded is used in many places. It lazy-creates it and returns it.

I think we can use a similar pattern here. The name with "if needed" is also more clear than "init".

```suggestion
serverDb *createDatabaseIfNeeded(int id) {
    if (server.db[id] == NULL) {
        server.db[id] = createDatabase(id);
    }
    return server.db[id];
}
```

It can be used for example like this for the SELECT command:

```c
    c->db = createDatabaseIfNeeded(id);
```



Code after:
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
}

/* Return non-zero if the database is empty  */
int dbHasNoKeys(int dbid) {
    return dbid < 0 || dbid >= server.dbnum || !server.db[dbid] || kvstoreSize(server.db[dbid]->keys) == 0;
}

bool dbsHaveNoKeys(void) {
    for (int i = 0; i < server.dbnum; i++) {
        if (server.db[i] && kvstoreSize(server.db[i]->keys) != 0) {
            return false;
        }
    }
    return true;
}

serverDb *createDatabase(int id) {
    int slot_count_bits = 0;
    int flags = KVSTORE_ALLOCATE_HASHTABLES_ON_DEMAND;
    if (server.cluster_enabled) {
        flags |= KVSTORE_FREE_EMPTY_HASHTABLES;
        slot_count_bits = CLUSTER_SLOT_MASK_BITS;
    }

    serverDb *db = zmalloc(sizeof(serverDb));
    db->keys = kvstoreCreate(&kvstoreKeysHashtableType, slot_count_bits, flags);
    db->expires = kvstoreCreate(&kvstoreExpiresHashtableType, slot_count_bits, flags);
    db->expires_cursor = 0;
    db->blocking_keys = dictCreate(&keylistDictType);
    db->blocking_keys_unblock_on_nokey = dictCreate(&objectKeyPointerValueDictType);
    db->ready_keys = dictCreate(&objectKeyPointerValueDictType);
    db->watched_keys = dictCreate(&keylistDictType);
    db->id = id;
    db->avg_ttl = 0;
    return db;
}

serverDb *createDatabaseIfNeeded(int id) {
    if (server.db[id] == NULL) {
        server.db[id] = createDatabase(id);
    }
    return server.db[id];
}

void initServer(void) {
    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    setupSignalHandlers();
    ThreadsManager_init();
    makeThreadKillable();