Use sync.Map instead of link actor

This commit is contained in:
Neil Alexander 2023-05-20 18:31:01 +01:00
parent 6e338b6f89
commit 5ba9dadc49
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
2 changed files with 49 additions and 62 deletions

View File

@ -71,31 +71,32 @@ func (c *Core) GetPeers() []PeerInfo {
conns[p.Conn] = p
}
phony.Block(&c.links, func() {
for info, state := range c.links._links {
var peerinfo PeerInfo
var conn net.Conn
phony.Block(state, func() {
peerinfo.URI = info.uri
peerinfo.LastError = state._err
peerinfo.LastErrorTime = state._errtime
if c := state._conn; c != nil {
conn = c
peerinfo.Up = true
peerinfo.Inbound = info.linkType == linkTypeIncoming
peerinfo.RXBytes = c.rx
peerinfo.TXBytes = c.tx
peerinfo.Uptime = time.Since(c.up)
}
})
if p, ok := conns[conn]; ok {
peerinfo.Key = p.Key
peerinfo.Root = p.Root
peerinfo.Port = p.Port
peerinfo.Priority = p.Priority
c.links.links.Range(func(key, value any) bool {
info := key.(linkInfo)
state := value.(*link)
var peerinfo PeerInfo
var conn net.Conn
phony.Block(state, func() {
peerinfo.URI = info.uri
peerinfo.LastError = state._err
peerinfo.LastErrorTime = state._errtime
if c := state._conn; c != nil {
conn = c
peerinfo.Up = true
peerinfo.Inbound = info.linkType == linkTypeIncoming
peerinfo.RXBytes = c.rx
peerinfo.TXBytes = c.tx
peerinfo.Uptime = time.Since(c.up)
}
peers = append(peers, peerinfo)
})
if p, ok := conns[conn]; ok {
peerinfo.Key = p.Key
peerinfo.Root = p.Root
peerinfo.Port = p.Port
peerinfo.Priority = p.Priority
}
peers = append(peers, peerinfo)
return true
})
return peers

View File

@ -12,6 +12,7 @@ import (
"net/url"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
@ -28,13 +29,12 @@ const (
)
type links struct {
phony.Inbox
core *Core
tcp *linkTCP // TCP interface support
tls *linkTLS // TLS interface support
unix *linkUNIX // UNIX interface support
socks *linkSOCKS // SOCKS interface support
_links map[linkInfo]*link // *link is nil if connection in progress
core *Core
tcp *linkTCP // TCP interface support
tls *linkTLS // TLS interface support
unix *linkUNIX // UNIX interface support
socks *linkSOCKS // SOCKS interface support
links sync.Map // map[linkInfo]*link // *link is nil if connection in progress
}
type linkProtocol interface {
@ -92,7 +92,6 @@ func (l *links) init(c *Core) error {
l.tls = l.newLinkTLS(l.tcp)
l.unix = l.newLinkUNIX()
l.socks = l.newLinkSOCKS()
l._links = make(map[linkInfo]*link)
var listeners []ListenAddress
phony.Block(c, func() {
@ -124,15 +123,11 @@ func (l *links) shutdown() {
}
func (l *links) isConnectedTo(info linkInfo) bool {
var isConnected bool
phony.Block(l, func() {
link, ok := l._links[info]
if !ok {
return
}
isConnected = link._conn != nil
})
return isConnected
li, ok := l.links.Load(info)
if !ok || li == nil {
return false
}
return li.(*link)._conn != nil
}
type linkError string
@ -152,12 +147,12 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
sintf: sintf,
linkType: linkType,
}
var state *link
var ok bool
phony.Block(l, func() {
state, ok = l._links[info]
})
if ok && state != nil {
if s, ok := l.links.Load(info); ok {
state = s.(*link)
}
if state != nil {
select {
case state.kick <- struct{}{}:
default:
@ -201,9 +196,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
// Store the state of the link, try to connect and then run
// the handler.
phony.Block(l, func() {
l._links[info] = state
})
l.links.Store(info, state)
// Track how many consecutive connection failures we have had,
// as we will back off exponentially rather than hammering the
@ -234,9 +227,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
// then the loop will run endlessly, using backoffs as needed.
// Otherwise the loop will end, cleaning up the link entry.
go func() {
defer phony.Block(l, func() {
delete(l._links, info)
})
l.links.Delete(info)
for {
conn, err := l.connect(u, info, options)
if err != nil {
@ -333,11 +324,10 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
continue
}
var state *link
var ok bool
phony.Block(l, func() {
state = l._links[info]
})
if !ok || state == nil {
if s, ok := l.links.Load(info); ok {
state = s.(*link)
}
if state == nil {
state = &link{
info: info,
}
@ -352,9 +342,7 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
state._err = nil
state.linkProto = strings.ToUpper(u.Scheme)
})
phony.Block(l, func() {
l._links[info] = state
})
l.links.Store(info, state)
if err = l.handler(&info, options, lc); err != nil && err != io.EOF {
l.core.log.Debugf("Link %s error: %s\n", u.Host, err)
}
@ -364,9 +352,7 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
state._errtime = time.Now()
}
})
phony.Block(l, func() {
delete(l._links, info)
})
l.links.Delete(info)
}
}()
return li, nil