github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/admin/admin_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 admin_test
    15  
    16  import (
    17  	"testing"
    18  
    19  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    20  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    21  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    22  	. "github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    24  	"github.com/whtcorpsinc/milevadb/ekv"
    25  	. "github.com/whtcorpsinc/milevadb/soliton/admin"
    26  	"github.com/whtcorpsinc/milevadb/soliton/mock"
    27  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    28  	"github.com/whtcorpsinc/milevadb/spacetime"
    29  )
    30  
    31  func TestT(t *testing.T) {
    32  	CustomVerboseFlag = true
    33  	TestingT(t)
    34  }
    35  
    36  var _ = Suite(&testSuite{})
    37  
    38  type testSuite struct {
    39  	causetstore ekv.CausetStorage
    40  	ctx         *mock.Context
    41  }
    42  
    43  func (s *testSuite) SetUpSuite(c *C) {
    44  	testleak.BeforeTest()
    45  	var err error
    46  	s.causetstore, err = mockstore.NewMockStore()
    47  	c.Assert(err, IsNil)
    48  	s.ctx = mock.NewContext()
    49  	s.ctx.CausetStore = s.causetstore
    50  }
    51  
    52  func (s *testSuite) TearDownSuite(c *C) {
    53  	err := s.causetstore.Close()
    54  	c.Assert(err, IsNil)
    55  	testleak.AfterTest(c)()
    56  }
    57  
    58  func (s *testSuite) TestGetDBSInfo(c *C) {
    59  	txn, err := s.causetstore.Begin()
    60  	c.Assert(err, IsNil)
    61  	t := spacetime.NewMeta(txn)
    62  
    63  	dbInfo2 := &perceptron.DBInfo{
    64  		ID:    2,
    65  		Name:  perceptron.NewCIStr("b"),
    66  		State: perceptron.StateNone,
    67  	}
    68  	job := &perceptron.Job{
    69  		SchemaID: dbInfo2.ID,
    70  		Type:     perceptron.CausetActionCreateSchema,
    71  		RowCount: 0,
    72  	}
    73  	job1 := &perceptron.Job{
    74  		SchemaID: dbInfo2.ID,
    75  		Type:     perceptron.CausetActionAddIndex,
    76  		RowCount: 0,
    77  	}
    78  	err = t.EnQueueDBSJob(job)
    79  	c.Assert(err, IsNil)
    80  	info, err := GetDBSInfo(txn)
    81  	c.Assert(err, IsNil)
    82  	c.Assert(info.Jobs, HasLen, 1)
    83  	c.Assert(info.Jobs[0], DeepEquals, job)
    84  	c.Assert(info.ReorgHandle, Equals, nil)
    85  	// Two jobs.
    86  	t = spacetime.NewMeta(txn, spacetime.AddIndexJobListKey)
    87  	err = t.EnQueueDBSJob(job1)
    88  	c.Assert(err, IsNil)
    89  	info, err = GetDBSInfo(txn)
    90  	c.Assert(err, IsNil)
    91  	c.Assert(info.Jobs, HasLen, 2)
    92  	c.Assert(info.Jobs[0], DeepEquals, job)
    93  	c.Assert(info.Jobs[1], DeepEquals, job1)
    94  	c.Assert(info.ReorgHandle, Equals, nil)
    95  	err = txn.Rollback()
    96  	c.Assert(err, IsNil)
    97  }
    98  
    99  func (s *testSuite) TestGetDBSJobs(c *C) {
   100  	txn, err := s.causetstore.Begin()
   101  	c.Assert(err, IsNil)
   102  	t := spacetime.NewMeta(txn)
   103  	cnt := 10
   104  	jobs := make([]*perceptron.Job, cnt)
   105  	var currJobs2 []*perceptron.Job
   106  	for i := 0; i < cnt; i++ {
   107  		jobs[i] = &perceptron.Job{
   108  			ID:       int64(i),
   109  			SchemaID: 1,
   110  			Type:     perceptron.CausetActionCreateBlock,
   111  		}
   112  		err = t.EnQueueDBSJob(jobs[i])
   113  		c.Assert(err, IsNil)
   114  		currJobs, err1 := GetDBSJobs(txn)
   115  		c.Assert(err1, IsNil)
   116  		c.Assert(currJobs, HasLen, i+1)
   117  		currJobs2 = currJobs2[:0]
   118  		err = IterAllDBSJobs(txn, func(jobs []*perceptron.Job) (b bool, e error) {
   119  			for _, job := range jobs {
   120  				if job.State == perceptron.JobStateNone {
   121  					currJobs2 = append(currJobs2, job)
   122  				} else {
   123  					return true, nil
   124  				}
   125  			}
   126  			return false, nil
   127  		})
   128  		c.Assert(err, IsNil)
   129  		c.Assert(currJobs2, HasLen, i+1)
   130  	}
   131  
   132  	currJobs, err := GetDBSJobs(txn)
   133  	c.Assert(err, IsNil)
   134  	for i, job := range jobs {
   135  		c.Assert(job.ID, Equals, currJobs[i].ID)
   136  		c.Assert(job.SchemaID, Equals, int64(1))
   137  		c.Assert(job.Type, Equals, perceptron.CausetActionCreateBlock)
   138  	}
   139  	c.Assert(currJobs, DeepEquals, currJobs2)
   140  
   141  	err = txn.Rollback()
   142  	c.Assert(err, IsNil)
   143  }
   144  
   145  func isJobsSorted(jobs []*perceptron.Job) bool {
   146  	if len(jobs) <= 1 {
   147  		return true
   148  	}
   149  	for i := 1; i < len(jobs); i++ {
   150  		if jobs[i].ID <= jobs[i-1].ID {
   151  			return false
   152  		}
   153  	}
   154  	return true
   155  }
   156  
   157  func enQueueDBSJobs(c *C, t *spacetime.Meta, jobType perceptron.CausetActionType, start, end int) {
   158  	for i := start; i < end; i++ {
   159  		job := &perceptron.Job{
   160  			ID:       int64(i),
   161  			SchemaID: 1,
   162  			Type:     jobType,
   163  		}
   164  		err := t.EnQueueDBSJob(job)
   165  		c.Assert(err, IsNil)
   166  	}
   167  }
   168  
   169  func (s *testSuite) TestGetDBSJobsIsSort(c *C) {
   170  	txn, err := s.causetstore.Begin()
   171  	c.Assert(err, IsNil)
   172  
   173  	// insert 5 drop causet jobs to DefaultJobListKey queue
   174  	t := spacetime.NewMeta(txn)
   175  	enQueueDBSJobs(c, t, perceptron.CausetActionDropBlock, 10, 15)
   176  
   177  	// insert 5 create causet jobs to DefaultJobListKey queue
   178  	enQueueDBSJobs(c, t, perceptron.CausetActionCreateBlock, 0, 5)
   179  
   180  	// insert add index jobs to AddIndexJobListKey queue
   181  	t = spacetime.NewMeta(txn, spacetime.AddIndexJobListKey)
   182  	enQueueDBSJobs(c, t, perceptron.CausetActionAddIndex, 5, 10)
   183  
   184  	currJobs, err := GetDBSJobs(txn)
   185  	c.Assert(err, IsNil)
   186  	c.Assert(currJobs, HasLen, 15)
   187  
   188  	isSort := isJobsSorted(currJobs)
   189  	c.Assert(isSort, Equals, true)
   190  
   191  	err = txn.Rollback()
   192  	c.Assert(err, IsNil)
   193  }
   194  
   195  func (s *testSuite) TestCancelJobs(c *C) {
   196  	txn, err := s.causetstore.Begin()
   197  	c.Assert(err, IsNil)
   198  	t := spacetime.NewMeta(txn)
   199  	cnt := 10
   200  	ids := make([]int64, cnt)
   201  	for i := 0; i < cnt; i++ {
   202  		job := &perceptron.Job{
   203  			ID:       int64(i),
   204  			SchemaID: 1,
   205  			Type:     perceptron.CausetActionCreateBlock,
   206  		}
   207  		if i == 0 {
   208  			job.State = perceptron.JobStateDone
   209  		}
   210  		if i == 1 {
   211  			job.State = perceptron.JobStateCancelled
   212  		}
   213  		ids[i] = int64(i)
   214  		err = t.EnQueueDBSJob(job)
   215  		c.Assert(err, IsNil)
   216  	}
   217  
   218  	errs, err := CancelJobs(txn, ids)
   219  	c.Assert(err, IsNil)
   220  	for i, err := range errs {
   221  		if i == 0 {
   222  			c.Assert(err, NotNil)
   223  			continue
   224  		}
   225  		c.Assert(err, IsNil)
   226  	}
   227  
   228  	errs, err = CancelJobs(txn, []int64{})
   229  	c.Assert(err, IsNil)
   230  	c.Assert(errs, IsNil)
   231  	errs, err = CancelJobs(txn, []int64{-1})
   232  	c.Assert(err, IsNil)
   233  	c.Assert(errs[0], NotNil)
   234  	c.Assert(errs[0].Error(), Matches, "*DBS Job:-1 not found")
   235  
   236  	// test cancel finish job.
   237  	job := &perceptron.Job{
   238  		ID:       100,
   239  		SchemaID: 1,
   240  		Type:     perceptron.CausetActionCreateBlock,
   241  		State:    perceptron.JobStateDone,
   242  	}
   243  	err = t.EnQueueDBSJob(job)
   244  	c.Assert(err, IsNil)
   245  	errs, err = CancelJobs(txn, []int64{100})
   246  	c.Assert(err, IsNil)
   247  	c.Assert(errs[0], NotNil)
   248  	c.Assert(errs[0].Error(), Matches, "*This job:100 is finished, so can't be cancelled")
   249  
   250  	// test can't cancelable job.
   251  	job.Type = perceptron.CausetActionDropIndex
   252  	job.SchemaState = perceptron.StateWriteOnly
   253  	job.State = perceptron.JobStateRunning
   254  	job.ID = 101
   255  	err = t.EnQueueDBSJob(job)
   256  	c.Assert(err, IsNil)
   257  	errs, err = CancelJobs(txn, []int64{101})
   258  	c.Assert(err, IsNil)
   259  	c.Assert(errs[0], NotNil)
   260  	c.Assert(errs[0].Error(), Matches, "*This job:101 is almost finished, can't be cancelled now")
   261  
   262  	// When both types of jobs exist in the DBS queue,
   263  	// we first cancel the job with a larger ID.
   264  	job = &perceptron.Job{
   265  		ID:       1000,
   266  		SchemaID: 1,
   267  		BlockID:  2,
   268  		Type:     perceptron.CausetActionAddIndex,
   269  	}
   270  	job1 := &perceptron.Job{
   271  		ID:       1001,
   272  		SchemaID: 1,
   273  		BlockID:  2,
   274  		Type:     perceptron.CausetActionAddDeferredCauset,
   275  	}
   276  	job2 := &perceptron.Job{
   277  		ID:       1002,
   278  		SchemaID: 1,
   279  		BlockID:  2,
   280  		Type:     perceptron.CausetActionAddIndex,
   281  	}
   282  	job3 := &perceptron.Job{
   283  		ID:       1003,
   284  		SchemaID: 1,
   285  		BlockID:  2,
   286  		Type:     perceptron.CausetActionRepairBlock,
   287  	}
   288  	err = t.EnQueueDBSJob(job, spacetime.AddIndexJobListKey)
   289  	c.Assert(err, IsNil)
   290  	err = t.EnQueueDBSJob(job1)
   291  	c.Assert(err, IsNil)
   292  	err = t.EnQueueDBSJob(job2, spacetime.AddIndexJobListKey)
   293  	c.Assert(err, IsNil)
   294  	err = t.EnQueueDBSJob(job3)
   295  	c.Assert(err, IsNil)
   296  	errs, err = CancelJobs(txn, []int64{job1.ID, job.ID, job2.ID, job3.ID})
   297  	c.Assert(err, IsNil)
   298  	for _, err := range errs {
   299  		c.Assert(err, IsNil)
   300  	}
   301  
   302  	err = txn.Rollback()
   303  	c.Assert(err, IsNil)
   304  }
   305  
   306  func (s *testSuite) TestGetHistoryDBSJobs(c *C) {
   307  	txn, err := s.causetstore.Begin()
   308  	c.Assert(err, IsNil)
   309  	t := spacetime.NewMeta(txn)
   310  	cnt := 11
   311  	jobs := make([]*perceptron.Job, cnt)
   312  	for i := 0; i < cnt; i++ {
   313  		jobs[i] = &perceptron.Job{
   314  			ID:       int64(i),
   315  			SchemaID: 1,
   316  			Type:     perceptron.CausetActionCreateBlock,
   317  		}
   318  		err = t.AddHistoryDBSJob(jobs[i], true)
   319  		c.Assert(err, IsNil)
   320  		historyJobs, err1 := GetHistoryDBSJobs(txn, DefNumHistoryJobs)
   321  		c.Assert(err1, IsNil)
   322  		if i+1 > MaxHistoryJobs {
   323  			c.Assert(historyJobs, HasLen, MaxHistoryJobs)
   324  		} else {
   325  			c.Assert(historyJobs, HasLen, i+1)
   326  		}
   327  	}
   328  
   329  	delta := cnt - MaxHistoryJobs
   330  	historyJobs, err := GetHistoryDBSJobs(txn, DefNumHistoryJobs)
   331  	c.Assert(err, IsNil)
   332  	c.Assert(historyJobs, HasLen, MaxHistoryJobs)
   333  	l := len(historyJobs) - 1
   334  	for i, job := range historyJobs {
   335  		c.Assert(job.ID, Equals, jobs[delta+l-i].ID)
   336  		c.Assert(job.SchemaID, Equals, int64(1))
   337  		c.Assert(job.Type, Equals, perceptron.CausetActionCreateBlock)
   338  	}
   339  
   340  	var historyJobs2 []*perceptron.Job
   341  	err = IterHistoryDBSJobs(txn, func(jobs []*perceptron.Job) (b bool, e error) {
   342  		for _, job := range jobs {
   343  			historyJobs2 = append(historyJobs2, job)
   344  			if len(historyJobs2) == DefNumHistoryJobs {
   345  				return true, nil
   346  			}
   347  		}
   348  		return false, nil
   349  	})
   350  	c.Assert(err, IsNil)
   351  	c.Assert(historyJobs2, DeepEquals, historyJobs)
   352  
   353  	err = txn.Rollback()
   354  	c.Assert(err, IsNil)
   355  }
   356  
   357  func (s *testSuite) TestIsJobRollbackable(c *C) {
   358  	cases := []struct {
   359  		tp     perceptron.CausetActionType
   360  		state  perceptron.SchemaState
   361  		result bool
   362  	}{
   363  		{perceptron.CausetActionDropIndex, perceptron.StateNone, true},
   364  		{perceptron.CausetActionDropIndex, perceptron.StateDeleteOnly, false},
   365  		{perceptron.CausetActionDropSchema, perceptron.StateDeleteOnly, false},
   366  		{perceptron.CausetActionDropDeferredCauset, perceptron.StateDeleteOnly, false},
   367  		{perceptron.CausetActionDropDeferredCausets, perceptron.StateDeleteOnly, false},
   368  	}
   369  	job := &perceptron.Job{}
   370  	for _, ca := range cases {
   371  		job.Type = ca.tp
   372  		job.SchemaState = ca.state
   373  		re := IsJobRollbackable(job)
   374  		c.Assert(re == ca.result, IsTrue)
   375  	}
   376  }
   377  
   378  func (s *testSuite) TestError(c *C) {
   379  	ekvErrs := []*terror.Error{
   380  		ErrDataInConsistent,
   381  		ErrDBSJobNotFound,
   382  		ErrCancelFinishedDBSJob,
   383  		ErrCannotCancelDBSJob,
   384  	}
   385  	for _, err := range ekvErrs {
   386  		code := terror.ToALLEGROSQLError(err).Code
   387  		c.Assert(code != allegrosql.ErrUnknown && code == uint16(err.Code()), IsTrue, Commentf("err: %v", err))
   388  	}
   389  }