github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnbase/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 txnbase
    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  
    26  	"github.com/RoaringBitmap/roaring"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    29  )
    30  
    31  const (
    32  	CmdPointer int16 = iota
    33  	CmdDeleteBitmap
    34  	CmdBatch
    35  	CmdAppend
    36  	CmdDelete
    37  	CmdComposed
    38  	CmdTxn
    39  	CmdTxnState
    40  	CmdCustomized
    41  )
    42  
    43  func init() {
    44  	txnif.RegisterCmdFactory(CmdPointer, func(int16) txnif.TxnCmd {
    45  		return new(PointerCmd)
    46  	})
    47  	txnif.RegisterCmdFactory(CmdDeleteBitmap, func(int16) txnif.TxnCmd {
    48  		return new(DeleteBitmapCmd)
    49  	})
    50  	txnif.RegisterCmdFactory(CmdBatch, func(int16) txnif.TxnCmd {
    51  		return new(BatchCmd)
    52  	})
    53  	txnif.RegisterCmdFactory(CmdComposed, func(int16) txnif.TxnCmd {
    54  		return new(ComposedCmd)
    55  	})
    56  	txnif.RegisterCmdFactory(CmdTxn, func(int16) txnif.TxnCmd {
    57  		return NewEmptyTxnCmd()
    58  	})
    59  	txnif.RegisterCmdFactory(CmdTxnState, func(int16) txnif.TxnCmd {
    60  		return NewEmptyTxnStateCmd()
    61  	})
    62  }
    63  
    64  type CustomizedCmd interface {
    65  	GetID() uint32
    66  }
    67  
    68  func IsCustomizedCmd(cmd txnif.TxnCmd) bool {
    69  	ctype := cmd.GetType()
    70  	return ctype >= CmdCustomized
    71  }
    72  
    73  type BaseCmd struct{}
    74  
    75  func (base *BaseCmd) Close() {}
    76  
    77  type PointerCmd struct {
    78  	BaseCmd
    79  	Group uint32
    80  	Lsn   uint64
    81  }
    82  
    83  type DeleteBitmapCmd struct {
    84  	BaseCmd
    85  	Bitmap *roaring.Bitmap
    86  }
    87  
    88  type TxnCmd struct {
    89  	*ComposedCmd
    90  	*TxnCtx
    91  	Txn txnif.AsyncTxn
    92  }
    93  
    94  type TxnStateCmd struct {
    95  	ID       string
    96  	State    txnif.TxnState
    97  	CommitTs types.TS
    98  }
    99  
   100  type BatchCmd struct {
   101  	BaseCmd
   102  	Bat *containers.Batch
   103  }
   104  
   105  type ComposedCmd struct {
   106  	BaseCmd
   107  	Cmds    []txnif.TxnCmd
   108  	CmdSize uint32
   109  }
   110  
   111  type BaseCustomizedCmd struct {
   112  	BaseCmd
   113  	ID   uint32
   114  	Impl txnif.TxnCmd
   115  }
   116  
   117  func NewBaseCustomizedCmd(id uint32, impl txnif.TxnCmd) *BaseCustomizedCmd {
   118  	return &BaseCustomizedCmd{
   119  		ID:   id,
   120  		Impl: impl,
   121  	}
   122  }
   123  
   124  func NewDeleteBitmapCmd(bitmap *roaring.Bitmap) *DeleteBitmapCmd {
   125  	return &DeleteBitmapCmd{
   126  		Bitmap: bitmap,
   127  	}
   128  }
   129  
   130  func NewBatchCmd(bat *containers.Batch) *BatchCmd {
   131  	return &BatchCmd{
   132  		Bat: bat,
   133  	}
   134  }
   135  
   136  func NewComposedCmd() *ComposedCmd {
   137  	return &ComposedCmd{
   138  		Cmds: make([]txnif.TxnCmd, 0),
   139  	}
   140  }
   141  
   142  func (c *BaseCustomizedCmd) GetID() uint32 {
   143  	return c.ID
   144  }
   145  
   146  func NewEmptyTxnStateCmd() *TxnStateCmd {
   147  	return &TxnStateCmd{}
   148  }
   149  
   150  func NewTxnStateCmd(id string, state txnif.TxnState, cts types.TS) *TxnStateCmd {
   151  	return &TxnStateCmd{
   152  		ID:       id,
   153  		State:    state,
   154  		CommitTs: cts,
   155  	}
   156  }
   157  
   158  func NewTxnCmd() *TxnCmd {
   159  	return &TxnCmd{
   160  		ComposedCmd: NewComposedCmd(),
   161  		TxnCtx:      &TxnCtx{},
   162  	}
   163  }
   164  
   165  func NewEmptyTxnCmd() *TxnCmd {
   166  	return &TxnCmd{
   167  		ComposedCmd: NewComposedCmd(),
   168  		TxnCtx:      NewEmptyTxnCtx(),
   169  	}
   170  }
   171  func (c *TxnStateCmd) WriteTo(w io.Writer) (n int64, err error) {
   172  	if err = binary.Write(w, binary.BigEndian, c.GetType()); err != nil {
   173  		return
   174  	}
   175  	n += 2
   176  	var sn int64
   177  	if sn, err = common.WriteString(c.ID, w); err != nil {
   178  		return
   179  	}
   180  	n += sn
   181  	if err = binary.Write(w, binary.BigEndian, c.State); err != nil {
   182  		return
   183  	}
   184  	n += 4
   185  	if err = binary.Write(w, binary.BigEndian, c.CommitTs); err != nil {
   186  		return
   187  	}
   188  	n += types.TxnTsSize
   189  	return
   190  }
   191  func (c *TxnStateCmd) ReadFrom(r io.Reader) (n int64, err error) {
   192  	var sn int64
   193  	if c.ID, sn, err = common.ReadString(r); err != nil {
   194  		return
   195  	}
   196  	n += sn
   197  	if err = binary.Read(r, binary.BigEndian, &c.State); err != nil {
   198  		return
   199  	}
   200  	n += 4
   201  	if err = binary.Read(r, binary.BigEndian, &c.CommitTs); err != nil {
   202  		return
   203  	}
   204  	n += types.TxnTsSize
   205  	return
   206  }
   207  func (c *TxnStateCmd) Marshal() (buf []byte, err error) {
   208  	var bbuf bytes.Buffer
   209  	if _, err = c.WriteTo(&bbuf); err != nil {
   210  		return
   211  	}
   212  	buf = bbuf.Bytes()
   213  	return
   214  }
   215  func (c *TxnStateCmd) ApplyCommit()                  {}
   216  func (c *TxnStateCmd) ApplyRollback()                {}
   217  func (c *TxnStateCmd) SetReplayTxn(_ txnif.AsyncTxn) {}
   218  func (c *TxnStateCmd) Unmarshal(buf []byte) (err error) {
   219  	bbuf := bytes.NewBuffer(buf)
   220  	_, err = c.ReadFrom(bbuf)
   221  	return err
   222  }
   223  func (c *TxnStateCmd) GetType() int16 { return CmdTxnState }
   224  func (c *TxnStateCmd) Desc() string {
   225  	return fmt.Sprintf("Tid=%s,State=%s,Cts=%s", c.ID, txnif.TxnStrState(c.State), c.CommitTs.ToString())
   226  }
   227  func (c *TxnStateCmd) String() string {
   228  	return fmt.Sprintf("Tid=%s,State=%v,Cts=%s", c.ID, txnif.TxnStrState(c.State), c.CommitTs.ToString())
   229  }
   230  func (c *TxnStateCmd) VerboseString() string {
   231  	return fmt.Sprintf("Tid=%s,State=%v,Cts=%s", c.ID, txnif.TxnStrState(c.State), c.CommitTs.ToString())
   232  }
   233  func (c *TxnStateCmd) Close() {
   234  }
   235  func (c *TxnCmd) ApplyCommit() {
   236  	c.ComposedCmd.ApplyCommit()
   237  }
   238  func (c *TxnCmd) ApplyRollback() {
   239  	c.ComposedCmd.ApplyRollback()
   240  }
   241  func (c *TxnCmd) SetReplayTxn(txn txnif.AsyncTxn) {
   242  	c.ComposedCmd.SetReplayTxn(txn)
   243  }
   244  func (c *TxnCmd) SetTxn(txn txnif.AsyncTxn) {
   245  	c.Txn = txn
   246  	c.ID = txn.GetID()
   247  	c.StartTS = txn.GetStartTS()
   248  	c.PrepareTS = txn.GetPrepareTS()
   249  	c.Participants = txn.GetParticipants()
   250  	c.Memo = txn.GetMemo()
   251  }
   252  func (c *TxnCmd) WriteTo(w io.Writer) (n int64, err error) {
   253  	if err = binary.Write(w, binary.BigEndian, c.GetType()); err != nil {
   254  		return
   255  	}
   256  	n += 2
   257  	var sn int64
   258  	sn, err = c.ComposedCmd.WriteTo(w)
   259  	if err != nil {
   260  		return
   261  	}
   262  	n += sn
   263  	if sn, err = common.WriteString(c.ID, w); err != nil {
   264  		return
   265  	}
   266  	n += sn
   267  	//start ts
   268  	if err = binary.Write(w, binary.BigEndian, c.StartTS); err != nil {
   269  		return
   270  	}
   271  	n += types.TxnTsSize
   272  	//prepare ts
   273  	if err = binary.Write(w, binary.BigEndian, c.PrepareTS); err != nil {
   274  		return
   275  	}
   276  	n += types.TxnTsSize
   277  	//participants
   278  	if err = binary.Write(w, binary.BigEndian, uint32(len(c.Participants))); err != nil {
   279  		return
   280  	}
   281  	n += 4
   282  	for _, p := range c.Participants {
   283  		if err = binary.Write(w, binary.BigEndian, p); err != nil {
   284  			return
   285  		}
   286  		n += 8
   287  	}
   288  	if sn, err = c.Memo.WriteTo(w); err != nil {
   289  		return
   290  	}
   291  	n += sn
   292  	return
   293  }
   294  func (c *TxnCmd) ReadFrom(r io.Reader) (n int64, err error) {
   295  	var sn int64
   296  	var cmd txnif.TxnCmd
   297  	cmd, sn, err = BuildCommandFrom(r)
   298  	if err != nil {
   299  		return
   300  	}
   301  	c.ComposedCmd = cmd.(*ComposedCmd)
   302  	n += sn
   303  	if c.ID, sn, err = common.ReadString(r); err != nil {
   304  		return
   305  	}
   306  	n += sn
   307  	// start timestamp
   308  	if err = binary.Read(r, binary.BigEndian, &c.StartTS); err != nil {
   309  		return
   310  	}
   311  	n += types.TxnTsSize
   312  	// prepare timestamp
   313  	if err = binary.Read(r, binary.BigEndian, &c.PrepareTS); err != nil {
   314  		return
   315  	}
   316  	n += types.TxnTsSize
   317  	// participants
   318  	num := uint32(0)
   319  	if err = binary.Read(r, binary.BigEndian, &num); err != nil {
   320  		return
   321  	}
   322  	n += 4
   323  	c.Participants = make([]uint64, num)
   324  	for i := 0; i < int(num); i++ {
   325  		id := uint64(0)
   326  		if err = binary.Read(r, binary.BigEndian, &id); err != nil {
   327  			break
   328  		} else {
   329  			c.Participants = append(c.Participants, id)
   330  			n += 8
   331  		}
   332  	}
   333  	if sn, err = c.Memo.ReadFrom(r); err != nil {
   334  		return
   335  	}
   336  	n += sn
   337  	return
   338  
   339  }
   340  func (c *TxnCmd) Marshal() (buf []byte, err error) {
   341  	var bbuf bytes.Buffer
   342  	if _, err = c.WriteTo(&bbuf); err != nil {
   343  		return
   344  	}
   345  	buf = bbuf.Bytes()
   346  	return
   347  }
   348  func (c *TxnCmd) Unmarshal(buf []byte) (err error) {
   349  	bbuf := bytes.NewBuffer(buf)
   350  	_, err = c.ReadFrom(bbuf)
   351  	return err
   352  }
   353  func (c *TxnCmd) GetType() int16 { return CmdTxn }
   354  func (c *TxnCmd) Desc() string {
   355  	return fmt.Sprintf("Tid=%X,Is2PC=%v,%s", c.ID, c.Is2PC(), c.ComposedCmd.Desc())
   356  }
   357  func (c *TxnCmd) String() string {
   358  	return fmt.Sprintf("Tid=%X,Is2PC=%v,%s", c.ID, c.Is2PC(), c.ComposedCmd.String())
   359  }
   360  func (c *TxnCmd) VerboseString() string {
   361  	return fmt.Sprintf("Tid=%X,Is2PC=%v,%s", c.ID, c.Is2PC(), c.ComposedCmd.VerboseString())
   362  }
   363  func (c *TxnCmd) Close() {
   364  	c.ComposedCmd.Close()
   365  }
   366  func (e *PointerCmd) ApplyCommit()                  {}
   367  func (e *PointerCmd) ApplyRollback()                {}
   368  func (e *PointerCmd) SetReplayTxn(_ txnif.AsyncTxn) {}
   369  func (e *PointerCmd) GetType() int16 {
   370  	return CmdPointer
   371  }
   372  func (e *PointerCmd) Desc() string {
   373  	s := fmt.Sprintf("CmdName=Ptr;Group=%d;Lsn=%d", e.Group, e.Lsn)
   374  	return s
   375  }
   376  func (e *PointerCmd) String() string {
   377  	s := fmt.Sprintf("CmdName=Ptr;Group=%d;Lsn=%d]", e.Group, e.Lsn)
   378  	return s
   379  }
   380  
   381  func (e *PointerCmd) VerboseString() string {
   382  	s := fmt.Sprintf("CmdName=Ptr;Group=%d;Lsn=%d]", e.Group, e.Lsn)
   383  	return s
   384  }
   385  func (e *PointerCmd) WriteTo(w io.Writer) (n int64, err error) {
   386  	if err = binary.Write(w, binary.BigEndian, e.GetType()); err != nil {
   387  		return
   388  	}
   389  	if err = binary.Write(w, binary.BigEndian, e.Group); err != nil {
   390  		return
   391  	}
   392  	if err = binary.Write(w, binary.BigEndian, e.Lsn); err != nil {
   393  		return
   394  	}
   395  	n = 14
   396  	return
   397  }
   398  
   399  func (e *PointerCmd) Marshal() (buf []byte, err error) {
   400  	var bbuf bytes.Buffer
   401  	if _, err = e.WriteTo(&bbuf); err != nil {
   402  		return
   403  	}
   404  	buf = bbuf.Bytes()
   405  	return
   406  }
   407  
   408  func (e *PointerCmd) ReadFrom(r io.Reader) (n int64, err error) {
   409  	if err = binary.Read(r, binary.BigEndian, &e.Group); err != nil {
   410  		return
   411  	}
   412  	if err = binary.Read(r, binary.BigEndian, &e.Lsn); err != nil {
   413  		return
   414  	}
   415  	n = 12
   416  	return
   417  }
   418  
   419  func (e *PointerCmd) Unmarshal(buf []byte) error {
   420  	bbuf := bytes.NewBuffer(buf)
   421  	_, err := e.ReadFrom(bbuf)
   422  	return err
   423  }
   424  func (e *DeleteBitmapCmd) ApplyCommit()                  {}
   425  func (e *DeleteBitmapCmd) ApplyRollback()                {}
   426  func (e *DeleteBitmapCmd) SetReplayTxn(_ txnif.AsyncTxn) {}
   427  func (e *DeleteBitmapCmd) GetType() int16 {
   428  	return CmdDeleteBitmap
   429  }
   430  
   431  func (e *DeleteBitmapCmd) ReadFrom(r io.Reader) (n int64, err error) {
   432  	e.Bitmap = roaring.NewBitmap()
   433  	n, err = e.Bitmap.ReadFrom(r)
   434  	return
   435  }
   436  
   437  func (e *DeleteBitmapCmd) WriteTo(w io.Writer) (n int64, err error) {
   438  	if e == nil {
   439  		return
   440  	}
   441  	if err = binary.Write(w, binary.BigEndian, e.GetType()); err != nil {
   442  		return
   443  	}
   444  	n, err = e.Bitmap.WriteTo(w)
   445  	n += 2
   446  	return
   447  }
   448  
   449  func (e *DeleteBitmapCmd) Marshal() (buf []byte, err error) {
   450  	var bbuf bytes.Buffer
   451  	if _, err = e.WriteTo(&bbuf); err != nil {
   452  		return
   453  	}
   454  	buf = bbuf.Bytes()
   455  	return
   456  }
   457  
   458  func (e *DeleteBitmapCmd) Unmarshal(buf []byte) error {
   459  	bbuf := bytes.NewBuffer(buf)
   460  	_, err := e.ReadFrom(bbuf)
   461  	return err
   462  }
   463  
   464  func (e *DeleteBitmapCmd) Desc() string {
   465  	s := fmt.Sprintf("CmdName=DEL;Cardinality=%d", e.Bitmap.GetCardinality())
   466  	return s
   467  }
   468  
   469  func (e *DeleteBitmapCmd) String() string {
   470  	s := fmt.Sprintf("CmdName=DEL;Cardinality=%d", e.Bitmap.GetCardinality())
   471  	return s
   472  }
   473  
   474  func (e *DeleteBitmapCmd) VerboseString() string {
   475  	s := fmt.Sprintf("CmdName=DEL;Cardinality=%d;Deletes=%v", e.Bitmap.GetCardinality(), e.Bitmap.String())
   476  	return s
   477  }
   478  func (e *BatchCmd) GetType() int16 {
   479  	return CmdBatch
   480  }
   481  func (e *BatchCmd) ApplyCommit()                  {}
   482  func (e *BatchCmd) ApplyRollback()                {}
   483  func (e *BatchCmd) SetReplayTxn(_ txnif.AsyncTxn) {}
   484  func (e *BatchCmd) Close() {
   485  	if e.Bat != nil {
   486  		e.Bat.Close()
   487  		e.Bat = nil
   488  	}
   489  }
   490  
   491  func (e *BatchCmd) Marshal() (buf []byte, err error) {
   492  	var bbuf bytes.Buffer
   493  	if _, err = e.WriteTo(&bbuf); err != nil {
   494  		return
   495  	}
   496  	buf = bbuf.Bytes()
   497  	return
   498  }
   499  
   500  func (e *BatchCmd) Unmarshal(buf []byte) error {
   501  	bbuf := bytes.NewBuffer(buf)
   502  	_, err := e.ReadFrom(bbuf)
   503  	return err
   504  }
   505  
   506  func (e *BatchCmd) ReadFrom(r io.Reader) (n int64, err error) {
   507  	e.Bat = containers.NewBatch()
   508  	n, err = e.Bat.ReadFrom(r)
   509  	return
   510  }
   511  
   512  func (e *BatchCmd) WriteTo(w io.Writer) (n int64, err error) {
   513  	if err = binary.Write(w, binary.BigEndian, e.GetType()); err != nil {
   514  		return
   515  	}
   516  	if n, err = e.Bat.WriteTo(w); err != nil {
   517  		return
   518  	}
   519  	n += 2
   520  	return
   521  }
   522  
   523  func (e *BatchCmd) Desc() string {
   524  	s := fmt.Sprintf("CmdName=BAT;Rows=%d", e.Bat.Length())
   525  	if e.Bat.HasDelete() {
   526  		s = fmt.Sprintf("%s;DelCnt=%d", s, e.Bat.DeleteCnt())
   527  	}
   528  	return s
   529  }
   530  
   531  func (e *BatchCmd) String() string {
   532  	return e.Desc()
   533  }
   534  
   535  func (e *BatchCmd) VerboseString() string {
   536  	s := fmt.Sprintf("CmdName=BAT;Rows=%d;Data=%v", e.Bat.Length(), e.Bat)
   537  	return s
   538  }
   539  func (cc *ComposedCmd) ApplyCommit() {
   540  	for _, c := range cc.Cmds {
   541  		c.ApplyCommit()
   542  	}
   543  }
   544  func (cc *ComposedCmd) ApplyRollback() {
   545  	for _, c := range cc.Cmds {
   546  		c.ApplyRollback()
   547  	}
   548  }
   549  func (cc *ComposedCmd) SetReplayTxn(txn txnif.AsyncTxn) {
   550  	for _, c := range cc.Cmds {
   551  		c.SetReplayTxn(txn)
   552  	}
   553  }
   554  func (cc *ComposedCmd) Close() {
   555  	for _, cmd := range cc.Cmds {
   556  		cmd.Close()
   557  	}
   558  }
   559  func (cc *ComposedCmd) GetType() int16 {
   560  	return CmdComposed
   561  }
   562  
   563  func (cc *ComposedCmd) Marshal() (buf []byte, err error) {
   564  	var bbuf bytes.Buffer
   565  	if _, err = cc.WriteTo(&bbuf); err != nil {
   566  		return
   567  	}
   568  	buf = bbuf.Bytes()
   569  	return
   570  }
   571  
   572  func (cc *ComposedCmd) Unmarshal(buf []byte) (err error) {
   573  	bbuf := bytes.NewBuffer(buf)
   574  	_, err = cc.ReadFrom(bbuf)
   575  	return err
   576  }
   577  
   578  func (cc *ComposedCmd) WriteTo(w io.Writer) (n int64, err error) {
   579  	if err = binary.Write(w, binary.BigEndian, cc.GetType()); err != nil {
   580  		return
   581  	}
   582  	n += 2
   583  	if err = binary.Write(w, binary.BigEndian, cc.CmdSize); err != nil {
   584  		return
   585  	}
   586  	n += 4
   587  	cmds := uint32(len(cc.Cmds))
   588  	if err = binary.Write(w, binary.BigEndian, cmds); err != nil {
   589  		return
   590  	}
   591  	n += 4
   592  	var cn int64
   593  	for _, cmd := range cc.Cmds {
   594  		if cn, err = cmd.WriteTo(w); err != nil {
   595  			break
   596  		} else {
   597  			n += cn
   598  		}
   599  	}
   600  	return
   601  }
   602  
   603  func (cc *ComposedCmd) ReadFrom(r io.Reader) (n int64, err error) {
   604  	if err = binary.Read(r, binary.BigEndian, &cc.CmdSize); err != nil {
   605  		return
   606  	}
   607  	n += 4
   608  	cmds := uint32(0)
   609  	if err = binary.Read(r, binary.BigEndian, &cmds); err != nil {
   610  		return
   611  	}
   612  	n += 4
   613  	var cn int64
   614  	cc.Cmds = make([]txnif.TxnCmd, cmds)
   615  	for i := 0; i < int(cmds); i++ {
   616  		if cc.Cmds[i], cn, err = BuildCommandFrom(r); err != nil {
   617  			break
   618  		} else {
   619  			n += cn
   620  		}
   621  	}
   622  	return
   623  }
   624  
   625  func (cc *ComposedCmd) AddCmd(cmd txnif.TxnCmd) {
   626  	cc.Cmds = append(cc.Cmds, cmd)
   627  }
   628  
   629  func (cc *ComposedCmd) SetCmdSize(size uint32) {
   630  	cc.CmdSize = size
   631  }
   632  
   633  func (cc *ComposedCmd) ToString(prefix string) string {
   634  	s := fmt.Sprintf("%sComposedCmd: Cnt=%d/%d", prefix, cc.CmdSize, len(cc.Cmds))
   635  	for _, cmd := range cc.Cmds {
   636  		s = fmt.Sprintf("%s\n%s\t%s", s, prefix, cmd.String())
   637  	}
   638  	return s
   639  }
   640  
   641  func (cc *ComposedCmd) ToDesc(prefix string) string {
   642  	s := fmt.Sprintf("%sComposedCmd: Cnt=%d/%d", prefix, cc.CmdSize, len(cc.Cmds))
   643  	for _, cmd := range cc.Cmds {
   644  		s = fmt.Sprintf("%s\n%s\t%s", s, prefix, cmd.Desc())
   645  	}
   646  	return s
   647  }
   648  func (cc *ComposedCmd) ToVerboseString(prefix string) string {
   649  	s := fmt.Sprintf("%sComposedCmd: Cnt=%d/%d", prefix, cc.CmdSize, len(cc.Cmds))
   650  	for _, cmd := range cc.Cmds {
   651  		s = fmt.Sprintf("%s\n%s\t%s", s, prefix, cmd.VerboseString())
   652  	}
   653  	return s
   654  }
   655  
   656  func (cc *ComposedCmd) VerboseString() string {
   657  	return cc.ToVerboseString("")
   658  }
   659  func (cc *ComposedCmd) String() string {
   660  	return cc.ToString("")
   661  }
   662  func (cc *ComposedCmd) Desc() string {
   663  	return cc.ToDesc("")
   664  }
   665  func BuildCommandFrom(r io.Reader) (cmd txnif.TxnCmd, n int64, err error) {
   666  	var cmdType int16
   667  	if err = binary.Read(r, binary.BigEndian, &cmdType); err != nil {
   668  		return
   669  	}
   670  
   671  	factory := txnif.GetCmdFactory(cmdType)
   672  
   673  	cmd = factory(cmdType)
   674  	n, err = cmd.ReadFrom(r)
   675  	n += 2
   676  	return
   677  }