github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/meta/meta.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
    15  
    16  import (
    17  	"encoding/binary"
    18  	"encoding/json"
    19  	"fmt"
    20  	"math"
    21  	"sort"
    22  	"strconv"
    23  	"strings"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    28  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    29  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    30  	"github.com/whtcorpsinc/errors"
    31  	"github.com/whtcorpsinc/milevadb/ekv"
    32  	"github.com/whtcorpsinc/milevadb/metrics"
    33  	"github.com/whtcorpsinc/milevadb/soliton/logutil"
    34  	"github.com/whtcorpsinc/milevadb/structure"
    35  	"go.uber.org/zap"
    36  )
    37  
    38  var (
    39  	globalIDMutex sync.Mutex
    40  )
    41  
    42  // Meta structure:
    43  //	NextGlobalID -> int64
    44  //	SchemaVersion -> int64
    45  //	DBs -> {
    46  //		EDB:1 -> EDB spacetime data []byte
    47  //		EDB:2 -> EDB spacetime data []byte
    48  //	}
    49  //	EDB:1 -> {
    50  //		Block:1 -> causet spacetime data []byte
    51  //		Block:2 -> causet spacetime data []byte
    52  //		TID:1 -> int64
    53  //		TID:2 -> int64
    54  //	}
    55  //
    56  
    57  var (
    58  	mMetaPrefix       = []byte("m")
    59  	mNextGlobalIDKey  = []byte("NextGlobalID")
    60  	mSchemaVersionKey = []byte("SchemaVersionKey")
    61  	mDBs              = []byte("DBs")
    62  	mDBPrefix         = "EDB"
    63  	mBlockPrefix      = "Block"
    64  	mSequencePrefix   = "SID"
    65  	mSeqCyclePrefix   = "SequenceCycle"
    66  	mBlockIDPrefix    = "TID"
    67  	mRandomIDPrefix   = "TARID"
    68  	mBootstrapKey     = []byte("BootstrapKey")
    69  	mSchemaDiffPrefix = "Diff"
    70  )
    71  
    72  var (
    73  	// ErrDBExists is the error for EDB exists.
    74  	ErrDBExists = terror.ClassMeta.New(allegrosql.ErrDBCreateExists, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrDBCreateExists])
    75  	// ErrDBNotExists is the error for EDB not exists.
    76  	ErrDBNotExists = terror.ClassMeta.New(allegrosql.ErrBadDB, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrBadDB])
    77  	// ErrBlockExists is the error for causet exists.
    78  	ErrBlockExists = terror.ClassMeta.New(allegrosql.ErrBlockExists, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrBlockExists])
    79  	// ErrBlockNotExists is the error for causet not exists.
    80  	ErrBlockNotExists = terror.ClassMeta.New(allegrosql.ErrNoSuchBlock, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrNoSuchBlock])
    81  )
    82  
    83  // Meta is for handling spacetime information in a transaction.
    84  type Meta struct {
    85  	txn        *structure.TxStructure
    86  	StartTS    uint64 // StartTS is the txn's start TS.
    87  	jobListKey JobListKeyType
    88  }
    89  
    90  // NewMeta creates a Meta in transaction txn.
    91  // If the current Meta needs to handle a job, jobListKey is the type of the job's list.
    92  func NewMeta(txn ekv.Transaction, jobListKeys ...JobListKeyType) *Meta {
    93  	txn.SetOption(ekv.Priority, ekv.PriorityHigh)
    94  	txn.SetOption(ekv.SyncLog, true)
    95  	t := structure.NewStructure(txn, txn, mMetaPrefix)
    96  	listKey := DefaultJobListKey
    97  	if len(jobListKeys) != 0 {
    98  		listKey = jobListKeys[0]
    99  	}
   100  	return &Meta{txn: t,
   101  		StartTS:    txn.StartTS(),
   102  		jobListKey: listKey,
   103  	}
   104  }
   105  
   106  // NewSnapshotMeta creates a Meta with snapshot.
   107  func NewSnapshotMeta(snapshot ekv.Snapshot) *Meta {
   108  	t := structure.NewStructure(snapshot, nil, mMetaPrefix)
   109  	return &Meta{txn: t}
   110  }
   111  
   112  // GenGlobalID generates next id globally.
   113  func (m *Meta) GenGlobalID() (int64, error) {
   114  	globalIDMutex.Lock()
   115  	defer globalIDMutex.Unlock()
   116  
   117  	return m.txn.Inc(mNextGlobalIDKey, 1)
   118  }
   119  
   120  // GenGlobalIDs generates the next n global IDs.
   121  func (m *Meta) GenGlobalIDs(n int) ([]int64, error) {
   122  	globalIDMutex.Lock()
   123  	defer globalIDMutex.Unlock()
   124  
   125  	newID, err := m.txn.Inc(mNextGlobalIDKey, int64(n))
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  	origID := newID - int64(n)
   130  	ids := make([]int64, 0, n)
   131  	for i := origID + 1; i <= newID; i++ {
   132  		ids = append(ids, i)
   133  	}
   134  	return ids, nil
   135  }
   136  
   137  // GetGlobalID gets current global id.
   138  func (m *Meta) GetGlobalID() (int64, error) {
   139  	return m.txn.GetInt64(mNextGlobalIDKey)
   140  }
   141  
   142  func (m *Meta) dbKey(dbID int64) []byte {
   143  	return []byte(fmt.Sprintf("%s:%d", mDBPrefix, dbID))
   144  }
   145  
   146  func (m *Meta) autoBlockIDKey(blockID int64) []byte {
   147  	return []byte(fmt.Sprintf("%s:%d", mBlockIDPrefix, blockID))
   148  }
   149  
   150  func (m *Meta) autoRandomBlockIDKey(blockID int64) []byte {
   151  	return []byte(fmt.Sprintf("%s:%d", mRandomIDPrefix, blockID))
   152  }
   153  
   154  func (m *Meta) blockKey(blockID int64) []byte {
   155  	return []byte(fmt.Sprintf("%s:%d", mBlockPrefix, blockID))
   156  }
   157  
   158  func (m *Meta) sequenceKey(sequenceID int64) []byte {
   159  	return []byte(fmt.Sprintf("%s:%d", mSequencePrefix, sequenceID))
   160  }
   161  
   162  func (m *Meta) sequenceCycleKey(sequenceID int64) []byte {
   163  	return []byte(fmt.Sprintf("%s:%d", mSeqCyclePrefix, sequenceID))
   164  }
   165  
   166  // DBSJobHistoryKey is only used for testing.
   167  func DBSJobHistoryKey(m *Meta, jobID int64) []byte {
   168  	return m.txn.EncodeHashDataKey(mDBSJobHistoryKey, m.jobIDKey(jobID))
   169  }
   170  
   171  // GenAutoBlockIDKeyValue generates spacetime key by dbID, blockID and corresponding value by autoID.
   172  func (m *Meta) GenAutoBlockIDKeyValue(dbID, blockID, autoID int64) (key, value []byte) {
   173  	dbKey := m.dbKey(dbID)
   174  	autoBlockIDKey := m.autoBlockIDKey(blockID)
   175  	return m.txn.EncodeHashAutoIDKeyValue(dbKey, autoBlockIDKey, autoID)
   176  }
   177  
   178  // GenAutoBlockID adds step to the auto ID of the causet and returns the sum.
   179  func (m *Meta) GenAutoBlockID(dbID, blockID, step int64) (int64, error) {
   180  	// Check if EDB exists.
   181  	dbKey := m.dbKey(dbID)
   182  	if err := m.checkDBExists(dbKey); err != nil {
   183  		return 0, errors.Trace(err)
   184  	}
   185  	// Check if causet exists.
   186  	blockKey := m.blockKey(blockID)
   187  	if err := m.checkBlockExists(dbKey, blockKey); err != nil {
   188  		return 0, errors.Trace(err)
   189  	}
   190  
   191  	return m.txn.HInc(dbKey, m.autoBlockIDKey(blockID), step)
   192  }
   193  
   194  // GenAutoRandomID adds step to the auto shard ID of the causet and returns the sum.
   195  func (m *Meta) GenAutoRandomID(dbID, blockID, step int64) (int64, error) {
   196  	// Check if EDB exists.
   197  	dbKey := m.dbKey(dbID)
   198  	if err := m.checkDBExists(dbKey); err != nil {
   199  		return 0, errors.Trace(err)
   200  	}
   201  	// Check if causet exists.
   202  	blockKey := m.blockKey(blockID)
   203  	if err := m.checkBlockExists(dbKey, blockKey); err != nil {
   204  		return 0, errors.Trace(err)
   205  	}
   206  
   207  	return m.txn.HInc(dbKey, m.autoRandomBlockIDKey(blockID), step)
   208  }
   209  
   210  // GetAutoBlockID gets current auto id with causet id.
   211  func (m *Meta) GetAutoBlockID(dbID int64, blockID int64) (int64, error) {
   212  	return m.txn.HGetInt64(m.dbKey(dbID), m.autoBlockIDKey(blockID))
   213  }
   214  
   215  // GetAutoRandomID gets current auto random id with causet id.
   216  func (m *Meta) GetAutoRandomID(dbID int64, blockID int64) (int64, error) {
   217  	return m.txn.HGetInt64(m.dbKey(dbID), m.autoRandomBlockIDKey(blockID))
   218  }
   219  
   220  // GenSequenceValue adds step to the sequence value and returns the sum.
   221  func (m *Meta) GenSequenceValue(dbID, sequenceID, step int64) (int64, error) {
   222  	// Check if EDB exists.
   223  	dbKey := m.dbKey(dbID)
   224  	if err := m.checkDBExists(dbKey); err != nil {
   225  		return 0, errors.Trace(err)
   226  	}
   227  	// Check if sequence exists.
   228  	blockKey := m.blockKey(sequenceID)
   229  	if err := m.checkBlockExists(dbKey, blockKey); err != nil {
   230  		return 0, errors.Trace(err)
   231  	}
   232  	return m.txn.HInc(dbKey, m.sequenceKey(sequenceID), step)
   233  }
   234  
   235  // GetSequenceValue gets current sequence value with sequence id.
   236  func (m *Meta) GetSequenceValue(dbID int64, sequenceID int64) (int64, error) {
   237  	return m.txn.HGetInt64(m.dbKey(dbID), m.sequenceKey(sequenceID))
   238  }
   239  
   240  // SetSequenceValue sets start value when sequence in cycle.
   241  func (m *Meta) SetSequenceValue(dbID int64, sequenceID int64, start int64) error {
   242  	return m.txn.HSet(m.dbKey(dbID), m.sequenceKey(sequenceID), []byte(strconv.FormatInt(start, 10)))
   243  }
   244  
   245  // GetSequenceCycle gets current sequence cycle times with sequence id.
   246  func (m *Meta) GetSequenceCycle(dbID int64, sequenceID int64) (int64, error) {
   247  	return m.txn.HGetInt64(m.dbKey(dbID), m.sequenceCycleKey(sequenceID))
   248  }
   249  
   250  // SetSequenceCycle sets cycle times value when sequence in cycle.
   251  func (m *Meta) SetSequenceCycle(dbID int64, sequenceID int64, round int64) error {
   252  	return m.txn.HSet(m.dbKey(dbID), m.sequenceCycleKey(sequenceID), []byte(strconv.FormatInt(round, 10)))
   253  }
   254  
   255  // GetSchemaVersion gets current global schemaReplicant version.
   256  func (m *Meta) GetSchemaVersion() (int64, error) {
   257  	return m.txn.GetInt64(mSchemaVersionKey)
   258  }
   259  
   260  // GenSchemaVersion generates next schemaReplicant version.
   261  func (m *Meta) GenSchemaVersion() (int64, error) {
   262  	return m.txn.Inc(mSchemaVersionKey, 1)
   263  }
   264  
   265  func (m *Meta) checkDBExists(dbKey []byte) error {
   266  	v, err := m.txn.HGet(mDBs, dbKey)
   267  	if err == nil && v == nil {
   268  		err = ErrDBNotExists.GenWithStack("database doesn't exist")
   269  	}
   270  	return errors.Trace(err)
   271  }
   272  
   273  func (m *Meta) checkDBNotExists(dbKey []byte) error {
   274  	v, err := m.txn.HGet(mDBs, dbKey)
   275  	if err == nil && v != nil {
   276  		err = ErrDBExists.GenWithStack("database already exists")
   277  	}
   278  	return errors.Trace(err)
   279  }
   280  
   281  func (m *Meta) checkBlockExists(dbKey []byte, blockKey []byte) error {
   282  	v, err := m.txn.HGet(dbKey, blockKey)
   283  	if err == nil && v == nil {
   284  		err = ErrBlockNotExists.GenWithStack("causet doesn't exist")
   285  	}
   286  	return errors.Trace(err)
   287  }
   288  
   289  func (m *Meta) checkBlockNotExists(dbKey []byte, blockKey []byte) error {
   290  	v, err := m.txn.HGet(dbKey, blockKey)
   291  	if err == nil && v != nil {
   292  		err = ErrBlockExists.GenWithStack("causet already exists")
   293  	}
   294  	return errors.Trace(err)
   295  }
   296  
   297  // CreateDatabase creates a database with EDB info.
   298  func (m *Meta) CreateDatabase(dbInfo *perceptron.DBInfo) error {
   299  	dbKey := m.dbKey(dbInfo.ID)
   300  
   301  	if err := m.checkDBNotExists(dbKey); err != nil {
   302  		return errors.Trace(err)
   303  	}
   304  
   305  	data, err := json.Marshal(dbInfo)
   306  	if err != nil {
   307  		return errors.Trace(err)
   308  	}
   309  
   310  	return m.txn.HSet(mDBs, dbKey, data)
   311  }
   312  
   313  // UFIDelateDatabase uFIDelates a database with EDB info.
   314  func (m *Meta) UFIDelateDatabase(dbInfo *perceptron.DBInfo) error {
   315  	dbKey := m.dbKey(dbInfo.ID)
   316  
   317  	if err := m.checkDBExists(dbKey); err != nil {
   318  		return errors.Trace(err)
   319  	}
   320  
   321  	data, err := json.Marshal(dbInfo)
   322  	if err != nil {
   323  		return errors.Trace(err)
   324  	}
   325  
   326  	return m.txn.HSet(mDBs, dbKey, data)
   327  }
   328  
   329  // CreateBlockOrView creates a causet with blockInfo in database.
   330  func (m *Meta) CreateBlockOrView(dbID int64, blockInfo *perceptron.BlockInfo) error {
   331  	// Check if EDB exists.
   332  	dbKey := m.dbKey(dbID)
   333  	if err := m.checkDBExists(dbKey); err != nil {
   334  		return errors.Trace(err)
   335  	}
   336  
   337  	// Check if causet exists.
   338  	blockKey := m.blockKey(blockInfo.ID)
   339  	if err := m.checkBlockNotExists(dbKey, blockKey); err != nil {
   340  		return errors.Trace(err)
   341  	}
   342  
   343  	data, err := json.Marshal(blockInfo)
   344  	if err != nil {
   345  		return errors.Trace(err)
   346  	}
   347  
   348  	return m.txn.HSet(dbKey, blockKey, data)
   349  }
   350  
   351  // CreateBlockAndSetAutoID creates a causet with blockInfo in database,
   352  // and rebases the causet autoID.
   353  func (m *Meta) CreateBlockAndSetAutoID(dbID int64, blockInfo *perceptron.BlockInfo, autoIncID, autoRandID int64) error {
   354  	err := m.CreateBlockOrView(dbID, blockInfo)
   355  	if err != nil {
   356  		return errors.Trace(err)
   357  	}
   358  	_, err = m.txn.HInc(m.dbKey(dbID), m.autoBlockIDKey(blockInfo.ID), autoIncID)
   359  	if err != nil {
   360  		return errors.Trace(err)
   361  	}
   362  	if blockInfo.AutoRandomBits > 0 {
   363  		_, err = m.txn.HInc(m.dbKey(dbID), m.autoRandomBlockIDKey(blockInfo.ID), autoRandID)
   364  		if err != nil {
   365  			return errors.Trace(err)
   366  		}
   367  	}
   368  	return nil
   369  }
   370  
   371  // CreateSequenceAndSetSeqValue creates sequence with blockInfo in database, and rebase the sequence seqValue.
   372  func (m *Meta) CreateSequenceAndSetSeqValue(dbID int64, blockInfo *perceptron.BlockInfo, seqValue int64) error {
   373  	err := m.CreateBlockOrView(dbID, blockInfo)
   374  	if err != nil {
   375  		return errors.Trace(err)
   376  	}
   377  	_, err = m.txn.HInc(m.dbKey(dbID), m.sequenceKey(blockInfo.ID), seqValue)
   378  	return errors.Trace(err)
   379  }
   380  
   381  // DroFIDelatabase drops whole database.
   382  func (m *Meta) DroFIDelatabase(dbID int64) error {
   383  	// Check if EDB exists.
   384  	dbKey := m.dbKey(dbID)
   385  	if err := m.txn.HClear(dbKey); err != nil {
   386  		return errors.Trace(err)
   387  	}
   388  
   389  	if err := m.txn.HDel(mDBs, dbKey); err != nil {
   390  		return errors.Trace(err)
   391  	}
   392  
   393  	return nil
   394  }
   395  
   396  // DropSequence drops sequence in database.
   397  // Sequence is made of causet struct and ekv value pair.
   398  func (m *Meta) DropSequence(dbID int64, tblID int64, delAutoID bool) error {
   399  	err := m.DropBlockOrView(dbID, tblID, delAutoID)
   400  	if err != nil {
   401  		return err
   402  	}
   403  	err = m.txn.HDel(m.dbKey(dbID), m.sequenceKey(tblID))
   404  	return errors.Trace(err)
   405  }
   406  
   407  // DropBlockOrView drops causet in database.
   408  // If delAutoID is true, it will delete the auto_increment id key-value of the causet.
   409  // For rename causet, we do not need to rename auto_increment id key-value.
   410  func (m *Meta) DropBlockOrView(dbID int64, tblID int64, delAutoID bool) error {
   411  	// Check if EDB exists.
   412  	dbKey := m.dbKey(dbID)
   413  	if err := m.checkDBExists(dbKey); err != nil {
   414  		return errors.Trace(err)
   415  	}
   416  
   417  	// Check if causet exists.
   418  	blockKey := m.blockKey(tblID)
   419  	if err := m.checkBlockExists(dbKey, blockKey); err != nil {
   420  		return errors.Trace(err)
   421  	}
   422  
   423  	if err := m.txn.HDel(dbKey, blockKey); err != nil {
   424  		return errors.Trace(err)
   425  	}
   426  	if delAutoID {
   427  		if err := m.txn.HDel(dbKey, m.autoBlockIDKey(tblID)); err != nil {
   428  			return errors.Trace(err)
   429  		}
   430  		if err := m.txn.HDel(dbKey, m.autoRandomBlockIDKey(tblID)); err != nil {
   431  			return errors.Trace(err)
   432  		}
   433  	}
   434  	return nil
   435  }
   436  
   437  // UFIDelateBlock uFIDelates the causet with causet info.
   438  func (m *Meta) UFIDelateBlock(dbID int64, blockInfo *perceptron.BlockInfo) error {
   439  	// Check if EDB exists.
   440  	dbKey := m.dbKey(dbID)
   441  	if err := m.checkDBExists(dbKey); err != nil {
   442  		return errors.Trace(err)
   443  	}
   444  
   445  	// Check if causet exists.
   446  	blockKey := m.blockKey(blockInfo.ID)
   447  	if err := m.checkBlockExists(dbKey, blockKey); err != nil {
   448  		return errors.Trace(err)
   449  	}
   450  
   451  	data, err := json.Marshal(blockInfo)
   452  	if err != nil {
   453  		return errors.Trace(err)
   454  	}
   455  
   456  	err = m.txn.HSet(dbKey, blockKey, data)
   457  	return errors.Trace(err)
   458  }
   459  
   460  // ListBlocks shows all blocks in database.
   461  func (m *Meta) ListBlocks(dbID int64) ([]*perceptron.BlockInfo, error) {
   462  	dbKey := m.dbKey(dbID)
   463  	if err := m.checkDBExists(dbKey); err != nil {
   464  		return nil, errors.Trace(err)
   465  	}
   466  
   467  	res, err := m.txn.HGetAll(dbKey)
   468  	if err != nil {
   469  		return nil, errors.Trace(err)
   470  	}
   471  
   472  	blocks := make([]*perceptron.BlockInfo, 0, len(res)/2)
   473  	for _, r := range res {
   474  		// only handle causet spacetime
   475  		blockKey := string(r.Field)
   476  		if !strings.HasPrefix(blockKey, mBlockPrefix) {
   477  			continue
   478  		}
   479  
   480  		tbInfo := &perceptron.BlockInfo{}
   481  		err = json.Unmarshal(r.Value, tbInfo)
   482  		if err != nil {
   483  			return nil, errors.Trace(err)
   484  		}
   485  
   486  		blocks = append(blocks, tbInfo)
   487  	}
   488  
   489  	return blocks, nil
   490  }
   491  
   492  // ListDatabases shows all databases.
   493  func (m *Meta) ListDatabases() ([]*perceptron.DBInfo, error) {
   494  	res, err := m.txn.HGetAll(mDBs)
   495  	if err != nil {
   496  		return nil, errors.Trace(err)
   497  	}
   498  
   499  	dbs := make([]*perceptron.DBInfo, 0, len(res))
   500  	for _, r := range res {
   501  		dbInfo := &perceptron.DBInfo{}
   502  		err = json.Unmarshal(r.Value, dbInfo)
   503  		if err != nil {
   504  			return nil, errors.Trace(err)
   505  		}
   506  		dbs = append(dbs, dbInfo)
   507  	}
   508  	return dbs, nil
   509  }
   510  
   511  // GetDatabase gets the database value with ID.
   512  func (m *Meta) GetDatabase(dbID int64) (*perceptron.DBInfo, error) {
   513  	dbKey := m.dbKey(dbID)
   514  	value, err := m.txn.HGet(mDBs, dbKey)
   515  	if err != nil || value == nil {
   516  		return nil, errors.Trace(err)
   517  	}
   518  
   519  	dbInfo := &perceptron.DBInfo{}
   520  	err = json.Unmarshal(value, dbInfo)
   521  	return dbInfo, errors.Trace(err)
   522  }
   523  
   524  // GetBlock gets the causet value in database with blockID.
   525  func (m *Meta) GetBlock(dbID int64, blockID int64) (*perceptron.BlockInfo, error) {
   526  	// Check if EDB exists.
   527  	dbKey := m.dbKey(dbID)
   528  	if err := m.checkDBExists(dbKey); err != nil {
   529  		return nil, errors.Trace(err)
   530  	}
   531  
   532  	blockKey := m.blockKey(blockID)
   533  	value, err := m.txn.HGet(dbKey, blockKey)
   534  	if err != nil || value == nil {
   535  		return nil, errors.Trace(err)
   536  	}
   537  
   538  	blockInfo := &perceptron.BlockInfo{}
   539  	err = json.Unmarshal(value, blockInfo)
   540  	return blockInfo, errors.Trace(err)
   541  }
   542  
   543  // DBS job structure
   544  //	DBSJobList: list jobs
   545  //	DBSJobHistory: hash
   546  //	DBSJobReorg: hash
   547  //
   548  // for multi DBS workers, only one can become the tenant
   549  // to operate DBS jobs, and dispatch them to MR Jobs.
   550  
   551  var (
   552  	mDBSJobListKey    = []byte("DBSJobList")
   553  	mDBSJobAddIdxList = []byte("DBSJobAddIdxList")
   554  	mDBSJobHistoryKey = []byte("DBSJobHistory")
   555  	mDBSJobReorgKey   = []byte("DBSJobReorg")
   556  )
   557  
   558  // JobListKeyType is a key type of the DBS job queue.
   559  type JobListKeyType []byte
   560  
   561  var (
   562  	// DefaultJobListKey keeps all actions of DBS jobs except "add index".
   563  	DefaultJobListKey JobListKeyType = mDBSJobListKey
   564  	// AddIndexJobListKey only keeps the action of adding index.
   565  	AddIndexJobListKey JobListKeyType = mDBSJobAddIdxList
   566  )
   567  
   568  func (m *Meta) enQueueDBSJob(key []byte, job *perceptron.Job) error {
   569  	b, err := job.Encode(true)
   570  	if err == nil {
   571  		err = m.txn.RPush(key, b)
   572  	}
   573  	return errors.Trace(err)
   574  }
   575  
   576  // EnQueueDBSJob adds a DBS job to the list.
   577  func (m *Meta) EnQueueDBSJob(job *perceptron.Job, jobListKeys ...JobListKeyType) error {
   578  	listKey := m.jobListKey
   579  	if len(jobListKeys) != 0 {
   580  		listKey = jobListKeys[0]
   581  	}
   582  
   583  	return m.enQueueDBSJob(listKey, job)
   584  }
   585  
   586  func (m *Meta) deQueueDBSJob(key []byte) (*perceptron.Job, error) {
   587  	value, err := m.txn.LPop(key)
   588  	if err != nil || value == nil {
   589  		return nil, errors.Trace(err)
   590  	}
   591  
   592  	job := &perceptron.Job{}
   593  	err = job.Decode(value)
   594  	return job, errors.Trace(err)
   595  }
   596  
   597  // DeQueueDBSJob pops a DBS job from the list.
   598  func (m *Meta) DeQueueDBSJob() (*perceptron.Job, error) {
   599  	return m.deQueueDBSJob(m.jobListKey)
   600  }
   601  
   602  func (m *Meta) getDBSJob(key []byte, index int64) (*perceptron.Job, error) {
   603  	value, err := m.txn.LIndex(key, index)
   604  	if err != nil || value == nil {
   605  		return nil, errors.Trace(err)
   606  	}
   607  
   608  	job := &perceptron.Job{
   609  		// For compatibility, if the job is enqueued by old version MilevaDB and Priority field is omitted,
   610  		// set the default priority to ekv.PriorityLow.
   611  		Priority: ekv.PriorityLow,
   612  	}
   613  	err = job.Decode(value)
   614  	// Check if the job.Priority is valid.
   615  	if job.Priority < ekv.PriorityNormal || job.Priority > ekv.PriorityHigh {
   616  		job.Priority = ekv.PriorityLow
   617  	}
   618  	return job, errors.Trace(err)
   619  }
   620  
   621  // GetDBSJobByIdx returns the corresponding DBS job by the index.
   622  // The length of jobListKeys can only be 1 or 0.
   623  // If its length is 1, we need to replace m.jobListKey with jobListKeys[0].
   624  // Otherwise, we use m.jobListKey directly.
   625  func (m *Meta) GetDBSJobByIdx(index int64, jobListKeys ...JobListKeyType) (*perceptron.Job, error) {
   626  	listKey := m.jobListKey
   627  	if len(jobListKeys) != 0 {
   628  		listKey = jobListKeys[0]
   629  	}
   630  
   631  	startTime := time.Now()
   632  	job, err := m.getDBSJob(listKey, index)
   633  	metrics.MetaHistogram.WithLabelValues(metrics.GetDBSJobByIdx, metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds())
   634  	return job, errors.Trace(err)
   635  }
   636  
   637  // uFIDelateDBSJob uFIDelates the DBS job with index and key.
   638  // uFIDelateRawArgs is used to determine whether to uFIDelate the raw args when encode the job.
   639  func (m *Meta) uFIDelateDBSJob(index int64, job *perceptron.Job, key []byte, uFIDelateRawArgs bool) error {
   640  	b, err := job.Encode(uFIDelateRawArgs)
   641  	if err == nil {
   642  		err = m.txn.LSet(key, index, b)
   643  	}
   644  	return errors.Trace(err)
   645  }
   646  
   647  // UFIDelateDBSJob uFIDelates the DBS job with index.
   648  // uFIDelateRawArgs is used to determine whether to uFIDelate the raw args when encode the job.
   649  // The length of jobListKeys can only be 1 or 0.
   650  // If its length is 1, we need to replace m.jobListKey with jobListKeys[0].
   651  // Otherwise, we use m.jobListKey directly.
   652  func (m *Meta) UFIDelateDBSJob(index int64, job *perceptron.Job, uFIDelateRawArgs bool, jobListKeys ...JobListKeyType) error {
   653  	listKey := m.jobListKey
   654  	if len(jobListKeys) != 0 {
   655  		listKey = jobListKeys[0]
   656  	}
   657  
   658  	startTime := time.Now()
   659  	err := m.uFIDelateDBSJob(index, job, listKey, uFIDelateRawArgs)
   660  	metrics.MetaHistogram.WithLabelValues(metrics.UFIDelateDBSJob, metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds())
   661  	return errors.Trace(err)
   662  }
   663  
   664  // DBSJobQueueLen returns the DBS job queue length.
   665  // The length of jobListKeys can only be 1 or 0.
   666  // If its length is 1, we need to replace m.jobListKey with jobListKeys[0].
   667  // Otherwise, we use m.jobListKey directly.
   668  func (m *Meta) DBSJobQueueLen(jobListKeys ...JobListKeyType) (int64, error) {
   669  	listKey := m.jobListKey
   670  	if len(jobListKeys) != 0 {
   671  		listKey = jobListKeys[0]
   672  	}
   673  	return m.txn.LLen(listKey)
   674  }
   675  
   676  // GetAllDBSJobsInQueue gets all DBS Jobs in the current queue.
   677  // The length of jobListKeys can only be 1 or 0.
   678  // If its length is 1, we need to replace m.jobListKey with jobListKeys[0].
   679  // Otherwise, we use m.jobListKey directly.
   680  func (m *Meta) GetAllDBSJobsInQueue(jobListKeys ...JobListKeyType) ([]*perceptron.Job, error) {
   681  	listKey := m.jobListKey
   682  	if len(jobListKeys) != 0 {
   683  		listKey = jobListKeys[0]
   684  	}
   685  
   686  	values, err := m.txn.LGetAll(listKey)
   687  	if err != nil || values == nil {
   688  		return nil, errors.Trace(err)
   689  	}
   690  
   691  	jobs := make([]*perceptron.Job, 0, len(values))
   692  	for _, val := range values {
   693  		job := &perceptron.Job{}
   694  		err = job.Decode(val)
   695  		if err != nil {
   696  			return nil, errors.Trace(err)
   697  		}
   698  		jobs = append(jobs, job)
   699  	}
   700  
   701  	return jobs, nil
   702  }
   703  
   704  func (m *Meta) jobIDKey(id int64) []byte {
   705  	b := make([]byte, 8)
   706  	binary.BigEndian.PutUint64(b, uint64(id))
   707  	return b
   708  }
   709  
   710  func (m *Meta) reorgJobStartHandle(id int64) []byte {
   711  	// There is no "_start", to make it compatible with the older MilevaDB versions.
   712  	return m.jobIDKey(id)
   713  }
   714  
   715  func (m *Meta) reorgJobEndHandle(id int64) []byte {
   716  	b := make([]byte, 8, 12)
   717  	binary.BigEndian.PutUint64(b, uint64(id))
   718  	b = append(b, "_end"...)
   719  	return b
   720  }
   721  
   722  func (m *Meta) reorgJobPhysicalBlockID(id int64) []byte {
   723  	b := make([]byte, 8, 12)
   724  	binary.BigEndian.PutUint64(b, uint64(id))
   725  	b = append(b, "_pid"...)
   726  	return b
   727  }
   728  
   729  func (m *Meta) addHistoryDBSJob(key []byte, job *perceptron.Job, uFIDelateRawArgs bool) error {
   730  	b, err := job.Encode(uFIDelateRawArgs)
   731  	if err == nil {
   732  		err = m.txn.HSet(key, m.jobIDKey(job.ID), b)
   733  	}
   734  	return errors.Trace(err)
   735  }
   736  
   737  // AddHistoryDBSJob adds DBS job to history.
   738  func (m *Meta) AddHistoryDBSJob(job *perceptron.Job, uFIDelateRawArgs bool) error {
   739  	return m.addHistoryDBSJob(mDBSJobHistoryKey, job, uFIDelateRawArgs)
   740  }
   741  
   742  func (m *Meta) getHistoryDBSJob(key []byte, id int64) (*perceptron.Job, error) {
   743  	value, err := m.txn.HGet(key, m.jobIDKey(id))
   744  	if err != nil || value == nil {
   745  		return nil, errors.Trace(err)
   746  	}
   747  
   748  	job := &perceptron.Job{}
   749  	err = job.Decode(value)
   750  	return job, errors.Trace(err)
   751  }
   752  
   753  // GetHistoryDBSJob gets a history DBS job.
   754  func (m *Meta) GetHistoryDBSJob(id int64) (*perceptron.Job, error) {
   755  	startTime := time.Now()
   756  	job, err := m.getHistoryDBSJob(mDBSJobHistoryKey, id)
   757  	metrics.MetaHistogram.WithLabelValues(metrics.GetHistoryDBSJob, metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds())
   758  	return job, errors.Trace(err)
   759  }
   760  
   761  // GetAllHistoryDBSJobs gets all history DBS jobs.
   762  func (m *Meta) GetAllHistoryDBSJobs() ([]*perceptron.Job, error) {
   763  	pairs, err := m.txn.HGetAll(mDBSJobHistoryKey)
   764  	if err != nil {
   765  		return nil, errors.Trace(err)
   766  	}
   767  	jobs, err := decodeJob(pairs)
   768  	if err != nil {
   769  		return nil, errors.Trace(err)
   770  	}
   771  	// sort job.
   772  	sorter := &jobsSorter{jobs: jobs}
   773  	sort.Sort(sorter)
   774  	return jobs, nil
   775  }
   776  
   777  // GetLastNHistoryDBSJobs gets latest N history dbs jobs.
   778  func (m *Meta) GetLastNHistoryDBSJobs(num int) ([]*perceptron.Job, error) {
   779  	pairs, err := m.txn.HGetLastN(mDBSJobHistoryKey, num)
   780  	if err != nil {
   781  		return nil, errors.Trace(err)
   782  	}
   783  	return decodeJob(pairs)
   784  }
   785  
   786  // LastJobIterator is the iterator for gets latest history.
   787  type LastJobIterator struct {
   788  	iter *structure.ReverseHashIterator
   789  }
   790  
   791  // GetLastHistoryDBSJobsIterator gets latest N history dbs jobs iterator.
   792  func (m *Meta) GetLastHistoryDBSJobsIterator() (*LastJobIterator, error) {
   793  	iter, err := structure.NewHashReverseIter(m.txn, mDBSJobHistoryKey)
   794  	if err != nil {
   795  		return nil, err
   796  	}
   797  	return &LastJobIterator{
   798  		iter: iter,
   799  	}, nil
   800  }
   801  
   802  // GetLastJobs gets last several jobs.
   803  func (i *LastJobIterator) GetLastJobs(num int, jobs []*perceptron.Job) ([]*perceptron.Job, error) {
   804  	if len(jobs) < num {
   805  		jobs = make([]*perceptron.Job, 0, num)
   806  	}
   807  	jobs = jobs[:0]
   808  	iter := i.iter
   809  	for iter.Valid() && len(jobs) < num {
   810  		job := &perceptron.Job{}
   811  		err := job.Decode(iter.Value())
   812  		if err != nil {
   813  			return nil, errors.Trace(err)
   814  		}
   815  		jobs = append(jobs, job)
   816  		err = iter.Next()
   817  		if err != nil {
   818  			return nil, errors.Trace(err)
   819  		}
   820  	}
   821  	return jobs, nil
   822  }
   823  
   824  func decodeJob(jobPairs []structure.HashPair) ([]*perceptron.Job, error) {
   825  	jobs := make([]*perceptron.Job, 0, len(jobPairs))
   826  	for _, pair := range jobPairs {
   827  		job := &perceptron.Job{}
   828  		err := job.Decode(pair.Value)
   829  		if err != nil {
   830  			return nil, errors.Trace(err)
   831  		}
   832  		jobs = append(jobs, job)
   833  	}
   834  	return jobs, nil
   835  }
   836  
   837  // jobsSorter implements the sort.Interface interface.
   838  type jobsSorter struct {
   839  	jobs []*perceptron.Job
   840  }
   841  
   842  func (s *jobsSorter) Swap(i, j int) {
   843  	s.jobs[i], s.jobs[j] = s.jobs[j], s.jobs[i]
   844  }
   845  
   846  func (s *jobsSorter) Len() int {
   847  	return len(s.jobs)
   848  }
   849  
   850  func (s *jobsSorter) Less(i, j int) bool {
   851  	return s.jobs[i].ID < s.jobs[j].ID
   852  }
   853  
   854  // GetBootstrapVersion returns the version of the server which bootstrap the causetstore.
   855  // If the causetstore is not bootstraped, the version will be zero.
   856  func (m *Meta) GetBootstrapVersion() (int64, error) {
   857  	value, err := m.txn.GetInt64(mBootstrapKey)
   858  	return value, errors.Trace(err)
   859  }
   860  
   861  // FinishBootstrap finishes bootstrap.
   862  func (m *Meta) FinishBootstrap(version int64) error {
   863  	err := m.txn.Set(mBootstrapKey, []byte(fmt.Sprintf("%d", version)))
   864  	return errors.Trace(err)
   865  }
   866  
   867  // UFIDelateDBSReorgStartHandle saves the job reorganization latest processed start handle for later resuming.
   868  func (m *Meta) UFIDelateDBSReorgStartHandle(job *perceptron.Job, startHandle ekv.Handle) error {
   869  	return setReorgJobFieldHandle(m.txn, m.reorgJobStartHandle(job.ID), startHandle)
   870  }
   871  
   872  // UFIDelateDBSReorgHandle saves the job reorganization latest processed information for later resuming.
   873  func (m *Meta) UFIDelateDBSReorgHandle(job *perceptron.Job, startHandle, endHandle ekv.Handle, physicalBlockID int64) error {
   874  	err := setReorgJobFieldHandle(m.txn, m.reorgJobStartHandle(job.ID), startHandle)
   875  	if err != nil {
   876  		return errors.Trace(err)
   877  	}
   878  	err = setReorgJobFieldHandle(m.txn, m.reorgJobEndHandle(job.ID), endHandle)
   879  	if err != nil {
   880  		return errors.Trace(err)
   881  	}
   882  	err = m.txn.HSet(mDBSJobReorgKey, m.reorgJobPhysicalBlockID(job.ID), []byte(strconv.FormatInt(physicalBlockID, 10)))
   883  	return errors.Trace(err)
   884  }
   885  
   886  func setReorgJobFieldHandle(t *structure.TxStructure, reorgJobField []byte, handle ekv.Handle) error {
   887  	if handle == nil {
   888  		return nil
   889  	}
   890  	var handleEncodedBytes []byte
   891  	if handle.IsInt() {
   892  		handleEncodedBytes = []byte(strconv.FormatInt(handle.IntValue(), 10))
   893  	} else {
   894  		handleEncodedBytes = handle.Encoded()
   895  	}
   896  	return t.HSet(mDBSJobReorgKey, reorgJobField, handleEncodedBytes)
   897  }
   898  
   899  // RemoveDBSReorgHandle removes the job reorganization related handles.
   900  func (m *Meta) RemoveDBSReorgHandle(job *perceptron.Job) error {
   901  	err := m.txn.HDel(mDBSJobReorgKey, m.reorgJobStartHandle(job.ID))
   902  	if err != nil {
   903  		return errors.Trace(err)
   904  	}
   905  	if err = m.txn.HDel(mDBSJobReorgKey, m.reorgJobEndHandle(job.ID)); err != nil {
   906  		logutil.BgLogger().Warn("remove DBS reorg end handle", zap.Error(err))
   907  	}
   908  	if err = m.txn.HDel(mDBSJobReorgKey, m.reorgJobPhysicalBlockID(job.ID)); err != nil {
   909  		logutil.BgLogger().Warn("remove DBS reorg physical ID", zap.Error(err))
   910  	}
   911  	return nil
   912  }
   913  
   914  // GetDBSReorgHandle gets the latest processed DBS reorganize position.
   915  func (m *Meta) GetDBSReorgHandle(job *perceptron.Job, isCommonHandle bool) (startHandle, endHandle ekv.Handle, physicalBlockID int64, err error) {
   916  	startHandle, err = getReorgJobFieldHandle(m.txn, m.reorgJobStartHandle(job.ID), isCommonHandle)
   917  	if err != nil {
   918  		return nil, nil, 0, errors.Trace(err)
   919  	}
   920  	endHandle, err = getReorgJobFieldHandle(m.txn, m.reorgJobEndHandle(job.ID), isCommonHandle)
   921  	if err != nil {
   922  		return nil, nil, 0, errors.Trace(err)
   923  	}
   924  
   925  	physicalBlockID, err = m.txn.HGetInt64(mDBSJobReorgKey, m.reorgJobPhysicalBlockID(job.ID))
   926  	if err != nil {
   927  		err = errors.Trace(err)
   928  		return
   929  	}
   930  	// physicalBlockID may be 0, because older version MilevaDB (without causet partition) doesn't causetstore them.
   931  	// uFIDelate them to causet's in this case.
   932  	if physicalBlockID == 0 {
   933  		if job.ReorgMeta != nil {
   934  			endHandle = ekv.IntHandle(job.ReorgMeta.EndHandle)
   935  		} else {
   936  			endHandle = ekv.IntHandle(math.MaxInt64)
   937  		}
   938  		physicalBlockID = job.BlockID
   939  		logutil.BgLogger().Warn("new MilevaDB binary running on old MilevaDB DBS reorg data",
   940  			zap.Int64("partition ID", physicalBlockID),
   941  			zap.Stringer("startHandle", startHandle),
   942  			zap.Stringer("endHandle", endHandle))
   943  	}
   944  	return
   945  }
   946  
   947  func getReorgJobFieldHandle(t *structure.TxStructure, reorgJobField []byte, isCommonHandle bool) (ekv.Handle, error) {
   948  	bs, err := t.HGet(mDBSJobReorgKey, reorgJobField)
   949  	if err != nil {
   950  		return nil, errors.Trace(err)
   951  	}
   952  	keyNotFound := bs == nil
   953  	if keyNotFound {
   954  		return nil, nil
   955  	}
   956  	if isCommonHandle {
   957  		return ekv.NewCommonHandle(bs)
   958  	}
   959  	var n int64
   960  	n, err = strconv.ParseInt(string(bs), 10, 64)
   961  	if err != nil {
   962  		return nil, err
   963  	}
   964  	return ekv.IntHandle(n), nil
   965  }
   966  
   967  func (m *Meta) schemaDiffKey(schemaVersion int64) []byte {
   968  	return []byte(fmt.Sprintf("%s:%d", mSchemaDiffPrefix, schemaVersion))
   969  }
   970  
   971  // GetSchemaDiff gets the modification information on a given schemaReplicant version.
   972  func (m *Meta) GetSchemaDiff(schemaVersion int64) (*perceptron.SchemaDiff, error) {
   973  	diffKey := m.schemaDiffKey(schemaVersion)
   974  	startTime := time.Now()
   975  	data, err := m.txn.Get(diffKey)
   976  	metrics.MetaHistogram.WithLabelValues(metrics.GetSchemaDiff, metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds())
   977  	if err != nil || len(data) == 0 {
   978  		return nil, errors.Trace(err)
   979  	}
   980  	diff := &perceptron.SchemaDiff{}
   981  	err = json.Unmarshal(data, diff)
   982  	return diff, errors.Trace(err)
   983  }
   984  
   985  // SetSchemaDiff sets the modification information on a given schemaReplicant version.
   986  func (m *Meta) SetSchemaDiff(diff *perceptron.SchemaDiff) error {
   987  	data, err := json.Marshal(diff)
   988  	if err != nil {
   989  		return errors.Trace(err)
   990  	}
   991  	diffKey := m.schemaDiffKey(diff.Version)
   992  	startTime := time.Now()
   993  	err = m.txn.Set(diffKey, data)
   994  	metrics.MetaHistogram.WithLabelValues(metrics.SetSchemaDiff, metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds())
   995  	return errors.Trace(err)
   996  }