github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/global_vars_cache_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 petri
    15  
    16  import (
    17  	"sync"
    18  	"sync/atomic"
    19  	"time"
    20  
    21  	. "github.com/whtcorpsinc/check"
    22  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    23  	"github.com/whtcorpsinc/BerolinaSQL/charset"
    24  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    25  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    26  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    27  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    28  	"github.com/whtcorpsinc/milevadb/types"
    29  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    30  	"github.com/whtcorpsinc/milevadb/soliton/stmtsummary"
    31  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    32  )
    33  
    34  var _ = SerialSuites(&testGVCSuite{})
    35  
    36  type testGVCSuite struct{}
    37  
    38  func (gvcSuite *testGVCSuite) TestSimple(c *C) {
    39  	defer testleak.AfterTest(c)()
    40  	testleak.BeforeTest()
    41  
    42  	causetstore, err := mockstore.NewMockStore()
    43  	c.Assert(err, IsNil)
    44  	defer causetstore.Close()
    45  	dbsLease := 50 * time.Millisecond
    46  	dom := NewPetri(causetstore, dbsLease, 0, 0, mockFactory)
    47  	err = dom.Init(dbsLease, sysMockFactory)
    48  	c.Assert(err, IsNil)
    49  	defer dom.Close()
    50  
    51  	// Get empty global vars cache.
    52  	gvc := dom.GetGlobalVarsCache()
    53  	succ, rows, fields := gvc.Get()
    54  	c.Assert(succ, IsFalse)
    55  	c.Assert(rows, IsNil)
    56  	c.Assert(fields, IsNil)
    57  	// Get a variable from global vars cache.
    58  	rf := getResultField("c", 1, 0)
    59  	rf1 := getResultField("c1", 2, 1)
    60  	ft := &types.FieldType{
    61  		Tp:      allegrosql.TypeString,
    62  		Charset: charset.CharsetBin,
    63  		DefCauslate: charset.DefCauslationBin,
    64  	}
    65  	ft1 := &types.FieldType{
    66  		Tp:      allegrosql.TypeString,
    67  		Charset: charset.CharsetBin,
    68  		DefCauslate: charset.DefCauslationBin,
    69  	}
    70  	ck := chunk.NewChunkWithCapacity([]*types.FieldType{ft, ft1}, 1024)
    71  	ck.AppendString(0, "variable1")
    72  	ck.AppendString(1, "value1")
    73  	event := ck.GetEvent(0)
    74  	gvc.UFIDelate([]chunk.Event{event}, []*ast.ResultField{rf, rf1})
    75  	succ, rows, fields = gvc.Get()
    76  	c.Assert(succ, IsTrue)
    77  	c.Assert(rows[0], Equals, event)
    78  	c.Assert(fields, DeepEquals, []*ast.ResultField{rf, rf1})
    79  	// Disable the cache.
    80  	gvc.Disable()
    81  	succ, rows, fields = gvc.Get()
    82  	c.Assert(succ, IsFalse)
    83  	c.Assert(rows[0], Equals, event)
    84  	c.Assert(fields, DeepEquals, []*ast.ResultField{rf, rf1})
    85  }
    86  
    87  func getResultField(defCausName string, id, offset int) *ast.ResultField {
    88  	return &ast.ResultField{
    89  		DeferredCauset: &perceptron.DeferredCausetInfo{
    90  			Name:   perceptron.NewCIStr(defCausName),
    91  			ID:     int64(id),
    92  			Offset: offset,
    93  			FieldType: types.FieldType{
    94  				Tp:      allegrosql.TypeString,
    95  				Charset: charset.CharsetUTF8,
    96  				DefCauslate: charset.DefCauslationUTF8,
    97  			},
    98  		},
    99  		BlockAsName: perceptron.NewCIStr("tbl"),
   100  		DBName:      perceptron.NewCIStr("test"),
   101  	}
   102  }
   103  
   104  func (gvcSuite *testGVCSuite) TestConcurrentOneFlight(c *C) {
   105  	defer testleak.AfterTest(c)()
   106  	testleak.BeforeTest()
   107  	gvc := &GlobalVariableCache{}
   108  	succ, rows, fields := gvc.Get()
   109  	c.Assert(succ, IsFalse)
   110  	c.Assert(rows, IsNil)
   111  	c.Assert(fields, IsNil)
   112  
   113  	// Get a variable from global vars cache.
   114  	rf := getResultField("c", 1, 0)
   115  	rf1 := getResultField("c1", 2, 1)
   116  	ft := &types.FieldType{
   117  		Tp:      allegrosql.TypeString,
   118  		Charset: charset.CharsetBin,
   119  		DefCauslate: charset.DefCauslationBin,
   120  	}
   121  	ft1 := &types.FieldType{
   122  		Tp:      allegrosql.TypeString,
   123  		Charset: charset.CharsetBin,
   124  		DefCauslate: charset.DefCauslationBin,
   125  	}
   126  	ckLow := chunk.NewChunkWithCapacity([]*types.FieldType{ft, ft1}, 1024)
   127  	val := "fromStorage"
   128  	val1 := "fromStorage1"
   129  	ckLow.AppendString(0, val)
   130  	ckLow.AppendString(1, val1)
   131  
   132  	// Let cache become invalid, and try concurrent load
   133  	counter := int32(0)
   134  	waitToStart := new(sync.WaitGroup)
   135  	waitToStart.Add(1)
   136  	gvc.lastModify = time.Now().Add(time.Duration(-10) * time.Second)
   137  	loadFunc := func() ([]chunk.Event, []*ast.ResultField, error) {
   138  		time.Sleep(100 * time.Millisecond)
   139  		atomic.AddInt32(&counter, 1)
   140  		return []chunk.Event{ckLow.GetEvent(0)}, []*ast.ResultField{rf, rf1}, nil
   141  	}
   142  	wg := new(sync.WaitGroup)
   143  	worker := 100
   144  	resArray := make([]loadResult, worker)
   145  	for i := 0; i < worker; i++ {
   146  		wg.Add(1)
   147  		go func(idx int) {
   148  			defer wg.Done()
   149  			waitToStart.Wait()
   150  			resEvent, resField, _ := gvc.LoadGlobalVariables(loadFunc)
   151  			resArray[idx].rows = resEvent
   152  			resArray[idx].fields = resField
   153  		}(i)
   154  	}
   155  	waitToStart.Done()
   156  	wg.Wait()
   157  	succ, rows, fields = gvc.Get()
   158  	c.Assert(counter, Equals, int32(1))
   159  	c.Assert(resArray[0].rows[0].GetString(0), Equals, val)
   160  	c.Assert(resArray[0].rows[0].GetString(1), Equals, val1)
   161  	for i := 0; i < worker; i++ {
   162  		c.Assert(resArray[0].rows[0], Equals, resArray[i].rows[0])
   163  		c.Assert(resArray[i].rows[0].GetString(0), Equals, val)
   164  		c.Assert(resArray[i].rows[0].GetString(1), Equals, val1)
   165  	}
   166  	// Validate cache
   167  	c.Assert(succ, IsTrue)
   168  	c.Assert(rows[0], Equals, resArray[0].rows[0])
   169  	c.Assert(fields, DeepEquals, []*ast.ResultField{rf, rf1})
   170  }
   171  
   172  func (gvcSuite *testGVCSuite) TestCheckEnableStmtSummary(c *C) {
   173  	defer testleak.AfterTest(c)()
   174  	testleak.BeforeTest()
   175  
   176  	causetstore, err := mockstore.NewMockStore()
   177  	c.Assert(err, IsNil)
   178  	defer causetstore.Close()
   179  	dbsLease := 50 * time.Millisecond
   180  	dom := NewPetri(causetstore, dbsLease, 0, 0, mockFactory)
   181  	err = dom.Init(dbsLease, sysMockFactory)
   182  	c.Assert(err, IsNil)
   183  	defer dom.Close()
   184  
   185  	gvc := dom.GetGlobalVarsCache()
   186  
   187  	rf := getResultField("c", 1, 0)
   188  	rf1 := getResultField("c1", 2, 1)
   189  	ft := &types.FieldType{
   190  		Tp:      allegrosql.TypeString,
   191  		Charset: charset.CharsetBin,
   192  		DefCauslate: charset.DefCauslationBin,
   193  	}
   194  	ft1 := &types.FieldType{
   195  		Tp:      allegrosql.TypeString,
   196  		Charset: charset.CharsetBin,
   197  		DefCauslate: charset.DefCauslationBin,
   198  	}
   199  
   200  	stmtsummary.StmtSummaryByDigestMap.SetEnabled("0", false)
   201  	ck := chunk.NewChunkWithCapacity([]*types.FieldType{ft, ft1}, 1024)
   202  	ck.AppendString(0, variable.MilevaDBEnableStmtSummary)
   203  	ck.AppendString(1, "1")
   204  	event := ck.GetEvent(0)
   205  	gvc.UFIDelate([]chunk.Event{event}, []*ast.ResultField{rf, rf1})
   206  	c.Assert(stmtsummary.StmtSummaryByDigestMap.Enabled(), Equals, true)
   207  
   208  	ck = chunk.NewChunkWithCapacity([]*types.FieldType{ft, ft1}, 1024)
   209  	ck.AppendString(0, variable.MilevaDBEnableStmtSummary)
   210  	ck.AppendString(1, "0")
   211  	event = ck.GetEvent(0)
   212  	gvc.UFIDelate([]chunk.Event{event}, []*ast.ResultField{rf, rf1})
   213  	c.Assert(stmtsummary.StmtSummaryByDigestMap.Enabled(), Equals, false)
   214  }