Track command-line targets in a separate set, to simplify tracking of targets

This commit is contained in:
Bryan Boreham committed 2014-09-10 14:12:37 +01:00
1 parent 634d4e0fe3
commit 4335615688
3 files changed
+37 -32

No files matched your search

+35 -30
View File
@@ -21,7 +21,6 @@ const (
const (
CSUnconnected ConnectionState = iota
CSAttempting = iota
CSEstablished = iota
)
func StartConnectionMaker(router *Router) *ConnectionMaker {
@@ -29,6 +28,7 @@ func StartConnectionMaker(router *Router) *ConnectionMaker {
state := &ConnectionMaker{
router: router,
queryChan: queryChan,
cmdLineAddress: make(map[string]bool),
targets: make(map[string]*Target)}
go state.queryLoop(queryChan)
return state
@@ -69,7 +69,7 @@ func (cm *ConnectionMaker) queryLoop(queryChan <-chan *ConnectionMakerInteractio
}
switch {
case query.code == CMInitiate:
cm.addToTargets(true, query.address)
cm.cmdLineAddress[query.address] = true;
tickNow()
case query.code == CMStatus:
query.resultChan <- cm.status()
@@ -96,62 +96,69 @@ func (cm *ConnectionMaker) queryLoop(queryChan <-chan *ConnectionMakerInteractio
func (cm *ConnectionMaker) checkStateAndAttemptConnections(now time.Time) {
ourself := cm.router.Ourself
validTarget := make(map[string]bool)
// Any targets that are now connected, we don't need to attempt any more
for address, target := range cm.targets {
for address, _ := range cm.targets {
if _, found := ourself.ConnectionOn(address); found {
if target.isCmdLine {
// We need to keep hold of targets supplied on the
// command-line, because that info isn't
// tracked anywhere else
target.state = CSEstablished
target.tryInterval = InitialInterval
} else {
delete(cm.targets, address)
}
} else if target.isCmdLine {
// This is a target that we are not connected to - if we are not currently attempting to connect, make sure we record it as unconnected
if target.state != CSAttempting {
target.state = CSUnconnected
}
//log.Println("Deleting target now connected:", address)
delete(cm.targets, address)
}
}
// build a map of peers we are connected to, so we can access it without locking
// Add command-line targets that are not connected
for address, _ := range cm.cmdLineAddress {
if _, found := ourself.ConnectionOn(address); !found {
//log.Println("Unconnected cmdline:", address)
cm.addToTargets(address)
validTarget[address] = true
}
}
// copy the set of peers we are connected to, so we can access it without locking
our_connected_peers := make(map[PeerName]bool)
ourself.ForEachConnection(func(peer PeerName, _ Connection) {
our_connected_peers[peer] = true
})
// Now look for peers that someone else is connected to, but we don't have a connection to.
// Add peers that someone else is connected to, but we aren't
cm.router.Peers.ForEach(func(name PeerName, peer *Peer) {
peer.ForEachConnection(func(peer2 PeerName, conn Connection) {
if peer2 != ourself.Name && !our_connected_peers[peer2] {
address := conn.RemoteTCPAddr()
//log.Println("Unconnected peer:", peer2, address)
// try both portnumber of connection and standart port
if host, port, err := ExtractHostPort(address); err == nil {
if port != Port {
cm.addToTargets(false, address)
cm.addToTargets(address)
validTarget[address] = true
}
cm.addToTargets(false, host)
cm.addToTargets(host)
validTarget[host] = true
}
}
})
})
for address, target := range cm.targets {
if target.state == CSUnconnected && now.After(target.tryAfter) {
target.attemptCount += 1
target.state = CSAttempting
go cm.attemptConnection(address, target.isCmdLine)
if validTarget[address] {
if target.state == CSUnconnected && now.After(target.tryAfter) {
target.attemptCount += 1
target.state = CSAttempting
go cm.attemptConnection(address, cm.cmdLineAddress[address])
}
} else {
//log.Println("Deleting target no longer valid:", address)
delete(cm.targets, address)
}
}
}
func (cm *ConnectionMaker) addToTargets(isCmdLine bool, address string) {
func (cm *ConnectionMaker) addToTargets(address string) {
target := cm.targets[address]
if target == nil {
target = &Target{
state: CSUnconnected,
isCmdLine: isCmdLine,
}
target.tryAfter, target.tryInterval = tryImmediately()
cm.targets[address] = target
@@ -161,9 +168,7 @@ func (cm *ConnectionMaker) addToTargets(isCmdLine bool, address string) {
func (cm *ConnectionMaker) status() string {
var buf bytes.Buffer
for address, target := range cm.targets {
if target.state == CSEstablished {
buf.WriteString(fmt.Sprintf("%s connected\n", address))
} else if target.state == CSAttempting {
if target.state == CSAttempting {
buf.WriteString(fmt.Sprintf("%s (%v attempts, trying since %v)\n", address, target.attemptCount, target.tryAfter))
} else {
buf.WriteString(fmt.Sprintf("%s (%v attempts, next at %v)\n", address, target.attemptCount, target.tryAfter))
+1 -1
View File
@@ -63,7 +63,7 @@ func (router *Router) Status() string {
buf.WriteString(fmt.Sprintf("MACs:\n%s", router.Macs))
buf.WriteString(fmt.Sprintf("Peers:\n%s", router.Peers))
buf.WriteString(fmt.Sprintf("Topology:\n%s", router.Topology))
buf.WriteString(fmt.Sprintf("Connections:\n%s", router.ConnectionMaker))
buf.WriteString(fmt.Sprintf("Reconnections:\n%s", router.ConnectionMaker))
return buf.String()
}
+1 -1
View File
@@ -162,13 +162,13 @@ type ConnectionMaker struct {
router *Router
queryChan chan<- *ConnectionMakerInteraction
targets map[string]*Target
cmdLineAddress map[string]bool
}
type ConnectionState int
// Information about an address where we may find a peer
type Target struct {
isCmdLine bool // was this address given to us on the command line?
state ConnectionState
tryAfter time.Time // next time to try this address
tryInterval time.Duration // backoff time on next failure