Swap two databases at runtime so that all clients will magically see * the new database even if already connected. Note that the client * structure c->db points to a given DB, so we need to be smarter and * swap the underlying referenced structures, otherwise we would need * to fix all the references to the Redis DB structure. * * Returns C_ERR if at least one of the DB ids are out of range,
| 1719 | * Returns C_ERR if at least one of the DB ids are out of range, otherwise |
| 1720 | * C_OK is returned. */ |
| 1721 | int dbSwapDatabases(int id1, int id2) { |
| 1722 | if (id1 < 0 || id1 >= cserver.dbnum || |
| 1723 | id2 < 0 || id2 >= cserver.dbnum) return C_ERR; |
| 1724 | if (id1 == id2) return C_OK; |
| 1725 | std::swap(g_pserver->db[id1], g_pserver->db[id2]); |
| 1726 | |
| 1727 | //swap db's id too, otherwise db does not match its id |
| 1728 | std::swap(g_pserver->db[id1]->id, g_pserver->db[id2]->id); |
| 1729 | |
| 1730 | /* Note that we don't swap blocking_keys, |
| 1731 | * ready_keys and watched_keys, since we want clients to |
| 1732 | * remain in the same DB they were. so put them back */ |
| 1733 | std::swap(g_pserver->db[id1]->blocking_keys, g_pserver->db[id2]->blocking_keys); |
| 1734 | std::swap(g_pserver->db[id2]->ready_keys, g_pserver->db[id2]->ready_keys); |
| 1735 | std::swap(g_pserver->db[id2]->watched_keys, g_pserver->db[id2]->watched_keys); |
| 1736 | |
| 1737 | /* Now we need to handle clients blocked on lists: as an effect |
| 1738 | * of swapping the two DBs, a client that was waiting for list |
| 1739 | * X in a given DB, may now actually be unblocked if X happens |
| 1740 | * to exist in the new version of the DB, after the swap. |
| 1741 | * |
| 1742 | * However normally we only do this check for efficiency reasons |
| 1743 | * in dbAdd() when a list is created. So here we need to rescan |
| 1744 | * the list of clients blocked on lists and signal lists as ready |
| 1745 | * if needed. |
| 1746 | * |
| 1747 | * Also the swapdb should make transaction fail if there is any |
| 1748 | * client watching keys */ |
| 1749 | scanDatabaseForReadyLists(g_pserver->db[id1]); |
| 1750 | touchAllWatchedKeysInDb(g_pserver->db[id1], g_pserver->db[id2]); |
| 1751 | scanDatabaseForReadyLists(g_pserver->db[id2]); |
| 1752 | touchAllWatchedKeysInDb(g_pserver->db[id2], g_pserver->db[id1]); |
| 1753 | return C_OK; |
| 1754 | } |
| 1755 | |
| 1756 | /* SWAPDB db1 db2 */ |
| 1757 | void swapdbCommand(client *c) { |
no test coverage detected