github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/logstore/store/checkpointinfo.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 store 16 17 import ( 18 "encoding/binary" 19 "fmt" 20 "io" 21 22 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 23 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/entry" 24 ) 25 26 type checkpointInfo struct { 27 ranges *common.ClosedIntervals 28 partial map[uint64]*partialCkpInfo 29 } 30 31 func newCheckpointInfo() *checkpointInfo { 32 return &checkpointInfo{ 33 ranges: common.NewClosedIntervals(), 34 partial: make(map[uint64]*partialCkpInfo), 35 } 36 } 37 38 func (info *checkpointInfo) UpdateWtihRanges(intervals *common.ClosedIntervals) { 39 info.ranges.TryMerge(*intervals) 40 for lsn := range info.partial { 41 if intervals.ContainsInt(lsn) { 42 delete(info.partial, lsn) 43 } 44 } 45 } 46 47 func (info *checkpointInfo) UpdateWtihPartialCheckpoint(lsn uint64, ckps *partialCkpInfo) { 48 if info.ranges.Contains(*common.NewClosedIntervalsByInt(lsn)) { 49 return 50 } 51 partialInfo, ok := info.partial[lsn] 52 if !ok { 53 partialInfo = newPartialCkpInfo(ckps.size) 54 info.partial[lsn] = partialInfo 55 } 56 partialInfo.MergePartialCkpInfo(ckps) 57 if partialInfo.IsAllCheckpointed() { 58 info.ranges.TryMerge(*common.NewClosedIntervalsByInt(lsn)) 59 delete(info.partial, lsn) 60 } 61 } 62 63 func (info *checkpointInfo) UpdateWithCommandInfo(lsn uint64, cmds *entry.CommandInfo) { 64 if info.ranges.Contains(*common.NewClosedIntervalsByInt(lsn)) { 65 return 66 } 67 partialInfo, ok := info.partial[lsn] 68 if !ok { 69 partialInfo = newPartialCkpInfo(cmds.Size) 70 info.partial[lsn] = partialInfo 71 } 72 partialInfo.MergeCommandInfos(cmds) 73 if partialInfo.IsAllCheckpointed() { 74 info.ranges.TryMerge(*common.NewClosedIntervalsByInt(lsn)) 75 delete(info.partial, lsn) 76 } 77 } 78 79 func (info *checkpointInfo) MergeCommandMap(cmdMap map[uint64]entry.CommandInfo) { 80 ckpedLsn := make([]uint64, 0) 81 for lsn, cmds := range cmdMap { 82 if info.ranges.Contains(*common.NewClosedIntervalsByInt(lsn)) { 83 continue 84 } 85 partialInfo, ok := info.partial[lsn] 86 if !ok { 87 partialInfo = newPartialCkpInfo(cmds.Size) 88 info.partial[lsn] = partialInfo 89 } 90 partialInfo.MergeCommandInfos(&cmds) 91 if partialInfo.IsAllCheckpointed() { 92 ckpedLsn = append(ckpedLsn, lsn) 93 delete(info.partial, lsn) 94 } 95 } 96 if len(ckpedLsn) == 0 { 97 return 98 } 99 intervals := common.NewClosedIntervalsBySlice(ckpedLsn) 100 info.ranges.TryMerge(*intervals) 101 } 102 103 func (info *checkpointInfo) MergeCheckpointInfo(ockp *checkpointInfo) { 104 info.ranges.TryMerge(*ockp.ranges) 105 for lsn, ockpinfo := range ockp.partial { 106 ckpinfo, ok := info.partial[lsn] 107 if !ok { 108 info.partial[lsn] = ockpinfo 109 } else { 110 if ckpinfo.size != ockpinfo.size { 111 panic("logic err") 112 } 113 ckpinfo.ckps.Or(ockpinfo.ckps) 114 if ckpinfo.IsAllCheckpointed() { 115 info.ranges.TryMerge(*common.NewClosedIntervalsByInt(lsn)) 116 delete(info.partial, lsn) 117 } 118 } 119 } 120 } 121 122 func (info *checkpointInfo) GetCheckpointed() uint64 { 123 if info.ranges == nil || len(info.ranges.Intervals) == 0 { 124 return 0 125 } 126 if info.ranges.Intervals[0].Start > 1 { 127 return 0 128 } 129 return info.ranges.Intervals[0].End 130 } 131 132 func (info *checkpointInfo) String() string { 133 s := fmt.Sprintf("range %v, partial ", info.ranges) 134 for lsn, partial := range info.partial { 135 s = fmt.Sprintf("%s[%d-%v]", s, lsn, partial) 136 } 137 return s 138 } 139 140 func (info *checkpointInfo) GetCkpCnt() uint64 { 141 cnt := uint64(0) 142 cnt += uint64(info.ranges.GetCardinality()) 143 // cnt += uint64(len(info.partial)) 144 return cnt 145 } 146 147 func (info *checkpointInfo) WriteTo(w io.Writer) (n int64, err error) { 148 sn, err := info.ranges.WriteTo(w) 149 n += sn 150 if err != nil { 151 return 152 } 153 length := uint64(len(info.partial)) 154 if err = binary.Write(w, binary.BigEndian, length); err != nil { 155 return 156 } 157 n += 8 158 for lsn, partialInfo := range info.partial { 159 if err = binary.Write(w, binary.BigEndian, lsn); err != nil { 160 return 161 } 162 n += 8 163 sn, err = partialInfo.WriteTo(w) 164 n += sn 165 if err != nil { 166 return 167 } 168 } 169 return 170 } 171 172 func (info *checkpointInfo) ReadFrom(r io.Reader) (n int64, err error) { 173 info.ranges = common.NewClosedIntervals() 174 sn, err := info.ranges.ReadFrom(r) 175 n += sn 176 if err != nil { 177 return 178 } 179 length := uint64(0) 180 if err = binary.Read(r, binary.BigEndian, &length); err != nil { 181 return 182 } 183 n += 8 184 for i := 0; i < int(length); i++ { 185 lsn := uint64(0) 186 if err = binary.Read(r, binary.BigEndian, &lsn); err != nil { 187 return 188 } 189 n += 8 190 partial := newPartialCkpInfo(0) 191 sn, err = partial.ReadFrom(r) 192 n += sn 193 if err != nil { 194 return 195 } 196 info.partial[lsn] = partial 197 } 198 return 199 }