github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/embedded/cache.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package embedded
    15  
    16  import (
    17  	"math"
    18  	"sync/atomic"
    19  	"time"
    20  
    21  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    22  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    23  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    24  	"github.com/whtcorpsinc/milevadb/ekv"
    25  	"github.com/whtcorpsinc/milevadb/soliton/codec"
    26  	"github.com/whtcorpsinc/milevadb/soliton/ekvcache"
    27  	"github.com/whtcorpsinc/milevadb/soliton/replog"
    28  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    29  	"github.com/whtcorpsinc/milevadb/types"
    30  	atomic2 "go.uber.org/atomic"
    31  )
    32  
    33  var (
    34  	// preparedCausetCacheEnabledValue stores the global config "prepared-plan-cache-enabled".
    35  	// If the value of "prepared-plan-cache-enabled" is true, preparedCausetCacheEnabledValue's value is 1.
    36  	// Otherwise, preparedCausetCacheEnabledValue's value is 0.
    37  	preparedCausetCacheEnabledValue int32
    38  	// PreparedCausetCacheCapacity stores the global config "prepared-plan-cache-capacity".
    39  	PreparedCausetCacheCapacity uint = 100
    40  	// PreparedCausetCacheMemoryGuardRatio stores the global config "prepared-plan-cache-memory-guard-ratio".
    41  	PreparedCausetCacheMemoryGuardRatio = 0.1
    42  	// PreparedCausetCacheMaxMemory stores the max memory size defined in the global config "performance-server-memory-quota".
    43  	PreparedCausetCacheMaxMemory = *atomic2.NewUint64(math.MaxUint64)
    44  )
    45  
    46  const (
    47  	preparedCausetCacheEnabled = 1
    48  	preparedCausetCacheUnable  = 0
    49  )
    50  
    51  // SetPreparedCausetCache sets isEnabled to true, then prepared plan cache is enabled.
    52  func SetPreparedCausetCache(isEnabled bool) {
    53  	if isEnabled {
    54  		atomic.StoreInt32(&preparedCausetCacheEnabledValue, preparedCausetCacheEnabled)
    55  	} else {
    56  		atomic.StoreInt32(&preparedCausetCacheEnabledValue, preparedCausetCacheUnable)
    57  	}
    58  }
    59  
    60  // PreparedCausetCacheEnabled returns whether the prepared plan cache is enabled.
    61  func PreparedCausetCacheEnabled() bool {
    62  	isEnabled := atomic.LoadInt32(&preparedCausetCacheEnabledValue)
    63  	return isEnabled == preparedCausetCacheEnabled
    64  }
    65  
    66  type pstmtCausetCacheKey struct {
    67  	database             string
    68  	connID               uint64
    69  	pstmtID              uint32
    70  	snapshot             uint64
    71  	schemaVersion        int64
    72  	sqlMode              allegrosql.ALLEGROSQLMode
    73  	timezoneOffset       int
    74  	isolationReadEngines map[ekv.StoreType]struct{}
    75  	selectLimit          uint64
    76  
    77  	hash []byte
    78  }
    79  
    80  // Hash implements Key interface.
    81  func (key *pstmtCausetCacheKey) Hash() []byte {
    82  	if len(key.hash) == 0 {
    83  		var (
    84  			dbBytes    = replog.Slice(key.database)
    85  			bufferSize = len(dbBytes) + 8*6 + 3*8
    86  		)
    87  		if key.hash == nil {
    88  			key.hash = make([]byte, 0, bufferSize)
    89  		}
    90  		key.hash = append(key.hash, dbBytes...)
    91  		key.hash = codec.EncodeInt(key.hash, int64(key.connID))
    92  		key.hash = codec.EncodeInt(key.hash, int64(key.pstmtID))
    93  		key.hash = codec.EncodeInt(key.hash, int64(key.snapshot))
    94  		key.hash = codec.EncodeInt(key.hash, key.schemaVersion)
    95  		key.hash = codec.EncodeInt(key.hash, int64(key.sqlMode))
    96  		key.hash = codec.EncodeInt(key.hash, int64(key.timezoneOffset))
    97  		if _, ok := key.isolationReadEngines[ekv.MilevaDB]; ok {
    98  			key.hash = append(key.hash, ekv.MilevaDB.Name()...)
    99  		}
   100  		if _, ok := key.isolationReadEngines[ekv.EinsteinDB]; ok {
   101  			key.hash = append(key.hash, ekv.EinsteinDB.Name()...)
   102  		}
   103  		if _, ok := key.isolationReadEngines[ekv.TiFlash]; ok {
   104  			key.hash = append(key.hash, ekv.TiFlash.Name()...)
   105  		}
   106  		key.hash = codec.EncodeInt(key.hash, int64(key.selectLimit))
   107  	}
   108  	return key.hash
   109  }
   110  
   111  // SetPstmtIDSchemaVersion implements PstmtCacheKeyMutator interface to change pstmtID and schemaVersion of cacheKey.
   112  // so we can reuse Key instead of new every time.
   113  func SetPstmtIDSchemaVersion(key ekvcache.Key, pstmtID uint32, schemaVersion int64, isolationReadEngines map[ekv.StoreType]struct{}) {
   114  	psStmtKey, isPsStmtKey := key.(*pstmtCausetCacheKey)
   115  	if !isPsStmtKey {
   116  		return
   117  	}
   118  	psStmtKey.pstmtID = pstmtID
   119  	psStmtKey.schemaVersion = schemaVersion
   120  	psStmtKey.isolationReadEngines = make(map[ekv.StoreType]struct{})
   121  	for k, v := range isolationReadEngines {
   122  		psStmtKey.isolationReadEngines[k] = v
   123  	}
   124  	psStmtKey.hash = psStmtKey.hash[:0]
   125  }
   126  
   127  // NewPSTMTCausetCacheKey creates a new pstmtCausetCacheKey object.
   128  func NewPSTMTCausetCacheKey(stochastikVars *variable.StochastikVars, pstmtID uint32, schemaVersion int64) ekvcache.Key {
   129  	timezoneOffset := 0
   130  	if stochastikVars.TimeZone != nil {
   131  		_, timezoneOffset = time.Now().In(stochastikVars.TimeZone).Zone()
   132  	}
   133  	key := &pstmtCausetCacheKey{
   134  		database:             stochastikVars.CurrentDB,
   135  		connID:               stochastikVars.ConnectionID,
   136  		pstmtID:              pstmtID,
   137  		snapshot:             stochastikVars.SnapshotTS,
   138  		schemaVersion:        schemaVersion,
   139  		sqlMode:              stochastikVars.ALLEGROSQLMode,
   140  		timezoneOffset:       timezoneOffset,
   141  		isolationReadEngines: make(map[ekv.StoreType]struct{}),
   142  		selectLimit:          stochastikVars.SelectLimit,
   143  	}
   144  	for k, v := range stochastikVars.IsolationReadEngines {
   145  		key.isolationReadEngines[k] = v
   146  	}
   147  	return key
   148  }
   149  
   150  // PSTMTCausetCacheValue stores the cached Statement and StmtNode.
   151  type PSTMTCausetCacheValue struct {
   152  	Causet            Causet
   153  	OutPutNames       []*types.FieldName
   154  	TblInfo2UnionScan map[*perceptron.BlockInfo]bool
   155  }
   156  
   157  // NewPSTMTCausetCacheValue creates a ALLEGROSQLCacheValue.
   158  func NewPSTMTCausetCacheValue(plan Causet, names []*types.FieldName, srcMap map[*perceptron.BlockInfo]bool) *PSTMTCausetCacheValue {
   159  	dstMap := make(map[*perceptron.BlockInfo]bool)
   160  	for k, v := range srcMap {
   161  		dstMap[k] = v
   162  	}
   163  	return &PSTMTCausetCacheValue{
   164  		Causet:            plan,
   165  		OutPutNames:       names,
   166  		TblInfo2UnionScan: dstMap,
   167  	}
   168  }
   169  
   170  // CachedPrepareStmt causetstore prepared ast from PrepareInterDirc and other related fields
   171  type CachedPrepareStmt struct {
   172  	PreparedAst             *ast.Prepared
   173  	VisitInfos              []visitInfo
   174  	DeferredCausetInfos     interface{}
   175  	InterlockingDirectorate interface{}
   176  	NormalizedALLEGROSQL    string
   177  	NormalizedCauset        string
   178  	ALLEGROSQLDigest        string
   179  	CausetDigest            string
   180  }