github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/disttae/logtail.go (about)

     1  // Copyright 2022 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 disttae
    16  
    17  import (
    18  	"context"
    19  	"time"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/catalog"
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    24  	"github.com/matrixorigin/matrixone/pkg/container/types"
    25  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    26  	"github.com/matrixorigin/matrixone/pkg/logutil"
    27  	"github.com/matrixorigin/matrixone/pkg/pb/api"
    28  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    29  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    30  	"github.com/matrixorigin/matrixone/pkg/pb/txn"
    31  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logtail"
    33  )
    34  
    35  func updatePartition(idx, primaryIdx int, tbl *table, ts timestamp.Timestamp,
    36  	ctx context.Context, op client.TxnOperator, db *DB,
    37  	mvcc MVCC, dn DNStore, req api.SyncLogTailReq) error {
    38  	reqs, err := genLogTailReq(dn, req)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	logTails, err := getLogTail(ctx, op, reqs)
    43  	if err != nil {
    44  		return err
    45  	}
    46  	for i := range logTails {
    47  		if err := consumeLogTail(idx, primaryIdx, tbl, ts, ctx, db, mvcc, logTails[i]); err != nil {
    48  			logutil.Errorf("consume %d-%s logtail error: %v\n", tbl.tableId, tbl.tableName, err)
    49  			return err
    50  		}
    51  	}
    52  	return nil
    53  }
    54  
    55  func getLogTail(ctx context.Context, op client.TxnOperator, reqs []txn.TxnRequest) ([]*api.SyncLogTailResp, error) {
    56  	ctx, cancel := context.WithTimeout(ctx, time.Minute)
    57  	defer cancel()
    58  	result, err := op.Read(ctx, reqs)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	logTails := make([]*api.SyncLogTailResp, len(result.Responses))
    63  	for i, resp := range result.Responses {
    64  		logTails[i] = new(api.SyncLogTailResp)
    65  		if err := types.Decode(resp.CNOpResponse.Payload, logTails[i]); err != nil {
    66  			return nil, err
    67  		}
    68  	}
    69  	return logTails, nil
    70  }
    71  
    72  func consumeLogTail(idx, primaryIdx int, tbl *table, ts timestamp.Timestamp,
    73  	ctx context.Context, db *DB, mvcc MVCC, logTail *api.SyncLogTailResp) (err error) {
    74  	var entries []*api.Entry
    75  
    76  	if entries, err = logtail.LoadCheckpointEntries(
    77  		ctx,
    78  		logTail.CkpLocation,
    79  		tbl.tableId,
    80  		tbl.tableName,
    81  		tbl.db.databaseId,
    82  		tbl.db.databaseName,
    83  		tbl.db.fs); err != nil {
    84  		return
    85  	}
    86  	for _, e := range entries {
    87  		if err = consumeEntry(idx, primaryIdx, tbl, ts, ctx,
    88  			db, mvcc, e); err != nil {
    89  			return
    90  		}
    91  	}
    92  
    93  	for i := 0; i < len(logTail.Commands); i++ {
    94  		if err = consumeEntry(idx, primaryIdx, tbl, ts, ctx,
    95  			db, mvcc, logTail.Commands[i]); err != nil {
    96  			return
    97  		}
    98  	}
    99  	return nil
   100  }
   101  
   102  func consumeEntry(idx, primaryIdx int, tbl *table, ts timestamp.Timestamp,
   103  	ctx context.Context, db *DB, mvcc MVCC, e *api.Entry) error {
   104  	if e.EntryType == api.Entry_Insert {
   105  		if isMetaTable(e.TableName) {
   106  			vec, err := vector.ProtoVectorToVector(e.Bat.Vecs[catalog.BLOCKMETA_ID_IDX+MO_PRIMARY_OFF])
   107  			if err != nil {
   108  				return err
   109  			}
   110  			timeVec, err := vector.ProtoVectorToVector(e.Bat.Vecs[catalog.BLOCKMETA_COMMITTS_IDX+MO_PRIMARY_OFF])
   111  			if err != nil {
   112  				return err
   113  			}
   114  			vs := vector.MustTCols[uint64](vec)
   115  			timestamps := vector.MustTCols[types.TS](timeVec)
   116  			for i, v := range vs {
   117  				if err := tbl.parts[idx].DeleteByBlockID(ctx, timestamps[i].ToTimestamp(), v); err != nil {
   118  					if !moerr.IsMoErrCode(err, moerr.ErrTxnWriteConflict) {
   119  						return err
   120  					}
   121  				}
   122  			}
   123  			return db.getMetaPartitions(e.TableName)[idx].Insert(ctx, -1, e.Bat, false)
   124  		}
   125  		switch e.TableId {
   126  		case catalog.MO_TABLES_ID:
   127  			bat, _ := batch.ProtoBatchToBatch(e.Bat)
   128  			tbl.db.txn.catalog.InsertTable(bat)
   129  		case catalog.MO_DATABASE_ID:
   130  			bat, _ := batch.ProtoBatchToBatch(e.Bat)
   131  			tbl.db.txn.catalog.InsertDatabase(bat)
   132  		case catalog.MO_COLUMNS_ID:
   133  			bat, _ := batch.ProtoBatchToBatch(e.Bat)
   134  			tbl.db.txn.catalog.InsertColumns(bat)
   135  		}
   136  		if primaryIdx >= 0 {
   137  			return mvcc.Insert(ctx, MO_PRIMARY_OFF+primaryIdx, e.Bat, false)
   138  		}
   139  		return mvcc.Insert(ctx, primaryIdx, e.Bat, false)
   140  	}
   141  	if isMetaTable(e.TableName) {
   142  		return db.getMetaPartitions(e.TableName)[idx].Delete(ctx, e.Bat)
   143  	}
   144  	switch e.TableId {
   145  	case catalog.MO_TABLES_ID:
   146  		bat, _ := batch.ProtoBatchToBatch(e.Bat)
   147  		tbl.db.txn.catalog.DeleteTable(bat)
   148  	case catalog.MO_DATABASE_ID:
   149  		bat, _ := batch.ProtoBatchToBatch(e.Bat)
   150  		tbl.db.txn.catalog.DeleteDatabase(bat)
   151  	}
   152  	return mvcc.Delete(ctx, e.Bat)
   153  }
   154  
   155  func genSyncLogTailReq(have, want timestamp.Timestamp, databaseId,
   156  	tableId uint64) api.SyncLogTailReq {
   157  	return api.SyncLogTailReq{
   158  		CnHave: &have,
   159  		CnWant: &want,
   160  		Table: &api.TableID{
   161  			DbId: databaseId,
   162  			TbId: tableId,
   163  		},
   164  	}
   165  }
   166  
   167  func genLogTailReq(dn DNStore, req api.SyncLogTailReq) ([]txn.TxnRequest, error) {
   168  	payload, err := types.Encode(req)
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	reqs := make([]txn.TxnRequest, len(dn.Shards))
   173  	for i, info := range dn.Shards {
   174  		reqs[i] = txn.TxnRequest{
   175  			CNRequest: &txn.CNOpRequest{
   176  				OpCode:  uint32(api.OpCode_OpGetLogTail),
   177  				Payload: payload,
   178  				Target: metadata.DNShard{
   179  					DNShardRecord: metadata.DNShardRecord{
   180  						ShardID: info.ShardID,
   181  					},
   182  					ReplicaID: info.ReplicaID,
   183  					Address:   dn.ServiceAddress,
   184  				},
   185  			},
   186  			Options: &txn.TxnRequestOptions{
   187  				RetryCodes: []int32{
   188  					// dn shard not found
   189  					int32(moerr.ErrDNShardNotFound),
   190  				},
   191  				RetryInterval: int64(time.Second),
   192  			},
   193  		}
   194  	}
   195  	return reqs, nil
   196  }