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

Code before:
    moduleFireServerEvent(VALKEYMODULE_EVENT_FLUSHDB, VALKEYMODULE_SUBEVENT_FLUSHDB_START, &fi);

    /* Make sure the WATCHed keys are affected by the FLUSH* commands.
     * Note that we need to call the function while the keys are still
     * there. */
    signalFlushedDb(dbnum, async);

    /* Empty the database structure. */
    removed = emptyDbStructure(server.db, dbnum, async, callback);

    if (dbnum == -1) flushReplicaKeysWithExpireList();

    if (with_functions) {
        serverAssert(dbnum == -1);
        /* TODO: fix this callback incompatibility. The arg is not used. */
        functionsLibCtxClearCurrent(async, (void (*)(dict *))callback);
    }

    /* Also fire the end event. Note that this event will fire almost
     * immediately after the start event if the flush is asynchronous. */
    moduleFireServerEvent(VALKEYMODULE_EVENT_FLUSHDB, VALKEYMODULE_SUBEVENT_FLUSHDB_END, &fi);

    return removed;
}

/* Empty and release all databases in the temp db array and set them to NULL. */
void discardTempDb(serverDb **tempDb) {
    /* Release temp DBs. */
    emptyDbStructure(tempDb, -1, 1, NULL);
    for (int i = 0; i < server.dbnum; i++) {
        if (tempDb[i]) {
            kvstoreRelease(tempDb[i]->keys);
            kvstoreRelease(tempDb[i]->expires);

            /* These are expected to be empty on temporary databases */
            serverAssert(dictSize(tempDb[i]->blocking_keys) == 0);
            serverAssert(dictSize(tempDb[i]->blocking_keys_unblock_on_nokey) == 0);
            serverAssert(dictSize(tempDb[i]->ready_keys) == 0);
            serverAssert(dictSize(tempDb[i]->watched_keys) == 0);

            dictRelease(tempDb[i]->blocking_keys);
            dictRelease(tempDb[i]->blocking_keys_unblock_on_nokey);
            dictRelease(tempDb[i]->ready_keys);
            dictRelease(tempDb[i]->watched_keys);
            zfree(tempDb[i]);
            tempDb[i] = NULL;
        }
    }
    zfree(tempDb);
}


Review comment (suggestion):
Hm... :thinking: I suggested this comment but missed the `zfree(tempDb)` in the bottom of the function. :smile: So we do actually free the whole thing.

I guess I was confused by the fact that we set `tempDb[i] = NULL;` if we're going to free the array anyway. It's unnecessary to set the elements to null here but I guess it's considered good practice...

```suggestion
/* Discard tempDb array. It's always async. */
```

Code after:
    /* Fire the flushdb modules event. */
    moduleFireServerEvent(VALKEYMODULE_EVENT_FLUSHDB, VALKEYMODULE_SUBEVENT_FLUSHDB_START, &fi);

    /* Make sure the WATCHed keys are affected by the FLUSH* commands.
     * Note that we need to call the function while the keys are still
     * there. */
    signalFlushedDb(dbnum, async);

    /* Empty the database structure. */
    removed = emptyDbStructure(server.db, dbnum, async, callback);

    if (dbnum == -1) flushReplicaKeysWithExpireList();

    if (with_functions) {
        serverAssert(dbnum == -1);
        /* TODO: fix this callback incompatibility. The arg is not used. */
        functionsLibCtxClearCurrent(async, (void (*)(dict *))callback);
    }

    /* Also fire the end event. Note that this event will fire almost
     * immediately after the start event if the flush is asynchronous. */
    moduleFireServerEvent(VALKEYMODULE_EVENT_FLUSHDB, VALKEYMODULE_SUBEVENT_FLUSHDB_END, &fi);

    return removed;
}

/* Discard tempDb array. It's always async. */
void discardTempDb(serverDb **tempDb) {
    /* Release temp DBs. */
    emptyDbStructure(tempDb, -1, 1, NULL);
    for (int i = 0; i < server.dbnum; i++) {
        if (tempDb[i]) {
            kvstoreRelease(tempDb[i]->keys);
            kvstoreRelease(tempDb[i]->expires);

            /* These are expected to be empty on temporary databases */
            serverAssert(dictSize(tempDb[i]->blocking_keys) == 0);
            serverAssert(dictSize(tempDb[i]->blocking_keys_unblock_on_nokey) == 0);
            serverAssert(dictSize(tempDb[i]->ready_keys) == 0);
            serverAssert(dictSize(tempDb[i]->watched_keys) == 0);

            dictRelease(tempDb[i]->blocking_keys);
            dictRelease(tempDb[i]->blocking_keys_unblock_on_nokey);
            dictRelease(tempDb[i]->ready_keys);
            dictRelease(tempDb[i]->watched_keys);
            zfree(tempDb[i]);
            tempDb[i] = NULL;
        }
    }
    zfree(tempDb);
}