github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/p2pserver/sync/org/org_block_sync.go (about) 1 package org 2 3 import ( 4 "github.com/sixexorg/magnetic-ring/p2pserver/temp" 5 "math" 6 "sort" 7 "sync" 8 "time" 9 10 "github.com/sixexorg/magnetic-ring/common" 11 "github.com/sixexorg/magnetic-ring/core/orgchain/types" 12 "github.com/sixexorg/magnetic-ring/log" 13 p2pComm "github.com/sixexorg/magnetic-ring/p2pserver/common" 14 msgpack "github.com/sixexorg/magnetic-ring/p2pserver/message" 15 "github.com/sixexorg/magnetic-ring/p2pserver/peer" 16 "github.com/sixexorg/magnetic-ring/p2pserver/sync/p2pserprotocol" 17 ledger "github.com/sixexorg/magnetic-ring/store/orgchain/storages" 18 "github.com/sixexorg/magnetic-ring/store/orgchain/validation" 19 ) 20 21 const ( 22 SYNC_MAX_HEADER_FORWARD_SIZE = 5000 //keep CurrentHeaderHeight - CurrentBlockHeight <= SYNC_MAX_HEADER_FORWARD_SIZE 23 SYNC_MAX_FLIGHT_HEADER_SIZE = 1 //Number of headers on flight 24 SYNC_MAX_FLIGHT_BLOCK_SIZE = 50 //Number of blocks on flight 25 SYNC_MAX_BLOCK_CACHE_SIZE = 500 //Cache size of block wait to commit to ledger 26 SYNC_HEADER_REQUEST_TIMEOUT = 2 //s, Request header timeout time. If header haven't receive after SYNC_HEADER_REQUEST_TIMEOUT second, retry 27 SYNC_BLOCK_REQUEST_TIMEOUT = 2 //s, Request block timeout time. If block haven't received after SYNC_BLOCK_REQUEST_TIMEOUT second, retry 28 SYNC_NEXT_BLOCK_TIMES = 3 //Request times of next height block 29 SYNC_NEXT_BLOCKS_HEIGHT = 2 //for current block height plus next 30 SYNC_NODE_RECORD_SPEED_CNT = 3 //Record speed count for accuracy 31 SYNC_NODE_RECORD_TIME_CNT = 3 //Record request time for accuracy 32 SYNC_NODE_SPEED_INIT = 100 * 1024 //Init a big speed (100MB/s) for every node in first round 33 SYNC_MAX_ERROR_RESP_TIMES = 5 //Max error headers/blocks response times, if reaches, delete it 34 SYNC_MAX_HEIGHT_OFFSET = 5 //Offset of the max height and current height 35 ) 36 37 //NodeWeight record some params of node, using for sort 38 type NodeWeight struct { 39 id uint64 //NodeID 40 speed []float32 //Record node request-response speed, using for calc the avg speed, unit kB/s 41 timeoutCnt int //Node response timeout count 42 errorRespCnt int //Node response error data count 43 reqTime []int64 //Record request time, using for calc the avg req time interval, unit millisecond 44 } 45 46 //NewNodeWeight new a nodeweight 47 func NewNodeWeight(id uint64) *NodeWeight { 48 s := make([]float32, 0, SYNC_NODE_RECORD_SPEED_CNT) 49 for i := 0; i < SYNC_NODE_RECORD_SPEED_CNT; i++ { 50 s = append(s, float32(SYNC_NODE_SPEED_INIT)) 51 } 52 r := make([]int64, 0, SYNC_NODE_RECORD_TIME_CNT) 53 now := time.Now().UnixNano() / int64(time.Millisecond) 54 for i := 0; i < SYNC_NODE_RECORD_TIME_CNT; i++ { 55 r = append(r, now) 56 } 57 return &NodeWeight{ 58 id: id, 59 speed: s, 60 timeoutCnt: 0, 61 errorRespCnt: 0, 62 reqTime: r, 63 } 64 } 65 66 //AddTimeoutCnt incre timeout count 67 func (that *NodeWeight) AddTimeoutCnt() { 68 that.timeoutCnt++ 69 } 70 71 //AddErrorRespCnt incre receive error header/block count 72 func (that *NodeWeight) AddErrorRespCnt() { 73 that.errorRespCnt++ 74 } 75 76 //GetErrorRespCnt get the error response count 77 func (that *NodeWeight) GetErrorRespCnt() int { 78 return that.errorRespCnt 79 } 80 81 //AppendNewReqTime append new request time 82 func (that *NodeWeight) AppendNewReqtime() { 83 copy(that.reqTime[0:SYNC_NODE_RECORD_TIME_CNT-1], that.reqTime[1:]) 84 that.reqTime[SYNC_NODE_RECORD_TIME_CNT-1] = time.Now().UnixNano() / int64(time.Millisecond) 85 } 86 87 //addNewSpeed apend the new speed to tail, remove the oldest one 88 func (that *NodeWeight) AppendNewSpeed(s float32) { 89 copy(that.speed[0:SYNC_NODE_RECORD_SPEED_CNT-1], that.speed[1:]) 90 that.speed[SYNC_NODE_RECORD_SPEED_CNT-1] = s 91 } 92 93 //Weight calculate node's weight for sort. Highest weight node will be accessed first for next request. 94 func (that *NodeWeight) Weight() float32 { 95 avgSpeed := float32(0.0) 96 for _, s := range that.speed { 97 avgSpeed += s 98 } 99 avgSpeed = avgSpeed / float32(len(that.speed)) 100 101 avgInterval := float32(0.0) 102 now := time.Now().UnixNano() / int64(time.Millisecond) 103 for _, t := range that.reqTime { 104 avgInterval += float32(now - t) 105 } 106 avgInterval = avgInterval / float32(len(that.reqTime)) 107 w := avgSpeed + avgInterval 108 return w 109 } 110 111 //NodeWeights implement sorting 112 type NodeWeights []*NodeWeight 113 114 func (nws NodeWeights) Len() int { 115 return len(nws) 116 } 117 118 func (nws NodeWeights) Swap(i, j int) { 119 nws[i], nws[j] = nws[j], nws[i] 120 } 121 func (nws NodeWeights) Less(i, j int) bool { 122 ni := nws[i] 123 nj := nws[j] 124 return ni.Weight() < nj.Weight() && ni.errorRespCnt >= nj.errorRespCnt && ni.timeoutCnt >= nj.timeoutCnt 125 } 126 127 //SyncFlightInfo record the info of fight object(header or block) 128 type SyncFlightInfo struct { 129 Height uint32 //BlockHeight of HeaderHeight 130 nodeId uint64 //The current node to send msg 131 startTime time.Time //Request start time 132 failedNodes map[uint64]int //Map nodeId => timeout times 133 totalFailed int //Total timeout times 134 lock sync.RWMutex 135 } 136 137 //NewSyncFlightInfo return a new SyncFlightInfo instance 138 func NewSyncFlightInfo(height uint32, nodeId uint64) *SyncFlightInfo { 139 return &SyncFlightInfo{ 140 Height: height, 141 nodeId: nodeId, 142 startTime: time.Now(), 143 failedNodes: make(map[uint64]int, 0), 144 } 145 } 146 147 //GetNodeId return current node id for sending msg 148 func (that *SyncFlightInfo) GetNodeId() uint64 { 149 that.lock.RLock() 150 defer that.lock.RUnlock() 151 return that.nodeId 152 } 153 154 //SetNodeId set a new node id 155 func (that *SyncFlightInfo) SetNodeId(nodeId uint64) { 156 that.lock.Lock() 157 defer that.lock.Unlock() 158 that.nodeId = nodeId 159 } 160 161 //MarkFailedNode mark node failed, after request timeout 162 func (that *SyncFlightInfo) MarkFailedNode() { 163 that.lock.Lock() 164 defer that.lock.Unlock() 165 that.failedNodes[that.nodeId] += 1 166 that.totalFailed++ 167 } 168 169 //GetFailedTimes return failed times of a node 170 func (that *SyncFlightInfo) GetFailedTimes(nodeId uint64) int { 171 that.lock.RLock() 172 defer that.lock.RUnlock() 173 times, ok := that.failedNodes[nodeId] 174 if !ok { 175 return 0 176 } 177 return times 178 } 179 180 //GetTotalFailedTimes return the total failed times of request 181 func (that *SyncFlightInfo) GetTotalFailedTimes() int { 182 that.lock.RLock() 183 defer that.lock.RUnlock() 184 return that.totalFailed 185 } 186 187 //ResetStartTime 188 func (that *SyncFlightInfo) ResetStartTime() { 189 that.lock.Lock() 190 defer that.lock.Unlock() 191 that.startTime = time.Now() 192 } 193 194 //GetStartTime return the start time of request 195 func (that *SyncFlightInfo) GetStartTime() time.Time { 196 that.lock.RLock() 197 defer that.lock.RUnlock() 198 return that.startTime 199 } 200 201 //BlockInfo is used for saving block information in cache 202 type BlockInfo struct { 203 nodeID uint64 204 block *types.Block 205 } 206 207 //OrgBlockSyncMgr is the manager class to deal with block sync 208 type OrgBlockSyncMgr struct { 209 flightBlocks map[common.Hash][]*SyncFlightInfo //Map BlockHash => []SyncFlightInfo, using for manager all of those block flights 210 flightHeaders map[uint32]*SyncFlightInfo //Map HeaderHeight => SyncFlightInfo, using for manager all of those header flights 211 blocksCache map[uint32]*BlockInfo //Map BlockHash => BlockInfo, using for cache the blocks receive from net, and waiting for commit to ledger 212 server p2pserprotocol.SyncP2PSer //Pointer to the local node 213 syncBlockLock bool //Help to avoid send block sync request duplicate 214 syncHeaderLock bool //Help to avoid send header sync request duplicate 215 saveBlockLock bool //Help to avoid saving block concurrently 216 exitCh chan interface{} //ExitCh to receive exit signal 217 ledger *ledger.LedgerStoreImp //ledger 218 lock sync.RWMutex //lock 219 nodeWeights map[uint64]*NodeWeight //Map NodeID => NodeStatus, using for getNextNode 220 // org 221 orgID common.Address 222 } 223 224 //NewOrgBlockSyncMgr return a OrgBlockSyncMgr instance 225 func NewOrgBlockSyncMgr(server p2pserprotocol.SyncP2PSer, orgID common.Address) *OrgBlockSyncMgr { 226 return &OrgBlockSyncMgr{ 227 flightBlocks: make(map[common.Hash][]*SyncFlightInfo, 0), 228 flightHeaders: make(map[uint32]*SyncFlightInfo, 0), 229 blocksCache: make(map[uint32]*BlockInfo, 0), 230 server: server, 231 // ledger: server.GetLedger(), 232 ledger: temp.GetLedger(orgID), 233 234 exitCh: make(chan interface{}, 1), 235 nodeWeights: make(map[uint64]*NodeWeight, 0), 236 orgID: orgID, 237 } 238 } 239 240 //Start to sync 241 func (that *OrgBlockSyncMgr) Start() { 242 getledger := func() { 243 if that.ledger == nil { 244 that.ledger = temp.GetLedger(that.orgID) 245 } 246 } 247 for true { 248 getledger() 249 if that.ledger != nil { 250 break 251 } 252 time.Sleep(time.Second) 253 //fmt.Println(" ****** for true for true for true ...... ") 254 } 255 256 go that.sync() 257 go that.printHeight() 258 ticker := time.NewTicker(time.Second) 259 for { 260 select { 261 case <-that.exitCh: 262 return 263 case <-ticker.C: 264 go that.checkTimeout() 265 go that.sync() 266 go that.saveBlock() 267 } 268 } 269 } 270 271 272 func (that *OrgBlockSyncMgr) printHeight() { 273 t := time.NewTicker(p2pComm.DEFAULT_GEN_BLOCK_TIME * time.Second) 274 defer t.Stop() 275 276 for { 277 select { 278 case <-t.C: 279 log.Info(" **** orgID", "orgID", that.orgID, "CurrentBlockHeight", that.ledger.GetCurrentBlockHeight( /*that.orgID*/ )) 280 //fmt.Println(" ******* CurrentHeaderHeight:", that.ledger.GetCurrentHeaderHeight()) 281 case <-that.exitCh: 282 return 283 } 284 } 285 } 286 287 func (that *OrgBlockSyncMgr) checkTimeout() { 288 now := time.Now() 289 headerTimeoutFlights := make(map[uint32]*SyncFlightInfo, 0) 290 blockTimeoutFlights := make(map[common.Hash][]*SyncFlightInfo, 0) 291 that.lock.RLock() 292 // 293 for height, flightInfo := range that.flightHeaders { 294 // 295 if int(now.Sub(flightInfo.startTime).Seconds()) >= SYNC_HEADER_REQUEST_TIMEOUT { 296 headerTimeoutFlights[height] = flightInfo 297 } 298 } 299 300 for blockHash, flightInfos := range that.flightBlocks { 301 for _, flightInfo := range flightInfos { 302 if int(now.Sub(flightInfo.startTime).Seconds()) >= SYNC_BLOCK_REQUEST_TIMEOUT { 303 blockTimeoutFlights[blockHash] = append(blockTimeoutFlights[blockHash], flightInfo) 304 } 305 } 306 } 307 that.lock.RUnlock() 308 309 curHeaderHeight := that.ledger.GetCurrentHeaderHeight( /*that.orgID*/ ) 310 curBlockHeight := that.ledger.GetCurrentBlockHeight( /*that.orgID*/ ) 311 312 //Header request processing after timeout 313 for height, flightInfo := range headerTimeoutFlights { 314 that.addTimeoutCnt(flightInfo.GetNodeId()) 315 if height <= uint32(curHeaderHeight) { 316 that.delFlightHeader(height) 317 continue 318 } 319 flightInfo.ResetStartTime() 320 flightInfo.MarkFailedNode() 321 log.Trace("[p2p]checkTimeout org sync headers from", "id", flightInfo.GetNodeId(), 322 "height", height, "after", SYNC_HEADER_REQUEST_TIMEOUT, "Times", flightInfo.GetTotalFailedTimes()) 323 reqNode := that.getNodeWithMinFailedTimes(flightInfo, uint32(curBlockHeight)) 324 if reqNode == nil { 325 break 326 } 327 flightInfo.SetNodeId(reqNode.GetID()) 328 329 headerHash := that.ledger.GetCurrentHeaderHash( /*that.orgID*/ ) 330 msg := msgpack.NewHeadersReq(headerHash, that.orgID, p2pComm.SYNC_DATA_ORG) 331 err := that.server.Send(reqNode, msg, false) 332 if err != nil { 333 log.Warn("[p2p]checkTimeout failed to send a new headersReq", "err", err) 334 } else { 335 that.appendReqTime(reqNode.GetID()) 336 } 337 } 338 // 339 for blockHash, flightInfos := range blockTimeoutFlights { 340 for _, flightInfo := range flightInfos { 341 that.addTimeoutCnt(flightInfo.GetNodeId()) 342 if flightInfo.Height <= uint32(curBlockHeight) { 343 that.delFlightBlock(blockHash) 344 continue 345 } 346 flightInfo.ResetStartTime() 347 flightInfo.MarkFailedNode() 348 log.Trace("[p2p]checkTimeout sync", "height", flightInfo.Height, "block", blockHash, "after", SYNC_BLOCK_REQUEST_TIMEOUT, "times", flightInfo.GetTotalFailedTimes()) 349 reqNode := that.getNodeWithMinFailedTimes(flightInfo, uint32(curBlockHeight)) 350 if reqNode == nil { 351 break 352 } 353 flightInfo.SetNodeId(reqNode.GetID()) 354 355 msg := msgpack.NewBlkDataReq(blockHash, that.orgID, p2pComm.SYNC_DATA_ORG) 356 err := that.server.Send(reqNode, msg, false) 357 if err != nil { 358 log.Warn("[p2p]checkTimeout reqNode", "ID", reqNode.GetID(), "err", err) 359 continue 360 } else { 361 that.appendReqTime(reqNode.GetID()) 362 } 363 } 364 } 365 } 366 367 func (that *OrgBlockSyncMgr) sync() { 368 that.syncHeader() 369 that.syncBlock() 370 } 371 372 func (that *OrgBlockSyncMgr) reachMinConnection() bool { 373 374 minCount := p2pComm.ORG_MIN_NODE_NUM 375 376 that.lock.Lock() 377 defer that.lock.Unlock() 378 379 return len(that.nodeWeights) >= minCount 380 } 381 382 func (that *OrgBlockSyncMgr) syncHeader() { 383 384 if !that.reachMinConnection() { 385 log.Info("[OrgBlockSyncMgr] orgid:%v Wait for minimum connection", "orgID", that.orgID) 386 return 387 } 388 389 if that.tryGetSyncHeaderLock() { 390 return 391 } 392 defer that.releaseSyncHeaderLock() 393 394 395 if that.getFlightHeaderCount() >= SYNC_MAX_FLIGHT_HEADER_SIZE { 396 return 397 } 398 curBlockHeight := that.ledger.GetCurrentBlockHeight( /*that.orgID*/ ) 399 400 curHeaderHeight := that.ledger.GetCurrentHeaderHeight( /*that.orgID*/ ) 401 //Waiting for block catch up header 402 if curHeaderHeight-curBlockHeight >= SYNC_MAX_HEADER_FORWARD_SIZE { 403 return 404 } 405 NextHeaderId := uint32(curHeaderHeight) + 1 406 reqNode := that.getNextNode(NextHeaderId) 407 if reqNode == nil { 408 return 409 } 410 that.addFlightHeader(reqNode.GetID(), NextHeaderId) 411 412 headerHash := that.ledger.GetCurrentHeaderHash( /*that.orgID*/ ) 413 414 testHeight := that.ledger.GetCurrentHeaderHeight() 415 msg := msgpack.NewHeadersReq(headerHash, that.orgID, p2pComm.SYNC_DATA_ORG, testHeight) 416 417 err := that.server.Send(reqNode, msg, false) 418 if err != nil { 419 log.Warn("[p2p]syncHeader failed to send a new headersReq") 420 } else { 421 that.appendReqTime(reqNode.GetID()) 422 } 423 424 log.Info("sub chain--> Header sync request ", "height", NextHeaderId) 425 } 426 427 // Storage provides two interfaces, one is to take data from the database, and the other is to take data from memory. 428 func (that *OrgBlockSyncMgr) MainGetBlockHashByHeight(nextBlockHeight uint64) common.Hash { 429 nextBlockHeaderHash := that.ledger.GetBlockHeaderHashByHeight(nextBlockHeight) 430 empty := common.Hash{} 431 if nextBlockHeaderHash != empty { 432 return nextBlockHeaderHash 433 } 434 nextBlockHash, _ := that.ledger.GetBlockHashByHeight(nextBlockHeight) 435 return nextBlockHash 436 } 437 438 func (that *OrgBlockSyncMgr) syncBlock() { 439 if that.tryGetSyncBlockLock() { 440 return 441 } 442 defer that.releaseSyncBlockLock() 443 444 availCount := SYNC_MAX_FLIGHT_BLOCK_SIZE - that.getFlightBlockCount() 445 if availCount <= 0 { 446 return 447 } 448 curBlockHeight := uint32(that.ledger.GetCurrentBlockHeight( /*that.orgID*/ )) 449 curHeaderHeight := uint32(that.ledger.GetCurrentHeaderHeight( /*that.orgID*/ )) 450 count := int(curHeaderHeight - curBlockHeight) 451 if count <= 0 { 452 return 453 } 454 if count > availCount { 455 count = availCount 456 } 457 cacheCap := SYNC_MAX_BLOCK_CACHE_SIZE - that.getBlockCacheSize() 458 if count > cacheCap { 459 count = cacheCap 460 } 461 462 counter := 1 463 i := uint32(0) 464 reqTimes := 1 465 for { 466 if counter > count { 467 break 468 } 469 i++ 470 nextBlockHeight := curBlockHeight + i 471 // nextBlockHash,_ := that.ledger.GetBlockHashByHeight(uint64(nextBlockHeight)/*,that.orgID*/) 472 nextBlockHash := that.MainGetBlockHashByHeight(uint64(nextBlockHeight)) 473 empty := common.Hash{} 474 if nextBlockHash == empty { 475 return 476 } 477 if that.isBlockOnFlight(nextBlockHash) { 478 if nextBlockHeight <= curBlockHeight+SYNC_NEXT_BLOCKS_HEIGHT { 479 //request more nodes for next block height 480 reqTimes = SYNC_NEXT_BLOCK_TIMES 481 } else { 482 continue 483 } 484 } 485 if that.isInBlockCache(nextBlockHeight) { 486 continue 487 } 488 if nextBlockHeight <= curBlockHeight+SYNC_NEXT_BLOCKS_HEIGHT { 489 reqTimes = SYNC_NEXT_BLOCK_TIMES 490 } 491 for t := 0; t < reqTimes; t++ { 492 reqNode := that.getNextNode(nextBlockHeight) 493 if reqNode == nil { 494 return 495 } 496 that.addFlightBlock(reqNode.GetID(), nextBlockHeight, nextBlockHash) 497 msg := msgpack.NewBlkDataReq(nextBlockHash, that.orgID, p2pComm.SYNC_DATA_ORG) 498 err := that.server.Send(reqNode, msg, false) 499 if err != nil { 500 log.Warn("[p2p]syncBlock ", "Height", nextBlockHeight, "ReqBlkData error", err) 501 return 502 } else { 503 that.appendReqTime(reqNode.GetID()) 504 } 505 } 506 counter++ 507 reqTimes = 1 508 } 509 } 510 511 //OnHeaderReceive receive header from net 512 func (that *OrgBlockSyncMgr) OnHeaderReceive(fromID uint64, headers []*types.Header) { 513 if len(headers) == 0 { 514 return 515 } 516 log.Info("Header receive ", "height", headers[0].Height, "Height", headers[len(headers)-1].Height) 517 height := uint32(headers[0].Height) 518 curHeaderHeight := uint32(that.ledger.GetCurrentHeaderHeight( /*that.orgID*/ )) 519 520 //Means another gorountinue is adding header 521 if height <= curHeaderHeight { 522 return 523 } 524 if !that.isHeaderOnFlight(height) { 525 return 526 } 527 err := that.ledger.AddHeaders(headers /*,that.orgID*/) 528 that.delFlightHeader(height) 529 if err != nil { 530 that.addErrorRespCnt(fromID) 531 n := that.getNodeWeight(fromID) 532 if n != nil && n.GetErrorRespCnt() >= SYNC_MAX_ERROR_RESP_TIMES { 533 that.delNode(fromID) 534 } 535 log.Warn("[p2p]OnHeaderReceive AddHeaders ", "error", err) 536 return 537 } 538 that.syncHeader() 539 } 540 541 //OnBlockReceive receive block from net 542 func (that *OrgBlockSyncMgr) OnBlockReceive(fromID uint64, blockSize uint32, block *types.Block) { 543 height := uint32(block.Header.Height) 544 blockHash := block.Hash() 545 log.Trace("[p2p]OnBlockReceive ", "Height", height) 546 that.lock.Lock() 547 flightInfos := that.flightBlocks[blockHash] 548 that.lock.Unlock() 549 550 for _, flightInfo := range flightInfos { 551 if flightInfo.GetNodeId() == fromID { 552 t := (time.Now().UnixNano() - flightInfo.GetStartTime().UnixNano()) / int64(time.Millisecond) 553 s := float32(blockSize) / float32(t) * 1000.0 / 1024.0 554 that.addNewSpeed(fromID, s) 555 break 556 } 557 } 558 559 that.delFlightBlock(blockHash) 560 curHeaderHeight := uint32(that.ledger.GetCurrentHeaderHeight( /*that.orgID*/ )) 561 nextHeader := curHeaderHeight + 1 562 if height > nextHeader { 563 return 564 } 565 curBlockHeight := that.ledger.GetCurrentBlockHeight( /*that.orgID*/ ) 566 if height <= uint32(curBlockHeight) { 567 return 568 } 569 570 that.addBlockCache(fromID, block) 571 go that.saveBlock() 572 that.syncBlock() 573 } 574 575 //OnAddNode to node list when a new node added 576 func (that *OrgBlockSyncMgr) OnAddNode(nodeId uint64) { 577 log.Debug("[p2p]OnAddNode", "nodeId", nodeId) 578 that.lock.Lock() 579 defer that.lock.Unlock() 580 if _, ok := that.nodeWeights[nodeId]; !ok { 581 that.server.SentConnectToBootNode(nodeId) 582 583 w := NewNodeWeight(nodeId) 584 that.nodeWeights[nodeId] = w 585 //fmt.Println(" ****** OrgBlockSyncMgr OnAddNode nodeId:", nodeId) 586 } 587 } 588 589 //OnDelNode remove from node list. When the node disconnect 590 func (that *OrgBlockSyncMgr) OnDelNode(nodeId uint64) { 591 that.delNode(nodeId) 592 } 593 594 //delNode remove from node list 595 596 func (that *OrgBlockSyncMgr) delNode(nodeId uint64) { 597 that.lock.Lock() 598 defer that.lock.Unlock() 599 600 if _, ok := that.nodeWeights[nodeId]; ok { 601 that.server.SentDisconnectToBootNode(nodeId, false) 602 remote := that.server.GetNode(nodeId) 603 if remote != nil { 604 remote.DelRemoteOrg(that.orgID) 605 } 606 log.Info(" ***** OnDelNode", "nodeId", nodeId) 607 } 608 609 delete(that.nodeWeights, nodeId) 610 log.Info("delNode", "nodeId", nodeId) 611 if len(that.nodeWeights) == 0 { 612 log.Warn("no sync nodes") 613 } 614 } 615 616 func (that *OrgBlockSyncMgr) tryGetSyncHeaderLock() bool { 617 that.lock.Lock() 618 defer that.lock.Unlock() 619 if that.syncHeaderLock { 620 return true 621 } 622 that.syncHeaderLock = true 623 return false 624 } 625 626 func (that *OrgBlockSyncMgr) releaseSyncHeaderLock() { 627 that.lock.Lock() 628 defer that.lock.Unlock() 629 that.syncHeaderLock = false 630 } 631 632 func (that *OrgBlockSyncMgr) tryGetSyncBlockLock() bool { 633 that.lock.Lock() 634 defer that.lock.Unlock() 635 if that.syncBlockLock { 636 return true 637 } 638 that.syncBlockLock = true 639 return false 640 } 641 642 func (that *OrgBlockSyncMgr) releaseSyncBlockLock() { 643 that.lock.Lock() 644 defer that.lock.Unlock() 645 that.syncBlockLock = false 646 } 647 648 func (that *OrgBlockSyncMgr) addBlockCache(nodeID uint64, block *types.Block) bool { 649 that.lock.Lock() 650 defer that.lock.Unlock() 651 blockInfo := &BlockInfo{ 652 nodeID: nodeID, 653 block: block, 654 } 655 that.blocksCache[uint32(block.Header.Height)] = blockInfo 656 return true 657 } 658 659 func (that *OrgBlockSyncMgr) getBlockCache(blockHeight uint32) (uint64, *types.Block) { 660 that.lock.RLock() 661 defer that.lock.RUnlock() 662 blockInfo, ok := that.blocksCache[blockHeight] 663 if !ok { 664 return 0, nil 665 } 666 return blockInfo.nodeID, blockInfo.block 667 } 668 669 func (that *OrgBlockSyncMgr) delBlockCache(blockHeight uint32) { 670 that.lock.Lock() 671 defer that.lock.Unlock() 672 delete(that.blocksCache, blockHeight) 673 } 674 675 // used 676 func (that *OrgBlockSyncMgr) tryGetSaveBlockLock() bool { 677 that.lock.Lock() 678 defer that.lock.Unlock() 679 if that.saveBlockLock { 680 return true 681 } 682 that.saveBlockLock = true 683 return false 684 } 685 686 func (that *OrgBlockSyncMgr) releaseSaveBlockLock() { 687 that.lock.Lock() 688 defer that.lock.Unlock() 689 that.saveBlockLock = false 690 } 691 692 func (that *OrgBlockSyncMgr) saveBlock() { 693 // 只有这里用 694 if that.tryGetSaveBlockLock() { 695 return 696 } 697 defer that.releaseSaveBlockLock() 698 curBlockHeight := uint32(that.ledger.GetCurrentBlockHeight( /*that.orgID*/ )) 699 nextBlockHeight := curBlockHeight + 1 700 that.lock.Lock() 701 for height := range that.blocksCache { 702 if height <= curBlockHeight { 703 delete(that.blocksCache, height) 704 } 705 } 706 that.lock.Unlock() 707 for { 708 fromID, nextBlock := that.getBlockCache(nextBlockHeight) 709 if nextBlock == nil { 710 return 711 } 712 // err := that.ledger.AddBlock(nextBlock,that.orgID) 713 // swp 714 blkInfo, err := validation.ValidateBlock(nextBlock, that.ledger) 715 if err == nil { 716 err = that.ledger.SaveAll(blkInfo) 717 } 718 719 that.delBlockCache(nextBlockHeight) 720 if err != nil { 721 that.addErrorRespCnt(fromID) 722 n := that.getNodeWeight(fromID) 723 if n != nil && n.GetErrorRespCnt() >= SYNC_MAX_ERROR_RESP_TIMES { 724 that.delNode(fromID) 725 } 726 log.Warn("[p2p]saveBlock ", "Height", nextBlockHeight, " AddBlock error", err) 727 reqNode := that.getNextNode(nextBlockHeight) 728 if reqNode == nil { 729 return 730 } 731 that.addFlightBlock(reqNode.GetID(), nextBlockHeight, nextBlock.Hash()) 732 msg := msgpack.NewBlkDataReq(nextBlock.Hash(), that.orgID, p2pComm.SYNC_DATA_ORG) 733 err := that.server.Send(reqNode, msg, false) 734 if err != nil { 735 log.Warn("[p2p]require new block", " error", err) 736 return 737 } else { 738 that.appendReqTime(reqNode.GetID()) 739 } 740 return 741 } 742 nextBlockHeight++ 743 that.pingOutsyncNodes(nextBlockHeight - 1) 744 } 745 } 746 747 func (that *OrgBlockSyncMgr) isInBlockCache(blockHeight uint32) bool { 748 that.lock.RLock() 749 defer that.lock.RUnlock() 750 _, ok := that.blocksCache[blockHeight] 751 return ok 752 } 753 754 func (that *OrgBlockSyncMgr) getBlockCacheSize() int { 755 that.lock.RLock() 756 defer that.lock.RUnlock() 757 return len(that.blocksCache) 758 } 759 760 func (that *OrgBlockSyncMgr) addFlightHeader(nodeId uint64, height uint32) { 761 that.lock.Lock() 762 defer that.lock.Unlock() 763 that.flightHeaders[height] = NewSyncFlightInfo(height, nodeId) 764 } 765 766 func (that *OrgBlockSyncMgr) getFlightHeader(height uint32) *SyncFlightInfo { 767 that.lock.RLock() 768 defer that.lock.RUnlock() 769 info, ok := that.flightHeaders[height] 770 if !ok { 771 return nil 772 } 773 return info 774 } 775 776 func (that *OrgBlockSyncMgr) delFlightHeader(height uint32) bool { 777 that.lock.Lock() 778 defer that.lock.Unlock() 779 _, ok := that.flightHeaders[height] 780 if !ok { 781 return false 782 } 783 delete(that.flightHeaders, height) 784 return true 785 } 786 787 func (that *OrgBlockSyncMgr) getFlightHeaderCount() int { 788 that.lock.RLock() 789 defer that.lock.RUnlock() 790 return len(that.flightHeaders) 791 } 792 793 // used 794 func (that *OrgBlockSyncMgr) isHeaderOnFlight(height uint32) bool { 795 flightInfo := that.getFlightHeader(height) 796 return flightInfo != nil 797 } 798 799 // used 800 func (that *OrgBlockSyncMgr) addFlightBlock(nodeId uint64, height uint32, blockHash common.Hash) { 801 that.lock.Lock() 802 defer that.lock.Unlock() 803 that.flightBlocks[blockHash] = append(that.flightBlocks[blockHash], NewSyncFlightInfo(height, nodeId)) 804 } 805 806 // used 807 func (that *OrgBlockSyncMgr) getFlightBlock(blockHash common.Hash) []*SyncFlightInfo { 808 that.lock.RLock() 809 defer that.lock.RUnlock() 810 info, ok := that.flightBlocks[blockHash] 811 if !ok { 812 return nil 813 } 814 return info 815 } 816 817 // used 818 func (that *OrgBlockSyncMgr) delFlightBlock(blockHash common.Hash) bool { 819 that.lock.Lock() 820 defer that.lock.Unlock() 821 _, ok := that.flightBlocks[blockHash] 822 if !ok { 823 return false 824 } 825 delete(that.flightBlocks, blockHash) 826 return true 827 } 828 829 // used 830 func (that *OrgBlockSyncMgr) getFlightBlockCount() int { 831 that.lock.RLock() 832 defer that.lock.RUnlock() 833 cnt := 0 834 for hash := range that.flightBlocks { 835 cnt += len(that.flightBlocks[hash]) 836 } 837 return cnt 838 } 839 840 // used 841 func (that *OrgBlockSyncMgr) isBlockOnFlight(blockHash common.Hash) bool { 842 flightInfos := that.getFlightBlock(blockHash) 843 if len(flightInfos) != 0 { 844 return true 845 } 846 return false 847 } 848 849 func (that *OrgBlockSyncMgr) getNextNode(nextBlockHeight uint32) *peer.Peer { 850 weights := that.getAllNodeWeights() 851 sort.Sort(sort.Reverse(weights)) 852 nodelist := make([]uint64, 0) 853 for _, n := range weights { 854 nodelist = append(nodelist, n.id) 855 } 856 nextNodeIndex := 0 857 triedNode := make(map[uint64]bool, 0) 858 for { 859 var nextNodeId uint64 860 nextNodeIndex, nextNodeId = getNextNodeId(nextNodeIndex, nodelist) 861 if nextNodeId == 0 { 862 return nil 863 } 864 _, ok := triedNode[nextNodeId] 865 if ok { 866 return nil 867 } 868 triedNode[nextNodeId] = true 869 n := that.server.GetNode(nextNodeId) 870 if n == nil { 871 continue 872 } 873 if n.GetSyncState() != p2pComm.ESTABLISH { 874 continue 875 } 876 nodeBlockHeight := n.GetRemoteOrgHeight(that.orgID) 877 if nextBlockHeight <= uint32(nodeBlockHeight) { 878 return n 879 } 880 } 881 } 882 883 // used 884 func (that *OrgBlockSyncMgr) getNodeWithMinFailedTimes(flightInfo *SyncFlightInfo, curBlockHeight uint32) *peer.Peer { 885 var minFailedTimes = math.MaxInt64 886 var minFailedTimesNode *peer.Peer 887 triedNode := make(map[uint64]bool, 0) 888 for { 889 nextNode := that.getNextNode(curBlockHeight + 1) 890 if nextNode == nil { 891 return nil 892 } 893 failedTimes := flightInfo.GetFailedTimes(nextNode.GetID()) 894 if failedTimes == 0 { 895 return nextNode 896 } 897 _, ok := triedNode[nextNode.GetID()] 898 if ok { 899 return minFailedTimesNode 900 } 901 triedNode[nextNode.GetID()] = true 902 if failedTimes < minFailedTimes { 903 minFailedTimes = failedTimes 904 minFailedTimesNode = nextNode 905 } 906 } 907 } 908 909 //Stop to sync 910 func (that *OrgBlockSyncMgr) Close() { 911 close(that.exitCh) 912 } 913 914 //getNodeWeight get nodeweight by id // used 915 func (that *OrgBlockSyncMgr) getNodeWeight(nodeId uint64) *NodeWeight { 916 that.lock.RLock() 917 defer that.lock.RUnlock() 918 return that.nodeWeights[nodeId] 919 } 920 921 //getAllNodeWeights get all nodeweight and return a slice 922 func (that *OrgBlockSyncMgr) getAllNodeWeights() NodeWeights { 923 that.lock.RLock() 924 defer that.lock.RUnlock() 925 weights := make(NodeWeights, 0, len(that.nodeWeights)) 926 for _, w := range that.nodeWeights { 927 weights = append(weights, w) 928 } 929 return weights 930 } 931 932 //addTimeoutCnt incre a node's timeout count // used 933 func (that *OrgBlockSyncMgr) addTimeoutCnt(nodeId uint64) { 934 n := that.getNodeWeight(nodeId) 935 if n != nil { 936 n.AddTimeoutCnt() 937 } 938 } 939 940 //addErrorRespCnt incre a node's error resp count // used 941 func (that *OrgBlockSyncMgr) addErrorRespCnt(nodeId uint64) { 942 n := that.getNodeWeight(nodeId) 943 if n != nil { 944 n.AddErrorRespCnt() 945 } 946 } 947 948 //appendReqTime append a node's request time // used 949 func (that *OrgBlockSyncMgr) appendReqTime(nodeId uint64) { 950 n := that.getNodeWeight(nodeId) 951 if n != nil { 952 n.AppendNewReqtime() 953 } 954 } 955 956 //addNewSpeed apend the new speed to tail, remove the oldest one 957 func (that *OrgBlockSyncMgr) addNewSpeed(nodeId uint64, speed float32) { 958 n := that.getNodeWeight(nodeId) 959 if n != nil { 960 n.AppendNewSpeed(speed) 961 } 962 } 963 964 //pingOutsyncNodes send ping msg to lower height nodes for syncing 965 func (that *OrgBlockSyncMgr) pingOutsyncNodes(curHeight uint32) { 966 peers := make([]*peer.Peer, 0) 967 that.lock.RLock() 968 maxHeight := curHeight 969 for id := range that.nodeWeights { 970 peer := that.server.GetNode(id) 971 if peer == nil { 972 continue 973 } 974 peerHeight := uint32(peer.GetRemoteOrgHeight(that.orgID)) 975 if peerHeight >= maxHeight { 976 maxHeight = peerHeight 977 } 978 if peerHeight < curHeight { 979 peers = append(peers, peer) 980 } 981 } 982 that.lock.RUnlock() 983 if curHeight > maxHeight-SYNC_MAX_HEIGHT_OFFSET && len(peers) > 0 { 984 that.server.PingTo(peers, false, that.orgID) 985 } 986 } 987 988 //Using polling for load balance 989 func getNextNodeId(nextNodeIndex int, nodeList []uint64) (int, uint64) { 990 num := len(nodeList) 991 if num == 0 { 992 return 0, 0 993 } 994 if nextNodeIndex >= num { 995 nextNodeIndex = 0 996 } 997 index := nextNodeIndex 998 nextNodeIndex++ 999 return nextNodeIndex, nodeList[index] 1000 }