github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/meta/meta_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 spacetime_test
    15  
    16  import (
    17  	"context"
    18  	"math"
    19  	"strconv"
    20  	"sync"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    25  	. "github.com/whtcorpsinc/check"
    26  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    27  	"github.com/whtcorpsinc/milevadb/ekv"
    28  	"github.com/whtcorpsinc/milevadb/soliton/codec"
    29  	. "github.com/whtcorpsinc/milevadb/soliton/solitonutil"
    30  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    31  	"github.com/whtcorpsinc/milevadb/spacetime"
    32  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    33  	"github.com/whtcorpsinc/milevadb/types"
    34  )
    35  
    36  func TestT(t *testing.T) {
    37  	CustomVerboseFlag = true
    38  	TestingT(t)
    39  }
    40  
    41  var _ = Suite(&testSuite{})
    42  
    43  type testSuite struct {
    44  	CommonHandleSuite
    45  }
    46  
    47  func (s *testSuite) TestMeta(c *C) {
    48  	defer testleak.AfterTest(c)()
    49  	causetstore, err := mockstore.NewMockStore()
    50  	c.Assert(err, IsNil)
    51  	defer causetstore.Close()
    52  
    53  	txn, err := causetstore.Begin()
    54  	c.Assert(err, IsNil)
    55  	defer txn.Rollback()
    56  
    57  	t := spacetime.NewMeta(txn)
    58  
    59  	n, err := t.GenGlobalID()
    60  	c.Assert(err, IsNil)
    61  	c.Assert(n, Equals, int64(1))
    62  
    63  	n, err = t.GetGlobalID()
    64  	c.Assert(err, IsNil)
    65  	c.Assert(n, Equals, int64(1))
    66  
    67  	var wg sync.WaitGroup
    68  	wg.Add(1)
    69  	go func() {
    70  		defer wg.Done()
    71  		ids, err := t.GenGlobalIDs(3)
    72  		c.Assert(err, IsNil)
    73  		anyMatch(c, ids, []int64{2, 3, 4}, []int64{6, 7, 8})
    74  	}()
    75  
    76  	wg.Add(1)
    77  	go func() {
    78  		defer wg.Done()
    79  		ids, err := t.GenGlobalIDs(4)
    80  		c.Assert(err, IsNil)
    81  		anyMatch(c, ids, []int64{5, 6, 7, 8}, []int64{2, 3, 4, 5})
    82  	}()
    83  	wg.Wait()
    84  
    85  	n, err = t.GetSchemaVersion()
    86  	c.Assert(err, IsNil)
    87  	c.Assert(n, Equals, int64(0))
    88  
    89  	n, err = t.GenSchemaVersion()
    90  	c.Assert(err, IsNil)
    91  	c.Assert(n, Equals, int64(1))
    92  
    93  	n, err = t.GetSchemaVersion()
    94  	c.Assert(err, IsNil)
    95  	c.Assert(n, Equals, int64(1))
    96  
    97  	dbInfo := &perceptron.DBInfo{
    98  		ID:   1,
    99  		Name: perceptron.NewCIStr("a"),
   100  	}
   101  	err = t.CreateDatabase(dbInfo)
   102  	c.Assert(err, IsNil)
   103  
   104  	err = t.CreateDatabase(dbInfo)
   105  	c.Assert(err, NotNil)
   106  	c.Assert(spacetime.ErrDBExists.Equal(err), IsTrue)
   107  
   108  	v, err := t.GetDatabase(1)
   109  	c.Assert(err, IsNil)
   110  	c.Assert(v, DeepEquals, dbInfo)
   111  
   112  	dbInfo.Name = perceptron.NewCIStr("aa")
   113  	err = t.UFIDelateDatabase(dbInfo)
   114  	c.Assert(err, IsNil)
   115  
   116  	v, err = t.GetDatabase(1)
   117  	c.Assert(err, IsNil)
   118  	c.Assert(v, DeepEquals, dbInfo)
   119  
   120  	dbs, err := t.ListDatabases()
   121  	c.Assert(err, IsNil)
   122  	c.Assert(dbs, DeepEquals, []*perceptron.DBInfo{dbInfo})
   123  
   124  	tbInfo := &perceptron.BlockInfo{
   125  		ID:   1,
   126  		Name: perceptron.NewCIStr("t"),
   127  	}
   128  	err = t.CreateBlockOrView(1, tbInfo)
   129  	c.Assert(err, IsNil)
   130  
   131  	n, err = t.GenAutoBlockID(1, 1, 10)
   132  	c.Assert(err, IsNil)
   133  	c.Assert(n, Equals, int64(10))
   134  
   135  	n, err = t.GetAutoBlockID(1, 1)
   136  	c.Assert(err, IsNil)
   137  	c.Assert(n, Equals, int64(10))
   138  
   139  	err = t.CreateBlockOrView(1, tbInfo)
   140  	c.Assert(err, NotNil)
   141  	c.Assert(spacetime.ErrBlockExists.Equal(err), IsTrue)
   142  
   143  	tbInfo.Name = perceptron.NewCIStr("tt")
   144  	err = t.UFIDelateBlock(1, tbInfo)
   145  	c.Assert(err, IsNil)
   146  
   147  	causet, err := t.GetBlock(1, 1)
   148  	c.Assert(err, IsNil)
   149  	c.Assert(causet, DeepEquals, tbInfo)
   150  
   151  	causet, err = t.GetBlock(1, 2)
   152  	c.Assert(err, IsNil)
   153  	c.Assert(causet, IsNil)
   154  
   155  	tbInfo2 := &perceptron.BlockInfo{
   156  		ID:   2,
   157  		Name: perceptron.NewCIStr("bb"),
   158  	}
   159  	err = t.CreateBlockOrView(1, tbInfo2)
   160  	c.Assert(err, IsNil)
   161  
   162  	blocks, err := t.ListBlocks(1)
   163  	c.Assert(err, IsNil)
   164  	c.Assert(blocks, DeepEquals, []*perceptron.BlockInfo{tbInfo, tbInfo2})
   165  	// Generate an auto id.
   166  	n, err = t.GenAutoBlockID(1, 2, 10)
   167  	c.Assert(err, IsNil)
   168  	c.Assert(n, Equals, int64(10))
   169  	// Make sure the auto id key-value entry is there.
   170  	n, err = t.GetAutoBlockID(1, 2)
   171  	c.Assert(err, IsNil)
   172  	c.Assert(n, Equals, int64(10))
   173  
   174  	err = t.DropBlockOrView(1, tbInfo2.ID, true)
   175  	c.Assert(err, IsNil)
   176  	// Make sure auto id key-value entry is gone.
   177  	n, err = t.GetAutoBlockID(1, 2)
   178  	c.Assert(err, IsNil)
   179  	c.Assert(n, Equals, int64(0))
   180  
   181  	blocks, err = t.ListBlocks(1)
   182  	c.Assert(err, IsNil)
   183  	c.Assert(blocks, DeepEquals, []*perceptron.BlockInfo{tbInfo})
   184  
   185  	// Test case for drop a causet without delete auto id key-value entry.
   186  	tid := int64(100)
   187  	tbInfo100 := &perceptron.BlockInfo{
   188  		ID:   tid,
   189  		Name: perceptron.NewCIStr("t_rename"),
   190  	}
   191  	// Create causet.
   192  	err = t.CreateBlockOrView(1, tbInfo100)
   193  	c.Assert(err, IsNil)
   194  	// UFIDelate auto ID.
   195  	currentDBID := int64(1)
   196  	n, err = t.GenAutoBlockID(currentDBID, tid, 10)
   197  	c.Assert(err, IsNil)
   198  	c.Assert(n, Equals, int64(10))
   199  	// Fail to uFIDelate auto ID.
   200  	// The causet ID doesn't exist.
   201  	nonExistentID := int64(1234)
   202  	_, err = t.GenAutoBlockID(currentDBID, nonExistentID, 10)
   203  	c.Assert(err, NotNil)
   204  	c.Assert(spacetime.ErrBlockNotExists.Equal(err), IsTrue)
   205  	// Fail to uFIDelate auto ID.
   206  	// The current database ID doesn't exist.
   207  	currentDBID = nonExistentID
   208  	_, err = t.GenAutoBlockID(currentDBID, tid, 10)
   209  	c.Assert(err, NotNil)
   210  	c.Assert(spacetime.ErrDBNotExists.Equal(err), IsTrue)
   211  	// Test case for CreateBlockAndSetAutoID.
   212  	tbInfo3 := &perceptron.BlockInfo{
   213  		ID:   3,
   214  		Name: perceptron.NewCIStr("tbl3"),
   215  	}
   216  	err = t.CreateBlockAndSetAutoID(1, tbInfo3, 123, 0)
   217  	c.Assert(err, IsNil)
   218  	id, err := t.GetAutoBlockID(1, tbInfo3.ID)
   219  	c.Assert(err, IsNil)
   220  	c.Assert(id, Equals, int64(123))
   221  	// Test case for GenAutoBlockIDKeyValue.
   222  	key, val := t.GenAutoBlockIDKeyValue(1, tbInfo3.ID, 1234)
   223  	c.Assert(val, DeepEquals, []byte(strconv.FormatInt(1234, 10)))
   224  	c.Assert(key, DeepEquals, []byte{0x6d, 0x44, 0x42, 0x3a, 0x31, 0x0, 0x0, 0x0, 0x0, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x54, 0x49, 0x44, 0x3a, 0x33, 0x0, 0x0, 0x0, 0xfc})
   225  
   226  	err = t.DroFIDelatabase(1)
   227  	c.Assert(err, IsNil)
   228  	err = t.DroFIDelatabase(currentDBID)
   229  	c.Assert(err, IsNil)
   230  
   231  	dbs, err = t.ListDatabases()
   232  	c.Assert(err, IsNil)
   233  	c.Assert(dbs, HasLen, 0)
   234  
   235  	bootstrapVer, err := t.GetBootstrapVersion()
   236  	c.Assert(err, IsNil)
   237  	c.Assert(bootstrapVer, Equals, int64(0))
   238  
   239  	err = t.FinishBootstrap(int64(1))
   240  	c.Assert(err, IsNil)
   241  
   242  	bootstrapVer, err = t.GetBootstrapVersion()
   243  	c.Assert(err, IsNil)
   244  	c.Assert(bootstrapVer, Equals, int64(1))
   245  
   246  	// Test case for spacetime.FinishBootstrap with a version.
   247  	err = t.FinishBootstrap(int64(10))
   248  	c.Assert(err, IsNil)
   249  	bootstrapVer, err = t.GetBootstrapVersion()
   250  	c.Assert(err, IsNil)
   251  	c.Assert(bootstrapVer, Equals, int64(10))
   252  
   253  	// Test case for SchemaDiff.
   254  	schemaDiff := &perceptron.SchemaDiff{
   255  		Version:    100,
   256  		SchemaID:   1,
   257  		Type:       perceptron.CausetActionTruncateBlock,
   258  		BlockID:    2,
   259  		OldBlockID: 3,
   260  	}
   261  	err = t.SetSchemaDiff(schemaDiff)
   262  	c.Assert(err, IsNil)
   263  	readDiff, err := t.GetSchemaDiff(schemaDiff.Version)
   264  	c.Assert(err, IsNil)
   265  	c.Assert(readDiff, DeepEquals, schemaDiff)
   266  
   267  	err = txn.Commit(context.Background())
   268  	c.Assert(err, IsNil)
   269  
   270  	// Test for DBSJobHistoryKey.
   271  	key = spacetime.DBSJobHistoryKey(t, 888)
   272  	c.Assert(key, DeepEquals, []byte{0x6d, 0x44, 0x44, 0x4c, 0x4a, 0x6f, 0x62, 0x48, 0x69, 0xff, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x78, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf7})
   273  }
   274  
   275  func (s *testSuite) TestSnapshot(c *C) {
   276  	defer testleak.AfterTest(c)()
   277  	causetstore, err := mockstore.NewMockStore()
   278  	c.Assert(err, IsNil)
   279  	defer causetstore.Close()
   280  
   281  	txn, _ := causetstore.Begin()
   282  	m := spacetime.NewMeta(txn)
   283  	m.GenGlobalID()
   284  	n, _ := m.GetGlobalID()
   285  	c.Assert(n, Equals, int64(1))
   286  	txn.Commit(context.Background())
   287  
   288  	ver1, _ := causetstore.CurrentVersion()
   289  	time.Sleep(time.Millisecond)
   290  	txn, _ = causetstore.Begin()
   291  	m = spacetime.NewMeta(txn)
   292  	m.GenGlobalID()
   293  	n, _ = m.GetGlobalID()
   294  	c.Assert(n, Equals, int64(2))
   295  	txn.Commit(context.Background())
   296  
   297  	snapshot, _ := causetstore.GetSnapshot(ver1)
   298  	snapMeta := spacetime.NewSnapshotMeta(snapshot)
   299  	n, _ = snapMeta.GetGlobalID()
   300  	c.Assert(n, Equals, int64(1))
   301  	_, err = snapMeta.GenGlobalID()
   302  	c.Assert(err, NotNil)
   303  	c.Assert(err.Error(), Equals, "[structure:8220]write on snapshot")
   304  }
   305  
   306  func (s *testSuite) TestDBS(c *C) {
   307  	defer testleak.AfterTest(c)()
   308  	causetstore, err := mockstore.NewMockStore()
   309  	c.Assert(err, IsNil)
   310  	defer causetstore.Close()
   311  
   312  	txn, err := causetstore.Begin()
   313  	c.Assert(err, IsNil)
   314  
   315  	defer txn.Rollback()
   316  
   317  	t := spacetime.NewMeta(txn)
   318  
   319  	job := &perceptron.Job{ID: 1}
   320  	err = t.EnQueueDBSJob(job)
   321  	c.Assert(err, IsNil)
   322  	n, err := t.DBSJobQueueLen()
   323  	c.Assert(err, IsNil)
   324  	c.Assert(n, Equals, int64(1))
   325  
   326  	v, err := t.GetDBSJobByIdx(0)
   327  	c.Assert(err, IsNil)
   328  	c.Assert(v, DeepEquals, job)
   329  	v, err = t.GetDBSJobByIdx(1)
   330  	c.Assert(err, IsNil)
   331  	c.Assert(v, IsNil)
   332  	job.ID = 2
   333  	err = t.UFIDelateDBSJob(0, job, true)
   334  	c.Assert(err, IsNil)
   335  
   336  	// There are 3 spacetime key relate to index reorganization:
   337  	// start_handle, end_handle and physical_block_id.
   338  	// Only start_handle is initialized.
   339  	err = t.UFIDelateDBSReorgStartHandle(job, ekv.IntHandle(1))
   340  	c.Assert(err, IsNil)
   341  
   342  	// Since physical_block_id is uninitialized, we simulate older MilevaDB version that doesn't causetstore them.
   343  	// In this case GetDBSReorgHandle always return maxInt64 as end_handle.
   344  	i, j, k, err := t.GetDBSReorgHandle(job, false)
   345  	c.Assert(err, IsNil)
   346  	c.Assert(i, HandleEquals, ekv.IntHandle(1))
   347  	c.Assert(j, HandleEquals, ekv.IntHandle(math.MaxInt64))
   348  	c.Assert(k, Equals, int64(0))
   349  
   350  	startHandle := s.NewHandle().Int(1).Common("abc", 1222, "string")
   351  	endHandle := s.NewHandle().Int(2).Common("dddd", 1222, "string")
   352  	err = t.UFIDelateDBSReorgHandle(job, startHandle, endHandle, 3)
   353  	c.Assert(err, IsNil)
   354  
   355  	i, j, k, err = t.GetDBSReorgHandle(job, s.IsCommonHandle)
   356  	c.Assert(err, IsNil)
   357  	c.Assert(i, HandleEquals, startHandle)
   358  	c.Assert(j, HandleEquals, endHandle)
   359  	c.Assert(k, Equals, int64(3))
   360  
   361  	err = t.RemoveDBSReorgHandle(job)
   362  	c.Assert(err, IsNil)
   363  
   364  	// new MilevaDB binary running on old MilevaDB DBS reorg data.
   365  	i, j, k, err = t.GetDBSReorgHandle(job, s.IsCommonHandle)
   366  	c.Assert(err, IsNil)
   367  	c.Assert(i, IsNil)
   368  	// The default value for endHandle is MaxInt64, not 0.
   369  	c.Assert(j, HandleEquals, ekv.IntHandle(math.MaxInt64))
   370  	c.Assert(k, Equals, int64(0))
   371  
   372  	// Test GetDBSReorgHandle failed.
   373  	_, _, _, err = t.GetDBSReorgHandle(job, s.IsCommonHandle)
   374  	c.Assert(err, IsNil)
   375  
   376  	v, err = t.DeQueueDBSJob()
   377  	c.Assert(err, IsNil)
   378  	c.Assert(v, DeepEquals, job)
   379  
   380  	err = t.AddHistoryDBSJob(job, true)
   381  	c.Assert(err, IsNil)
   382  	v, err = t.GetHistoryDBSJob(2)
   383  	c.Assert(err, IsNil)
   384  	c.Assert(v, DeepEquals, job)
   385  
   386  	// Add multiple history jobs.
   387  	arg := "test arg"
   388  	historyJob1 := &perceptron.Job{ID: 1234}
   389  	historyJob1.Args = append(job.Args, arg)
   390  	err = t.AddHistoryDBSJob(historyJob1, true)
   391  	c.Assert(err, IsNil)
   392  	historyJob2 := &perceptron.Job{ID: 123}
   393  	historyJob2.Args = append(job.Args, arg)
   394  	err = t.AddHistoryDBSJob(historyJob2, false)
   395  	c.Assert(err, IsNil)
   396  	all, err := t.GetAllHistoryDBSJobs()
   397  	c.Assert(err, IsNil)
   398  	var lastID int64
   399  	for _, job := range all {
   400  		c.Assert(job.ID, Greater, lastID)
   401  		lastID = job.ID
   402  		arg1 := ""
   403  		job.DecodeArgs(&arg1)
   404  		if job.ID == historyJob1.ID {
   405  			c.Assert(*(job.Args[0].(*string)), Equals, historyJob1.Args[0])
   406  		} else {
   407  			c.Assert(job.Args, HasLen, 0)
   408  		}
   409  	}
   410  
   411  	// Test for get last N history dbs jobs.
   412  	historyJobs, err := t.GetLastNHistoryDBSJobs(2)
   413  	c.Assert(err, IsNil)
   414  	c.Assert(len(historyJobs), Equals, 2)
   415  	c.Assert(historyJobs[0].ID == 1234, IsTrue)
   416  	c.Assert(historyJobs[1].ID == 123, IsTrue)
   417  
   418  	// Test GetAllDBSJobsInQueue.
   419  	err = t.EnQueueDBSJob(job)
   420  	c.Assert(err, IsNil)
   421  	job1 := &perceptron.Job{ID: 2}
   422  	err = t.EnQueueDBSJob(job1)
   423  	c.Assert(err, IsNil)
   424  	jobs, err := t.GetAllDBSJobsInQueue()
   425  	c.Assert(err, IsNil)
   426  	expectJobs := []*perceptron.Job{job, job1}
   427  	c.Assert(jobs, DeepEquals, expectJobs)
   428  
   429  	err = txn.Commit(context.Background())
   430  	c.Assert(err, IsNil)
   431  
   432  	// Test for add index job.
   433  	txn1, err := causetstore.Begin()
   434  	c.Assert(err, IsNil)
   435  	defer txn1.Rollback()
   436  
   437  	m := spacetime.NewMeta(txn1, spacetime.AddIndexJobListKey)
   438  	err = m.EnQueueDBSJob(job)
   439  	c.Assert(err, IsNil)
   440  	job.ID = 123
   441  	err = m.UFIDelateDBSJob(0, job, true, spacetime.AddIndexJobListKey)
   442  	c.Assert(err, IsNil)
   443  	v, err = m.GetDBSJobByIdx(0, spacetime.AddIndexJobListKey)
   444  	c.Assert(err, IsNil)
   445  	c.Assert(v, DeepEquals, job)
   446  	l, err := m.DBSJobQueueLen(spacetime.AddIndexJobListKey)
   447  	c.Assert(err, IsNil)
   448  	c.Assert(l, Equals, int64(1))
   449  	jobs, err = m.GetAllDBSJobsInQueue(spacetime.AddIndexJobListKey)
   450  	c.Assert(err, IsNil)
   451  	expectJobs = []*perceptron.Job{job}
   452  	c.Assert(jobs, DeepEquals, expectJobs)
   453  
   454  	err = txn1.Commit(context.Background())
   455  	c.Assert(err, IsNil)
   456  
   457  	s.RerunWithCommonHandleEnabled(c, s.TestDBS)
   458  }
   459  
   460  func (s *testSuite) BenchmarkGenGlobalIDs(c *C) {
   461  	defer testleak.AfterTest(c)()
   462  	causetstore, err := mockstore.NewMockStore()
   463  	c.Assert(err, IsNil)
   464  	defer causetstore.Close()
   465  
   466  	txn, err := causetstore.Begin()
   467  	c.Assert(err, IsNil)
   468  	defer txn.Rollback()
   469  
   470  	t := spacetime.NewMeta(txn)
   471  
   472  	c.ResetTimer()
   473  	var ids []int64
   474  	for i := 0; i < c.N; i++ {
   475  		ids, _ = t.GenGlobalIDs(10)
   476  	}
   477  	c.Assert(ids, HasLen, 10)
   478  	c.Assert(ids[9], Equals, int64(c.N)*10)
   479  }
   480  
   481  func (s *testSuite) BenchmarkGenGlobalIDOneByOne(c *C) {
   482  	defer testleak.AfterTest(c)()
   483  	causetstore, err := mockstore.NewMockStore()
   484  	c.Assert(err, IsNil)
   485  	defer causetstore.Close()
   486  
   487  	txn, err := causetstore.Begin()
   488  	c.Assert(err, IsNil)
   489  	defer txn.Rollback()
   490  
   491  	t := spacetime.NewMeta(txn)
   492  
   493  	c.ResetTimer()
   494  	var id int64
   495  	for i := 0; i < c.N; i++ {
   496  		for j := 0; j < 10; j++ {
   497  			id, _ = t.GenGlobalID()
   498  		}
   499  	}
   500  	c.Assert(id, Equals, int64(c.N)*10)
   501  }
   502  
   503  func anyMatch(c *C, ids []int64, candidates ...[]int64) {
   504  	var match bool
   505  OUTER:
   506  	for _, cand := range candidates {
   507  		if len(ids) != len(cand) {
   508  			continue
   509  		}
   510  		for i, v := range cand {
   511  			if ids[i] != v {
   512  				continue OUTER
   513  			}
   514  		}
   515  		match = true
   516  		break
   517  	}
   518  	c.Assert(match, IsTrue)
   519  }
   520  
   521  func mustNewCommonHandle(c *C, values ...interface{}) *ekv.CommonHandle {
   522  	encoded, err := codec.EncodeKey(new(stmtctx.StatementContext), nil, types.MakeCausets(values...)...)
   523  	c.Assert(err, IsNil)
   524  	ch, err := ekv.NewCommonHandle(encoded)
   525  	c.Assert(err, IsNil)
   526  	return ch
   527  }