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 }