@@ -56,6 +56,9 @@ type Network struct {
5656 Nodes []* Node `json:"nodes"`
5757 nodeMap map [enode.ID ]int
5858
59+ // Maps a node property string to node indexes of all nodes that hold this property
60+ propertyMap map [string ][]int
61+
5962 Conns []* Conn `json:"conns"`
6063 connMap map [string ]int
6164
@@ -71,6 +74,7 @@ func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network
7174 NetworkConfig : * conf ,
7275 nodeAdapter : nodeAdapter ,
7376 nodeMap : make (map [enode.ID ]int ),
77+ propertyMap : make (map [string ][]int ),
7478 connMap : make (map [string ]int ),
7579 quitc : make (chan struct {}),
7680 }
@@ -120,9 +124,16 @@ func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error)
120124 Config : conf ,
121125 }
122126 log .Trace ("Node created" , "id" , conf .ID )
123- net .nodeMap [conf .ID ] = len (net .Nodes )
127+
128+ nodeIndex := len (net .Nodes )
129+ net .nodeMap [conf .ID ] = nodeIndex
124130 net .Nodes = append (net .Nodes , node )
125131
132+ // Register any node properties with the network-level propertyMap
133+ for _ , property := range conf .Properties {
134+ net .propertyMap [property ] = append (net .propertyMap [property ], nodeIndex )
135+ }
136+
126137 // emit a "control" event
127138 net .events .Send (ControlEvent (node ))
128139
@@ -410,7 +421,7 @@ func (net *Network) getNode(id enode.ID) *Node {
410421 return net .Nodes [i ]
411422}
412423
413- // GetNode gets the node with the given name, returning nil if the node does
424+ // GetNodeByName gets the node with the given name, returning nil if the node does
414425// not exist
415426func (net * Network ) GetNodeByName (name string ) * Node {
416427 net .lock .RLock ()
@@ -427,19 +438,104 @@ func (net *Network) getNodeByName(name string) *Node {
427438 return nil
428439}
429440
430- // GetNodes returns the existing nodes
431- func (net * Network ) GetNodes () (nodes []* Node ) {
441+ // GetNodeIDs returns the IDs of all existing nodes
442+ // Nodes can optionally be excluded by specifying their enode.ID.
443+ func (net * Network ) GetNodeIDs (excludeIDs ... enode.ID ) []enode.ID {
444+ net .lock .RLock ()
445+ defer net .lock .RUnlock ()
446+
447+ return net .getNodeIDs (excludeIDs )
448+ }
449+
450+ func (net * Network ) getNodeIDs (excludeIDs []enode.ID ) []enode.ID {
451+ // Get all curent nodeIDs
452+ nodeIDs := make ([]enode.ID , 0 , len (net .nodeMap ))
453+ for id := range net .nodeMap {
454+ nodeIDs = append (nodeIDs , id )
455+ }
456+
457+ if len (excludeIDs ) > 0 {
458+ // Return the difference of nodeIDs and excludeIDs
459+ return filterIDs (nodeIDs , excludeIDs )
460+ } else {
461+ return nodeIDs
462+ }
463+ }
464+
465+ // GetNodes returns the existing nodes.
466+ // Nodes can optionally be excluded by specifying their enode.ID.
467+ func (net * Network ) GetNodes (excludeIDs ... enode.ID ) []* Node {
468+ net .lock .RLock ()
469+ defer net .lock .RUnlock ()
470+
471+ return net .getNodes (excludeIDs )
472+ }
473+
474+ func (net * Network ) getNodes (excludeIDs []enode.ID ) []* Node {
475+ if len (excludeIDs ) > 0 {
476+ nodeIDs := net .getNodeIDs (excludeIDs )
477+ return net .getNodesByID (nodeIDs )
478+ } else {
479+ return net .Nodes
480+ }
481+ }
482+
483+ // GetNodesByID returns existing nodes with the given enode.IDs.
484+ // If a node doesn't exist with a given enode.ID, it is ignored.
485+ func (net * Network ) GetNodesByID (nodeIDs []enode.ID ) []* Node {
486+ net .lock .RLock ()
487+ defer net .lock .RUnlock ()
488+
489+ return net .getNodesByID (nodeIDs )
490+ }
491+
492+ func (net * Network ) getNodesByID (nodeIDs []enode.ID ) []* Node {
493+ nodes := make ([]* Node , 0 , len (nodeIDs ))
494+ for _ , id := range nodeIDs {
495+ node := net .getNode (id )
496+ if node != nil {
497+ nodes = append (nodes , node )
498+ }
499+ }
500+
501+ return nodes
502+ }
503+
504+ // GetNodesByProperty returns existing nodes that have the given property string registered in their NodeConfig
505+ func (net * Network ) GetNodesByProperty (property string ) []* Node {
432506 net .lock .RLock ()
433507 defer net .lock .RUnlock ()
434508
435- return net .getNodes ( )
509+ return net .getNodesByProperty ( property )
436510}
437511
438- func (net * Network ) getNodes () (nodes []* Node ) {
439- nodes = append (nodes , net .Nodes ... )
512+ func (net * Network ) getNodesByProperty (property string ) []* Node {
513+ nodes := make ([]* Node , 0 , len (net .propertyMap [property ]))
514+ for _ , nodeIndex := range net .propertyMap [property ] {
515+ nodes = append (nodes , net .Nodes [nodeIndex ])
516+ }
517+
440518 return nodes
441519}
442520
521+ // GetNodeIDsByProperty returns existing node's enode IDs that have the given property string registered in the NodeConfig
522+ func (net * Network ) GetNodeIDsByProperty (property string ) []enode.ID {
523+ net .lock .RLock ()
524+ defer net .lock .RUnlock ()
525+
526+ return net .getNodeIDsByProperty (property )
527+ }
528+
529+ func (net * Network ) getNodeIDsByProperty (property string ) []enode.ID {
530+ nodeIDs := make ([]enode.ID , 0 , len (net .propertyMap [property ]))
531+ for _ , nodeIndex := range net .propertyMap [property ] {
532+ node := net .Nodes [nodeIndex ]
533+ nodeIDs = append (nodeIDs , node .ID ())
534+ }
535+
536+ return nodeIDs
537+ }
538+
443539// GetRandomUpNode returns a random node on the network, which is running.
444540func (net * Network ) GetRandomUpNode (excludeIDs ... enode.ID ) * Node {
445541 net .lock .RLock ()
@@ -469,14 +565,21 @@ func (net *Network) GetRandomDownNode(excludeIDs ...enode.ID) *Node {
469565}
470566
471567func (net * Network ) getDownNodeIDs () (ids []enode.ID ) {
472- for _ , node := range net .getNodes () {
568+ for _ , node := range net .Nodes {
473569 if ! node .Up () {
474570 ids = append (ids , node .ID ())
475571 }
476572 }
477573 return ids
478574}
479575
576+ // GetRandomNode returns a random node on the network, regardless of whether it is running or not
577+ func (net * Network ) GetRandomNode (excludeIDs ... enode.ID ) * Node {
578+ net .lock .RLock ()
579+ defer net .lock .RUnlock ()
580+ return net .getRandomNode (net .getNodeIDs (nil ), excludeIDs ) // no need to exclude twice
581+ }
582+
480583func (net * Network ) getRandomNode (ids []enode.ID , excludeIDs []enode.ID ) * Node {
481584 filtered := filterIDs (ids , excludeIDs )
482585
@@ -616,6 +719,7 @@ func (net *Network) Reset() {
616719 //re-initialize the maps
617720 net .connMap = make (map [string ]int )
618721 net .nodeMap = make (map [enode.ID ]int )
722+ net .propertyMap = make (map [string ][]int )
619723
620724 net .Nodes = nil
621725 net .Conns = nil
@@ -634,12 +738,14 @@ type Node struct {
634738 upMu sync.RWMutex
635739}
636740
741+ // Up returns whether the node is currently up (online)
637742func (n * Node ) Up () bool {
638743 n .upMu .RLock ()
639744 defer n .upMu .RUnlock ()
640745 return n .up
641746}
642747
748+ // SetUp sets the up (online) status of the nodes with the given value
643749func (n * Node ) SetUp (up bool ) {
644750 n .upMu .Lock ()
645751 defer n .upMu .Unlock ()
0 commit comments