github.com/turingchain2020/turingchain@v1.1.21/system/p2p/dht/protocol/p2pstore/republish.go (about) 1 package p2pstore 2 3 import ( 4 "context" 5 "time" 6 7 "github.com/turingchain2020/turingchain/system/p2p/dht/protocol" 8 types2 "github.com/turingchain2020/turingchain/system/p2p/dht/types" 9 "github.com/turingchain2020/turingchain/types" 10 "github.com/libp2p/go-libp2p-core/peer" 11 dht "github.com/libp2p/go-libp2p-kad-dht" 12 kb "github.com/libp2p/go-libp2p-kbucket" 13 ) 14 15 func (p *Protocol) republish() { 16 //全节点的p2pstore保存所有chunk, 不进行republish操作 17 if p.SubConfig.DisableShard || p.SubConfig.IsFullNode { 18 return 19 } 20 reply, err := p.API.IsSync() 21 if err != nil || !reply.IsOk { 22 // 没有同步完,不进行republish操作 23 return 24 } 25 m := make(map[string]LocalChunkInfo) 26 p.localChunkInfoMutex.RLock() 27 for k, v := range p.localChunkInfo { 28 m[k] = v 29 } 30 p.localChunkInfoMutex.RUnlock() 31 invertedIndex := make(map[peer.ID][]*types.ChunkInfoMsg) 32 tmpRoutingTable := p.genTempRoutingTable(nil, 100) 33 34 for hash, info := range m { 35 if time.Since(info.Time) > types2.ExpiredTime { 36 log.Info("republish deleteChunkBlock", "hash", hash, "start", info.Start) 37 if err := p.deleteChunkBlock(info.ChunkHash); err != nil { 38 log.Error("republish deleteChunkBlock error", "hash", hash, "error", err) 39 } 40 continue 41 } 42 if time.Since(info.Time) > types2.RefreshInterval*11/10 { 43 continue 44 } 45 log.Info("local chunk", "hash", hash, "start", info.Start) 46 peers := tmpRoutingTable.NearestPeers(genDHTID(info.ChunkHash), backup-1) 47 for _, pid := range peers { 48 invertedIndex[pid] = append(invertedIndex[pid], info.ChunkInfoMsg) 49 } 50 } 51 52 log.Info("republish", "invertedIndex length", len(invertedIndex)) 53 for pid, infos := range invertedIndex { 54 log.Info("republish", "pid", pid, "info len", len(infos)) 55 if err := p.storeChunksOnPeer(pid, infos...); err != nil { 56 log.Error("republish", "storeChunksOnPeer error", err, "pid", pid) 57 } 58 } 59 log.Info("republish ok") 60 } 61 62 // 通知最近的 *BackUp-1* 个节点备份数据,加上本节点共Backup个 63 func (p *Protocol) notifyStoreChunk(req *types.ChunkInfoMsg) { 64 tmpRoutingTable := p.genTempRoutingTable(req.ChunkHash, 100) 65 for _, pid := range tmpRoutingTable.NearestPeers(genDHTID(req.ChunkHash), backup-1) { 66 err := p.storeChunksOnPeer(pid, req) 67 if err != nil { 68 log.Error("notifyStoreChunk", "peer id", pid, "error", err) 69 } 70 } 71 } 72 73 func (p *Protocol) storeChunksOnPeer(pid peer.ID, req ...*types.ChunkInfoMsg) error { 74 ctx, cancel := context.WithTimeout(p.Ctx, time.Minute) 75 defer cancel() 76 p.Host.ConnManager().Protect(pid, storeChunk) 77 defer p.Host.ConnManager().Unprotect(pid, storeChunk) 78 stream, err := p.Host.NewStream(ctx, pid, storeChunk) 79 if err != nil { 80 log.Error("new stream error when store chunk", "peer id", pid, "error", err) 81 return err 82 } 83 defer protocol.CloseStream(stream) 84 msg := types.P2PRequest{} 85 msg.Request = &types.P2PRequest_ChunkInfoList{ 86 ChunkInfoList: &types.ChunkInfoList{ 87 Items: req, 88 }} 89 return protocol.SignAndWriteStream(&msg, stream) 90 } 91 92 func (p *Protocol) genTempRoutingTable(key []byte, count int) *kb.RoutingTable { 93 tmpRoutingTable := kb.NewRoutingTable(dht.KValue*2, kb.ConvertPeerID(p.Host.ID()), time.Minute, p.Host.Peerstore()) 94 peers := p.ShardHealthyRoutingTable.ListPeers() 95 for _, pid := range peers { 96 _, _ = tmpRoutingTable.Update(pid) 97 } 98 if key != nil { 99 peers = p.ShardHealthyRoutingTable.NearestPeers(genDHTID(key), backup-1) 100 } 101 102 for i, pid := range peers { 103 // 至少从 3 个节点上获取新节点,保证 tmpRoutingTable 至少有 3*backup 个节点,但至多从 10 个节点上获取新节点 104 if i+1 > 3 && (tmpRoutingTable.Size() > 3*backup || i+1 > 10) { 105 break 106 } 107 closerPeers, err := p.fetchCloserPeers(key, count, pid) 108 if err != nil { 109 log.Error("genTempRoutingTable", "fetchCloserPeers error", err, "peer id", pid) 110 continue 111 } 112 for _, cPid := range closerPeers { 113 if cPid == p.Host.ID() { 114 continue 115 } 116 _, _ = tmpRoutingTable.Update(cPid) 117 } 118 } 119 log.Info("genTempRoutingTable", "tmpRoutingTable peer count", tmpRoutingTable.Size()) 120 121 return tmpRoutingTable 122 }