github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/cdc/owner/barrier.go (about) 1 // Copyright 2021 PingCAP, 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 owner 15 16 import ( 17 "math" 18 19 "github.com/pingcap/log" 20 "github.com/pingcap/ticdc/cdc/model" 21 ) 22 23 type barrierType int 24 25 const ( 26 // ddlJobBarrier denotes a replication barrier caused by a DDL. 27 ddlJobBarrier barrierType = iota 28 // syncPointBarrier denotes a barrier for snapshot replication. 29 syncPointBarrier 30 // finishBarrier denotes a barrier for changefeed finished. 31 finishBarrier 32 ) 33 34 // barriers stores some barrierType and barrierTs, and can calculate the min barrierTs 35 // barriers is NOT-THREAD-SAFE 36 type barriers struct { 37 inner map[barrierType]model.Ts 38 dirty bool 39 min barrierType 40 } 41 42 func newBarriers() *barriers { 43 return &barriers{ 44 inner: make(map[barrierType]model.Ts), 45 dirty: true, 46 } 47 } 48 49 func (b *barriers) Update(tp barrierType, barrierTs model.Ts) { 50 // the barriers structure was given the ability to handle a fallback barrierTs by design. 51 // but the barrierTs should never fallback in owner replication model 52 if !b.dirty && (tp == b.min || barrierTs <= b.inner[b.min]) { 53 b.dirty = true 54 } 55 b.inner[tp] = barrierTs 56 } 57 58 func (b *barriers) Min() (tp barrierType, barrierTs model.Ts) { 59 if !b.dirty { 60 return b.min, b.inner[b.min] 61 } 62 tp, minTs := b.calcMin() 63 b.min = tp 64 b.dirty = false 65 return tp, minTs 66 } 67 68 func (b *barriers) calcMin() (tp barrierType, barrierTs model.Ts) { 69 barrierTs = uint64(math.MaxUint64) 70 for br, ts := range b.inner { 71 if ts <= barrierTs { 72 tp = br 73 barrierTs = ts 74 } 75 } 76 if barrierTs == math.MaxUint64 { 77 log.Panic("the barriers is empty, please report a bug") 78 } 79 return 80 } 81 82 func (b *barriers) Remove(tp barrierType) { 83 delete(b.inner, tp) 84 b.dirty = true 85 }