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  }