@@ -16,6 +16,7 @@ import (
1616 "slices"
1717 "sort"
1818 "sync"
19+ "sync/atomic"
1920 "time"
2021
2122 "github.com/ethereum/go-ethereum/common/hexutil"
@@ -1488,64 +1489,44 @@ func (p *PortalProtocol) collectTableNodes(rip net.IP, distances []uint, limit i
14881489
14891490func (p * PortalProtocol ) ContentLookup (contentKey , contentId []byte ) ([]byte , bool , error ) {
14901491 lookupContext , cancel := context .WithCancel (context .Background ())
1491- defer cancel ()
1492- resChan := make (chan * ContentInfoResp , 1 )
1493- defer close (resChan )
1492+
1493+ resChan := make (chan * traceContentInfoResp , alpha )
1494+ hasResult := int32 (0 )
1495+
1496+ result := ContentInfoResp {}
1497+
1498+ var wg sync.WaitGroup
1499+ wg .Add (1 )
1500+
1501+ go func () {
1502+ defer wg .Done ()
1503+ for res := range resChan {
1504+ if res .Flag != portalwire .ContentEnrsSelector {
1505+ result .Content = res .Content .([]byte )
1506+ result .UtpTransfer = res .UtpTransfer
1507+ }
1508+ }
1509+ }()
1510+
14941511 newLookup (lookupContext , p .table , enode .ID (contentId ), func (n * node ) ([]* node , error ) {
1495- return p .contentLookupWorker (unwrapNode (n ), contentKey , resChan )
1512+ return p .contentLookupWorker (unwrapNode (n ), contentKey , resChan , cancel , & hasResult )
14961513 }).run ()
1514+ close (resChan )
14971515
1498- if len ( resChan ) > 0 {
1499- res := <- resChan
1500- return res .Content , res .UtpTransfer , nil
1516+ wg . Wait ()
1517+ if hasResult == 1 {
1518+ return result .Content , result .UtpTransfer , nil
15011519 }
1520+ defer cancel ()
15021521 return nil , false , ContentNotFound
15031522}
15041523
1505- func (p * PortalProtocol ) contentLookupWorker (n * enode.Node , contentKey []byte , resChan chan <- * ContentInfoResp ) ([]* node , error ) {
1506- wrapedNode := make ([]* node , 0 )
1507- flag , content , err := p .findContent (n , contentKey )
1508- if err != nil {
1509- p .Log .Error ("contentLookupWorker failed" , "ip" , n .IP ().String (), "err" , err )
1510- return nil , err
1511- }
1512- p .Log .Debug ("contentLookupWorker reveice response" , "ip" , n .IP ().String (), "flag" , flag )
1513- // has find content
1514- if len (resChan ) > 0 {
1515- return []* node {}, nil
1516- }
1517- switch flag {
1518- case portalwire .ContentRawSelector , portalwire .ContentConnIdSelector :
1519- content , ok := content .([]byte )
1520- if ! ok {
1521- return wrapedNode , fmt .Errorf ("failed to assert to raw content, value is: %v" , content )
1522- }
1523- res := & ContentInfoResp {
1524- Content : content ,
1525- }
1526- if flag == portalwire .ContentConnIdSelector {
1527- res .UtpTransfer = true
1528- }
1529- resChan <- res
1530- return wrapedNode , err
1531- case portalwire .ContentEnrsSelector :
1532- nodes , ok := content .([]* enode.Node )
1533- if ! ok {
1534- return wrapedNode , fmt .Errorf ("failed to assert to enrs content, value is: %v" , content )
1535- }
1536- return wrapNodes (nodes ), nil
1537- }
1538- return wrapedNode , nil
1539- }
1540-
15411524func (p * PortalProtocol ) TraceContentLookup (contentKey , contentId []byte ) (* TraceContentResult , error ) {
15421525 lookupContext , cancel := context .WithCancel (context .Background ())
1543- defer cancel ()
1544- requestNodeChan := make (chan * enode.Node , 3 )
1545- resChan := make (chan * traceContentInfoResp , 3 )
1526+ // resp channel
1527+ resChan := make (chan * traceContentInfoResp , alpha )
15461528
1547- requestNode := make ([]* enode.Node , 0 )
1548- requestRes := make (map [string ]* traceContentInfoResp )
1529+ hasResult := int32 (0 )
15491530
15501531 traceContentRes := & TraceContentResult {}
15511532
@@ -1555,7 +1536,7 @@ func (p *PortalProtocol) TraceContentLookup(contentKey, contentId []byte) (*Trac
15551536 Origin : selfHexId ,
15561537 TargetId : hexutil .Encode (contentId ),
15571538 StartedAtMs : int (time .Now ().UnixMilli ()),
1558- Responses : make (map [string ][] string ),
1539+ Responses : make (map [string ]RespByNode ),
15591540 Metadata : make (map [string ]* NodeMetadata ),
15601541 Cancelled : make ([]string , 0 ),
15611542 }
@@ -1567,7 +1548,10 @@ func (p *PortalProtocol) TraceContentLookup(contentKey, contentId []byte) (*Trac
15671548 id := "0x" + node .ID ().String ()
15681549 localResponse = append (localResponse , id )
15691550 }
1570- trace .Responses [selfHexId ] = localResponse
1551+ trace .Responses [selfHexId ] = RespByNode {
1552+ DurationMs : 0 ,
1553+ RespondedWith : localResponse ,
1554+ }
15711555
15721556 dis := p .Distance (p .Self ().ID (), enode .ID (contentId ))
15731557
@@ -1577,82 +1561,73 @@ func (p *PortalProtocol) TraceContentLookup(contentKey, contentId []byte) (*Trac
15771561 }
15781562
15791563 var wg sync.WaitGroup
1580- wg .Add (2 )
1581- go func () {
1582- defer wg .Done ()
1583- for node := range requestNodeChan {
1584- requestNode = append (requestNode , node )
1585- }
1586- }()
1564+ wg .Add (1 )
15871565
15881566 go func () {
15891567 defer wg .Done ()
15901568 for res := range resChan {
1591- key := res .Node .ID ().String ()
1592- requestRes [key ] = res
1593- if res .Flag == portalwire .ContentRawSelector || res .Flag == portalwire .ContentConnIdSelector {
1594- // get the content
1595- return
1569+ node := res .Node
1570+ hexId := "0x" + node .ID ().String ()
1571+ dis := p .Distance (node .ID (), enode .ID (contentId ))
1572+ p .Log .Debug ("reveice res" , "id" , hexId , "flag" , res .Flag )
1573+ trace .Metadata [hexId ] = & NodeMetadata {
1574+ Enr : node .String (),
1575+ Distance : hexutil .Encode (dis [:]),
1576+ }
1577+ // 没有返回 content
1578+ if traceContentRes .Content == "" {
1579+ if res .Flag == portalwire .ContentRawSelector || res .Flag == portalwire .ContentConnIdSelector {
1580+ trace .ReceivedFrom = hexId
1581+ content := res .Content .([]byte )
1582+ traceContentRes .Content = hexutil .Encode (content )
1583+ traceContentRes .UtpTransfer = res .UtpTransfer
1584+ trace .Responses [hexId ] = RespByNode {}
1585+ } else {
1586+ nodes := res .Content .([]* enode.Node )
1587+ respByNode := RespByNode {
1588+ RespondedWith : make ([]string , 0 , len (nodes )),
1589+ }
1590+ for _ , node := range nodes {
1591+ idInner := "0x" + node .ID ().String ()
1592+ respByNode .RespondedWith = append (respByNode .RespondedWith , idInner )
1593+ if _ , ok := trace .Metadata [idInner ]; ! ok {
1594+ dis := p .Distance (node .ID (), enode .ID (contentId ))
1595+ trace .Metadata [idInner ] = & NodeMetadata {
1596+ Enr : node .String (),
1597+ Distance : hexutil .Encode (dis [:]),
1598+ }
1599+ }
1600+ trace .Responses [hexId ] = respByNode
1601+ }
1602+ }
1603+ } else {
1604+ trace .Cancelled = append (trace .Cancelled , hexId )
15961605 }
15971606 }
15981607 }()
15991608
1600- newLookup (lookupContext , p .table , enode .ID (contentId ), func (n * node ) ([]* node , error ) {
1601- node := unwrapNode (n )
1602- requestNodeChan <- node
1603- return p .traceContentLookupWorker (node , contentKey , resChan )
1604- }).run ()
1605-
1606- close (requestNodeChan )
1609+ lookup := newLookup (lookupContext , p .table , enode .ID (contentId ), func (n * node ) ([]* node , error ) {
1610+ return p .contentLookupWorker (unwrapNode (n ), contentKey , resChan , cancel , & hasResult )
1611+ })
1612+ lookup .run ()
16071613 close (resChan )
16081614
16091615 wg .Wait ()
1610-
1611- for _ , node := range requestNode {
1612- id := node .ID ().String ()
1613- hexId := "0x" + id
1614- dis := p .Distance (node .ID (), enode .ID (contentId ))
1615- trace .Metadata [hexId ] = & NodeMetadata {
1616- Enr : node .String (),
1617- Distance : hexutil .Encode (dis [:]),
1618- }
1619- if res , ok := requestRes [id ]; ok {
1620- if res .Flag == portalwire .ContentRawSelector || res .Flag == portalwire .ContentConnIdSelector {
1621- trace .ReceivedFrom = hexId
1622- content := res .Content .([]byte )
1623- traceContentRes .Content = hexutil .Encode (content )
1624- traceContentRes .UtpTransfer = res .UtpTransfer
1625- trace .Responses [hexId ] = make ([]string , 0 )
1626- } else {
1627- content := res .Content .([]* enode.Node )
1628- ids := make ([]string , 0 )
1629- for _ , n := range content {
1630- hexId := "0x" + n .ID ().String ()
1631- ids = append (ids , hexId )
1632- }
1633- trace .Responses [hexId ] = ids
1634- }
1635- } else {
1636- trace .Cancelled = append (trace .Cancelled , id )
1637- }
1616+ if hasResult == 0 {
1617+ cancel ()
16381618 }
1639-
16401619 traceContentRes .Trace = * trace
16411620
16421621 return traceContentRes , nil
16431622}
16441623
1645- func (p * PortalProtocol ) traceContentLookupWorker (n * enode.Node , contentKey []byte , resChan chan <- * traceContentInfoResp ) ([]* node , error ) {
1624+ func (p * PortalProtocol ) contentLookupWorker (n * enode.Node , contentKey []byte , resChan chan <- * traceContentInfoResp , cancel context. CancelFunc , done * int32 ) ([]* node , error ) {
16461625 wrapedNode := make ([]* node , 0 )
16471626 flag , content , err := p .findContent (n , contentKey )
16481627 if err != nil {
16491628 return nil , err
16501629 }
16511630 p .Log .Debug ("traceContentLookupWorker reveice response" , "ip" , n .IP ().String (), "flag" , flag )
1652- // has find content
1653- if len (resChan ) > 0 {
1654- return []* node {}, nil
1655- }
16561631
16571632 switch flag {
16581633 case portalwire .ContentRawSelector , portalwire .ContentConnIdSelector :
@@ -1669,17 +1644,23 @@ func (p *PortalProtocol) traceContentLookupWorker(n *enode.Node, contentKey []by
16691644 if flag == portalwire .ContentConnIdSelector {
16701645 res .UtpTransfer = true
16711646 }
1672- resChan <- res
1647+ if atomic .CompareAndSwapInt32 (done , 0 , 1 ) {
1648+ p .Log .Debug ("contentLookupWorker find content" , "ip" , n .IP ().String (), "port" , n .UDP ())
1649+ resChan <- res
1650+ cancel ()
1651+ }
16731652 return wrapedNode , err
16741653 case portalwire .ContentEnrsSelector :
16751654 nodes , ok := content .([]* enode.Node )
16761655 if ! ok {
16771656 return wrapedNode , fmt .Errorf ("failed to assert to enrs content, value is: %v" , content )
16781657 }
1679- resChan <- & traceContentInfoResp {Node : n ,
1658+ resChan <- & traceContentInfoResp {
1659+ Node : n ,
16801660 Flag : flag ,
16811661 Content : content ,
1682- UtpTransfer : false }
1662+ UtpTransfer : false ,
1663+ }
16831664 return wrapNodes (nodes ), nil
16841665 }
16851666 return wrapedNode , nil
0 commit comments