github.com/matrixorigin/matrixone@v1.2.0/pkg/tests/service/network.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 service 16 17 import ( 18 "strconv" 19 "strings" 20 "testing" 21 22 "github.com/RoaringBitmap/roaring" 23 "github.com/matrixorigin/matrixone/pkg/tests" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 ) 27 28 // serviceAddresses contains addresses of all services. 29 type serviceAddresses struct { 30 t *testing.T 31 32 // Construct service addresses according to service number 33 logServiceNum int 34 tnServiceNum int 35 cnServiceNum int 36 37 logAddresses []logServiceAddress 38 tnAddresses []tnServiceAddress 39 cnAddresses []cnServiceAddress 40 } 41 42 // newServiceAddresses constructs addresses for all services. 43 func newServiceAddresses(t *testing.T, logServiceNum, tnServiceNum, cnServiceNum int, hostAddr string) *serviceAddresses { 44 address := &serviceAddresses{ 45 t: t, 46 logServiceNum: logServiceNum, 47 tnServiceNum: tnServiceNum, 48 } 49 50 // build log service addresses 51 logBatch := address.logServiceNum 52 logAddrs := make([]logServiceAddress, logBatch) 53 for i := 0; i < logBatch; i++ { 54 logAddr, err := newLogServiceAddress(hostAddr) 55 require.NoError(t, err) 56 logAddrs[i] = logAddr 57 } 58 address.logAddresses = logAddrs 59 60 // build tn service addresses 61 tnBatch := address.tnServiceNum 62 tnAddrs := make([]tnServiceAddress, tnBatch) 63 for i := 0; i < tnBatch; i++ { 64 tnAddr, err := newTNServiceAddress(hostAddr) 65 require.NoError(t, err) 66 tnAddrs[i] = tnAddr 67 } 68 address.tnAddresses = tnAddrs 69 70 address.buildCNAddress(t, cnServiceNum, hostAddr) 71 return address 72 } 73 74 func (a *serviceAddresses) buildCNAddress( 75 t *testing.T, 76 cnBatch int, 77 hostAddr string) { 78 for i := 0; i < cnBatch; i++ { 79 cnAddr, err := newCNServiceAddress(hostAddr) 80 require.NoError(t, err) 81 a.cnAddresses = append(a.cnAddresses, cnAddr) 82 a.cnServiceNum++ 83 } 84 } 85 86 // assertTNService asserts constructed address for tn service. 87 func (a serviceAddresses) assertTNService() { 88 assert.Equal(a.t, a.tnServiceNum, len(a.tnAddresses)) 89 } 90 91 // assertLogService asserts constructed address for log service. 92 func (a serviceAddresses) assertLogService() { 93 assert.Equal(a.t, a.logServiceNum, len(a.logAddresses)) 94 } 95 96 // assertCnService asserts constructed address for cn service. 97 func (a serviceAddresses) assertCnService() { 98 assert.Equal(a.t, a.cnServiceNum, len(a.cnAddresses)) 99 } 100 101 // getTnListenAddress gets tn listen address by its index. 102 func (a serviceAddresses) getTnListenAddress(index int) string { 103 a.assertTNService() 104 105 if index >= len(a.tnAddresses) || index < 0 { 106 return "" 107 } 108 return a.tnAddresses[index].listenAddr 109 } 110 111 // getTnLogtailAddress gets logtail server address by its index. 112 func (a serviceAddresses) getTnLogtailAddress(index int) string { 113 a.assertTNService() 114 115 if index >= len(a.tnAddresses) || index < 0 { 116 return "" 117 } 118 return a.tnAddresses[index].logtailAddr 119 } 120 121 func (a serviceAddresses) getTNLockListenAddress(index int) string { 122 a.assertTNService() 123 124 if index >= len(a.tnAddresses) || index < 0 { 125 return "" 126 } 127 return a.tnAddresses[index].lockAddr 128 } 129 130 func (a serviceAddresses) getCNLockListenAddress(index int) string { 131 a.assertTNService() 132 133 if index >= len(a.cnAddresses) || index < 0 { 134 return "" 135 } 136 return a.cnAddresses[index].lockAddr 137 } 138 139 func (a serviceAddresses) getCNQueryListenAddress(index int) string { 140 a.assertTNService() 141 142 if index >= len(a.cnAddresses) || index < 0 { 143 return "" 144 } 145 return a.cnAddresses[index].queryAddr 146 } 147 148 // getLogListenAddress gets log service address by its index. 149 func (a serviceAddresses) getLogListenAddress(index int) string { 150 a.assertLogService() 151 152 if index >= len(a.logAddresses) || index < 0 { 153 return "" 154 } 155 return a.logAddresses[index].listenAddr 156 } 157 158 func (a serviceAddresses) getCNListenAddress(index int) string { 159 a.assertCnService() 160 161 if index >= len(a.cnAddresses) || index < 0 { 162 return "" 163 } 164 return a.cnAddresses[index].listenAddr 165 } 166 167 // getLogRaftAddress gets log raft address by its index. 168 func (a serviceAddresses) getLogRaftAddress(index int) string { 169 a.assertLogService() 170 171 if index >= len(a.logAddresses) || index < 0 { 172 return "" 173 } 174 return a.logAddresses[index].raftAddr 175 } 176 177 // getLogGossipAddress gets log gossip address by its index. 178 func (a serviceAddresses) getLogGossipAddress(index int) string { 179 a.assertLogService() 180 181 if index >= len(a.logAddresses) || index < 0 { 182 return "" 183 } 184 return a.logAddresses[index].gossipAddr 185 } 186 187 // getLogGossipSeedAddresses gets all gossip seed addresses. 188 // 189 // Select gossip addresses of the first 3 log services. 190 // If the number of log services was less than 3, 191 // then select all of them. 192 func (a serviceAddresses) getLogGossipSeedAddresses() []string { 193 a.assertLogService() 194 195 n := gossipSeedNum(len(a.logAddresses)) 196 seedAddrs := make([]string, n) 197 for i := 0; i < n; i++ { 198 seedAddrs[i] = a.logAddresses[i].gossipAddr 199 } 200 return seedAddrs 201 } 202 203 // listHAKeeperListenAddresses gets addresses of all hakeeper servers. 204 // 205 // Select the first 3 log services to start hakeeper replica. 206 // If the number of log services was less than 3, 207 // then select the first of them. 208 func (a serviceAddresses) listHAKeeperListenAddresses() []string { 209 a.assertLogService() 210 211 n := haKeeperNum(len(a.logAddresses)) 212 listenAddrs := make([]string, n) 213 for i := 0; i < n; i++ { 214 listenAddrs[i] = a.logAddresses[i].listenAddr 215 } 216 return listenAddrs 217 } 218 219 // buildPartitionAddressSets returns service addresses by every partition. 220 func (a serviceAddresses) buildPartitionAddressSets(partitions ...NetworkPartition) []addressSet { 221 sets := make([]addressSet, 0, len(partitions)) 222 for _, part := range partitions { 223 sets = append(sets, a.listPartitionAddresses(part)) 224 } 225 return sets 226 } 227 228 // listPartitionAddresses returns all service addresses within the same partition. 229 func (a serviceAddresses) listPartitionAddresses(partition NetworkPartition) addressSet { 230 addrSet := newAddressSet() 231 for _, tnIndex := range partition.ListTNServiceIndex() { 232 addrs := a.listTnServiceAddresses(int(tnIndex)) 233 addrSet.addAddresses(addrs...) 234 } 235 for _, logIndex := range partition.ListLogServiceIndex() { 236 addrs := a.listLogServiceAddresses(int(logIndex)) 237 addrSet.addAddresses(addrs...) 238 } 239 for _, cnIndex := range partition.ListCNServiceIndex() { 240 addrs := a.listCnServiceAddresses(int(cnIndex)) 241 addrSet.addAddresses(addrs...) 242 } 243 return addrSet 244 } 245 246 // listTnServiceAddresses lists all addresses of tn service by its index. 247 func (a serviceAddresses) listTnServiceAddresses(index int) []string { 248 a.assertTNService() 249 250 if index >= len(a.tnAddresses) || index < 0 { 251 return nil 252 } 253 return a.tnAddresses[index].listAddresses() 254 } 255 256 // listLogServiceAddresses lists all addresses of log service by its index. 257 func (a serviceAddresses) listLogServiceAddresses(index int) []string { 258 a.assertLogService() 259 260 if index >= len(a.logAddresses) || index < 0 { 261 return nil 262 } 263 return a.logAddresses[index].listAddresses() 264 } 265 266 // listCnServiceAddresses lists all addresses of log service by its index. 267 func (a serviceAddresses) listCnServiceAddresses(index int) []string { 268 a.assertCnService() 269 270 if index >= len(a.cnAddresses) || index < 0 { 271 return nil 272 } 273 return a.cnAddresses[index].listAddresses() 274 } 275 276 // logServiceAddress contains addresses for log service. 277 type logServiceAddress struct { 278 listenAddr string 279 raftAddr string 280 gossipAddr string 281 } 282 283 func newLogServiceAddress(host string) (logServiceAddress, error) { 284 addrs, err := tests.GetAddressBatch(host, 3) 285 if err != nil { 286 return logServiceAddress{}, err 287 } 288 289 return logServiceAddress{ 290 listenAddr: addrs[0], 291 raftAddr: addrs[1], 292 gossipAddr: addrs[2], 293 }, nil 294 } 295 296 // listAddresses returns all addresses for single log service. 297 func (la logServiceAddress) listAddresses() []string { 298 return []string{la.listenAddr, la.raftAddr, la.gossipAddr} 299 } 300 301 // tnServiceAddress contains address for tn service. 302 type tnServiceAddress struct { 303 listenAddr string 304 logtailAddr string 305 lockAddr string 306 } 307 308 func newTNServiceAddress(host string) (tnServiceAddress, error) { 309 addrs, err := tests.GetAddressBatch(host, 3) 310 if err != nil { 311 return tnServiceAddress{}, err 312 } 313 return tnServiceAddress{ 314 listenAddr: addrs[0], 315 logtailAddr: addrs[1], 316 lockAddr: addrs[2], 317 }, nil 318 } 319 320 // listAddresses returns all addresses for single tn service. 321 func (da tnServiceAddress) listAddresses() []string { 322 return []string{da.listenAddr, da.logtailAddr} 323 } 324 325 type cnServiceAddress struct { 326 listenAddr string 327 lockAddr string 328 queryAddr string 329 } 330 331 func newCNServiceAddress(host string) (cnServiceAddress, error) { 332 addrs, err := tests.GetAddressBatch(host, 3) 333 if err != nil { 334 return cnServiceAddress{}, err 335 } 336 return cnServiceAddress{ 337 listenAddr: addrs[0], 338 lockAddr: addrs[1], 339 queryAddr: addrs[2], 340 }, nil 341 } 342 343 func (ca cnServiceAddress) listAddresses() []string { 344 return []string{ca.listenAddr} 345 } 346 347 // addressSet records addresses for services within the same partition. 348 type addressSet map[string]struct{} 349 350 func newAddressSet() addressSet { 351 return make(map[string]struct{}) 352 } 353 354 // addAddresses registers a list of addresses. 355 func (s addressSet) addAddresses(addrs ...string) { 356 for _, addr := range addrs { 357 s[addr] = struct{}{} 358 } 359 } 360 361 // contains checks address exist or not. 362 func (s addressSet) contains(addr string) bool { 363 _, ok := s[addr] 364 return ok 365 } 366 367 // NetworkPartition records index of services from the same network partition. 368 type NetworkPartition struct { 369 logIndexSet *roaring.Bitmap 370 tnIndexSet *roaring.Bitmap 371 cnIndexSet *roaring.Bitmap 372 } 373 374 // newNetworkPartition returns an instance of NetworkPartition. 375 // 376 // The returned instance only contains valid index according to service number. 377 func newNetworkPartition( 378 logServiceNum int, logIndexes []uint32, 379 tnServiceNum int, tnIndexes []uint32, 380 cnServiceNum int, cnIndexes []uint32, 381 ) NetworkPartition { 382 logTotal := roaring.FlipInt(roaring.NewBitmap(), 0, logServiceNum) 383 tnTotal := roaring.FlipInt(roaring.NewBitmap(), 0, tnServiceNum) 384 cnTotal := roaring.FlipInt(roaring.NewBitmap(), 0, cnServiceNum) 385 386 rawLogSet := roaring.BitmapOf(logIndexes...) 387 rawTnSet := roaring.BitmapOf(tnIndexes...) 388 rawCnSet := roaring.BitmapOf(cnIndexes...) 389 390 return NetworkPartition{ 391 logIndexSet: roaring.And(logTotal, rawLogSet), 392 tnIndexSet: roaring.And(tnTotal, rawTnSet), 393 cnIndexSet: roaring.And(cnTotal, rawCnSet), 394 } 395 } 396 397 // remainingNetworkPartition returns partition for the remaining services. 398 func remainingNetworkPartition(logServiceNum, tnServiceNum, cnServiceNum int, 399 partitions ...NetworkPartition) NetworkPartition { 400 logTotal := roaring.FlipInt(roaring.NewBitmap(), 0, logServiceNum) 401 tnTotal := roaring.FlipInt(roaring.NewBitmap(), 0, tnServiceNum) 402 cnTotal := roaring.FlipInt(roaring.NewBitmap(), 0, cnServiceNum) 403 404 logUsed := roaring.NewBitmap() 405 tnUsed := roaring.NewBitmap() 406 cnUsed := roaring.NewBitmap() 407 for _, p := range partitions { 408 tnUsed.Or(p.tnIndexSet) 409 logUsed.Or(p.logIndexSet) 410 cnUsed.Or(p.cnIndexSet) 411 } 412 413 return NetworkPartition{ 414 logIndexSet: roaring.AndNot(logTotal, logUsed), 415 tnIndexSet: roaring.AndNot(tnTotal, tnUsed), 416 cnIndexSet: roaring.AndNot(cnTotal, cnUsed), 417 } 418 } 419 420 // ListTNServiceIndex lists index of all tn services in the partition. 421 func (p NetworkPartition) ListTNServiceIndex() []uint32 { 422 set := p.tnIndexSet 423 424 if set.GetCardinality() == 0 { 425 return nil 426 } 427 428 indexes := make([]uint32, 0, set.GetCardinality()) 429 iter := set.Iterator() 430 for iter.HasNext() { 431 indexes = append(indexes, iter.Next()) 432 } 433 return indexes 434 } 435 436 // ListLogServiceIndex lists index of all log services in the partition. 437 func (p NetworkPartition) ListLogServiceIndex() []uint32 { 438 set := p.logIndexSet 439 440 if set.GetCardinality() == 0 { 441 return nil 442 } 443 444 indexes := make([]uint32, 0, set.GetCardinality()) 445 iter := set.Iterator() 446 for iter.HasNext() { 447 indexes = append(indexes, iter.Next()) 448 } 449 return indexes 450 } 451 452 func (p NetworkPartition) ListCNServiceIndex() []uint32 { 453 set := p.cnIndexSet 454 455 if set.GetCardinality() == 0 { 456 return nil 457 } 458 459 indexes := make([]uint32, 0, set.GetCardinality()) 460 iter := set.Iterator() 461 for iter.HasNext() { 462 indexes = append(indexes, iter.Next()) 463 } 464 return indexes 465 } 466 467 func getPort(addr string) int { 468 ss := strings.Split(addr, ":") 469 if len(ss) != 2 { 470 panic("bad address: " + addr) 471 } 472 p, err := strconv.Atoi(ss[1]) 473 if err != nil { 474 panic("bad address: " + addr) 475 } 476 return p 477 }