github.com/matrixorigin/matrixone@v0.7.0/pkg/pb/logservice/logservice.go (about) 1 // Copyright 2021 - 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 logservice 16 17 import ( 18 "fmt" 19 "reflect" 20 "sort" 21 22 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 23 ) 24 25 const ( 26 // NoLeader is the replica ID of the leader node. 27 NoLeader uint64 = 0 28 // HeaderSize is the size of the header for each logservice and 29 // hakeeper command. 30 HeaderSize = 4 31 ) 32 33 // ResizePayload resizes the payload length to length bytes. 34 func (m *LogRecord) ResizePayload(length int) { 35 m.Data = m.Data[:HeaderSize+8+length] 36 } 37 38 // Payload returns the payload byte slice. 39 func (m *LogRecord) Payload() []byte { 40 return m.Data[HeaderSize+8:] 41 } 42 43 // NewRSMState creates a new HAKeeperRSMState instance. 44 func NewRSMState() HAKeeperRSMState { 45 return HAKeeperRSMState{ 46 ScheduleCommands: make(map[string]CommandBatch), 47 LogShards: make(map[string]uint64), 48 CNState: NewCNState(), 49 DNState: NewDNState(), 50 LogState: NewLogState(), 51 ClusterInfo: newClusterInfo(), 52 } 53 } 54 55 func newClusterInfo() ClusterInfo { 56 return ClusterInfo{ 57 DNShards: make([]metadata.DNShardRecord, 0), 58 LogShards: make([]metadata.LogShardRecord, 0), 59 } 60 } 61 62 // NewCNState creates a new CNState. 63 func NewCNState() CNState { 64 return CNState{ 65 Stores: make(map[string]CNStoreInfo), 66 } 67 } 68 69 // Update applies the incoming CNStoreHeartbeat into HAKeeper. Tick is the 70 // current tick of the HAKeeper which is used as the timestamp of the heartbeat. 71 func (s *CNState) Update(hb CNStoreHeartbeat, tick uint64) { 72 storeInfo, ok := s.Stores[hb.UUID] 73 if !ok { 74 storeInfo = CNStoreInfo{} 75 } 76 storeInfo.Tick = tick 77 storeInfo.ServiceAddress = hb.ServiceAddress 78 storeInfo.SQLAddress = hb.SQLAddress 79 storeInfo.Role = hb.Role 80 storeInfo.TaskServiceCreated = hb.TaskServiceCreated 81 s.Stores[hb.UUID] = storeInfo 82 } 83 84 // NewDNState creates a new DNState. 85 func NewDNState() DNState { 86 return DNState{ 87 Stores: make(map[string]DNStoreInfo), 88 } 89 } 90 91 // Update applies the incoming DNStoreHeartbeat into HAKeeper. Tick is the 92 // current tick of the HAKeeper which is used as the timestamp of the heartbeat. 93 func (s *DNState) Update(hb DNStoreHeartbeat, tick uint64) { 94 storeInfo, ok := s.Stores[hb.UUID] 95 if !ok { 96 storeInfo = DNStoreInfo{} 97 } 98 storeInfo.Tick = tick 99 storeInfo.Shards = hb.Shards 100 storeInfo.ServiceAddress = hb.ServiceAddress 101 storeInfo.LogtailServerAddress = hb.LogtailServerAddress 102 storeInfo.TaskServiceCreated = hb.TaskServiceCreated 103 s.Stores[hb.UUID] = storeInfo 104 } 105 106 // NewLogState creates a new LogState. 107 func NewLogState() LogState { 108 return LogState{ 109 Shards: make(map[uint64]LogShardInfo), 110 Stores: make(map[string]LogStoreInfo), 111 } 112 } 113 114 // Update applies the incoming heartbeat message to the LogState with the 115 // specified tick used as the timestamp. 116 func (s *LogState) Update(hb LogStoreHeartbeat, tick uint64) { 117 s.updateStores(hb, tick) 118 s.updateShards(hb) 119 } 120 121 func (s *LogState) updateStores(hb LogStoreHeartbeat, tick uint64) { 122 storeInfo, ok := s.Stores[hb.UUID] 123 if !ok { 124 storeInfo = LogStoreInfo{} 125 } 126 storeInfo.Tick = tick 127 storeInfo.RaftAddress = hb.RaftAddress 128 storeInfo.ServiceAddress = hb.ServiceAddress 129 storeInfo.GossipAddress = hb.GossipAddress 130 storeInfo.Replicas = hb.Replicas 131 storeInfo.TaskServiceCreated = hb.TaskServiceCreated 132 s.Stores[hb.UUID] = storeInfo 133 } 134 135 func (s *LogState) updateShards(hb LogStoreHeartbeat) { 136 for _, incoming := range hb.Replicas { 137 recorded, ok := s.Shards[incoming.ShardID] 138 if !ok { 139 recorded = LogShardInfo{ 140 ShardID: incoming.ShardID, 141 Replicas: make(map[uint64]string), 142 } 143 } 144 145 if incoming.Epoch > recorded.Epoch { 146 recorded.Epoch = incoming.Epoch 147 recorded.Replicas = incoming.Replicas 148 } else if incoming.Epoch == recorded.Epoch && incoming.Epoch > 0 { 149 if !reflect.DeepEqual(recorded.Replicas, incoming.Replicas) { 150 panic("inconsistent replicas") 151 } 152 } 153 154 if incoming.Term > recorded.Term && incoming.LeaderID != NoLeader { 155 recorded.Term = incoming.Term 156 recorded.LeaderID = incoming.LeaderID 157 } 158 159 s.Shards[incoming.ShardID] = recorded 160 } 161 } 162 163 // LogString returns "ServiceType/ConfigChangeType UUID RepUuid:RepShardID:RepID InitialMembers". 164 // Do not add CN's StartTaskRunner info to log string, because there has user and password. 165 func (m *ScheduleCommand) LogString() string { 166 c := func(s string) string { 167 if len(s) > 6 { 168 return s[:6] 169 } 170 return s 171 } 172 173 serviceType := map[ServiceType]string{ 174 LogService: "L", 175 DNService: "D", 176 CNService: "C", 177 }[m.ServiceType] 178 179 target := c(m.UUID) 180 if m.ShutdownStore != nil { 181 return fmt.Sprintf("%s/shutdown %s", serviceType, target) 182 } 183 if m.CreateTaskService != nil { 184 return fmt.Sprintf("%s/CreateTask %s", serviceType, target) 185 } 186 if m.ConfigChange == nil { 187 return fmt.Sprintf("%s/unknown command %s", serviceType, m.String()) 188 } 189 190 configChangeType := "Unknown" 191 if m.ConfigChange != nil { 192 configChangeType = map[ConfigChangeType]string{ 193 AddReplica: "Add", 194 RemoveReplica: "Remove", 195 StartReplica: "Start", 196 StopReplica: "Stop", 197 KillZombie: "Kill", 198 }[m.ConfigChange.ChangeType] 199 } 200 201 replica := c(m.ConfigChange.Replica.UUID) 202 s := fmt.Sprintf("%s/%s %s %s:%d:%d:%d", 203 serviceType, configChangeType, target, replica, 204 m.ConfigChange.Replica.ShardID, 205 m.ConfigChange.Replica.ReplicaID, 206 m.ConfigChange.Replica.Epoch) 207 208 if len(m.ConfigChange.InitialMembers) != 0 { 209 initMembers := make([]string, 0, len(m.ConfigChange.InitialMembers)) 210 for repId, uuid := range m.ConfigChange.InitialMembers { 211 initMembers = append(initMembers, fmt.Sprintf("%d:%s", repId, c(uuid))) 212 } 213 sort.Strings(initMembers) 214 s += fmt.Sprintf(" %v", initMembers) 215 } 216 217 return s 218 }