@@ -572,7 +572,7 @@ robj *dbUnshareStringValue(serverDb *db, robj *key, robj *o) {
572572 * The dbnum can be -1 if all the DBs should be emptied, or the specified
573573 * DB index if we want to empty only a single database.
574574 * The function returns the number of keys removed from the database(s). */
575- long long emptyDbStructure (serverDb * dbarray , int dbnum , int async , void (callback )(hashtable * )) {
575+ long long emptyDbStructure (serverDb * * dbarray , int dbnum , int async , void (callback )(hashtable * )) {
576576 long long removed = 0 ;
577577 int startdb , enddb ;
578578
@@ -584,18 +584,18 @@ long long emptyDbStructure(serverDb *dbarray, int dbnum, int async, void(callbac
584584 }
585585
586586 for (int j = startdb ; j <= enddb ; j ++ ) {
587- if (kvstoreSize (dbarray [j ]. keys ) == 0 ) continue ;
587+ if (dbarray [ j ] == NULL || kvstoreSize (dbarray [j ]-> keys ) == 0 ) continue ;
588588
589- removed += kvstoreSize (dbarray [j ]. keys );
589+ removed += kvstoreSize (dbarray [j ]-> keys );
590590 if (async ) {
591- emptyDbAsync (& dbarray [j ]);
591+ emptyDbAsync (dbarray [j ]);
592592 } else {
593- kvstoreEmpty (dbarray [j ]. keys , callback );
594- kvstoreEmpty (dbarray [j ]. expires , callback );
593+ kvstoreEmpty (dbarray [j ]-> keys , callback );
594+ kvstoreEmpty (dbarray [j ]-> expires , callback );
595595 }
596596 /* Because all keys of database are removed, reset average ttl. */
597- dbarray [j ]. avg_ttl = 0 ;
598- dbarray [j ]. expires_cursor = 0 ;
597+ dbarray [j ]-> avg_ttl = 0 ;
598+ dbarray [j ]-> expires_cursor = 0 ;
599599 }
600600
601601 return removed ;
@@ -653,47 +653,44 @@ long long emptyData(int dbnum, int flags, void(callback)(hashtable *)) {
653653 return removed ;
654654}
655655
656- /* Initialize temporary db on replica for use during diskless replication. */
657- serverDb * initTempDb (void ) {
658- int slot_count_bits = 0 ;
659- int flags = KVSTORE_ALLOCATE_HASHTABLES_ON_DEMAND ;
660- if (server .cluster_enabled ) {
661- slot_count_bits = CLUSTER_SLOT_MASK_BITS ;
662- flags |= KVSTORE_FREE_EMPTY_HASHTABLES ;
663- }
664- serverDb * tempDb = zcalloc (sizeof (serverDb ) * server .dbnum );
665- for (int i = 0 ; i < server .dbnum ; i ++ ) {
666- tempDb [i ].id = i ;
667- tempDb [i ].keys = kvstoreCreate (& kvstoreKeysHashtableType , slot_count_bits , flags );
668- tempDb [i ].expires = kvstoreCreate (& kvstoreExpiresHashtableType , slot_count_bits , flags );
669- }
670-
671- return tempDb ;
672- }
673-
674- /* Discard tempDb, it's always async. */
675- void discardTempDb (serverDb * tempDb ) {
656+ /* Discard tempDb array. It's always async. */
657+ void discardTempDb (serverDb * * tempDb ) {
676658 /* Release temp DBs. */
677659 emptyDbStructure (tempDb , -1 , 1 , NULL );
678660 for (int i = 0 ; i < server .dbnum ; i ++ ) {
679- kvstoreRelease (tempDb [i ].keys );
680- kvstoreRelease (tempDb [i ].expires );
661+ if (tempDb [i ]) {
662+ kvstoreRelease (tempDb [i ]-> keys );
663+ kvstoreRelease (tempDb [i ]-> expires );
664+
665+ /* These are expected to be empty on temporary databases */
666+ serverAssert (dictSize (tempDb [i ]-> blocking_keys ) == 0 );
667+ serverAssert (dictSize (tempDb [i ]-> blocking_keys_unblock_on_nokey ) == 0 );
668+ serverAssert (dictSize (tempDb [i ]-> ready_keys ) == 0 );
669+ serverAssert (dictSize (tempDb [i ]-> watched_keys ) == 0 );
670+
671+ dictRelease (tempDb [i ]-> blocking_keys );
672+ dictRelease (tempDb [i ]-> blocking_keys_unblock_on_nokey );
673+ dictRelease (tempDb [i ]-> ready_keys );
674+ dictRelease (tempDb [i ]-> watched_keys );
675+ zfree (tempDb [i ]);
676+ tempDb [i ] = NULL ;
677+ }
681678 }
682-
683679 zfree (tempDb );
684680}
685681
686682int selectDb (client * c , int id ) {
687683 if (id < 0 || id >= server .dbnum ) return C_ERR ;
688- c -> db = & server . db [ id ] ;
684+ c -> db = createDatabaseIfNeeded ( id ) ;
689685 return C_OK ;
690686}
691687
692688long long dbTotalServerKeyCount (void ) {
693689 long long total = 0 ;
694690 int j ;
695691 for (j = 0 ; j < server .dbnum ; j ++ ) {
696- total += kvstoreSize (server .db [j ].keys );
692+ if (dbHasNoKeys (j )) continue ;
693+ total += kvstoreSize (server .db [j ]-> keys );
697694 }
698695 return total ;
699696}
@@ -724,8 +721,9 @@ void signalFlushedDb(int dbid, int async) {
724721 }
725722
726723 for (int j = startdb ; j <= enddb ; j ++ ) {
727- scanDatabaseForDeletedKeys (& server .db [j ], NULL );
728- touchAllWatchedKeysInDb (& server .db [j ], NULL );
724+ if (server .db [j ] == NULL ) continue ;
725+ scanDatabaseForDeletedKeys (server .db [j ], NULL );
726+ touchAllWatchedKeysInDb (server .db [j ], NULL );
729727 }
730728
731729 trackingInvalidateKeysOnFlush (async );
@@ -1642,8 +1640,9 @@ void scanDatabaseForDeletedKeys(serverDb *emptied, serverDb *replaced_with) {
16421640int dbSwapDatabases (int id1 , int id2 ) {
16431641 if (id1 < 0 || id1 >= server .dbnum || id2 < 0 || id2 >= server .dbnum ) return C_ERR ;
16441642 if (id1 == id2 ) return C_OK ;
1645- serverDb aux = server .db [id1 ];
1646- serverDb * db1 = & server .db [id1 ], * db2 = & server .db [id2 ];
1643+ serverDb * db1 = createDatabaseIfNeeded (id1 );
1644+ serverDb * db2 = createDatabaseIfNeeded (id2 );
1645+ serverDb aux = * db1 ;
16471646
16481647 /* Swapdb should make transaction fail if there is any
16491648 * client watching keys */
@@ -1684,10 +1683,13 @@ int dbSwapDatabases(int id1, int id2) {
16841683/* Logically, this discards (flushes) the old main database, and apply the newly loaded
16851684 * database (temp) as the main (active) database, the actual freeing of old database
16861685 * (which will now be placed in the temp one) is done later. */
1687- void swapMainDbWithTempDb (serverDb * tempDb ) {
1686+ void swapMainDbWithTempDb (serverDb * * tempDb ) {
16881687 for (int i = 0 ; i < server .dbnum ; i ++ ) {
1689- serverDb aux = server .db [i ];
1690- serverDb * activedb = & server .db [i ], * newdb = & tempDb [i ];
1688+ if (tempDb [i ] == NULL && server .db [i ] == NULL ) continue ;
1689+ if (tempDb [i ] == NULL ) tempDb [i ] = createDatabase (i );
1690+ if (server .db [i ] == NULL ) server .db [i ] = createDatabase (i );
1691+ serverDb aux = * server .db [i ];
1692+ serverDb * activedb = server .db [i ], * newdb = tempDb [i ];
16911693
16921694 /* Swapping databases should make transaction fail if there is any
16931695 * client watching keys. */
@@ -2848,12 +2850,3 @@ int bitfieldGetKeys(struct serverCommand *cmd, robj **argv, int argc, getKeysRes
28482850 }
28492851 return 1 ;
28502852}
2851-
2852- bool dbHasNoKeys (void ) {
2853- for (int i = 0 ; i < server .dbnum ; i ++ ) {
2854- if (kvstoreSize (server .db [i ].keys ) != 0 ) {
2855- return false;
2856- }
2857- }
2858- return true;
2859- }
0 commit comments