Skip to content

Commit

Permalink
Don't create a temporary slice when getting a connection
Browse files Browse the repository at this point in the history
  • Loading branch information
prashantv committed Mar 4, 2016
1 parent 013b422 commit 21489bf
Showing 1 changed file with 38 additions and 15 deletions.
53 changes: 38 additions & 15 deletions peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,28 +289,51 @@ func (p *Peer) HostPort() string {
return p.hostPort
}

// getActive returns a list of active connections.
// TODO(prashant): Should we clear inactive connections?
func (p *Peer) getActive() []*Connection {
var active []*Connection
p.runWithConnections(func(c *Connection) {
if c.IsActive() {
active = append(active, c)
// getConn treats inbound and outbound connections as a single virtual list
// that can be indexed. The peer must be read-locked.
func (p *Peer) getConn(i int) *Connection {
inboundLen := len(p.inboundConnections)
if i < inboundLen {
return p.inboundConnections[i]
}

return p.outboundConnections[i-inboundLen]
}

func (p *Peer) getActiveConnLocked() (*Connection, bool) {
allConns := len(p.inboundConnections) + len(p.outboundConnections)
if allConns == 0 {
return nil, false
}

startOffset := peerRng.Intn(allConns)

for i := 0; i < allConns; i++ {
connIndex := (i + startOffset) % allConns
if conn := p.getConn(connIndex); conn.IsActive() {
return conn, true
}
})
return active
}

return nil, false
}

func randConn(conns []*Connection) *Connection {
return conns[peerRng.Intn(len(conns))]
// getActiveConn will randomly select an active connection.
// TODO(prashant): Should we clear inactive connections?
// TODO(prashant): Do we want some sort of scoring for connections?
func (p *Peer) getActiveConn() (*Connection, bool) {
p.RLock()
conn, ok := p.getActiveConnLocked()
p.RUnlock()

return conn, ok
}

// GetConnection returns an active connection to this peer. If no active connections
// are found, it will create a new outbound connection and return it.
func (p *Peer) GetConnection(ctx context.Context) (*Connection, error) {
// TODO(prashant): Use some sort of scoring to pick a connection.
if activeConns := p.getActive(); len(activeConns) > 0 {
return randConn(activeConns), nil
if activeConn, ok := p.getActiveConn(); ok {
return activeConn, nil
}

// No active connections, make a new outgoing connection.
Expand Down Expand Up @@ -381,7 +404,7 @@ func (p *Peer) AddOutboundConnection(c *Connection) error {
}

// checkInboundConnection will check whether the changed connection is an inbound
// connection, and will remove any closed connections.
// connection, and will remove any gclosed connections.
func (p *Peer) checkInboundConnection(changed *Connection) (updated bool, isInbound bool) {
newConns := p.inboundConnections[:0]
for _, c := range p.inboundConnections {
Expand Down

0 comments on commit 21489bf

Please sign in to comment.