diff --git a/src/db.cpp b/src/db.cpp index dcf617c10..476908f5e 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -1769,7 +1769,7 @@ int dbSwapDatabases(int id1, int id2) { /* SWAPDB db1 db2 */ void swapdbCommand(client *c) { - int id1, id2, oriId; + int id1, id2, oriIdx; /* Not allowed in cluster mode: we have just DB 0 there. */ if (g_pserver->cluster_enabled) { @@ -1786,8 +1786,13 @@ void swapdbCommand(client *c) { "invalid second DB index") != C_OK) return; - //get client's original db's id - oriId=c->db->id; + // get client's original db's index + for (int idb=0; idb < cserver.dbnum; ++idb) { + if (g_pserver->db[idb]->id == c->db->id) { + oriIdx = idb; + break; + } + } /* Swap... */ if (dbSwapDatabases(id1,id2) == C_ERR) { @@ -1798,9 +1803,17 @@ void swapdbCommand(client *c) { moduleFireServerEvent(REDISMODULE_EVENT_SWAPDB,0,&si); g_pserver->dirty++; - //set client's db to original db - c->db=g_pserver->db[oriId]; + // set client's db to original db + c->db=g_pserver->db[oriIdx]; + // Persist the databse index to dbid mapping into FLASH for later recovery. + if (g_pserver->m_pstorageFactory != nullptr && g_pserver->metadataDb != nullptr) { + std::string dbid_key = "db-" + std::to_string(id1); + g_pserver->metadataDb->insert(dbid_key.c_str(), dbid_key.length(), &g_pserver->db[id1]->id, sizeof(g_pserver->db[id1]->id), true); + + dbid_key = "db-" + std::to_string(id2); + g_pserver->metadataDb->insert(dbid_key.c_str(), dbid_key.length(), &g_pserver->db[id2]->id, sizeof(g_pserver->db[id2]->id), true); + } addReply(c,shared.ok); } } diff --git a/src/server.cpp b/src/server.cpp index 70b8b4374..15afd2cde 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3881,9 +3881,25 @@ void initServer(void) { g_pserver->db = (redisDb**)zmalloc(sizeof(redisDb*)*cserver.dbnum, MALLOC_LOCAL); /* Create the Redis databases, and initialize other internal state. */ - for (int j = 0; j < cserver.dbnum; j++) { - g_pserver->db[j] = new (MALLOC_LOCAL) redisDb(); - g_pserver->db[j]->initialize(j); + if (g_pserver->m_pstorageFactory == nullptr) { + for (int j = 0; j < cserver.dbnum; j++) { + g_pserver->db[j] = new (MALLOC_LOCAL) redisDb(); + g_pserver->db[j]->initialize(j); + } + } else { + // Read FLASH metadata and load the appropriate dbid into each databse index, as each DB index can have different dbid mapped due to the swapdb command. + g_pserver->metadataDb = g_pserver->m_pstorageFactory->createMetadataDb(); + for (int idb = 0; idb < cserver.dbnum; ++idb) + { + int dbid = idb; + std::string dbid_key = "db-" + std::to_string(idb); + g_pserver->metadataDb->retrieve(dbid_key.c_str(), dbid_key.length(), [&](const char *, size_t, const void *data, size_t){ + dbid = *(int*)data; + }); + + g_pserver->db[idb] = new (MALLOC_LOCAL) redisDb(); + g_pserver->db[idb]->initialize(dbid); + } } for (int i = 0; i < MAX_EVENT_LOOPS; ++i) @@ -4033,7 +4049,6 @@ void initServer(void) { latencyMonitorInit(); if (g_pserver->m_pstorageFactory) { - g_pserver->metadataDb = g_pserver->m_pstorageFactory->createMetadataDb(); if (g_pserver->metadataDb) { g_pserver->metadataDb->retrieve("repl-id", 7, [&](const char *, size_t, const void *data, size_t cb){ if (cb == sizeof(g_pserver->replid)) {