@@ -18,6 +18,8 @@ import (
1818 "context"
1919 "math"
2020 "time"
21+
22+ "github.com/pingcap/errors"
2123)
2224
2325// Client is the interface for GC client.
@@ -32,6 +34,45 @@ type Client interface {
3234 GetGCStatesClient (keyspaceID uint32 ) GCStatesClient
3335}
3436
37+ // GCStatesAPIOptions represents all options for GC states API.
38+ //
39+ //nolint:revive
40+ type GCStatesAPIOptions struct {
41+ ExcludeGCBarriers bool
42+ ExcludeGlobalGCBarriers bool
43+ }
44+
45+ // DefaultGCStatesAPIOptions returns the default options for GC states API.
46+ func DefaultGCStatesAPIOptions () GCStatesAPIOptions {
47+ return GCStatesAPIOptions {
48+ ExcludeGCBarriers : true ,
49+ ExcludeGlobalGCBarriers : true ,
50+ }
51+ }
52+
53+ // GCStatesAPIOption is the type of option for GC states API.
54+ //
55+ //nolint:revive
56+ type GCStatesAPIOption func (* GCStatesAPIOptions )
57+
58+ // ExcludeGCBarriers controls whether GetGCState and GetAllKeyspacesGCStates should exclude GC barriers.
59+ // Enabling this can reduce the cost of reading GC states, and is recommended for most use cases.
60+ // When GC barriers are needed, explicitly set false to this option.
61+ func ExcludeGCBarriers (whetherToExclude bool ) GCStatesAPIOption {
62+ return func (opts * GCStatesAPIOptions ) {
63+ opts .ExcludeGCBarriers = whetherToExclude
64+ }
65+ }
66+
67+ // ExcludeGlobalGCBarriers controls whether GetAllKeyspacesGCStates should exclude global GC barriers.
68+ // Enabling this can reduce the cost of reading GC states, and is recommended for most use cases.
69+ // When global GC barriers are needed, explicitly set false to this option.
70+ func ExcludeGlobalGCBarriers (whetherToExclude bool ) GCStatesAPIOption {
71+ return func (opts * GCStatesAPIOptions ) {
72+ opts .ExcludeGlobalGCBarriers = whetherToExclude
73+ }
74+ }
75+
3576// GCStatesClient is the interface for users to access GC states.
3677// KeyspaceID is already bound to this type when created.
3778//
@@ -72,7 +113,7 @@ type GCStatesClient interface {
72113 //
73114 // When this method is called on a keyspace without keyspace-level GC enabled, it will be equivalent to calling it on
74115 // the NullKeyspace.
75- GetGCState (ctx context.Context ) (GCState , error )
116+ GetGCState (ctx context.Context , opts ... GCStatesAPIOption ) (GCState , error )
76117 // SetGlobalGCBarrier sets a global GC barrier, which blocks GC like how GC barriers do, but is effective for all
77118 // keyspaces. This API is designed for some special needs to block GC of all keyspaces.
78119 //
@@ -105,11 +146,11 @@ type GCStatesClient interface {
105146 SetGlobalGCBarrier (ctx context.Context , barrierID string , barrierTS uint64 , ttl time.Duration ) (* GlobalGCBarrierInfo , error )
106147 // DeleteGlobalGCBarrier deletes a global GC barrier.
107148 DeleteGlobalGCBarrier (ctx context.Context , barrierID string ) (* GlobalGCBarrierInfo , error )
108- // Get the GC states from all keyspaces.
149+ // GetAllKeyspacesGCStates gets GC states from all keyspaces.
109150 // The return value includes both GC states and global GC barriers information.
110151 // If a keyspace's state is not ENABLED(like DISABLE/ARCHIVED/TOMBSTONE), that keyspace is skipped.
111152 // If a keyspace is not configured with keyspace level GC, its GCState data is missing.
112- GetAllKeyspacesGCStates (ctx context.Context ) (ClusterGCStates , error )
153+ GetAllKeyspacesGCStates (ctx context.Context , opts ... GCStatesAPIOption ) (ClusterGCStates , error )
113154}
114155
115156// InternalController is the interface for controlling GC execution.
@@ -245,16 +286,89 @@ func (b *GlobalGCBarrierInfo) isExpiredImpl(now time.Time) bool {
245286//nolint:revive
246287type GCState struct {
247288 // The ID of the keyspace this GC state belongs to.
248- KeyspaceID uint32
249- TxnSafePoint uint64
250- GCSafePoint uint64
251- GCBarriers []* GCBarrierInfo
289+ KeyspaceID uint32
290+ TxnSafePoint uint64
291+ GCSafePoint uint64
292+ hasGCBarriers bool
293+ gcBarriers []* GCBarrierInfo
294+ }
295+
296+ // NewGCStateWithoutGCBarriers creates a GCState instance without GC barriers info.
297+ func NewGCStateWithoutGCBarriers (keyspaceID uint32 , txnSafePoint uint64 , gcSafePoint uint64 ) GCState {
298+ return GCState {
299+ KeyspaceID : keyspaceID ,
300+ TxnSafePoint : txnSafePoint ,
301+ GCSafePoint : gcSafePoint ,
302+ hasGCBarriers : false ,
303+ gcBarriers : nil ,
304+ }
305+ }
306+
307+ // NewGCStateWithGCBarriers creates a GCState instance with GC barriers info.
308+ func NewGCStateWithGCBarriers (keyspaceID uint32 , txnSafePoint uint64 , gcSafePoint uint64 , gcBarriers []* GCBarrierInfo ) GCState {
309+ return GCState {
310+ KeyspaceID : keyspaceID ,
311+ TxnSafePoint : txnSafePoint ,
312+ GCSafePoint : gcSafePoint ,
313+ hasGCBarriers : true ,
314+ gcBarriers : gcBarriers ,
315+ }
316+ }
317+
318+ // HasGCBarriers returns whether the GCState instance carries GC barriers info. Note that valid GC barriers info
319+ // can be empty.
320+ func (s GCState ) HasGCBarriers () bool {
321+ return s .hasGCBarriers
322+ }
323+
324+ // GetGCBarriers retrieves GC barriers from the GCState instance, or returns an error if it doesn't carry any GC barrier
325+ // info.
326+ func (s GCState ) GetGCBarriers () ([]* GCBarrierInfo , error ) {
327+ if ! s .HasGCBarriers () {
328+ return nil , errors .New ("trying to get GC barriers from GCState that doesn't provide GC barriers info. " +
329+ "to retrieve GC barriers, pass false to excludeGCBarriers parameter to GC APIs" )
330+ }
331+ return s .gcBarriers , nil
252332}
253333
254334// ClusterGCStates represents the information of the GC state for all keyspaces.
255335type ClusterGCStates struct {
256336 // Maps from keyspace id to GC state of that keyspace.
257- GCStates map [uint32 ]GCState
258- // All existing global GC barriers.
259- GlobalGCBarriers []* GlobalGCBarrierInfo
337+ GCStates map [uint32 ]GCState
338+ hasGlobalGCBarriers bool
339+ globalGCBarriers []* GlobalGCBarrierInfo
340+ }
341+
342+ // NewClusterGCStatesWithoutGlobalGCBarriers creates a ClusterGCStates instance without global GC barriers info.
343+ func NewClusterGCStatesWithoutGlobalGCBarriers (gcStates map [uint32 ]GCState ) ClusterGCStates {
344+ return ClusterGCStates {
345+ GCStates : gcStates ,
346+ hasGlobalGCBarriers : false ,
347+ globalGCBarriers : nil ,
348+ }
349+ }
350+
351+ // NewClusterGCStatesWithGlobalGCBarriers creates a ClusterGCStates instance with global GC barriers info.
352+ func NewClusterGCStatesWithGlobalGCBarriers (gcStates map [uint32 ]GCState , globalGCBarriers []* GlobalGCBarrierInfo ) ClusterGCStates {
353+ return ClusterGCStates {
354+ GCStates : gcStates ,
355+ hasGlobalGCBarriers : true ,
356+ globalGCBarriers : globalGCBarriers ,
357+ }
358+ }
359+
360+ // HasGlobalGCBarriers returns whether the ClusterGCStates instance carries global GC barriers info. Note that valid
361+ // global GC barriers info can be empty.
362+ func (s ClusterGCStates ) HasGlobalGCBarriers () bool {
363+ return s .hasGlobalGCBarriers
364+ }
365+
366+ // GetGlobalGCBarriers retrieves global GC barriers from the ClusterGCStates instance, or returns an error if it doesn't
367+ // carry any global GC barrier info.
368+ func (s ClusterGCStates ) GetGlobalGCBarriers () ([]* GlobalGCBarrierInfo , error ) {
369+ if ! s .HasGlobalGCBarriers () {
370+ return nil , errors .New ("trying to get global GC barriers from ClusterGCStates that doesn't provide global GC barriers info. " +
371+ "to retrieve global GC barriers, pass false to excludeGlobalGCBarriers parameter to GC APIs" )
372+ }
373+ return s .globalGCBarriers , nil
260374}
0 commit comments