@@ -12,12 +12,13 @@ import (
1212 "time"
1313
1414 "github.com/cockroachdb/cockroach/pkg/base"
15- "github.com/cockroachdb/cockroach/pkg/kv/kvclient/rangefeed"
16- "github.com/cockroachdb/cockroach/pkg/sql/catalog"
17- "github.com/cockroachdb/cockroach/pkg/sql/catalog/descs"
15+ "github.com/cockroachdb/cockroach/pkg/server"
16+ "github.com/cockroachdb/cockroach/pkg/sql"
1817 "github.com/cockroachdb/cockroach/pkg/sql/hintpb"
1918 "github.com/cockroachdb/cockroach/pkg/sql/hints"
19+ "github.com/cockroachdb/cockroach/pkg/storage/fs"
2020 "github.com/cockroachdb/cockroach/pkg/testutils"
21+ "github.com/cockroachdb/cockroach/pkg/testutils/listenerutil"
2122 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
2223 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
2324 "github.com/cockroachdb/cockroach/pkg/testutils/testcluster"
@@ -41,8 +42,7 @@ func TestHintCacheBasic(t *testing.T) {
4142 r := sqlutils .MakeSQLRunner (db )
4243 setTestDefaults (t , srv )
4344
44- // Create a hints cache.
45- hc := createHintsCache (t , ctx , ts )
45+ hc := ts .ExecutorConfig ().(sql.ExecutorConfig ).StatementHintsCache
4646 require .Equal (t , 0 , hc .TestingHashCount ())
4747
4848 // Insert a hint for a statement. The cache should soon contain the hash.
@@ -96,7 +96,7 @@ func TestHintCacheLRU(t *testing.T) {
9696 // Set cache size to 2 for testing eviction.
9797 r .Exec (t , "SET CLUSTER SETTING sql.hints.statement_hints_cache_size = 2" )
9898
99- hc := createHintsCache ( t , ctx , ts )
99+ hc := ts . ExecutorConfig ().(sql. ExecutorConfig ). StatementHintsCache
100100 require .Equal (t , 0 , hc .TestingHashCount ())
101101
102102 // Create test data: 3 different fingerprints.
@@ -121,46 +121,51 @@ func TestHintCacheLRU(t *testing.T) {
121121 return nil
122122 })
123123
124+ // Before the initial scan is complete, all queries unconditionally check
125+ // the hint cache and might perform DB reads, so we need to ignore all reads
126+ // that happened already.
127+ ignoredReads := hc .TestingNumTableReads ()
128+
124129 // Access the first two fingerprints to populate the cache.
125130 // This should result in 2 table reads.
126131 requireHintsCount (t , hc , ctx , fingerprints [0 ], 1 )
127- require .Equal (t , 1 , hc .TestingNumTableReads ())
132+ require .Equal (t , ignoredReads + 1 , hc .TestingNumTableReads ())
128133
129134 requireHintsCount (t , hc , ctx , fingerprints [1 ], 1 )
130- require .Equal (t , 2 , hc .TestingNumTableReads ())
135+ require .Equal (t , ignoredReads + 2 , hc .TestingNumTableReads ())
131136
132137 // Access the same fingerprints again - should be served from cache with no
133138 // additional reads.
134139 requireHintsCount (t , hc , ctx , fingerprints [0 ], 1 )
135140 requireHintsCount (t , hc , ctx , fingerprints [1 ], 1 )
136- require .Equal (t , 2 , hc .TestingNumTableReads ())
141+ require .Equal (t , ignoredReads + 2 , hc .TestingNumTableReads ())
137142
138143 // Access the third fingerprint. This should evict the first (LRU) due to
139144 // cache size limit of 2, resulting in one more table read.
140145 requireHintsCount (t , hc , ctx , fingerprints [2 ], 1 )
141- require .Equal (t , 3 , hc .TestingNumTableReads ())
146+ require .Equal (t , ignoredReads + 3 , hc .TestingNumTableReads ())
142147
143148 // Access the first fingerprint again. Since it was evicted, this should
144149 // result in another table read on the first access.
145150 requireHintsCount (t , hc , ctx , fingerprints [0 ], 1 )
146- require .Equal (t , 4 , hc .TestingNumTableReads ())
151+ require .Equal (t , ignoredReads + 4 , hc .TestingNumTableReads ())
147152
148153 // Access the second fingerprint. It should have been evicted by now, so
149154 // another table read on the first access.
150155 requireHintsCount (t , hc , ctx , fingerprints [1 ], 1 )
151- require .Equal (t , 5 , hc .TestingNumTableReads ())
156+ require .Equal (t , ignoredReads + 5 , hc .TestingNumTableReads ())
152157
153158 // The first and second fingerprint should now be cached, so accessing them
154159 // again should not increase table reads.
155160 requireHintsCount (t , hc , ctx , fingerprints [0 ], 1 )
156161 requireHintsCount (t , hc , ctx , fingerprints [1 ], 1 )
157- require .Equal (t , 5 , hc .TestingNumTableReads ())
162+ require .Equal (t , ignoredReads + 5 , hc .TestingNumTableReads ())
158163
159164 // Access the third fingerprint again - should have been evicted, so the first
160165 // access should cause a table read.
161166 requireHintsCount (t , hc , ctx , fingerprints [2 ], 1 )
162167 requireHintsCount (t , hc , ctx , fingerprints [2 ], 1 )
163- require .Equal (t , 6 , hc .TestingNumTableReads ())
168+ require .Equal (t , ignoredReads + 6 , hc .TestingNumTableReads ())
164169}
165170
166171// TestHintCacheInitialScan tests that a new cache correctly populates from
@@ -169,14 +174,29 @@ func TestHintCacheInitialScan(t *testing.T) {
169174 defer leaktest .AfterTest (t )()
170175 defer log .Scope (t ).Close (t )
171176
177+ listenerReg := listenerutil .NewListenerRegistry ()
178+ defer listenerReg .Close ()
179+ stickyVFSRegistry := fs .NewStickyRegistry ()
180+
172181 ctx := context .Background ()
173- srv , db , _ := serverutils .StartServer (t , base.TestServerArgs {})
174- defer srv .Stopper ().Stop (ctx )
175- ts := srv .ApplicationLayer ()
176- r := sqlutils .MakeSQLRunner (db )
177- setTestDefaults (t , srv )
182+ tc := serverutils .StartCluster (t , 1 , base.TestClusterArgs {
183+ ServerArgs : base.TestServerArgs {
184+ Knobs : base.TestingKnobs {
185+ Server : & server.TestingKnobs {
186+ // Sticky vfs is needed for cluster restart.
187+ StickyVFSRegistry : stickyVFSRegistry ,
188+ },
189+ },
190+ },
191+ // A listener is required for cluster restart.
192+ ReusableListenerReg : listenerReg ,
193+ })
194+ defer tc .Stopper ().Stop (ctx )
195+ ts := tc .ApplicationLayer (0 )
196+ r := sqlutils .MakeSQLRunner (ts .SQLConn (t ))
197+ setTestDefaults (t , tc .Server (0 ))
178198
179- // Insert multiple hints into the system table BEFORE creating the cache .
199+ // Insert multiple hints into the system table.
180200 fingerprints := []string {
181201 "SELECT a FROM t WHERE b = $1" ,
182202 "SELECT c FROM t WHERE d = $1" ,
@@ -191,9 +211,12 @@ func TestHintCacheInitialScan(t *testing.T) {
191211 // Insert multiple hints for the first fingerprint.
192212 insertStatementHint (t , r , fingerprints [0 ])
193213
194- // Now create a hints cache - it should populate from existing hints during
195- // initial scan.
196- hc := createHintsCache (t , ctx , ts )
214+ // Restart the cluster to trigger the initial scan for the hints cache.
215+ require .NoError (t , tc .Restart ())
216+ ts = tc .ApplicationLayer (0 )
217+ r = sqlutils .MakeSQLRunner (ts .SQLConn (t ))
218+
219+ hc := ts .ExecutorConfig ().(sql.ExecutorConfig ).StatementHintsCache
197220
198221 // The cache should have all the hashes once the initial scan completes.
199222 testutils .SucceedsSoon (t , func () error {
@@ -246,8 +269,8 @@ func TestHintCacheMultiNode(t *testing.T) {
246269 r2 := sqlutils .MakeSQLRunner (tc .ServerConn (2 ))
247270 setTestDefaults (t , tc .Server (0 ))
248271
249- // Create a hints cache on node 0.
250- hc := createHintsCache ( t , ctx , ts )
272+ // Use the hints cache from node 0.
273+ hc := ts . ExecutorConfig ().(sql. ExecutorConfig ). StatementHintsCache
251274 require .Equal (t , 0 , hc .TestingHashCount ())
252275
253276 // Insert hints from node 1.
@@ -307,9 +330,8 @@ func TestHintCacheMultiTenant(t *testing.T) {
307330 r1 := sqlutils .MakeSQLRunner (tenantConn1 )
308331 r2 := sqlutils .MakeSQLRunner (tenantConn2 )
309332
310- // Create hints caches for both tenants.
311- hc1 := createHintsCache (t , ctx , tenant1 )
312- hc2 := createHintsCache (t , ctx , tenant2 )
333+ hc1 := tenant1 .ExecutorConfig ().(sql.ExecutorConfig ).StatementHintsCache
334+ hc2 := tenant2 .ExecutorConfig ().(sql.ExecutorConfig ).StatementHintsCache
313335 require .Equal (t , 0 , hc1 .TestingHashCount ())
314336 require .Equal (t , 0 , hc2 .TestingHashCount ())
315337
@@ -390,8 +412,7 @@ func TestHintCacheGeneration(t *testing.T) {
390412 r := sqlutils .MakeSQLRunner (db )
391413 setTestDefaults (t , srv )
392414
393- // Create a hints cache.
394- hc := createHintsCache (t , ctx , ts )
415+ hc := ts .ExecutorConfig ().(sql.ExecutorConfig ).StatementHintsCache
395416
396417 // Helper that retrieves the generation and verifies that it doesn't change
397418 // over a short period.
@@ -475,21 +496,6 @@ func setTestDefaults(t *testing.T, srv serverutils.TestServerInterface) {
475496 r .Exec (t , "SET CLUSTER SETTING kv.rangefeed.closed_timestamp_refresh_interval = '10ms'" )
476497}
477498
478- func createHintsCache (
479- t * testing.T , ctx context.Context , ts serverutils.ApplicationLayerInterface ,
480- ) * hints.StatementHintsCache {
481- hc := hints .NewStatementHintsCache (
482- ts .Clock (),
483- ts .RangeFeedFactory ().(* rangefeed.Factory ),
484- ts .AppStopper (),
485- ts .Codec (),
486- ts .InternalDB ().(descs.DB ),
487- ts .ClusterSettings (),
488- )
489- require .NoError (t , hc .Start (ctx , ts .SystemTableIDResolver ().(catalog.SystemTableIDResolver )))
490- return hc
491- }
492-
493499// waitForUpdateOnFingerprintHash waits for the cache to automatically refresh
494500// to reflect a hint insertion or deletion.
495501func waitForUpdateOnFingerprintHash (
0 commit comments