@@ -94,6 +94,20 @@ type newGCStateManagerForTestOptions struct {
9494 etcdServerCfgModifier func (cfg * embed.Config )
9595}
9696
97+ func (opt * newGCStateManagerForTestOptions ) generateKeyspacesByCount (count int ) {
98+ createTime := time .Now ().Unix ()
99+ for i := range count {
100+ id := new (uint32 )
101+ * id = uint32 (i + 1 )
102+ opt .specifyInitialKeyspaces = append (opt .specifyInitialKeyspaces , & keyspace.CreateKeyspaceByIDRequest {
103+ ID : id ,
104+ Name : fmt .Sprintf ("ks%d" , * id ),
105+ Config : map [string ]string {keyspace .GCManagementType : keyspace .KeyspaceLevelGC },
106+ CreateTime : createTime ,
107+ })
108+ }
109+ }
110+
97111func newGCStateManagerForTest (t testing.TB , opt newGCStateManagerForTestOptions ) (storage * endpoint.StorageEndpoint , provider endpoint.GCStateProvider , gcStateManager * GCStateManager , clean func (), cancel context.CancelFunc ) {
98112 cfg := config .NewConfig ()
99113 re := require .New (t )
@@ -127,6 +141,7 @@ func newGCStateManagerForTest(t testing.TB, opt newGCStateManagerForTestOptions)
127141
128142 // The bootstrap keyspace (DefaultKeyspaceID or SystemKeyspaceID) exists automatically after bootstrapping.
129143 if opt .specifyInitialKeyspaces == nil {
144+ << << << < HEAD
130145 // In NextGen, all keyspaces should use keyspace_level GC
131146 // In Classic, we can have different GC management types
132147 var ks1Config map [string ]string
@@ -135,6 +150,8 @@ func newGCStateManagerForTest(t testing.TB, opt newGCStateManagerForTestOptions)
135150 } else {
136151 ks1Config = map [string ]string {"gc_management_type" : "unified" }
137152 }
153+ == == == =
154+ >> >> >> > 7 cbc3821d (gc : Optimize GetAllKeyspacesGCStates for scenarios where there are too many keyspaces (#9777 ))
138155 id := new (uint32 )
139156 * id = 1
140157 ks1 , err := keyspaceManager.CreateKeyspaceByID (& keyspace.CreateKeyspaceByIDRequest {
@@ -1868,7 +1885,7 @@ func (s *gcStateManagerTestSuite) TestGetAllKeyspacesMaxTxnSafePoint() {
18681885 var keyspaceID uint32
18691886 err := s .provider .RunInGCStateTransaction (func (wb * endpoint.GCStateWriteBatch ) error {
18701887 var err1 error
1871- txnSafePoint , keyspaceName , keyspaceID , err1 = s .manager .getAllKeyspacesMaxTxnSafePoint (wb )
1888+ txnSafePoint , keyspaceName , keyspaceID , err1 = s .manager .getMaxTxnSafePointAmongAllKeyspaces (wb )
18721889 return err1
18731890 })
18741891 re .NoError (err )
@@ -1883,7 +1900,7 @@ func (s *gcStateManagerTestSuite) TestGetAllKeyspacesMaxTxnSafePoint() {
18831900 }
18841901 err = s .provider .RunInGCStateTransaction (func (wb * endpoint.GCStateWriteBatch ) error {
18851902 var err1 error
1886- txnSafePoint , keyspaceName , keyspaceID , err1 = s .manager .getAllKeyspacesMaxTxnSafePoint (wb )
1903+ txnSafePoint , keyspaceName , keyspaceID , err1 = s .manager .getMaxTxnSafePointAmongAllKeyspaces (wb )
18871904 return err1
18881905 })
18891906 re .NoError (err )
@@ -2067,6 +2084,88 @@ func (s *gcStateManagerTestSuite) TestGetAllKeyspacesGCStatesConcurrentCallShari
20672084 re .Equal (int64 (2 ), executionCount .Load ())
20682085}
20692086
2087+ func TestGetAllKeysapcesGCStatesOnTooManyKeyspaces (t * testing.T ) {
2088+ re := require .New (t )
2089+
2090+ const totalKeyspaces = keyspace .IteratorLoadingBatchSize * 3
2091+
2092+ opt := newGCStateManagerForTestOptions {
2093+ specifyInitialKeyspaces : make ([]* keyspace.CreateKeyspaceByIDRequest , 0 , totalKeyspaces ),
2094+ }
2095+ opt .generateKeyspacesByCount (totalKeyspaces )
2096+
2097+ _ , _ , gcStateManager , clean , cancel := newGCStateManagerForTest (t , opt )
2098+ defer func () {
2099+ cancel ()
2100+ clean ()
2101+ }()
2102+
2103+ gcStates , err := gcStateManager .GetAllKeyspacesGCStates (context .Background ())
2104+ re .Len (gcStates , totalKeyspaces + 2 ) // Including the null keyspace, the default keyspace or the system keyspace.
2105+
2106+ re .NoError (err )
2107+ keyspaceIDs := make ([]uint32 , 0 , len (gcStates ))
2108+ for keyspaceID , gcState := range gcStates {
2109+ re .Equal (keyspaceID , gcState .KeyspaceID )
2110+ keyspaceIDs = append (keyspaceIDs , keyspaceID )
2111+ }
2112+ slices .Sort (keyspaceIDs )
2113+
2114+ expectedKeyspaceIDs := make ([]uint32 , 0 , len (gcStates ))
2115+ if ! kerneltype .IsNextGen () {
2116+ expectedKeyspaceIDs = append (expectedKeyspaceIDs , constant .DefaultKeyspaceID )
2117+ }
2118+ for i := range totalKeyspaces {
2119+ expectedKeyspaceIDs = append (expectedKeyspaceIDs , uint32 (i + 1 ))
2120+ }
2121+ if kerneltype .IsNextGen () {
2122+ expectedKeyspaceIDs = append (expectedKeyspaceIDs , constant .SystemKeyspaceID )
2123+ }
2124+ expectedKeyspaceIDs = append (expectedKeyspaceIDs , constant .NullKeyspaceID )
2125+ re .Equal (expectedKeyspaceIDs , keyspaceIDs )
2126+ }
2127+
2128+ func TestGetMaxTxnSafePointAmongAllKeyspacesOnTooManyKeyspaces (t * testing.T ) {
2129+ re := require .New (t )
2130+
2131+ const totalKeyspaces = keyspace .IteratorLoadingBatchSize * 2
2132+
2133+ opt := newGCStateManagerForTestOptions {
2134+ specifyInitialKeyspaces : make ([]* keyspace.CreateKeyspaceByIDRequest , 0 , totalKeyspaces ),
2135+ }
2136+ opt .generateKeyspacesByCount (totalKeyspaces )
2137+
2138+ _ , _ , gcStateManager , clean , cancel := newGCStateManagerForTest (t , opt )
2139+ defer func () {
2140+ cancel ()
2141+ clean ()
2142+ }()
2143+
2144+ now := time .Now ()
2145+ // Test around the boundary of two loading batches, so that it's likely to detect incorrectness when loading
2146+ // multiple batches.
2147+ for i := keyspace .IteratorLoadingBatchSize - 5 ; i <= keyspace .IteratorLoadingBatchSize + 5 ; i ++ {
2148+ keyspaceID := uint32 (i )
2149+ newTxnSafePoint := uint64 (i )
2150+ res , err := gcStateManager .AdvanceTxnSafePoint (keyspaceID , newTxnSafePoint , now )
2151+ re .NoError (err )
2152+ re .Equal (newTxnSafePoint , res .NewTxnSafePoint )
2153+
2154+ var maxTxnSafePoint uint64
2155+ var keyspaceIDWithMaxTxnSafePoint uint32
2156+ var keyspaceNameWithMaxTxnSafePoint string
2157+ err = gcStateManager .gcMetaStorage .RunInGCStateTransaction (func (wb * endpoint.GCStateWriteBatch ) error {
2158+ var err1 error
2159+ maxTxnSafePoint , keyspaceNameWithMaxTxnSafePoint , keyspaceIDWithMaxTxnSafePoint , err1 = gcStateManager .getMaxTxnSafePointAmongAllKeyspaces (wb )
2160+ return err1
2161+ })
2162+ re .NoError (err )
2163+ re .Equal (newTxnSafePoint , maxTxnSafePoint )
2164+ re .Equal (keyspaceID , keyspaceIDWithMaxTxnSafePoint )
2165+ re .Equal (fmt .Sprintf ("ks%d" , keyspaceID ), keyspaceNameWithMaxTxnSafePoint )
2166+ }
2167+ }
2168+
20702169func benchmarkGetAllKeyspacesGCStatesImpl (b * testing.B , keyspacesCount int , parallelism int ) {
20712170 re := require .New (b )
20722171 fname := testutil .InitTempFileLogger ("info" )
@@ -2078,7 +2177,10 @@ func benchmarkGetAllKeyspacesGCStatesImpl(b *testing.B, keyspacesCount int, para
20782177 cfg .LogOutputs = []string {fname }
20792178 },
20802179 }
2180+ << << << < HEAD
20812181
2182+ == == == =
2183+ >> >> >> > 7 cbc3821d (gc : Optimize GetAllKeyspacesGCStates for scenarios where there are too many keyspaces (#9777 ))
20822184 createTime := time .Now ().Unix ()
20832185 for i := range keyspacesCount {
20842186 id := new (uint32 )
0 commit comments