github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/cmd/benchdb/ddltest/index_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 dbstest
    15  
    16  import (
    17  	"fmt"
    18  	"io"
    19  	"math"
    20  	"sync"
    21  	"sync/atomic"
    22  	"time"
    23  
    24  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    25  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    26  	. "github.com/whtcorpsinc/check"
    27  	"github.com/whtcorpsinc/milevadb/causet"
    28  	"github.com/whtcorpsinc/milevadb/causet/blocks"
    29  	"github.com/whtcorpsinc/milevadb/causetstore/einsteindb"
    30  	"github.com/whtcorpsinc/milevadb/causetstore/einsteindb/gcworker"
    31  	"github.com/whtcorpsinc/milevadb/ekv"
    32  	"github.com/whtcorpsinc/milevadb/types"
    33  	goctx "golang.org/x/net/context"
    34  )
    35  
    36  func getIndex(t causet.Block, name string) causet.Index {
    37  	for _, idx := range t.Indices() {
    38  		if idx.Meta().Name.O == name {
    39  			return idx
    40  		}
    41  	}
    42  
    43  	return nil
    44  }
    45  
    46  func (s *TestDBSSuite) checkAddIndex(c *C, indexInfo *perceptron.IndexInfo) {
    47  	ctx := s.ctx
    48  	err := ctx.NewTxn(goctx.Background())
    49  	c.Assert(err, IsNil)
    50  	tbl := s.getTable(c, "test_index")
    51  
    52  	// read handles form causet
    53  	handles := ekv.NewHandleMap()
    54  	err = tbl.IterRecords(ctx, tbl.FirstKey(), tbl.DefCauss(),
    55  		func(h ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
    56  			handles.Set(h, struct{}{})
    57  			return true, nil
    58  		})
    59  	c.Assert(err, IsNil)
    60  
    61  	// read handles from index
    62  	idx := blocks.NewIndex(tbl.Meta().ID, tbl.Meta(), indexInfo)
    63  	err = ctx.NewTxn(goctx.Background())
    64  	c.Assert(err, IsNil)
    65  	txn, err := ctx.Txn(false)
    66  	c.Assert(err, IsNil)
    67  	defer func() {
    68  		txn.Rollback()
    69  	}()
    70  
    71  	it, err := idx.SeekFirst(txn)
    72  	c.Assert(err, IsNil)
    73  	defer it.Close()
    74  
    75  	for {
    76  		_, h, err := it.Next()
    77  		if terror.ErrorEqual(err, io.EOF) {
    78  			break
    79  		}
    80  
    81  		c.Assert(err, IsNil)
    82  		_, ok := handles.Get(h)
    83  		c.Assert(ok, IsTrue)
    84  		handles.Delete(h)
    85  	}
    86  
    87  	c.Assert(handles.Len(), Equals, 0)
    88  }
    89  
    90  func (s *TestDBSSuite) checkDropIndex(c *C, indexInfo *perceptron.IndexInfo) {
    91  	gcWorker, err := gcworker.NewMockGCWorker(s.causetstore.(einsteindb.CausetStorage))
    92  	c.Assert(err, IsNil)
    93  	err = gcWorker.DeleteRanges(goctx.Background(), uint64(math.MaxInt32))
    94  	c.Assert(err, IsNil)
    95  
    96  	ctx := s.ctx
    97  	err = ctx.NewTxn(goctx.Background())
    98  	c.Assert(err, IsNil)
    99  	tbl := s.getTable(c, "test_index")
   100  
   101  	// read handles from index
   102  	idx := blocks.NewIndex(tbl.Meta().ID, tbl.Meta(), indexInfo)
   103  	err = ctx.NewTxn(goctx.Background())
   104  	c.Assert(err, IsNil)
   105  	txn, err := ctx.Txn(false)
   106  	c.Assert(err, IsNil)
   107  	defer txn.Rollback()
   108  
   109  	it, err := idx.SeekFirst(txn)
   110  	c.Assert(err, IsNil)
   111  	defer it.Close()
   112  
   113  	handles := ekv.NewHandleMap()
   114  	for {
   115  		_, h, err := it.Next()
   116  		if terror.ErrorEqual(err, io.EOF) {
   117  			break
   118  		}
   119  
   120  		c.Assert(err, IsNil)
   121  		handles.Set(h, struct{}{})
   122  	}
   123  
   124  	// TODO: Uncomment this after apply pool is finished
   125  	// c.Assert(handles.Len(), Equals, 0)
   126  }
   127  
   128  // TestIndex operations on causet test_index (c int, c1 bigint, c2 double, c3 varchar(256), primary key(c)).
   129  func (s *TestDBSSuite) TestIndex(c *C) {
   130  	// first add many data
   131  	workerNum := 10
   132  	base := *dataNum / workerNum
   133  	var wg sync.WaitGroup
   134  	wg.Add(workerNum)
   135  	for i := 0; i < workerNum; i++ {
   136  		go func(i int) {
   137  			defer wg.Done()
   138  			for j := 0; j < base; j++ {
   139  				k := base*i + j
   140  				s.execInsert(c,
   141  					fmt.Sprintf("insert into test_index values (%d, %d, %f, '%s')",
   142  						k, randomInt(), randomFloat(), randomString(10)))
   143  			}
   144  		}(i)
   145  	}
   146  	wg.Wait()
   147  
   148  	tbl := []struct {
   149  		Query     string
   150  		IndexName string
   151  		Add       bool
   152  	}{
   153  		{"create index c1_index on test_index (c1)", "c1_index", true},
   154  		{"drop index c1_index on test_index", "c1_index", false},
   155  		{"create index c2_index on test_index (c2)", "c2_index", true},
   156  		{"drop index c2_index on test_index", "c2_index", false},
   157  		{"create index c3_index on test_index (c3)", "c3_index", true},
   158  		{"drop index c3_index on test_index", "c3_index", false},
   159  	}
   160  
   161  	insertID := int64(*dataNum)
   162  	var oldIndex causet.Index
   163  	for _, t := range tbl {
   164  		c.Logf("run DBS allegrosql %s", t.Query)
   165  		done := s.runDBS(t.Query)
   166  
   167  		ticker := time.NewTicker(time.Duration(*lease) * time.Second / 2)
   168  		defer ticker.Stop()
   169  	LOOP:
   170  		for {
   171  			select {
   172  			case err := <-done:
   173  				c.Assert(err, IsNil)
   174  				break LOOP
   175  			case <-ticker.C:
   176  				// add count new data
   177  				// delete count old data randomly
   178  				// uFIDelate count old data randomly
   179  				count := 10
   180  				s.execIndexOperations(c, workerNum, count, &insertID)
   181  			}
   182  		}
   183  
   184  		tbl := s.getTable(c, "test_index")
   185  		index := getIndex(tbl, t.IndexName)
   186  		if t.Add {
   187  			c.Assert(index, NotNil)
   188  			oldIndex = index
   189  			s.checkAddIndex(c, index.Meta())
   190  		} else {
   191  			c.Assert(index, IsNil)
   192  			s.checkDropIndex(c, oldIndex.Meta())
   193  		}
   194  	}
   195  }
   196  
   197  func (s *TestDBSSuite) execIndexOperations(c *C, workerNum, count int, insertID *int64) {
   198  	var wg sync.WaitGroup
   199  	// workerNum = 10
   200  	wg.Add(workerNum)
   201  	for i := 0; i < workerNum; i++ {
   202  		go func() {
   203  			defer wg.Done()
   204  			for j := 0; j < count; j++ {
   205  				id := atomic.AddInt64(insertID, 1)
   206  				allegrosql := fmt.Sprintf("insert into test_index values (%d, %d, %f, '%s')", id, randomInt(), randomFloat(), randomString(10))
   207  				s.execInsert(c, allegrosql)
   208  				c.Logf("allegrosql %s", allegrosql)
   209  				allegrosql = fmt.Sprintf("delete from test_index where c = %d", randomIntn(int(id)))
   210  				s.mustInterDirc(c, allegrosql)
   211  				c.Logf("allegrosql %s", allegrosql)
   212  				allegrosql = fmt.Sprintf("uFIDelate test_index set c1 = %d, c2 = %f, c3 = '%s' where c = %d", randomInt(), randomFloat(), randomString(10), randomIntn(int(id)))
   213  				s.mustInterDirc(c, allegrosql)
   214  				c.Logf("allegrosql %s", allegrosql)
   215  
   216  			}
   217  		}()
   218  	}
   219  	wg.Wait()
   220  }