github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/catalog/command.go (about)

     1  // Copyright 2021 Matrix Origin
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package catalog
    16  
    17  import (
    18  	"bytes"
    19  	"encoding/binary"
    20  	"fmt"
    21  	"io"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal"
    28  )
    29  
    30  const (
    31  	CmdUpdateDatabase = int16(256) + iota
    32  	CmdUpdateTable
    33  	CmdUpdateSegment
    34  	CmdUpdateBlock
    35  )
    36  
    37  var cmdNames = map[int16]string{
    38  	CmdUpdateDatabase: "UDB",
    39  	CmdUpdateTable:    "UTBL",
    40  	CmdUpdateSegment:  "USEG",
    41  	CmdUpdateBlock:    "UBLK",
    42  }
    43  
    44  func CmdName(t int16) string {
    45  	return cmdNames[t]
    46  }
    47  
    48  func init() {
    49  	txnif.RegisterCmdFactory(CmdUpdateDatabase, func(cmdType int16) txnif.TxnCmd {
    50  		return newEmptyEntryCmd(cmdType)
    51  	})
    52  	txnif.RegisterCmdFactory(CmdUpdateTable, func(cmdType int16) txnif.TxnCmd {
    53  		return newEmptyEntryCmd(cmdType)
    54  	})
    55  	txnif.RegisterCmdFactory(CmdUpdateSegment, func(cmdType int16) txnif.TxnCmd {
    56  		return newEmptyEntryCmd(cmdType)
    57  	})
    58  	txnif.RegisterCmdFactory(CmdUpdateBlock, func(cmdType int16) txnif.TxnCmd {
    59  		return newEmptyEntryCmd(cmdType)
    60  	})
    61  }
    62  
    63  type EntryCommand struct {
    64  	*txnbase.BaseCustomizedCmd
    65  	cmdType   int16
    66  	entry     BaseEntry
    67  	DBID      uint64
    68  	TableID   uint64
    69  	SegmentID uint64
    70  	DB        *DBEntry
    71  	Table     *TableEntry
    72  	Segment   *SegmentEntry
    73  	Block     *BlockEntry
    74  }
    75  
    76  func newEmptyEntryCmd(cmdType int16) *EntryCommand {
    77  	impl := &EntryCommand{
    78  		DB:      nil,
    79  		cmdType: cmdType,
    80  	}
    81  	impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(0, impl)
    82  	return impl
    83  }
    84  
    85  func newBlockCmd(id uint32, cmdType int16, entry *BlockEntry) *EntryCommand {
    86  	impl := &EntryCommand{
    87  		DB:      entry.GetSegment().GetTable().GetDB(),
    88  		Table:   entry.GetSegment().GetTable(),
    89  		Segment: entry.GetSegment(),
    90  		Block:   entry,
    91  		cmdType: cmdType,
    92  		entry:   entry.MetaBaseEntry,
    93  	}
    94  	impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(id, impl)
    95  	return impl
    96  }
    97  
    98  func newSegmentCmd(id uint32, cmdType int16, entry *SegmentEntry) *EntryCommand {
    99  	impl := &EntryCommand{
   100  		DB:      entry.GetTable().GetDB(),
   101  		Table:   entry.GetTable(),
   102  		Segment: entry,
   103  		cmdType: cmdType,
   104  		entry:   entry.MetaBaseEntry,
   105  	}
   106  	impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(id, impl)
   107  	return impl
   108  }
   109  
   110  func newTableCmd(id uint32, cmdType int16, entry *TableEntry) *EntryCommand {
   111  	impl := &EntryCommand{
   112  		DB:      entry.GetDB(),
   113  		Table:   entry,
   114  		cmdType: cmdType,
   115  		entry:   entry.TableBaseEntry,
   116  	}
   117  	impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(id, impl)
   118  	return impl
   119  }
   120  
   121  func newDBCmd(id uint32, cmdType int16, entry *DBEntry) *EntryCommand {
   122  	impl := &EntryCommand{
   123  		DB:      entry,
   124  		cmdType: cmdType,
   125  	}
   126  	if entry != nil {
   127  		impl.entry = entry.DBBaseEntry
   128  	}
   129  	impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(id, impl)
   130  	return impl
   131  }
   132  
   133  func (cmd *EntryCommand) Desc() string {
   134  	s := fmt.Sprintf("CmdName=%s;%s;TS=%s;CSN=%d", CmdName(cmd.cmdType), cmd.IDString(), cmd.GetTs().ToString(), cmd.ID)
   135  	return s
   136  }
   137  
   138  func (cmd *EntryCommand) GetLogIndex() *wal.Index {
   139  	if cmd.entry == nil {
   140  		return nil
   141  	}
   142  	return cmd.entry.GetLatestNodeLocked().GetLogIndex()
   143  }
   144  func (cmd *EntryCommand) SetReplayTxn(txn txnif.AsyncTxn) {
   145  	switch cmd.cmdType {
   146  	case CmdUpdateBlock, CmdUpdateSegment:
   147  		cmd.entry.GetLatestNodeLocked().(*MetadataMVCCNode).Txn = txn
   148  	case CmdUpdateTable:
   149  		cmd.entry.GetLatestNodeLocked().(*TableMVCCNode).Txn = txn
   150  	case CmdUpdateDatabase:
   151  		cmd.entry.GetLatestNodeLocked().(*DBMVCCNode).Txn = txn
   152  	default:
   153  		panic(fmt.Sprintf("invalid command type %d", cmd.cmdType))
   154  	}
   155  }
   156  func (cmd *EntryCommand) ApplyCommit() {
   157  	switch cmd.cmdType {
   158  	case CmdUpdateBlock, CmdUpdateSegment, CmdUpdateTable, CmdUpdateDatabase:
   159  		node := cmd.entry.GetLatestNodeLocked()
   160  		if node.Is1PC() {
   161  			return
   162  		}
   163  		if err := node.ApplyCommit(nil); err != nil {
   164  			panic(err)
   165  		}
   166  	default:
   167  		panic(fmt.Sprintf("invalid command type %d", cmd.cmdType))
   168  	}
   169  }
   170  func (cmd *EntryCommand) ApplyRollback() {
   171  	switch cmd.cmdType {
   172  	case CmdUpdateBlock, CmdUpdateSegment, CmdUpdateTable, CmdUpdateDatabase:
   173  		node := cmd.entry.GetLatestNodeLocked().(*MetadataMVCCNode)
   174  		if node.Is1PC() {
   175  			return
   176  		}
   177  		node.ApplyRollback(nil)
   178  	default:
   179  		panic(fmt.Sprintf("invalid command type %d", cmd.cmdType))
   180  	}
   181  }
   182  func (cmd *EntryCommand) GetTs() types.TS {
   183  	ts := cmd.entry.GetLatestNodeLocked().GetPrepare()
   184  	return ts
   185  }
   186  func (cmd *EntryCommand) IDString() string {
   187  	s := ""
   188  	dbid, id := cmd.GetID()
   189  	switch cmd.cmdType {
   190  	case CmdUpdateDatabase:
   191  		s = fmt.Sprintf("%sDB=%d", s, dbid)
   192  	case CmdUpdateTable:
   193  		s = fmt.Sprintf("%sDB=%d;CommonID=%s", s, dbid, id.TableString())
   194  	case CmdUpdateSegment:
   195  		s = fmt.Sprintf("%sDB=%d;CommonID=%s", s, dbid, id.SegmentString())
   196  	case CmdUpdateBlock:
   197  		s = fmt.Sprintf("%sDB=%d;CommonID=%s", s, dbid, id.BlockString())
   198  	}
   199  	return s
   200  }
   201  func (cmd *EntryCommand) GetID() (uint64, *common.ID) {
   202  	id := &common.ID{}
   203  	dbid := uint64(0)
   204  	switch cmd.cmdType {
   205  	case CmdUpdateDatabase:
   206  		dbid = cmd.entry.GetID()
   207  	case CmdUpdateTable:
   208  		if cmd.DBID != 0 {
   209  			dbid = cmd.DBID
   210  			id.TableID = cmd.Table.ID
   211  		} else {
   212  			dbid = cmd.Table.db.ID
   213  			id.TableID = cmd.entry.GetID()
   214  		}
   215  	case CmdUpdateSegment:
   216  		if cmd.DBID != 0 {
   217  			dbid = cmd.DBID
   218  			id.TableID = cmd.TableID
   219  			id.SegmentID = cmd.entry.GetID()
   220  		} else {
   221  			dbid = cmd.DB.ID
   222  			id.TableID = cmd.Table.ID
   223  			id.SegmentID = cmd.Segment.ID
   224  		}
   225  	case CmdUpdateBlock:
   226  		if cmd.DBID != 0 {
   227  			dbid = cmd.DBID
   228  			id.TableID = cmd.TableID
   229  			id.SegmentID = cmd.SegmentID
   230  			id.BlockID = cmd.entry.GetID()
   231  		} else {
   232  			dbid = cmd.DB.ID
   233  			id.TableID = cmd.Table.ID
   234  			id.SegmentID = cmd.Segment.ID
   235  			id.BlockID = cmd.entry.GetID()
   236  		}
   237  	}
   238  	return dbid, id
   239  }
   240  
   241  func (cmd *EntryCommand) String() string {
   242  	s := fmt.Sprintf("CmdName=%s;%s;TS=%s;CSN=%d;BaseEntry=%s", CmdName(cmd.cmdType), cmd.IDString(), cmd.GetTs().ToString(), cmd.ID, cmd.entry.String())
   243  	return s
   244  }
   245  
   246  func (cmd *EntryCommand) VerboseString() string {
   247  	s := fmt.Sprintf("CmdName=%s;%s;TS=%s;CSN=%d;BaseEntry=%s", CmdName(cmd.cmdType), cmd.IDString(), cmd.GetTs().ToString(), cmd.ID, cmd.entry.String())
   248  	switch cmd.cmdType {
   249  	case CmdUpdateTable:
   250  		s = fmt.Sprintf("%s;Schema=%v", s, cmd.Table.schema.String())
   251  	}
   252  	return s
   253  }
   254  func (cmd *EntryCommand) GetType() int16 { return cmd.cmdType }
   255  
   256  func (cmd *EntryCommand) WriteTo(w io.Writer) (n int64, err error) {
   257  	if err = binary.Write(w, binary.BigEndian, cmd.GetType()); err != nil {
   258  		return
   259  	}
   260  	if err = binary.Write(w, binary.BigEndian, cmd.ID); err != nil {
   261  		return
   262  	}
   263  	var sn int64
   264  	n = 4 + 2
   265  
   266  	if err = binary.Write(w, binary.BigEndian, cmd.entry.GetID()); err != nil {
   267  		return
   268  	}
   269  	n += 4
   270  	switch cmd.GetType() {
   271  	case CmdUpdateDatabase:
   272  		if sn, err = common.WriteString(cmd.DB.name, w); err != nil {
   273  			return
   274  		}
   275  		n += sn
   276  		if sn, err = cmd.DB.acInfo.WriteTo(w); err != nil {
   277  			return
   278  		}
   279  		n += sn
   280  		if sn, err = cmd.DB.WriteOneNodeTo(w); err != nil {
   281  			return
   282  		}
   283  		n += sn
   284  	case CmdUpdateTable:
   285  		if err = binary.Write(w, binary.BigEndian, cmd.Table.db.ID); err != nil {
   286  			return
   287  		}
   288  		n += 8
   289  		if sn, err = cmd.Table.WriteOneNodeTo(w); err != nil {
   290  			return
   291  		}
   292  		n += sn
   293  		var schemaBuf []byte
   294  		if schemaBuf, err = cmd.Table.schema.Marshal(); err != nil {
   295  			return
   296  		}
   297  		if _, err = w.Write(schemaBuf); err != nil {
   298  			return
   299  		}
   300  		n += int64(len(schemaBuf))
   301  	case CmdUpdateSegment:
   302  		if err = binary.Write(w, binary.BigEndian, cmd.DB.ID); err != nil {
   303  			return
   304  		}
   305  		if err = binary.Write(w, binary.BigEndian, cmd.Table.ID); err != nil {
   306  			return
   307  		}
   308  		if err = binary.Write(w, binary.BigEndian, cmd.Segment.state); err != nil {
   309  			return
   310  		}
   311  		if err = binary.Write(w, binary.BigEndian, cmd.Segment.sorted); err != nil {
   312  			return
   313  		}
   314  		n += 8 + 8 + 1 + 1
   315  		var n2 int64
   316  		n2, err = cmd.entry.WriteOneNodeTo(w)
   317  		if err != nil {
   318  			return
   319  		}
   320  		n += n2
   321  	case CmdUpdateBlock:
   322  		if err = binary.Write(w, binary.BigEndian, cmd.DB.ID); err != nil {
   323  			return
   324  		}
   325  		if err = binary.Write(w, binary.BigEndian, cmd.Table.ID); err != nil {
   326  			return
   327  		}
   328  		if err = binary.Write(w, binary.BigEndian, cmd.Segment.ID); err != nil {
   329  			return
   330  		}
   331  		n += 8 + 8 + 8
   332  		if err = binary.Write(w, binary.BigEndian, cmd.Block.state); err != nil {
   333  			return
   334  		}
   335  		n += 1
   336  		var n2 int64
   337  		n2, err = cmd.entry.WriteOneNodeTo(w)
   338  		if err != nil {
   339  			return
   340  		}
   341  		n += n2
   342  	}
   343  	return
   344  }
   345  func (cmd *EntryCommand) Marshal() (buf []byte, err error) {
   346  	var bbuf bytes.Buffer
   347  	if _, err = cmd.WriteTo(&bbuf); err != nil {
   348  		return
   349  	}
   350  	buf = bbuf.Bytes()
   351  	return
   352  }
   353  func (cmd *EntryCommand) ReadFrom(r io.Reader) (n int64, err error) {
   354  	if err = binary.Read(r, binary.BigEndian, &cmd.ID); err != nil {
   355  		return
   356  	}
   357  	n += 4
   358  	var sn int64
   359  	switch cmd.GetType() {
   360  	case CmdUpdateDatabase:
   361  		entry := NewReplayDBBaseEntry()
   362  		if err = binary.Read(r, binary.BigEndian, &entry.ID); err != nil {
   363  			return
   364  		}
   365  		n += 8
   366  		cmd.entry = entry
   367  		cmd.DB = NewReplayDBEntry()
   368  		if cmd.DB.name, sn, err = common.ReadString(r); err != nil {
   369  			return
   370  		}
   371  		n += sn
   372  		if sn, err = cmd.DB.acInfo.ReadFrom(r); err != nil {
   373  			return
   374  		}
   375  		n += sn
   376  		if sn, err = cmd.entry.ReadOneNodeFrom(r); err != nil {
   377  			return
   378  		}
   379  		n += sn
   380  		cmd.DB.DBBaseEntry = cmd.entry.(*DBBaseEntry)
   381  	case CmdUpdateTable:
   382  		entry := NewReplayTableBaseEntry()
   383  		if err = binary.Read(r, binary.BigEndian, &entry.ID); err != nil {
   384  			return
   385  		}
   386  		n += 8
   387  		cmd.entry = entry
   388  		if err = binary.Read(r, binary.BigEndian, &cmd.DBID); err != nil {
   389  			return
   390  		}
   391  
   392  		n += 8
   393  		if sn, err = cmd.entry.ReadOneNodeFrom(r); err != nil {
   394  			return
   395  		}
   396  		n += sn
   397  		cmd.Table = NewReplayTableEntry()
   398  		cmd.Table.TableBaseEntry = cmd.entry.(*TableBaseEntry)
   399  		cmd.Table.schema = NewEmptySchema("")
   400  		if sn, err = cmd.Table.schema.ReadFrom(r); err != nil {
   401  			return
   402  		}
   403  		n += sn
   404  	case CmdUpdateSegment:
   405  		entry := NewReplayMetaBaseEntry()
   406  		if err = binary.Read(r, binary.BigEndian, &entry.ID); err != nil {
   407  			return
   408  		}
   409  		n += 8
   410  		cmd.entry = entry
   411  		if err = binary.Read(r, binary.BigEndian, &cmd.DBID); err != nil {
   412  			return
   413  		}
   414  		n += 8
   415  		if err = binary.Read(r, binary.BigEndian, &cmd.TableID); err != nil {
   416  			return
   417  		}
   418  		n += 8
   419  		var state EntryState
   420  		if err = binary.Read(r, binary.BigEndian, &state); err != nil {
   421  			return
   422  		}
   423  		n += 1
   424  		var sorted bool
   425  		if err = binary.Read(r, binary.BigEndian, &sorted); err != nil {
   426  			return
   427  		}
   428  		n += 1
   429  		if sn, err = cmd.entry.ReadOneNodeFrom(r); err != nil {
   430  			return
   431  		}
   432  		n += sn
   433  		cmd.Segment = NewReplaySegmentEntry()
   434  		cmd.Segment.MetaBaseEntry = cmd.entry.(*MetaBaseEntry)
   435  		cmd.Segment.state = state
   436  		cmd.Segment.sorted = sorted
   437  	case CmdUpdateBlock:
   438  		entry := NewReplayMetaBaseEntry()
   439  		if err = binary.Read(r, binary.BigEndian, &entry.ID); err != nil {
   440  			return
   441  		}
   442  		n += 8
   443  		cmd.entry = entry
   444  		if err = binary.Read(r, binary.BigEndian, &cmd.DBID); err != nil {
   445  			return
   446  		}
   447  		if err = binary.Read(r, binary.BigEndian, &cmd.TableID); err != nil {
   448  			return
   449  		}
   450  		if err = binary.Read(r, binary.BigEndian, &cmd.SegmentID); err != nil {
   451  			return
   452  		}
   453  		var state EntryState
   454  		if err = binary.Read(r, binary.BigEndian, &state); err != nil {
   455  			return
   456  		}
   457  		var n2 int64
   458  		n2, err = cmd.entry.ReadOneNodeFrom(r)
   459  		if err != nil {
   460  			return
   461  		}
   462  		n += n2
   463  		cmd.Block = NewReplayBlockEntry()
   464  		cmd.Block.MetaBaseEntry = cmd.entry.(*MetaBaseEntry)
   465  		cmd.Block.state = state
   466  	}
   467  	return
   468  }
   469  
   470  func (cmd *EntryCommand) Unmarshal(buf []byte) (err error) {
   471  	bbuf := bytes.NewBuffer(buf)
   472  	_, err = cmd.ReadFrom(bbuf)
   473  	return
   474  }