github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/soliton/stmtsummary/statement_summary_test.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 stmtsummary
    15  
    16  import (
    17  	"container/list"
    18  	"fmt"
    19  	"strconv"
    20  	"strings"
    21  	"sync"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    26  	"github.com/whtcorpsinc/BerolinaSQL/auth"
    27  	. "github.com/whtcorpsinc/check"
    28  	"github.com/whtcorpsinc/milevadb/causetstore/einsteindb"
    29  	"github.com/whtcorpsinc/milevadb/config"
    30  	"github.com/whtcorpsinc/milevadb/soliton/execdetails"
    31  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    32  	"github.com/whtcorpsinc/milevadb/types"
    33  )
    34  
    35  var _ = Suite(&testStmtSummarySuite{})
    36  
    37  type testStmtSummarySuite struct {
    38  	ssMap *stmtSummaryByDigestMap
    39  }
    40  
    41  func emptyCausetGenerator() string {
    42  	return ""
    43  }
    44  
    45  func fakeCausetDigestGenerator() string {
    46  	return "point_get"
    47  }
    48  
    49  func (s *testStmtSummarySuite) SetUpSuite(c *C) {
    50  	s.ssMap = newStmtSummaryByDigestMap()
    51  	s.ssMap.SetEnabled("1", false)
    52  	s.ssMap.SetRefreshInterval("1800", false)
    53  	s.ssMap.SetHistorySize("24", false)
    54  }
    55  
    56  func TestT(t *testing.T) {
    57  	CustomVerboseFlag = true
    58  	TestingT(t)
    59  }
    60  
    61  // Test stmtSummaryByDigest.AddStatement.
    62  func (s *testStmtSummarySuite) TestAddStatement(c *C) {
    63  	s.ssMap.Clear()
    64  	now := time.Now().Unix()
    65  	s.ssMap.beginTimeForCurInterval = now + 60
    66  
    67  	blocks := []stmtctx.BlockEntry{{EDB: "db1", Block: "tb1"}, {EDB: "db2", Block: "tb2"}}
    68  	indexes := []string{"a", "b"}
    69  
    70  	// first memex
    71  	stmtInterDircInfo1 := generateAnyInterDircInfo()
    72  	stmtInterDircInfo1.InterDircDetail.CommitDetail.Mu.BackoffTypes = make([]fmt.Stringer, 0)
    73  	key := &stmtSummaryByDigestKey{
    74  		schemaName: stmtInterDircInfo1.SchemaName,
    75  		digest:     stmtInterDircInfo1.Digest,
    76  		planDigest: stmtInterDircInfo1.CausetDigest,
    77  	}
    78  	expectedSummaryElement := stmtSummaryByDigestElement{
    79  		beginTime:            now + 60,
    80  		endTime:              now + 1860,
    81  		sampleALLEGROSQL:            stmtInterDircInfo1.OriginalALLEGROSQL,
    82  		sampleCauset:           stmtInterDircInfo1.CausetGenerator(),
    83  		indexNames:           stmtInterDircInfo1.StmtCtx.IndexNames,
    84  		execCount:            1,
    85  		sumLatency:           stmtInterDircInfo1.TotalLatency,
    86  		maxLatency:           stmtInterDircInfo1.TotalLatency,
    87  		minLatency:           stmtInterDircInfo1.TotalLatency,
    88  		sumParseLatency:      stmtInterDircInfo1.ParseLatency,
    89  		maxParseLatency:      stmtInterDircInfo1.ParseLatency,
    90  		sumCompileLatency:    stmtInterDircInfo1.CompileLatency,
    91  		maxCompileLatency:    stmtInterDircInfo1.CompileLatency,
    92  		sumNumCausetTasks:    int64(stmtInterDircInfo1.CausetTasks.NumCausetTasks),
    93  		maxCopProcessTime:    stmtInterDircInfo1.CausetTasks.MaxProcessTime,
    94  		maxCopProcessAddress: stmtInterDircInfo1.CausetTasks.MaxProcessAddress,
    95  		maxCopWaitTime:       stmtInterDircInfo1.CausetTasks.MaxWaitTime,
    96  		maxCopWaitAddress:    stmtInterDircInfo1.CausetTasks.MaxWaitAddress,
    97  		sumProcessTime:       stmtInterDircInfo1.InterDircDetail.ProcessTime,
    98  		maxProcessTime:       stmtInterDircInfo1.InterDircDetail.ProcessTime,
    99  		sumWaitTime:          stmtInterDircInfo1.InterDircDetail.WaitTime,
   100  		maxWaitTime:          stmtInterDircInfo1.InterDircDetail.WaitTime,
   101  		sumBackoffTime:       stmtInterDircInfo1.InterDircDetail.BackoffTime,
   102  		maxBackoffTime:       stmtInterDircInfo1.InterDircDetail.BackoffTime,
   103  		sumTotalKeys:         stmtInterDircInfo1.InterDircDetail.TotalKeys,
   104  		maxTotalKeys:         stmtInterDircInfo1.InterDircDetail.TotalKeys,
   105  		sumProcessedKeys:     stmtInterDircInfo1.InterDircDetail.ProcessedKeys,
   106  		maxProcessedKeys:     stmtInterDircInfo1.InterDircDetail.ProcessedKeys,
   107  		sumGetCommitTsTime:   stmtInterDircInfo1.InterDircDetail.CommitDetail.GetCommitTsTime,
   108  		maxGetCommitTsTime:   stmtInterDircInfo1.InterDircDetail.CommitDetail.GetCommitTsTime,
   109  		sumPrewriteTime:      stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteTime,
   110  		maxPrewriteTime:      stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteTime,
   111  		sumCommitTime:        stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitTime,
   112  		maxCommitTime:        stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitTime,
   113  		sumLocalLatchTime:    stmtInterDircInfo1.InterDircDetail.CommitDetail.LocalLatchTime,
   114  		maxLocalLatchTime:    stmtInterDircInfo1.InterDircDetail.CommitDetail.LocalLatchTime,
   115  		sumCommitBackoffTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitBackoffTime,
   116  		maxCommitBackoffTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitBackoffTime,
   117  		sumResolveLockTime:   stmtInterDircInfo1.InterDircDetail.CommitDetail.ResolveLockTime,
   118  		maxResolveLockTime:   stmtInterDircInfo1.InterDircDetail.CommitDetail.ResolveLockTime,
   119  		sumWriteKeys:         int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteKeys),
   120  		maxWriteKeys:         stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteKeys,
   121  		sumWriteSize:         int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteSize),
   122  		maxWriteSize:         stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteSize,
   123  		sumPrewriteRegionNum: int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteRegionNum),
   124  		maxPrewriteRegionNum: stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteRegionNum,
   125  		sumTxnRetry:          int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.TxnRetry),
   126  		maxTxnRetry:          stmtInterDircInfo1.InterDircDetail.CommitDetail.TxnRetry,
   127  		backoffTypes:         make(map[fmt.Stringer]int),
   128  		sumMem:               stmtInterDircInfo1.MemMax,
   129  		maxMem:               stmtInterDircInfo1.MemMax,
   130  		sumDisk:              stmtInterDircInfo1.DiskMax,
   131  		maxDisk:              stmtInterDircInfo1.DiskMax,
   132  		sumAffectedRows:      stmtInterDircInfo1.StmtCtx.AffectedRows(),
   133  		firstSeen:            stmtInterDircInfo1.StartTime,
   134  		lastSeen:             stmtInterDircInfo1.StartTime,
   135  	}
   136  	history := list.New()
   137  	history.PushBack(&expectedSummaryElement)
   138  	expectedSummary := stmtSummaryByDigest{
   139  		schemaName:    stmtInterDircInfo1.SchemaName,
   140  		stmtType:      stmtInterDircInfo1.StmtCtx.StmtType,
   141  		digest:        stmtInterDircInfo1.Digest,
   142  		normalizedALLEGROSQL: stmtInterDircInfo1.NormalizedALLEGROSQL,
   143  		planDigest:    stmtInterDircInfo1.CausetDigest,
   144  		blockNames:    "db1.tb1,db2.tb2",
   145  		history:       history,
   146  	}
   147  	s.ssMap.AddStatement(stmtInterDircInfo1)
   148  	summary, ok := s.ssMap.summaryMap.Get(key)
   149  	c.Assert(ok, IsTrue)
   150  	c.Assert(matchStmtSummaryByDigest(summary.(*stmtSummaryByDigest), &expectedSummary), IsTrue)
   151  
   152  	// Second memex is similar with the first memex, and its values are
   153  	// greater than that of the first memex.
   154  	stmtInterDircInfo2 := &StmtInterDircInfo{
   155  		SchemaName:     "schema_name",
   156  		OriginalALLEGROSQL:    "original_sql2",
   157  		NormalizedALLEGROSQL:  "normalized_sql",
   158  		Digest:         "digest",
   159  		CausetDigest:     "plan_digest",
   160  		CausetGenerator:  emptyCausetGenerator,
   161  		User:           "user2",
   162  		TotalLatency:   20000,
   163  		ParseLatency:   200,
   164  		CompileLatency: 2000,
   165  		CausetTasks: &stmtctx.CausetTasksDetails{
   166  			NumCausetTasks:    20,
   167  			AvgProcessTime:    2000,
   168  			P90ProcessTime:    20000,
   169  			MaxProcessAddress: "200",
   170  			MaxProcessTime:    25000,
   171  			AvgWaitTime:       200,
   172  			P90WaitTime:       2000,
   173  			MaxWaitAddress:    "201",
   174  			MaxWaitTime:       2500,
   175  		},
   176  		InterDircDetail: &execdetails.InterDircDetails{
   177  			CalleeAddress: "202",
   178  			ProcessTime:   1500,
   179  			WaitTime:      150,
   180  			BackoffTime:   180,
   181  			RequestCount:  20,
   182  			TotalKeys:     6000,
   183  			ProcessedKeys: 1500,
   184  			CommitDetail: &execdetails.CommitDetails{
   185  				GetCommitTsTime:   500,
   186  				PrewriteTime:      50000,
   187  				CommitTime:        5000,
   188  				LocalLatchTime:    50,
   189  				CommitBackoffTime: 1000,
   190  				Mu: struct {
   191  					sync.Mutex
   192  					BackoffTypes []fmt.Stringer
   193  				}{
   194  					BackoffTypes: []fmt.Stringer{einsteindb.BoTxnLock},
   195  				},
   196  				ResolveLockTime:   10000,
   197  				WriteKeys:         100000,
   198  				WriteSize:         1000000,
   199  				PrewriteRegionNum: 100,
   200  				TxnRetry:          10,
   201  			},
   202  		},
   203  		StmtCtx: &stmtctx.StatementContext{
   204  			StmtType:   "Select",
   205  			Blocks:     blocks,
   206  			IndexNames: indexes,
   207  		},
   208  		MemMax:    20000,
   209  		DiskMax:   20000,
   210  		StartTime: time.Date(2020, 1, 1, 10, 10, 20, 10, time.UTC),
   211  		Succeed:   true,
   212  	}
   213  	stmtInterDircInfo2.StmtCtx.AddAffectedRows(200)
   214  	expectedSummaryElement.execCount++
   215  	expectedSummaryElement.sumLatency += stmtInterDircInfo2.TotalLatency
   216  	expectedSummaryElement.maxLatency = stmtInterDircInfo2.TotalLatency
   217  	expectedSummaryElement.sumParseLatency += stmtInterDircInfo2.ParseLatency
   218  	expectedSummaryElement.maxParseLatency = stmtInterDircInfo2.ParseLatency
   219  	expectedSummaryElement.sumCompileLatency += stmtInterDircInfo2.CompileLatency
   220  	expectedSummaryElement.maxCompileLatency = stmtInterDircInfo2.CompileLatency
   221  	expectedSummaryElement.sumNumCausetTasks += int64(stmtInterDircInfo2.CausetTasks.NumCausetTasks)
   222  	expectedSummaryElement.maxCopProcessTime = stmtInterDircInfo2.CausetTasks.MaxProcessTime
   223  	expectedSummaryElement.maxCopProcessAddress = stmtInterDircInfo2.CausetTasks.MaxProcessAddress
   224  	expectedSummaryElement.maxCopWaitTime = stmtInterDircInfo2.CausetTasks.MaxWaitTime
   225  	expectedSummaryElement.maxCopWaitAddress = stmtInterDircInfo2.CausetTasks.MaxWaitAddress
   226  	expectedSummaryElement.sumProcessTime += stmtInterDircInfo2.InterDircDetail.ProcessTime
   227  	expectedSummaryElement.maxProcessTime = stmtInterDircInfo2.InterDircDetail.ProcessTime
   228  	expectedSummaryElement.sumWaitTime += stmtInterDircInfo2.InterDircDetail.WaitTime
   229  	expectedSummaryElement.maxWaitTime = stmtInterDircInfo2.InterDircDetail.WaitTime
   230  	expectedSummaryElement.sumBackoffTime += stmtInterDircInfo2.InterDircDetail.BackoffTime
   231  	expectedSummaryElement.maxBackoffTime = stmtInterDircInfo2.InterDircDetail.BackoffTime
   232  	expectedSummaryElement.sumTotalKeys += stmtInterDircInfo2.InterDircDetail.TotalKeys
   233  	expectedSummaryElement.maxTotalKeys = stmtInterDircInfo2.InterDircDetail.TotalKeys
   234  	expectedSummaryElement.sumProcessedKeys += stmtInterDircInfo2.InterDircDetail.ProcessedKeys
   235  	expectedSummaryElement.maxProcessedKeys = stmtInterDircInfo2.InterDircDetail.ProcessedKeys
   236  	expectedSummaryElement.sumGetCommitTsTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.GetCommitTsTime
   237  	expectedSummaryElement.maxGetCommitTsTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.GetCommitTsTime
   238  	expectedSummaryElement.sumPrewriteTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.PrewriteTime
   239  	expectedSummaryElement.maxPrewriteTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.PrewriteTime
   240  	expectedSummaryElement.sumCommitTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.CommitTime
   241  	expectedSummaryElement.maxCommitTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.CommitTime
   242  	expectedSummaryElement.sumLocalLatchTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.LocalLatchTime
   243  	expectedSummaryElement.maxLocalLatchTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.LocalLatchTime
   244  	expectedSummaryElement.sumCommitBackoffTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.CommitBackoffTime
   245  	expectedSummaryElement.maxCommitBackoffTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.CommitBackoffTime
   246  	expectedSummaryElement.sumResolveLockTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.ResolveLockTime
   247  	expectedSummaryElement.maxResolveLockTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.ResolveLockTime
   248  	expectedSummaryElement.sumWriteKeys += int64(stmtInterDircInfo2.InterDircDetail.CommitDetail.WriteKeys)
   249  	expectedSummaryElement.maxWriteKeys = stmtInterDircInfo2.InterDircDetail.CommitDetail.WriteKeys
   250  	expectedSummaryElement.sumWriteSize += int64(stmtInterDircInfo2.InterDircDetail.CommitDetail.WriteSize)
   251  	expectedSummaryElement.maxWriteSize = stmtInterDircInfo2.InterDircDetail.CommitDetail.WriteSize
   252  	expectedSummaryElement.sumPrewriteRegionNum += int64(stmtInterDircInfo2.InterDircDetail.CommitDetail.PrewriteRegionNum)
   253  	expectedSummaryElement.maxPrewriteRegionNum = stmtInterDircInfo2.InterDircDetail.CommitDetail.PrewriteRegionNum
   254  	expectedSummaryElement.sumTxnRetry += int64(stmtInterDircInfo2.InterDircDetail.CommitDetail.TxnRetry)
   255  	expectedSummaryElement.maxTxnRetry = stmtInterDircInfo2.InterDircDetail.CommitDetail.TxnRetry
   256  	expectedSummaryElement.sumBackoffTimes += 1
   257  	expectedSummaryElement.backoffTypes[einsteindb.BoTxnLock] = 1
   258  	expectedSummaryElement.sumMem += stmtInterDircInfo2.MemMax
   259  	expectedSummaryElement.maxMem = stmtInterDircInfo2.MemMax
   260  	expectedSummaryElement.sumDisk += stmtInterDircInfo2.DiskMax
   261  	expectedSummaryElement.maxDisk = stmtInterDircInfo2.DiskMax
   262  	expectedSummaryElement.sumAffectedRows += stmtInterDircInfo2.StmtCtx.AffectedRows()
   263  	expectedSummaryElement.lastSeen = stmtInterDircInfo2.StartTime
   264  
   265  	s.ssMap.AddStatement(stmtInterDircInfo2)
   266  	summary, ok = s.ssMap.summaryMap.Get(key)
   267  	c.Assert(ok, IsTrue)
   268  	c.Assert(matchStmtSummaryByDigest(summary.(*stmtSummaryByDigest), &expectedSummary), IsTrue)
   269  
   270  	// Third memex is similar with the first memex, and its values are
   271  	// less than that of the first memex.
   272  	stmtInterDircInfo3 := &StmtInterDircInfo{
   273  		SchemaName:     "schema_name",
   274  		OriginalALLEGROSQL:    "original_sql3",
   275  		NormalizedALLEGROSQL:  "normalized_sql",
   276  		Digest:         "digest",
   277  		CausetDigest:     "plan_digest",
   278  		CausetGenerator:  emptyCausetGenerator,
   279  		User:           "user3",
   280  		TotalLatency:   1000,
   281  		ParseLatency:   50,
   282  		CompileLatency: 500,
   283  		CausetTasks: &stmtctx.CausetTasksDetails{
   284  			NumCausetTasks:    2,
   285  			AvgProcessTime:    100,
   286  			P90ProcessTime:    300,
   287  			MaxProcessAddress: "300",
   288  			MaxProcessTime:    350,
   289  			AvgWaitTime:       20,
   290  			P90WaitTime:       200,
   291  			MaxWaitAddress:    "301",
   292  			MaxWaitTime:       250,
   293  		},
   294  		InterDircDetail: &execdetails.InterDircDetails{
   295  			CalleeAddress: "302",
   296  			ProcessTime:   150,
   297  			WaitTime:      15,
   298  			BackoffTime:   18,
   299  			RequestCount:  2,
   300  			TotalKeys:     600,
   301  			ProcessedKeys: 150,
   302  			CommitDetail: &execdetails.CommitDetails{
   303  				GetCommitTsTime:   50,
   304  				PrewriteTime:      5000,
   305  				CommitTime:        500,
   306  				LocalLatchTime:    5,
   307  				CommitBackoffTime: 100,
   308  				Mu: struct {
   309  					sync.Mutex
   310  					BackoffTypes []fmt.Stringer
   311  				}{
   312  					BackoffTypes: []fmt.Stringer{einsteindb.BoTxnLock},
   313  				},
   314  				ResolveLockTime:   1000,
   315  				WriteKeys:         10000,
   316  				WriteSize:         100000,
   317  				PrewriteRegionNum: 10,
   318  				TxnRetry:          1,
   319  			},
   320  		},
   321  		StmtCtx: &stmtctx.StatementContext{
   322  			StmtType:   "Select",
   323  			Blocks:     blocks,
   324  			IndexNames: indexes,
   325  		},
   326  		MemMax:    200,
   327  		DiskMax:   200,
   328  		StartTime: time.Date(2020, 1, 1, 10, 10, 0, 10, time.UTC),
   329  		Succeed:   true,
   330  	}
   331  	stmtInterDircInfo3.StmtCtx.AddAffectedRows(20000)
   332  	expectedSummaryElement.execCount++
   333  	expectedSummaryElement.sumLatency += stmtInterDircInfo3.TotalLatency
   334  	expectedSummaryElement.minLatency = stmtInterDircInfo3.TotalLatency
   335  	expectedSummaryElement.sumParseLatency += stmtInterDircInfo3.ParseLatency
   336  	expectedSummaryElement.sumCompileLatency += stmtInterDircInfo3.CompileLatency
   337  	expectedSummaryElement.sumNumCausetTasks += int64(stmtInterDircInfo3.CausetTasks.NumCausetTasks)
   338  	expectedSummaryElement.sumProcessTime += stmtInterDircInfo3.InterDircDetail.ProcessTime
   339  	expectedSummaryElement.sumWaitTime += stmtInterDircInfo3.InterDircDetail.WaitTime
   340  	expectedSummaryElement.sumBackoffTime += stmtInterDircInfo3.InterDircDetail.BackoffTime
   341  	expectedSummaryElement.sumTotalKeys += stmtInterDircInfo3.InterDircDetail.TotalKeys
   342  	expectedSummaryElement.sumProcessedKeys += stmtInterDircInfo3.InterDircDetail.ProcessedKeys
   343  	expectedSummaryElement.sumGetCommitTsTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.GetCommitTsTime
   344  	expectedSummaryElement.sumPrewriteTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.PrewriteTime
   345  	expectedSummaryElement.sumCommitTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.CommitTime
   346  	expectedSummaryElement.sumLocalLatchTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.LocalLatchTime
   347  	expectedSummaryElement.sumCommitBackoffTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.CommitBackoffTime
   348  	expectedSummaryElement.sumResolveLockTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.ResolveLockTime
   349  	expectedSummaryElement.sumWriteKeys += int64(stmtInterDircInfo3.InterDircDetail.CommitDetail.WriteKeys)
   350  	expectedSummaryElement.sumWriteSize += int64(stmtInterDircInfo3.InterDircDetail.CommitDetail.WriteSize)
   351  	expectedSummaryElement.sumPrewriteRegionNum += int64(stmtInterDircInfo3.InterDircDetail.CommitDetail.PrewriteRegionNum)
   352  	expectedSummaryElement.sumTxnRetry += int64(stmtInterDircInfo3.InterDircDetail.CommitDetail.TxnRetry)
   353  	expectedSummaryElement.sumBackoffTimes += 1
   354  	expectedSummaryElement.backoffTypes[einsteindb.BoTxnLock] = 2
   355  	expectedSummaryElement.sumMem += stmtInterDircInfo3.MemMax
   356  	expectedSummaryElement.sumDisk += stmtInterDircInfo3.DiskMax
   357  	expectedSummaryElement.sumAffectedRows += stmtInterDircInfo3.StmtCtx.AffectedRows()
   358  	expectedSummaryElement.firstSeen = stmtInterDircInfo3.StartTime
   359  
   360  	s.ssMap.AddStatement(stmtInterDircInfo3)
   361  	summary, ok = s.ssMap.summaryMap.Get(key)
   362  	c.Assert(ok, IsTrue)
   363  	c.Assert(matchStmtSummaryByDigest(summary.(*stmtSummaryByDigest), &expectedSummary), IsTrue)
   364  
   365  	// Fourth memex is in a different schemaReplicant.
   366  	stmtInterDircInfo4 := stmtInterDircInfo1
   367  	stmtInterDircInfo4.SchemaName = "schema2"
   368  	stmtInterDircInfo4.InterDircDetail.CommitDetail = nil
   369  	key = &stmtSummaryByDigestKey{
   370  		schemaName: stmtInterDircInfo4.SchemaName,
   371  		digest:     stmtInterDircInfo4.Digest,
   372  		planDigest: stmtInterDircInfo4.CausetDigest,
   373  	}
   374  	s.ssMap.AddStatement(stmtInterDircInfo4)
   375  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 2)
   376  	_, ok = s.ssMap.summaryMap.Get(key)
   377  	c.Assert(ok, IsTrue)
   378  
   379  	// Fifth memex has a different digest.
   380  	stmtInterDircInfo5 := stmtInterDircInfo1
   381  	stmtInterDircInfo5.Digest = "digest2"
   382  	key = &stmtSummaryByDigestKey{
   383  		schemaName: stmtInterDircInfo5.SchemaName,
   384  		digest:     stmtInterDircInfo5.Digest,
   385  		planDigest: stmtInterDircInfo4.CausetDigest,
   386  	}
   387  	s.ssMap.AddStatement(stmtInterDircInfo5)
   388  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 3)
   389  	_, ok = s.ssMap.summaryMap.Get(key)
   390  	c.Assert(ok, IsTrue)
   391  
   392  	// Sixth memex has a different plan digest.
   393  	stmtInterDircInfo6 := stmtInterDircInfo1
   394  	stmtInterDircInfo6.CausetDigest = "plan_digest2"
   395  	key = &stmtSummaryByDigestKey{
   396  		schemaName: stmtInterDircInfo6.SchemaName,
   397  		digest:     stmtInterDircInfo6.Digest,
   398  		planDigest: stmtInterDircInfo6.CausetDigest,
   399  	}
   400  	s.ssMap.AddStatement(stmtInterDircInfo6)
   401  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 4)
   402  	_, ok = s.ssMap.summaryMap.Get(key)
   403  	c.Assert(ok, IsTrue)
   404  }
   405  
   406  func matchStmtSummaryByDigest(first, second *stmtSummaryByDigest) bool {
   407  	if first.schemaName != second.schemaName ||
   408  		first.digest != second.digest ||
   409  		first.normalizedALLEGROSQL != second.normalizedALLEGROSQL ||
   410  		first.planDigest != second.planDigest ||
   411  		first.blockNames != second.blockNames ||
   412  		!strings.EqualFold(first.stmtType, second.stmtType) {
   413  		return false
   414  	}
   415  	if first.history.Len() != second.history.Len() {
   416  		return false
   417  	}
   418  	ele1 := first.history.Front()
   419  	ele2 := second.history.Front()
   420  	for {
   421  		if ele1 == nil {
   422  			break
   423  		}
   424  		ssElement1 := ele1.Value.(*stmtSummaryByDigestElement)
   425  		ssElement2 := ele2.Value.(*stmtSummaryByDigestElement)
   426  		if ssElement1.beginTime != ssElement2.beginTime ||
   427  			ssElement1.endTime != ssElement2.endTime ||
   428  			ssElement1.sampleALLEGROSQL != ssElement2.sampleALLEGROSQL ||
   429  			ssElement1.sampleCauset != ssElement2.sampleCauset ||
   430  			ssElement1.prevALLEGROSQL != ssElement2.prevALLEGROSQL ||
   431  			ssElement1.execCount != ssElement2.execCount ||
   432  			ssElement1.sumErrors != ssElement2.sumErrors ||
   433  			ssElement1.sumWarnings != ssElement2.sumWarnings ||
   434  			ssElement1.sumLatency != ssElement2.sumLatency ||
   435  			ssElement1.maxLatency != ssElement2.maxLatency ||
   436  			ssElement1.minLatency != ssElement2.minLatency ||
   437  			ssElement1.sumParseLatency != ssElement2.sumParseLatency ||
   438  			ssElement1.maxParseLatency != ssElement2.maxParseLatency ||
   439  			ssElement1.sumCompileLatency != ssElement2.sumCompileLatency ||
   440  			ssElement1.maxCompileLatency != ssElement2.maxCompileLatency ||
   441  			ssElement1.sumNumCausetTasks != ssElement2.sumNumCausetTasks ||
   442  			ssElement1.maxCopProcessTime != ssElement2.maxCopProcessTime ||
   443  			ssElement1.maxCopProcessAddress != ssElement2.maxCopProcessAddress ||
   444  			ssElement1.maxCopWaitTime != ssElement2.maxCopWaitTime ||
   445  			ssElement1.maxCopWaitAddress != ssElement2.maxCopWaitAddress ||
   446  			ssElement1.sumProcessTime != ssElement2.sumProcessTime ||
   447  			ssElement1.maxProcessTime != ssElement2.maxProcessTime ||
   448  			ssElement1.sumWaitTime != ssElement2.sumWaitTime ||
   449  			ssElement1.maxWaitTime != ssElement2.maxWaitTime ||
   450  			ssElement1.sumBackoffTime != ssElement2.sumBackoffTime ||
   451  			ssElement1.maxBackoffTime != ssElement2.maxBackoffTime ||
   452  			ssElement1.sumTotalKeys != ssElement2.sumTotalKeys ||
   453  			ssElement1.maxTotalKeys != ssElement2.maxTotalKeys ||
   454  			ssElement1.sumProcessedKeys != ssElement2.sumProcessedKeys ||
   455  			ssElement1.maxProcessedKeys != ssElement2.maxProcessedKeys ||
   456  			ssElement1.sumGetCommitTsTime != ssElement2.sumGetCommitTsTime ||
   457  			ssElement1.maxGetCommitTsTime != ssElement2.maxGetCommitTsTime ||
   458  			ssElement1.sumPrewriteTime != ssElement2.sumPrewriteTime ||
   459  			ssElement1.maxPrewriteTime != ssElement2.maxPrewriteTime ||
   460  			ssElement1.sumCommitTime != ssElement2.sumCommitTime ||
   461  			ssElement1.maxCommitTime != ssElement2.maxCommitTime ||
   462  			ssElement1.sumLocalLatchTime != ssElement2.sumLocalLatchTime ||
   463  			ssElement1.maxLocalLatchTime != ssElement2.maxLocalLatchTime ||
   464  			ssElement1.sumCommitBackoffTime != ssElement2.sumCommitBackoffTime ||
   465  			ssElement1.maxCommitBackoffTime != ssElement2.maxCommitBackoffTime ||
   466  			ssElement1.sumResolveLockTime != ssElement2.sumResolveLockTime ||
   467  			ssElement1.maxResolveLockTime != ssElement2.maxResolveLockTime ||
   468  			ssElement1.sumWriteKeys != ssElement2.sumWriteKeys ||
   469  			ssElement1.maxWriteKeys != ssElement2.maxWriteKeys ||
   470  			ssElement1.sumWriteSize != ssElement2.sumWriteSize ||
   471  			ssElement1.maxWriteSize != ssElement2.maxWriteSize ||
   472  			ssElement1.sumPrewriteRegionNum != ssElement2.sumPrewriteRegionNum ||
   473  			ssElement1.maxPrewriteRegionNum != ssElement2.maxPrewriteRegionNum ||
   474  			ssElement1.sumTxnRetry != ssElement2.sumTxnRetry ||
   475  			ssElement1.maxTxnRetry != ssElement2.maxTxnRetry ||
   476  			ssElement1.sumBackoffTimes != ssElement2.sumBackoffTimes ||
   477  			ssElement1.sumMem != ssElement2.sumMem ||
   478  			ssElement1.maxMem != ssElement2.maxMem ||
   479  			ssElement1.sumAffectedRows != ssElement2.sumAffectedRows ||
   480  			ssElement1.firstSeen != ssElement2.firstSeen ||
   481  			ssElement1.lastSeen != ssElement2.lastSeen {
   482  			return false
   483  		}
   484  		if len(ssElement1.backoffTypes) != len(ssElement2.backoffTypes) {
   485  			return false
   486  		}
   487  		for key, value1 := range ssElement1.backoffTypes {
   488  			value2, ok := ssElement2.backoffTypes[key]
   489  			if !ok || value1 != value2 {
   490  				return false
   491  			}
   492  		}
   493  		if len(ssElement1.indexNames) != len(ssElement2.indexNames) {
   494  			return false
   495  		}
   496  		for key, value1 := range ssElement1.indexNames {
   497  			if value1 != ssElement2.indexNames[key] {
   498  				return false
   499  			}
   500  		}
   501  		ele1 = ele1.Next()
   502  		ele2 = ele2.Next()
   503  	}
   504  	return true
   505  }
   506  
   507  func match(c *C, event []types.Causet, expected ...interface{}) {
   508  	c.Assert(len(event), Equals, len(expected))
   509  	for i := range event {
   510  		got := fmt.Sprintf("%v", event[i].GetValue())
   511  		need := fmt.Sprintf("%v", expected[i])
   512  		c.Assert(got, Equals, need)
   513  	}
   514  }
   515  
   516  func generateAnyInterDircInfo() *StmtInterDircInfo {
   517  	blocks := []stmtctx.BlockEntry{{EDB: "db1", Block: "tb1"}, {EDB: "db2", Block: "tb2"}}
   518  	indexes := []string{"a"}
   519  	stmtInterDircInfo := &StmtInterDircInfo{
   520  		SchemaName:     "schema_name",
   521  		OriginalALLEGROSQL:    "original_sql1",
   522  		NormalizedALLEGROSQL:  "normalized_sql",
   523  		Digest:         "digest",
   524  		CausetDigest:     "plan_digest",
   525  		CausetGenerator:  emptyCausetGenerator,
   526  		User:           "user",
   527  		TotalLatency:   10000,
   528  		ParseLatency:   100,
   529  		CompileLatency: 1000,
   530  		CausetTasks: &stmtctx.CausetTasksDetails{
   531  			NumCausetTasks:    10,
   532  			AvgProcessTime:    1000,
   533  			P90ProcessTime:    10000,
   534  			MaxProcessAddress: "127",
   535  			MaxProcessTime:    15000,
   536  			AvgWaitTime:       100,
   537  			P90WaitTime:       1000,
   538  			MaxWaitAddress:    "128",
   539  			MaxWaitTime:       1500,
   540  		},
   541  		InterDircDetail: &execdetails.InterDircDetails{
   542  			CalleeAddress: "129",
   543  			ProcessTime:   500,
   544  			WaitTime:      50,
   545  			BackoffTime:   80,
   546  			RequestCount:  10,
   547  			TotalKeys:     1000,
   548  			ProcessedKeys: 500,
   549  			CommitDetail: &execdetails.CommitDetails{
   550  				GetCommitTsTime:   100,
   551  				PrewriteTime:      10000,
   552  				CommitTime:        1000,
   553  				LocalLatchTime:    10,
   554  				CommitBackoffTime: 200,
   555  				Mu: struct {
   556  					sync.Mutex
   557  					BackoffTypes []fmt.Stringer
   558  				}{
   559  					BackoffTypes: []fmt.Stringer{einsteindb.BoTxnLock},
   560  				},
   561  				ResolveLockTime:   2000,
   562  				WriteKeys:         20000,
   563  				WriteSize:         200000,
   564  				PrewriteRegionNum: 20,
   565  				TxnRetry:          2,
   566  			},
   567  		},
   568  		StmtCtx: &stmtctx.StatementContext{
   569  			StmtType:   "Select",
   570  			Blocks:     blocks,
   571  			IndexNames: indexes,
   572  		},
   573  		MemMax:    10000,
   574  		DiskMax:   10000,
   575  		StartTime: time.Date(2020, 1, 1, 10, 10, 10, 10, time.UTC),
   576  		Succeed:   true,
   577  	}
   578  	stmtInterDircInfo.StmtCtx.AddAffectedRows(10000)
   579  	return stmtInterDircInfo
   580  }
   581  
   582  // Test stmtSummaryByDigest.ToCauset.
   583  func (s *testStmtSummarySuite) TestToCauset(c *C) {
   584  	s.ssMap.Clear()
   585  	now := time.Now().Unix()
   586  	// to disable expiration
   587  	s.ssMap.beginTimeForCurInterval = now + 60
   588  
   589  	stmtInterDircInfo1 := generateAnyInterDircInfo()
   590  	s.ssMap.AddStatement(stmtInterDircInfo1)
   591  	datums := s.ssMap.ToCurrentCauset(nil, true)
   592  	c.Assert(len(datums), Equals, 1)
   593  	n := types.NewTime(types.FromGoTime(time.Unix(s.ssMap.beginTimeForCurInterval, 0)), allegrosql.TypeTimestamp, types.DefaultFsp)
   594  	e := types.NewTime(types.FromGoTime(time.Unix(s.ssMap.beginTimeForCurInterval+1800, 0)), allegrosql.TypeTimestamp, types.DefaultFsp)
   595  	t := types.NewTime(types.FromGoTime(stmtInterDircInfo1.StartTime), allegrosql.TypeTimestamp, types.DefaultFsp)
   596  	expectedCauset := []interface{}{n, e, "Select", stmtInterDircInfo1.SchemaName, stmtInterDircInfo1.Digest, stmtInterDircInfo1.NormalizedALLEGROSQL,
   597  		"db1.tb1,db2.tb2", "a", stmtInterDircInfo1.User, 1, 0, 0, int64(stmtInterDircInfo1.TotalLatency),
   598  		int64(stmtInterDircInfo1.TotalLatency), int64(stmtInterDircInfo1.TotalLatency), int64(stmtInterDircInfo1.TotalLatency),
   599  		int64(stmtInterDircInfo1.ParseLatency), int64(stmtInterDircInfo1.ParseLatency), int64(stmtInterDircInfo1.CompileLatency),
   600  		int64(stmtInterDircInfo1.CompileLatency), stmtInterDircInfo1.CausetTasks.NumCausetTasks, int64(stmtInterDircInfo1.CausetTasks.MaxProcessTime),
   601  		stmtInterDircInfo1.CausetTasks.MaxProcessAddress, int64(stmtInterDircInfo1.CausetTasks.MaxWaitTime),
   602  		stmtInterDircInfo1.CausetTasks.MaxWaitAddress, int64(stmtInterDircInfo1.InterDircDetail.ProcessTime), int64(stmtInterDircInfo1.InterDircDetail.ProcessTime),
   603  		int64(stmtInterDircInfo1.InterDircDetail.WaitTime), int64(stmtInterDircInfo1.InterDircDetail.WaitTime), int64(stmtInterDircInfo1.InterDircDetail.BackoffTime),
   604  		int64(stmtInterDircInfo1.InterDircDetail.BackoffTime), stmtInterDircInfo1.InterDircDetail.TotalKeys, stmtInterDircInfo1.InterDircDetail.TotalKeys,
   605  		stmtInterDircInfo1.InterDircDetail.ProcessedKeys, stmtInterDircInfo1.InterDircDetail.ProcessedKeys,
   606  		int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteTime), int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteTime),
   607  		int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitTime), int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitTime),
   608  		int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.GetCommitTsTime), int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.GetCommitTsTime),
   609  		stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitBackoffTime, stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitBackoffTime,
   610  		stmtInterDircInfo1.InterDircDetail.CommitDetail.ResolveLockTime, stmtInterDircInfo1.InterDircDetail.CommitDetail.ResolveLockTime,
   611  		int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.LocalLatchTime), int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.LocalLatchTime),
   612  		stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteKeys, stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteKeys,
   613  		stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteSize, stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteSize,
   614  		stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteRegionNum, stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteRegionNum,
   615  		stmtInterDircInfo1.InterDircDetail.CommitDetail.TxnRetry, stmtInterDircInfo1.InterDircDetail.CommitDetail.TxnRetry, 0, 0, 1,
   616  		"txnLock:1", stmtInterDircInfo1.MemMax, stmtInterDircInfo1.MemMax, stmtInterDircInfo1.DiskMax, stmtInterDircInfo1.DiskMax, stmtInterDircInfo1.StmtCtx.AffectedRows(),
   617  		t, t, 0, 0, stmtInterDircInfo1.OriginalALLEGROSQL, stmtInterDircInfo1.PrevALLEGROSQL, "plan_digest", ""}
   618  	match(c, datums[0], expectedCauset...)
   619  	datums = s.ssMap.ToHistoryCauset(nil, true)
   620  	c.Assert(len(datums), Equals, 1)
   621  	match(c, datums[0], expectedCauset...)
   622  }
   623  
   624  // Test AddStatement and ToCauset parallel.
   625  func (s *testStmtSummarySuite) TestAddStatementParallel(c *C) {
   626  	s.ssMap.Clear()
   627  	now := time.Now().Unix()
   628  	// to disable expiration
   629  	s.ssMap.beginTimeForCurInterval = now + 60
   630  
   631  	threads := 8
   632  	loops := 32
   633  	wg := sync.WaitGroup{}
   634  	wg.Add(threads)
   635  
   636  	addStmtFunc := func() {
   637  		defer wg.Done()
   638  		stmtInterDircInfo1 := generateAnyInterDircInfo()
   639  
   640  		// Add 32 times with different digest.
   641  		for i := 0; i < loops; i++ {
   642  			stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i)
   643  			s.ssMap.AddStatement(stmtInterDircInfo1)
   644  		}
   645  
   646  		// There would be 32 summaries.
   647  		datums := s.ssMap.ToCurrentCauset(nil, true)
   648  		c.Assert(len(datums), Equals, loops)
   649  	}
   650  
   651  	for i := 0; i < threads; i++ {
   652  		go addStmtFunc()
   653  	}
   654  	wg.Wait()
   655  
   656  	datums := s.ssMap.ToCurrentCauset(nil, true)
   657  	c.Assert(len(datums), Equals, loops)
   658  }
   659  
   660  // Test max number of memex count.
   661  func (s *testStmtSummarySuite) TestMaxStmtCount(c *C) {
   662  	s.ssMap.Clear()
   663  	now := time.Now().Unix()
   664  	// to disable expiration
   665  	s.ssMap.beginTimeForCurInterval = now + 60
   666  
   667  	// Test the original value and modify it.
   668  	maxStmtCount := s.ssMap.maxStmtCount()
   669  	c.Assert(maxStmtCount, Equals, int(config.GetGlobalConfig().StmtSummary.MaxStmtCount))
   670  	c.Assert(s.ssMap.SetMaxStmtCount("10", false), IsNil)
   671  	c.Assert(s.ssMap.maxStmtCount(), Equals, 10)
   672  	defer func() {
   673  		c.Assert(s.ssMap.SetMaxStmtCount("", false), IsNil)
   674  		c.Assert(s.ssMap.SetMaxStmtCount("", true), IsNil)
   675  		c.Assert(maxStmtCount, Equals, int(config.GetGlobalConfig().StmtSummary.MaxStmtCount))
   676  	}()
   677  
   678  	// 100 digests
   679  	stmtInterDircInfo1 := generateAnyInterDircInfo()
   680  	loops := 100
   681  	for i := 0; i < loops; i++ {
   682  		stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i)
   683  		s.ssMap.AddStatement(stmtInterDircInfo1)
   684  	}
   685  
   686  	// Summary count should be MaxStmtCount.
   687  	sm := s.ssMap.summaryMap
   688  	c.Assert(sm.Size(), Equals, 10)
   689  
   690  	// LRU cache should work.
   691  	for i := loops - 10; i < loops; i++ {
   692  		key := &stmtSummaryByDigestKey{
   693  			schemaName: stmtInterDircInfo1.SchemaName,
   694  			digest:     fmt.Sprintf("digest%d", i),
   695  			planDigest: stmtInterDircInfo1.CausetDigest,
   696  		}
   697  		_, ok := sm.Get(key)
   698  		c.Assert(ok, IsTrue)
   699  	}
   700  
   701  	// Change to a bigger value.
   702  	c.Assert(s.ssMap.SetMaxStmtCount("50", true), IsNil)
   703  	for i := 0; i < loops; i++ {
   704  		stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i)
   705  		s.ssMap.AddStatement(stmtInterDircInfo1)
   706  	}
   707  	c.Assert(sm.Size(), Equals, 50)
   708  
   709  	// Change to a smaller value.
   710  	c.Assert(s.ssMap.SetMaxStmtCount("10", true), IsNil)
   711  	for i := 0; i < loops; i++ {
   712  		stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i)
   713  		s.ssMap.AddStatement(stmtInterDircInfo1)
   714  	}
   715  	c.Assert(sm.Size(), Equals, 10)
   716  }
   717  
   718  // Test max length of normalized and sample ALLEGROALLEGROSQL.
   719  func (s *testStmtSummarySuite) TestMaxALLEGROSQLLength(c *C) {
   720  	s.ssMap.Clear()
   721  	now := time.Now().Unix()
   722  	// to disable expiration
   723  	s.ssMap.beginTimeForCurInterval = now + 60
   724  
   725  	// Test the original value and modify it.
   726  	maxALLEGROSQLLength := s.ssMap.maxALLEGROSQLLength()
   727  	c.Assert(maxALLEGROSQLLength, Equals, int(config.GetGlobalConfig().StmtSummary.MaxALLEGROSQLLength))
   728  
   729  	// Create a long ALLEGROALLEGROSQL
   730  	length := maxALLEGROSQLLength * 10
   731  	str := strings.Repeat("a", length)
   732  
   733  	stmtInterDircInfo1 := generateAnyInterDircInfo()
   734  	stmtInterDircInfo1.OriginalALLEGROSQL = str
   735  	stmtInterDircInfo1.NormalizedALLEGROSQL = str
   736  	s.ssMap.AddStatement(stmtInterDircInfo1)
   737  
   738  	key := &stmtSummaryByDigestKey{
   739  		schemaName: stmtInterDircInfo1.SchemaName,
   740  		digest:     stmtInterDircInfo1.Digest,
   741  		planDigest: stmtInterDircInfo1.CausetDigest,
   742  		prevDigest: stmtInterDircInfo1.PrevALLEGROSQLDigest,
   743  	}
   744  	value, ok := s.ssMap.summaryMap.Get(key)
   745  	c.Assert(ok, IsTrue)
   746  
   747  	expectedALLEGROSQL := fmt.Sprintf("%s(len:%d)", strings.Repeat("a", maxALLEGROSQLLength), length)
   748  	summary := value.(*stmtSummaryByDigest)
   749  	c.Assert(summary.normalizedALLEGROSQL, Equals, expectedALLEGROSQL)
   750  	ssElement := summary.history.Back().Value.(*stmtSummaryByDigestElement)
   751  	c.Assert(ssElement.sampleALLEGROSQL, Equals, expectedALLEGROSQL)
   752  
   753  	c.Assert(s.ssMap.SetMaxALLEGROSQLLength("100", false), IsNil)
   754  	c.Assert(s.ssMap.maxALLEGROSQLLength(), Equals, 100)
   755  	c.Assert(s.ssMap.SetMaxALLEGROSQLLength("10", true), IsNil)
   756  	c.Assert(s.ssMap.maxALLEGROSQLLength(), Equals, 10)
   757  	c.Assert(s.ssMap.SetMaxALLEGROSQLLength("", true), IsNil)
   758  	c.Assert(s.ssMap.maxALLEGROSQLLength(), Equals, 100)
   759  }
   760  
   761  // Test AddStatement and SetMaxStmtCount parallel.
   762  func (s *testStmtSummarySuite) TestSetMaxStmtCountParallel(c *C) {
   763  	s.ssMap.Clear()
   764  	now := time.Now().Unix()
   765  	// to disable expiration
   766  	s.ssMap.beginTimeForCurInterval = now + 60
   767  
   768  	threads := 8
   769  	loops := 20
   770  	wg := sync.WaitGroup{}
   771  	wg.Add(threads + 1)
   772  
   773  	addStmtFunc := func() {
   774  		defer wg.Done()
   775  		stmtInterDircInfo1 := generateAnyInterDircInfo()
   776  
   777  		// Add 32 times with different digest.
   778  		for i := 0; i < loops; i++ {
   779  			stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i)
   780  			s.ssMap.AddStatement(stmtInterDircInfo1)
   781  		}
   782  	}
   783  	for i := 0; i < threads; i++ {
   784  		go addStmtFunc()
   785  	}
   786  
   787  	defer c.Assert(s.ssMap.SetMaxStmtCount("", true), IsNil)
   788  	setStmtCountFunc := func() {
   789  		defer wg.Done()
   790  		// Turn down MaxStmtCount one by one.
   791  		for i := 10; i > 0; i-- {
   792  			c.Assert(s.ssMap.SetMaxStmtCount(strconv.Itoa(i), true), IsNil)
   793  		}
   794  	}
   795  	go setStmtCountFunc()
   796  
   797  	wg.Wait()
   798  
   799  	datums := s.ssMap.ToCurrentCauset(nil, true)
   800  	c.Assert(len(datums), Equals, 1)
   801  }
   802  
   803  // Test setting EnableStmtSummary to 0.
   804  func (s *testStmtSummarySuite) TestDisableStmtSummary(c *C) {
   805  	s.ssMap.Clear()
   806  	now := time.Now().Unix()
   807  
   808  	// Set false in global scope, it should work.
   809  	s.ssMap.SetEnabled("0", false)
   810  	s.ssMap.beginTimeForCurInterval = now + 60
   811  
   812  	stmtInterDircInfo1 := generateAnyInterDircInfo()
   813  	s.ssMap.AddStatement(stmtInterDircInfo1)
   814  	datums := s.ssMap.ToCurrentCauset(nil, true)
   815  	c.Assert(len(datums), Equals, 0)
   816  
   817  	// Set true in stochastik scope, it will overwrite global scope.
   818  	s.ssMap.SetEnabled("1", true)
   819  
   820  	s.ssMap.AddStatement(stmtInterDircInfo1)
   821  	datums = s.ssMap.ToCurrentCauset(nil, true)
   822  	c.Assert(len(datums), Equals, 1)
   823  
   824  	// Set false in global scope, it shouldn't work.
   825  	s.ssMap.SetEnabled("0", false)
   826  	s.ssMap.beginTimeForCurInterval = now + 60
   827  
   828  	stmtInterDircInfo2 := stmtInterDircInfo1
   829  	stmtInterDircInfo2.OriginalALLEGROSQL = "original_sql2"
   830  	stmtInterDircInfo2.NormalizedALLEGROSQL = "normalized_sql2"
   831  	stmtInterDircInfo2.Digest = "digest2"
   832  	s.ssMap.AddStatement(stmtInterDircInfo2)
   833  	datums = s.ssMap.ToCurrentCauset(nil, true)
   834  	c.Assert(len(datums), Equals, 2)
   835  
   836  	// Unset in stochastik scope.
   837  	s.ssMap.SetEnabled("", true)
   838  	s.ssMap.beginTimeForCurInterval = now + 60
   839  	s.ssMap.AddStatement(stmtInterDircInfo2)
   840  	datums = s.ssMap.ToCurrentCauset(nil, true)
   841  	c.Assert(len(datums), Equals, 0)
   842  
   843  	// Unset in global scope.
   844  	s.ssMap.SetEnabled("", false)
   845  	s.ssMap.beginTimeForCurInterval = now + 60
   846  	s.ssMap.AddStatement(stmtInterDircInfo1)
   847  	datums = s.ssMap.ToCurrentCauset(nil, true)
   848  	c.Assert(len(datums), Equals, 1)
   849  
   850  	// Set back.
   851  	s.ssMap.SetEnabled("1", false)
   852  }
   853  
   854  // Test disable and enable memex summary concurrently with adding memexs.
   855  func (s *testStmtSummarySuite) TestEnableSummaryParallel(c *C) {
   856  	s.ssMap.Clear()
   857  
   858  	threads := 8
   859  	loops := 32
   860  	wg := sync.WaitGroup{}
   861  	wg.Add(threads)
   862  
   863  	addStmtFunc := func() {
   864  		defer wg.Done()
   865  		stmtInterDircInfo1 := generateAnyInterDircInfo()
   866  
   867  		// Add 32 times with same digest.
   868  		for i := 0; i < loops; i++ {
   869  			// Sometimes enable it and sometimes disable it.
   870  			s.ssMap.SetEnabled(fmt.Sprintf("%d", i%2), false)
   871  			s.ssMap.AddStatement(stmtInterDircInfo1)
   872  			// Try to read it.
   873  			s.ssMap.ToHistoryCauset(nil, true)
   874  		}
   875  		s.ssMap.SetEnabled("1", false)
   876  	}
   877  
   878  	for i := 0; i < threads; i++ {
   879  		go addStmtFunc()
   880  	}
   881  	// Ensure that there's no deadlocks.
   882  	wg.Wait()
   883  
   884  	// Ensure that it's enabled at last.
   885  	c.Assert(s.ssMap.Enabled(), IsTrue)
   886  }
   887  
   888  // Test GetMoreThanOnceSelect.
   889  func (s *testStmtSummarySuite) TestGetMoreThanOnceSelect(c *C) {
   890  	s.ssMap.Clear()
   891  
   892  	stmtInterDircInfo1 := generateAnyInterDircInfo()
   893  	stmtInterDircInfo1.OriginalALLEGROSQL = "insert 1"
   894  	stmtInterDircInfo1.NormalizedALLEGROSQL = "insert ?"
   895  	stmtInterDircInfo1.StmtCtx.StmtType = "Insert"
   896  	s.ssMap.AddStatement(stmtInterDircInfo1)
   897  	schemas, sqls := s.ssMap.GetMoreThanOnceSelect()
   898  	c.Assert(len(schemas), Equals, 0)
   899  	c.Assert(len(sqls), Equals, 0)
   900  
   901  	stmtInterDircInfo1.NormalizedALLEGROSQL = "select ?"
   902  	stmtInterDircInfo1.Digest = "digest1"
   903  	stmtInterDircInfo1.StmtCtx.StmtType = "Select"
   904  	s.ssMap.AddStatement(stmtInterDircInfo1)
   905  	schemas, sqls = s.ssMap.GetMoreThanOnceSelect()
   906  	c.Assert(len(schemas), Equals, 0)
   907  	c.Assert(len(sqls), Equals, 0)
   908  
   909  	s.ssMap.AddStatement(stmtInterDircInfo1)
   910  	schemas, sqls = s.ssMap.GetMoreThanOnceSelect()
   911  	c.Assert(len(schemas), Equals, 1)
   912  	c.Assert(len(sqls), Equals, 1)
   913  }
   914  
   915  // Test `formatBackoffTypes`.
   916  func (s *testStmtSummarySuite) TestFormatBackoffTypes(c *C) {
   917  	backoffMap := make(map[fmt.Stringer]int)
   918  	c.Assert(formatBackoffTypes(backoffMap), IsNil)
   919  
   920  	backoffMap[einsteindb.BoFIDelRPC] = 1
   921  	c.Assert(formatBackoffTypes(backoffMap), Equals, "FIDelRPC:1")
   922  
   923  	backoffMap[einsteindb.BoTxnLock] = 2
   924  	c.Assert(formatBackoffTypes(backoffMap), Equals, "txnLock:2,FIDelRPC:1")
   925  }
   926  
   927  // Test refreshing current memex summary periodically.
   928  func (s *testStmtSummarySuite) TestRefreshCurrentSummary(c *C) {
   929  	s.ssMap.Clear()
   930  	now := time.Now().Unix()
   931  
   932  	s.ssMap.beginTimeForCurInterval = now + 10
   933  	stmtInterDircInfo1 := generateAnyInterDircInfo()
   934  	key := &stmtSummaryByDigestKey{
   935  		schemaName: stmtInterDircInfo1.SchemaName,
   936  		digest:     stmtInterDircInfo1.Digest,
   937  		planDigest: stmtInterDircInfo1.CausetDigest,
   938  	}
   939  	s.ssMap.AddStatement(stmtInterDircInfo1)
   940  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 1)
   941  	value, ok := s.ssMap.summaryMap.Get(key)
   942  	c.Assert(ok, IsTrue)
   943  	ssElement := value.(*stmtSummaryByDigest).history.Back().Value.(*stmtSummaryByDigestElement)
   944  	c.Assert(ssElement.beginTime, Equals, s.ssMap.beginTimeForCurInterval)
   945  	c.Assert(ssElement.execCount, Equals, int64(1))
   946  
   947  	s.ssMap.beginTimeForCurInterval = now - 1900
   948  	ssElement.beginTime = now - 1900
   949  	s.ssMap.AddStatement(stmtInterDircInfo1)
   950  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 1)
   951  	value, ok = s.ssMap.summaryMap.Get(key)
   952  	c.Assert(ok, IsTrue)
   953  	c.Assert(value.(*stmtSummaryByDigest).history.Len(), Equals, 2)
   954  	ssElement = value.(*stmtSummaryByDigest).history.Back().Value.(*stmtSummaryByDigestElement)
   955  	c.Assert(ssElement.beginTime, Greater, now-1900)
   956  	c.Assert(ssElement.execCount, Equals, int64(1))
   957  
   958  	s.ssMap.SetRefreshInterval("10", false)
   959  	s.ssMap.beginTimeForCurInterval = now - 20
   960  	ssElement.beginTime = now - 20
   961  	s.ssMap.AddStatement(stmtInterDircInfo1)
   962  	c.Assert(value.(*stmtSummaryByDigest).history.Len(), Equals, 3)
   963  }
   964  
   965  // Test expiring memex summary to history.
   966  func (s *testStmtSummarySuite) TestSummaryHistory(c *C) {
   967  	s.ssMap.Clear()
   968  	now := time.Now().Unix()
   969  	s.ssMap.SetRefreshInterval("10", false)
   970  	s.ssMap.SetHistorySize("10", false)
   971  	defer s.ssMap.SetRefreshInterval("1800", false)
   972  	defer s.ssMap.SetHistorySize("24", false)
   973  
   974  	stmtInterDircInfo1 := generateAnyInterDircInfo()
   975  	key := &stmtSummaryByDigestKey{
   976  		schemaName: stmtInterDircInfo1.SchemaName,
   977  		digest:     stmtInterDircInfo1.Digest,
   978  		planDigest: stmtInterDircInfo1.CausetDigest,
   979  	}
   980  	for i := 0; i < 11; i++ {
   981  		s.ssMap.beginTimeForCurInterval = now + int64(i+1)*10
   982  		s.ssMap.AddStatement(stmtInterDircInfo1)
   983  		c.Assert(s.ssMap.summaryMap.Size(), Equals, 1)
   984  		value, ok := s.ssMap.summaryMap.Get(key)
   985  		c.Assert(ok, IsTrue)
   986  		ssbd := value.(*stmtSummaryByDigest)
   987  		if i < 10 {
   988  			c.Assert(ssbd.history.Len(), Equals, i+1)
   989  			ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement)
   990  			c.Assert(ssElement.beginTime, Equals, s.ssMap.beginTimeForCurInterval)
   991  			c.Assert(ssElement.execCount, Equals, int64(1))
   992  		} else {
   993  			c.Assert(ssbd.history.Len(), Equals, 10)
   994  			ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement)
   995  			c.Assert(ssElement.beginTime, Equals, s.ssMap.beginTimeForCurInterval)
   996  			ssElement = ssbd.history.Front().Value.(*stmtSummaryByDigestElement)
   997  			c.Assert(ssElement.beginTime, Equals, now+20)
   998  		}
   999  	}
  1000  	causet := s.ssMap.ToHistoryCauset(nil, true)
  1001  	c.Assert(len(causet), Equals, 10)
  1002  
  1003  	s.ssMap.SetHistorySize("5", false)
  1004  	causet = s.ssMap.ToHistoryCauset(nil, true)
  1005  	c.Assert(len(causet), Equals, 5)
  1006  }
  1007  
  1008  // Test summary when PrevALLEGROSQL is not empty.
  1009  func (s *testStmtSummarySuite) TestPrevALLEGROSQL(c *C) {
  1010  	s.ssMap.Clear()
  1011  	now := time.Now().Unix()
  1012  	// to disable expiration
  1013  	s.ssMap.beginTimeForCurInterval = now + 60
  1014  
  1015  	stmtInterDircInfo1 := generateAnyInterDircInfo()
  1016  	stmtInterDircInfo1.PrevALLEGROSQL = "prevALLEGROSQL"
  1017  	stmtInterDircInfo1.PrevALLEGROSQLDigest = "prevALLEGROSQLDigest"
  1018  	s.ssMap.AddStatement(stmtInterDircInfo1)
  1019  	key := &stmtSummaryByDigestKey{
  1020  		schemaName: stmtInterDircInfo1.SchemaName,
  1021  		digest:     stmtInterDircInfo1.Digest,
  1022  		planDigest: stmtInterDircInfo1.CausetDigest,
  1023  		prevDigest: stmtInterDircInfo1.PrevALLEGROSQLDigest,
  1024  	}
  1025  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 1)
  1026  	_, ok := s.ssMap.summaryMap.Get(key)
  1027  	c.Assert(ok, IsTrue)
  1028  
  1029  	// same prevALLEGROSQL
  1030  	s.ssMap.AddStatement(stmtInterDircInfo1)
  1031  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 1)
  1032  
  1033  	// different prevALLEGROSQL
  1034  	stmtInterDircInfo2 := stmtInterDircInfo1
  1035  	stmtInterDircInfo2.PrevALLEGROSQL = "prevALLEGROSQL1"
  1036  	stmtInterDircInfo2.PrevALLEGROSQLDigest = "prevALLEGROSQLDigest1"
  1037  	key.prevDigest = stmtInterDircInfo2.PrevALLEGROSQLDigest
  1038  	s.ssMap.AddStatement(stmtInterDircInfo2)
  1039  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 2)
  1040  	_, ok = s.ssMap.summaryMap.Get(key)
  1041  	c.Assert(ok, IsTrue)
  1042  }
  1043  
  1044  func (s *testStmtSummarySuite) TestEndTime(c *C) {
  1045  	s.ssMap.Clear()
  1046  	now := time.Now().Unix()
  1047  	s.ssMap.beginTimeForCurInterval = now - 100
  1048  
  1049  	stmtInterDircInfo1 := generateAnyInterDircInfo()
  1050  	s.ssMap.AddStatement(stmtInterDircInfo1)
  1051  	key := &stmtSummaryByDigestKey{
  1052  		schemaName: stmtInterDircInfo1.SchemaName,
  1053  		digest:     stmtInterDircInfo1.Digest,
  1054  		planDigest: stmtInterDircInfo1.CausetDigest,
  1055  	}
  1056  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 1)
  1057  	value, ok := s.ssMap.summaryMap.Get(key)
  1058  	c.Assert(ok, IsTrue)
  1059  	ssbd := value.(*stmtSummaryByDigest)
  1060  	ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement)
  1061  	c.Assert(ssElement.beginTime, Equals, now-100)
  1062  	c.Assert(ssElement.endTime, Equals, now+1700)
  1063  
  1064  	s.ssMap.SetRefreshInterval("3600", false)
  1065  	defer s.ssMap.SetRefreshInterval("1800", false)
  1066  	s.ssMap.AddStatement(stmtInterDircInfo1)
  1067  	c.Assert(ssbd.history.Len(), Equals, 1)
  1068  	ssElement = ssbd.history.Back().Value.(*stmtSummaryByDigestElement)
  1069  	c.Assert(ssElement.beginTime, Equals, now-100)
  1070  	c.Assert(ssElement.endTime, Equals, now+3500)
  1071  
  1072  	s.ssMap.SetRefreshInterval("60", false)
  1073  	s.ssMap.AddStatement(stmtInterDircInfo1)
  1074  	c.Assert(ssbd.history.Len(), Equals, 2)
  1075  	now2 := time.Now().Unix()
  1076  	ssElement = ssbd.history.Front().Value.(*stmtSummaryByDigestElement)
  1077  	c.Assert(ssElement.beginTime, Equals, now-100)
  1078  	c.Assert(ssElement.endTime, GreaterEqual, now)
  1079  	c.Assert(ssElement.endTime, LessEqual, now2)
  1080  	ssElement = ssbd.history.Back().Value.(*stmtSummaryByDigestElement)
  1081  	c.Assert(ssElement.beginTime, GreaterEqual, now-60)
  1082  	c.Assert(ssElement.beginTime, LessEqual, now2)
  1083  	c.Assert(ssElement.endTime-ssElement.beginTime, Equals, int64(60))
  1084  }
  1085  
  1086  func (s *testStmtSummarySuite) TestPointGet(c *C) {
  1087  	s.ssMap.Clear()
  1088  	now := time.Now().Unix()
  1089  	s.ssMap.beginTimeForCurInterval = now - 100
  1090  
  1091  	stmtInterDircInfo1 := generateAnyInterDircInfo()
  1092  	stmtInterDircInfo1.CausetDigest = ""
  1093  	stmtInterDircInfo1.CausetDigestGen = fakeCausetDigestGenerator
  1094  	s.ssMap.AddStatement(stmtInterDircInfo1)
  1095  	key := &stmtSummaryByDigestKey{
  1096  		schemaName: stmtInterDircInfo1.SchemaName,
  1097  		digest:     stmtInterDircInfo1.Digest,
  1098  		planDigest: "",
  1099  	}
  1100  	c.Assert(s.ssMap.summaryMap.Size(), Equals, 1)
  1101  	value, ok := s.ssMap.summaryMap.Get(key)
  1102  	c.Assert(ok, IsTrue)
  1103  	ssbd := value.(*stmtSummaryByDigest)
  1104  	ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement)
  1105  	c.Assert(ssElement.execCount, Equals, int64(1))
  1106  
  1107  	s.ssMap.AddStatement(stmtInterDircInfo1)
  1108  	c.Assert(ssElement.execCount, Equals, int64(2))
  1109  }
  1110  
  1111  func (s *testStmtSummarySuite) TestAccessPrivilege(c *C) {
  1112  	s.ssMap.Clear()
  1113  
  1114  	loops := 32
  1115  	stmtInterDircInfo1 := generateAnyInterDircInfo()
  1116  
  1117  	for i := 0; i < loops; i++ {
  1118  		stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i)
  1119  		s.ssMap.AddStatement(stmtInterDircInfo1)
  1120  	}
  1121  
  1122  	user := &auth.UserIdentity{Username: "user"}
  1123  	badUser := &auth.UserIdentity{Username: "bad_user"}
  1124  
  1125  	datums := s.ssMap.ToCurrentCauset(user, false)
  1126  	c.Assert(len(datums), Equals, loops)
  1127  	datums = s.ssMap.ToCurrentCauset(badUser, false)
  1128  	c.Assert(len(datums), Equals, 0)
  1129  	datums = s.ssMap.ToCurrentCauset(badUser, true)
  1130  	c.Assert(len(datums), Equals, loops)
  1131  
  1132  	datums = s.ssMap.ToHistoryCauset(user, false)
  1133  	c.Assert(len(datums), Equals, loops)
  1134  	datums = s.ssMap.ToHistoryCauset(badUser, false)
  1135  	c.Assert(len(datums), Equals, 0)
  1136  	datums = s.ssMap.ToHistoryCauset(badUser, true)
  1137  	c.Assert(len(datums), Equals, loops)
  1138  }