mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 19:08:58 +00:00
lib: Replace done channel with contexts in and add names to util services (#6166)
This commit is contained in:
parent
552ea68672
commit
90d85fd0a2
@ -8,6 +8,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -136,7 +137,7 @@ func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonNam
|
|||||||
configChanged: make(chan struct{}),
|
configChanged: make(chan struct{}),
|
||||||
startedOnce: make(chan struct{}),
|
startedOnce: make(chan struct{}),
|
||||||
}
|
}
|
||||||
s.Service = util.AsService(s.serve)
|
s.Service = util.AsService(s.serve, s.String())
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +208,7 @@ func sendJSON(w http.ResponseWriter, jsonObject interface{}) {
|
|||||||
fmt.Fprintf(w, "%s\n", bs)
|
fmt.Fprintf(w, "%s\n", bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) serve(stop chan struct{}) {
|
func (s *service) serve(ctx context.Context) {
|
||||||
listener, err := s.getListener(s.cfg.GUI())
|
listener, err := s.getListener(s.cfg.GUI())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
select {
|
select {
|
||||||
@ -381,7 +382,7 @@ func (s *service) serve(stop chan struct{}) {
|
|||||||
// Wait for stop, restart or error signals
|
// Wait for stop, restart or error signals
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
// Shutting down permanently
|
// Shutting down permanently
|
||||||
l.Debugln("shutting down (stop)")
|
l.Debugln("shutting down (stop)")
|
||||||
case <-s.configChanged:
|
case <-s.configChanged:
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package beacon
|
package beacon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
@ -63,23 +64,23 @@ func newCast(name string) *cast {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cast) addReader(svc func(chan struct{}) error) {
|
func (c *cast) addReader(svc func(context.Context) error) {
|
||||||
c.reader = c.createService(svc, "reader")
|
c.reader = c.createService(svc, "reader")
|
||||||
c.Add(c.reader)
|
c.Add(c.reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cast) addWriter(svc func(stop chan struct{}) error) {
|
func (c *cast) addWriter(svc func(ctx context.Context) error) {
|
||||||
c.writer = c.createService(svc, "writer")
|
c.writer = c.createService(svc, "writer")
|
||||||
c.Add(c.writer)
|
c.Add(c.writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cast) createService(svc func(chan struct{}) error, suffix string) util.ServiceWithError {
|
func (c *cast) createService(svc func(context.Context) error, suffix string) util.ServiceWithError {
|
||||||
return util.AsServiceWithError(func(stop chan struct{}) error {
|
return util.AsServiceWithError(func(ctx context.Context) error {
|
||||||
l.Debugln("Starting", c.name, suffix)
|
l.Debugln("Starting", c.name, suffix)
|
||||||
err := svc(stop)
|
err := svc(ctx)
|
||||||
l.Debugf("Stopped %v %v: %v", c.name, suffix, err)
|
l.Debugf("Stopped %v %v: %v", c.name, suffix, err)
|
||||||
return err
|
return err
|
||||||
})
|
}, fmt.Sprintf("%s/%s", c, suffix))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cast) Stop() {
|
func (c *cast) Stop() {
|
||||||
|
@ -7,34 +7,32 @@
|
|||||||
package beacon
|
package beacon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewBroadcast(port int) Interface {
|
func NewBroadcast(port int) Interface {
|
||||||
c := newCast("broadcastBeacon")
|
c := newCast("broadcastBeacon")
|
||||||
c.addReader(func(stop chan struct{}) error {
|
c.addReader(func(ctx context.Context) error {
|
||||||
return readBroadcasts(c.outbox, port, stop)
|
return readBroadcasts(ctx, c.outbox, port)
|
||||||
})
|
})
|
||||||
c.addWriter(func(stop chan struct{}) error {
|
c.addWriter(func(ctx context.Context) error {
|
||||||
return writeBroadcasts(c.inbox, port, stop)
|
return writeBroadcasts(ctx, c.inbox, port)
|
||||||
})
|
})
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeBroadcasts(inbox <-chan []byte, port int, stop chan struct{}) error {
|
func writeBroadcasts(ctx context.Context, inbox <-chan []byte, port int) error {
|
||||||
conn, err := net.ListenUDP("udp4", nil)
|
conn, err := net.ListenUDP("udp4", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
done := make(chan struct{})
|
doneCtx, cancel := context.WithCancel(ctx)
|
||||||
defer close(done)
|
defer cancel()
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
<-doneCtx.Done()
|
||||||
case <-stop:
|
|
||||||
case <-done:
|
|
||||||
}
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -42,7 +40,7 @@ func writeBroadcasts(inbox <-chan []byte, port int, stop chan struct{}) error {
|
|||||||
var bs []byte
|
var bs []byte
|
||||||
select {
|
select {
|
||||||
case bs = <-inbox:
|
case bs = <-inbox:
|
||||||
case <-stop:
|
case <-doneCtx.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,19 +97,17 @@ func writeBroadcasts(inbox <-chan []byte, port int, stop chan struct{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readBroadcasts(outbox chan<- recv, port int, stop chan struct{}) error {
|
func readBroadcasts(ctx context.Context, outbox chan<- recv, port int) error {
|
||||||
conn, err := net.ListenUDP("udp4", &net.UDPAddr{Port: port})
|
conn, err := net.ListenUDP("udp4", &net.UDPAddr{Port: port})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
done := make(chan struct{})
|
|
||||||
defer close(done)
|
doneCtx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
<-doneCtx.Done()
|
||||||
case <-stop:
|
|
||||||
case <-done:
|
|
||||||
}
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -129,7 +125,7 @@ func readBroadcasts(outbox chan<- recv, port int, stop chan struct{}) error {
|
|||||||
copy(c, bs)
|
copy(c, bs)
|
||||||
select {
|
select {
|
||||||
case outbox <- recv{c, addr}:
|
case outbox <- recv{c, addr}:
|
||||||
case <-stop:
|
case <-doneCtx.Done():
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
l.Debugln("dropping message")
|
l.Debugln("dropping message")
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package beacon
|
package beacon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
@ -16,16 +17,16 @@ import (
|
|||||||
|
|
||||||
func NewMulticast(addr string) Interface {
|
func NewMulticast(addr string) Interface {
|
||||||
c := newCast("multicastBeacon")
|
c := newCast("multicastBeacon")
|
||||||
c.addReader(func(stop chan struct{}) error {
|
c.addReader(func(ctx context.Context) error {
|
||||||
return readMulticasts(c.outbox, addr, stop)
|
return readMulticasts(ctx, c.outbox, addr)
|
||||||
})
|
})
|
||||||
c.addWriter(func(stop chan struct{}) error {
|
c.addWriter(func(ctx context.Context) error {
|
||||||
return writeMulticasts(c.inbox, addr, stop)
|
return writeMulticasts(ctx, c.inbox, addr)
|
||||||
})
|
})
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeMulticasts(inbox <-chan []byte, addr string, stop chan struct{}) error {
|
func writeMulticasts(ctx context.Context, inbox <-chan []byte, addr string) error {
|
||||||
gaddr, err := net.ResolveUDPAddr("udp6", addr)
|
gaddr, err := net.ResolveUDPAddr("udp6", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
@ -37,13 +38,10 @@ func writeMulticasts(inbox <-chan []byte, addr string, stop chan struct{}) error
|
|||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
done := make(chan struct{})
|
doneCtx, cancel := context.WithCancel(ctx)
|
||||||
defer close(done)
|
defer cancel()
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
<-doneCtx.Done()
|
||||||
case <-stop:
|
|
||||||
case <-done:
|
|
||||||
}
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -57,7 +55,7 @@ func writeMulticasts(inbox <-chan []byte, addr string, stop chan struct{}) error
|
|||||||
var bs []byte
|
var bs []byte
|
||||||
select {
|
select {
|
||||||
case bs = <-inbox:
|
case bs = <-inbox:
|
||||||
case <-stop:
|
case <-doneCtx.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +82,7 @@ func writeMulticasts(inbox <-chan []byte, addr string, stop chan struct{}) error
|
|||||||
success++
|
success++
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-doneCtx.Done():
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@ -96,7 +94,7 @@ func writeMulticasts(inbox <-chan []byte, addr string, stop chan struct{}) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readMulticasts(outbox chan<- recv, addr string, stop chan struct{}) error {
|
func readMulticasts(ctx context.Context, outbox chan<- recv, addr string) error {
|
||||||
gaddr, err := net.ResolveUDPAddr("udp6", addr)
|
gaddr, err := net.ResolveUDPAddr("udp6", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
@ -108,13 +106,10 @@ func readMulticasts(outbox chan<- recv, addr string, stop chan struct{}) error {
|
|||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
done := make(chan struct{})
|
doneCtx, cancel := context.WithCancel(ctx)
|
||||||
defer close(done)
|
defer cancel()
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
<-doneCtx.Done()
|
||||||
case <-stop:
|
|
||||||
case <-done:
|
|
||||||
}
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -144,7 +139,7 @@ func readMulticasts(outbox chan<- recv, addr string, stop chan struct{}) error {
|
|||||||
bs := make([]byte, 65536)
|
bs := make([]byte, 65536)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-doneCtx.Done():
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -78,13 +78,9 @@ func (t *quicListener) OnExternalAddressChanged(address *stun.Host, via string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *quicListener) serve(stop chan struct{}) error {
|
func (t *quicListener) serve(ctx context.Context) error {
|
||||||
network := strings.Replace(t.uri.Scheme, "quic", "udp", -1)
|
network := strings.Replace(t.uri.Scheme, "quic", "udp", -1)
|
||||||
|
|
||||||
// Convert the stop channel into a context
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
go func() { <-stop; cancel() }()
|
|
||||||
|
|
||||||
packetConn, err := net.ListenPacket(network, t.uri.Host)
|
packetConn, err := net.ListenPacket(network, t.uri.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Infoln("Listen (BEP/quic):", err)
|
l.Infoln("Listen (BEP/quic):", err)
|
||||||
@ -205,7 +201,7 @@ func (f *quicListenerFactory) New(uri *url.URL, cfg config.Wrapper, tlsCfg *tls.
|
|||||||
conns: conns,
|
conns: conns,
|
||||||
factory: f,
|
factory: f,
|
||||||
}
|
}
|
||||||
l.ServiceWithError = util.AsServiceWithError(l.serve)
|
l.ServiceWithError = util.AsServiceWithError(l.serve, l.String())
|
||||||
l.nat.Store(stun.NATUnknown)
|
l.nat.Store(stun.NATUnknown)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package connections
|
package connections
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
@ -40,7 +41,7 @@ type relayListener struct {
|
|||||||
mut sync.RWMutex
|
mut sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *relayListener) serve(stop chan struct{}) error {
|
func (t *relayListener) serve(ctx context.Context) error {
|
||||||
clnt, err := client.NewClient(t.uri, t.tlsCfg.Certificates, nil, 10*time.Second)
|
clnt, err := client.NewClient(t.uri, t.tlsCfg.Certificates, nil, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Infoln("Listen (BEP/relay):", err)
|
l.Infoln("Listen (BEP/relay):", err)
|
||||||
@ -112,7 +113,7 @@ func (t *relayListener) serve(stop chan struct{}) error {
|
|||||||
t.notifyAddressesChanged(t)
|
t.notifyAddressesChanged(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +179,7 @@ func (f *relayListenerFactory) New(uri *url.URL, cfg config.Wrapper, tlsCfg *tls
|
|||||||
conns: conns,
|
conns: conns,
|
||||||
factory: f,
|
factory: f,
|
||||||
}
|
}
|
||||||
t.ServiceWithError = util.AsServiceWithError(t.serve)
|
t.ServiceWithError = util.AsServiceWithError(t.serve, t.String())
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package connections
|
package connections
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -185,18 +186,18 @@ func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *t
|
|||||||
// the common handling regardless of whether the connection was
|
// the common handling regardless of whether the connection was
|
||||||
// incoming or outgoing.
|
// incoming or outgoing.
|
||||||
|
|
||||||
service.Add(util.AsService(service.connect))
|
service.Add(util.AsService(service.connect, fmt.Sprintf("%s/connect", service)))
|
||||||
service.Add(util.AsService(service.handle))
|
service.Add(util.AsService(service.handle, fmt.Sprintf("%s/handle", service)))
|
||||||
service.Add(service.listenerSupervisor)
|
service.Add(service.listenerSupervisor)
|
||||||
|
|
||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) handle(stop chan struct{}) {
|
func (s *service) handle(ctx context.Context) {
|
||||||
var c internalConn
|
var c internalConn
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case c = <-s.conns:
|
case c = <-s.conns:
|
||||||
}
|
}
|
||||||
@ -324,7 +325,7 @@ func (s *service) handle(stop chan struct{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) connect(stop chan struct{}) {
|
func (s *service) connect(ctx context.Context) {
|
||||||
nextDial := make(map[string]time.Time)
|
nextDial := make(map[string]time.Time)
|
||||||
|
|
||||||
// Used as delay for the first few connection attempts, increases
|
// Used as delay for the first few connection attempts, increases
|
||||||
@ -480,7 +481,7 @@ func (s *service) connect(stop chan struct{}) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(sleep):
|
case <-time.After(sleep):
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package connections
|
package connections
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -42,7 +43,7 @@ type tcpListener struct {
|
|||||||
mut sync.RWMutex
|
mut sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcpListener) serve(stop chan struct{}) error {
|
func (t *tcpListener) serve(ctx context.Context) error {
|
||||||
tcaddr, err := net.ResolveTCPAddr(t.uri.Scheme, t.uri.Host)
|
tcaddr, err := net.ResolveTCPAddr(t.uri.Scheme, t.uri.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Infoln("Listen (BEP/tcp):", err)
|
l.Infoln("Listen (BEP/tcp):", err)
|
||||||
@ -76,7 +77,7 @@ func (t *tcpListener) serve(stop chan struct{}) error {
|
|||||||
listener.SetDeadline(time.Now().Add(time.Second))
|
listener.SetDeadline(time.Now().Add(time.Second))
|
||||||
conn, err := listener.Accept()
|
conn, err := listener.Accept()
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
if err == nil {
|
if err == nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
@ -183,7 +184,7 @@ func (f *tcpListenerFactory) New(uri *url.URL, cfg config.Wrapper, tlsCfg *tls.C
|
|||||||
natService: natService,
|
natService: natService,
|
||||||
factory: f,
|
factory: f,
|
||||||
}
|
}
|
||||||
l.ServiceWithError = util.AsServiceWithError(l.serve)
|
l.ServiceWithError = util.AsServiceWithError(l.serve, l.String())
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ package discover
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
@ -128,7 +129,7 @@ func NewGlobal(server string, cert tls.Certificate, addrList AddressLister, evLo
|
|||||||
noLookup: opts.noLookup,
|
noLookup: opts.noLookup,
|
||||||
evLogger: evLogger,
|
evLogger: evLogger,
|
||||||
}
|
}
|
||||||
cl.Service = util.AsService(cl.serve)
|
cl.Service = util.AsService(cl.serve, cl.String())
|
||||||
if !opts.noAnnounce {
|
if !opts.noAnnounce {
|
||||||
// If we are supposed to annonce, it's an error until we've done so.
|
// If we are supposed to annonce, it's an error until we've done so.
|
||||||
cl.setError(errors.New("not announced"))
|
cl.setError(errors.New("not announced"))
|
||||||
@ -188,11 +189,11 @@ func (c *globalClient) String() string {
|
|||||||
return "global@" + c.server
|
return "global@" + c.server
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *globalClient) serve(stop chan struct{}) {
|
func (c *globalClient) serve(ctx context.Context) {
|
||||||
if c.noAnnounce {
|
if c.noAnnounce {
|
||||||
// We're configured to not do announcements, only lookups. To maintain
|
// We're configured to not do announcements, only lookups. To maintain
|
||||||
// the same interface, we just pause here if Serve() is run.
|
// the same interface, we just pause here if Serve() is run.
|
||||||
<-stop
|
<-ctx.Done()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +213,7 @@ func (c *globalClient) serve(stop chan struct{}) {
|
|||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
c.sendAnnouncement(timer)
|
c.sendAnnouncement(timer)
|
||||||
|
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
package discover
|
package discover
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -81,9 +83,9 @@ func NewLocal(id protocol.DeviceID, addr string, addrList AddressLister, evLogge
|
|||||||
c.beacon = beacon.NewMulticast(addr)
|
c.beacon = beacon.NewMulticast(addr)
|
||||||
}
|
}
|
||||||
c.Add(c.beacon)
|
c.Add(c.beacon)
|
||||||
c.Add(util.AsService(c.recvAnnouncements))
|
c.Add(util.AsService(c.recvAnnouncements, fmt.Sprintf("%s/recv", c)))
|
||||||
|
|
||||||
c.Add(util.AsService(c.sendLocalAnnouncements))
|
c.Add(util.AsService(c.sendLocalAnnouncements, fmt.Sprintf("%s/sendLocal", c)))
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
@ -135,7 +137,7 @@ func (c *localClient) announcementPkt(instanceID int64, msg []byte) ([]byte, boo
|
|||||||
return msg, true
|
return msg, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *localClient) sendLocalAnnouncements(stop chan struct{}) {
|
func (c *localClient) sendLocalAnnouncements(ctx context.Context) {
|
||||||
var msg []byte
|
var msg []byte
|
||||||
var ok bool
|
var ok bool
|
||||||
instanceID := rand.Int63()
|
instanceID := rand.Int63()
|
||||||
@ -147,18 +149,18 @@ func (c *localClient) sendLocalAnnouncements(stop chan struct{}) {
|
|||||||
select {
|
select {
|
||||||
case <-c.localBcastTick:
|
case <-c.localBcastTick:
|
||||||
case <-c.forcedBcastTick:
|
case <-c.forcedBcastTick:
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *localClient) recvAnnouncements(stop chan struct{}) {
|
func (c *localClient) recvAnnouncements(ctx context.Context) {
|
||||||
b := c.beacon
|
b := c.beacon
|
||||||
warnedAbout := make(map[string]bool)
|
warnedAbout := make(map[string]bool)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,10 @@
|
|||||||
package events
|
package events
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -258,7 +260,7 @@ func NewLogger() Logger {
|
|||||||
funcs: make(chan func()),
|
funcs: make(chan func()),
|
||||||
toUnsubscribe: make(chan *subscription),
|
toUnsubscribe: make(chan *subscription),
|
||||||
}
|
}
|
||||||
l.Service = util.AsService(l.serve)
|
l.Service = util.AsService(l.serve, l.String())
|
||||||
// Make sure the timer is in the stopped state and hasn't fired anything
|
// Make sure the timer is in the stopped state and hasn't fired anything
|
||||||
// into the channel.
|
// into the channel.
|
||||||
if !l.timeout.Stop() {
|
if !l.timeout.Stop() {
|
||||||
@ -267,7 +269,7 @@ func NewLogger() Logger {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *logger) serve(stop chan struct{}) {
|
func (l *logger) serve(ctx context.Context) {
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -282,7 +284,7 @@ loop:
|
|||||||
case s := <-l.toUnsubscribe:
|
case s := <-l.toUnsubscribe:
|
||||||
l.unsubscribe(s)
|
l.unsubscribe(s)
|
||||||
|
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -388,6 +390,10 @@ func (l *logger) unsubscribe(s *subscription) {
|
|||||||
close(s.events)
|
close(s.events)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *logger) String() string {
|
||||||
|
return fmt.Sprintf("events.Logger/@%p", l)
|
||||||
|
}
|
||||||
|
|
||||||
// Poll returns an event from the subscription or an error if the poll times
|
// Poll returns an event from the subscription or an error if the poll times
|
||||||
// out of the event channel is closed. Poll should not be called concurrently
|
// out of the event channel is closed. Poll should not be called concurrently
|
||||||
// from multiple goroutines for a single subscription.
|
// from multiple goroutines for a single subscription.
|
||||||
|
@ -55,12 +55,12 @@ func (f *BasicFilesystem) Watch(name string, ignore Matcher, ctx context.Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
go f.watchLoop(name, roots, backendChan, outChan, errChan, ignore, ctx)
|
go f.watchLoop(ctx, name, roots, backendChan, outChan, errChan, ignore)
|
||||||
|
|
||||||
return outChan, errChan, nil
|
return outChan, errChan, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *BasicFilesystem) watchLoop(name string, roots []string, backendChan chan notify.EventInfo, outChan chan<- Event, errChan chan<- error, ignore Matcher, ctx context.Context) {
|
func (f *BasicFilesystem) watchLoop(ctx context.Context, name string, roots []string, backendChan chan notify.EventInfo, outChan chan<- Event, errChan chan<- error, ignore Matcher) {
|
||||||
for {
|
for {
|
||||||
// Detect channel overflow
|
// Detect channel overflow
|
||||||
if len(backendChan) == backendBuffer {
|
if len(backendChan) == backendBuffer {
|
||||||
|
@ -178,7 +178,7 @@ func TestWatchWinRoot(t *testing.T) {
|
|||||||
}
|
}
|
||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
fs.watchLoop(".", roots, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
fs.watchLoop(ctx, ".", roots, backendChan, outChan, errChan, fakeMatcher{})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// filepath.Dir as watch has a /... suffix
|
// filepath.Dir as watch has a /... suffix
|
||||||
@ -219,7 +219,7 @@ func expectErrorForPath(t *testing.T, path string) {
|
|||||||
// testFs is Filesystem, but we need BasicFilesystem here
|
// testFs is Filesystem, but we need BasicFilesystem here
|
||||||
fs := newBasicFilesystem(testDirAbs)
|
fs := newBasicFilesystem(testDirAbs)
|
||||||
|
|
||||||
go fs.watchLoop(".", []string{testDirAbs}, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
go fs.watchLoop(ctx, ".", []string{testDirAbs}, backendChan, outChan, errChan, fakeMatcher{})
|
||||||
|
|
||||||
backendChan <- fakeEventInfo(path)
|
backendChan <- fakeEventInfo(path)
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ func TestWatchSubpath(t *testing.T) {
|
|||||||
fs := newBasicFilesystem(testDirAbs)
|
fs := newBasicFilesystem(testDirAbs)
|
||||||
|
|
||||||
abs, _ := fs.rooted("sub")
|
abs, _ := fs.rooted("sub")
|
||||||
go fs.watchLoop("sub", []string{testDirAbs}, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
go fs.watchLoop(ctx, "sub", []string{testDirAbs}, backendChan, outChan, errChan, fakeMatcher{})
|
||||||
|
|
||||||
backendChan <- fakeEventInfo(filepath.Join(abs, "file"))
|
backendChan <- fakeEventInfo(filepath.Join(abs, "file"))
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ type folder struct {
|
|||||||
fset *db.FileSet
|
fset *db.FileSet
|
||||||
ignores *ignore.Matcher
|
ignores *ignore.Matcher
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
|
||||||
|
|
||||||
scanInterval time.Duration
|
scanInterval time.Duration
|
||||||
scanTimer *time.Timer
|
scanTimer *time.Timer
|
||||||
@ -80,8 +79,6 @@ type puller interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, evLogger events.Logger) folder {
|
func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, evLogger events.Logger) folder {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
|
|
||||||
return folder{
|
return folder{
|
||||||
stateTracker: newStateTracker(cfg.ID, evLogger),
|
stateTracker: newStateTracker(cfg.ID, evLogger),
|
||||||
FolderConfiguration: cfg,
|
FolderConfiguration: cfg,
|
||||||
@ -91,8 +88,6 @@ func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg conf
|
|||||||
shortID: model.shortID,
|
shortID: model.shortID,
|
||||||
fset: fset,
|
fset: fset,
|
||||||
ignores: ignores,
|
ignores: ignores,
|
||||||
ctx: ctx,
|
|
||||||
cancel: cancel,
|
|
||||||
|
|
||||||
scanInterval: time.Duration(cfg.RescanIntervalS) * time.Second,
|
scanInterval: time.Duration(cfg.RescanIntervalS) * time.Second,
|
||||||
scanTimer: time.NewTimer(time.Millisecond), // The first scan should be done immediately.
|
scanTimer: time.NewTimer(time.Millisecond), // The first scan should be done immediately.
|
||||||
@ -109,10 +104,12 @@ func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg conf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *folder) serve(_ chan struct{}) {
|
func (f *folder) serve(ctx context.Context) {
|
||||||
atomic.AddInt32(&f.model.foldersRunning, 1)
|
atomic.AddInt32(&f.model.foldersRunning, 1)
|
||||||
defer atomic.AddInt32(&f.model.foldersRunning, -1)
|
defer atomic.AddInt32(&f.model.foldersRunning, -1)
|
||||||
|
|
||||||
|
f.ctx = ctx
|
||||||
|
|
||||||
l.Debugln(f, "starting")
|
l.Debugln(f, "starting")
|
||||||
defer l.Debugln(f, "exiting")
|
defer l.Debugln(f, "exiting")
|
||||||
|
|
||||||
@ -256,11 +253,6 @@ func (f *folder) Delay(next time.Duration) {
|
|||||||
f.scanDelay <- next
|
f.scanDelay <- next
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *folder) Stop() {
|
|
||||||
f.cancel()
|
|
||||||
f.Service.Stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckHealth checks the folder for common errors, updates the folder state
|
// CheckHealth checks the folder for common errors, updates the folder state
|
||||||
// and returns the current folder error, or nil if the folder is healthy.
|
// and returns the current folder error, or nil if the folder is healthy.
|
||||||
func (f *folder) CheckHealth() error {
|
func (f *folder) CheckHealth() error {
|
||||||
@ -643,7 +635,7 @@ func (f *folder) monitorWatch(ctx context.Context) {
|
|||||||
failTimer.Reset(time.Minute)
|
failTimer.Reset(time.Minute)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
watchaggregator.Aggregate(eventChan, f.watchChan, f.FolderConfiguration, f.model.cfg, f.evLogger, aggrCtx)
|
watchaggregator.Aggregate(aggrCtx, eventChan, f.watchChan, f.FolderConfiguration, f.model.cfg, f.evLogger)
|
||||||
l.Debugln("Started filesystem watcher for folder", f.Description())
|
l.Debugln("Started filesystem watcher for folder", f.Description())
|
||||||
case err = <-errChan:
|
case err = <-errChan:
|
||||||
f.setWatchError(err)
|
f.setWatchError(err)
|
||||||
|
@ -30,7 +30,7 @@ func newSendOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher,
|
|||||||
folder: newFolder(model, fset, ignores, cfg, evLogger),
|
folder: newFolder(model, fset, ignores, cfg, evLogger),
|
||||||
}
|
}
|
||||||
f.folder.puller = f
|
f.folder.puller = f
|
||||||
f.folder.Service = util.AsService(f.serve)
|
f.folder.Service = util.AsService(f.serve, f.String())
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ func newSendReceiveFolder(model *model, fset *db.FileSet, ignores *ignore.Matche
|
|||||||
pullErrorsMut: sync.NewMutex(),
|
pullErrorsMut: sync.NewMutex(),
|
||||||
}
|
}
|
||||||
f.folder.puller = f
|
f.folder.puller = f
|
||||||
f.folder.Service = util.AsService(f.serve)
|
f.folder.Service = util.AsService(f.serve, f.String())
|
||||||
|
|
||||||
if f.Copiers == 0 {
|
if f.Copiers == 0 {
|
||||||
f.Copiers = defaultCopiers
|
f.Copiers = defaultCopiers
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -63,8 +64,8 @@ func NewFolderSummaryService(cfg config.Wrapper, m Model, id protocol.DeviceID,
|
|||||||
lastEventReqMut: sync.NewMutex(),
|
lastEventReqMut: sync.NewMutex(),
|
||||||
}
|
}
|
||||||
|
|
||||||
service.Add(util.AsService(service.listenForUpdates))
|
service.Add(util.AsService(service.listenForUpdates, fmt.Sprintf("%s/listenForUpdates", service)))
|
||||||
service.Add(util.AsService(service.calculateSummaries))
|
service.Add(util.AsService(service.calculateSummaries, fmt.Sprintf("%s/calculateSummaries", service)))
|
||||||
|
|
||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
@ -145,7 +146,7 @@ func (c *folderSummaryService) OnEventRequest() {
|
|||||||
|
|
||||||
// listenForUpdates subscribes to the event bus and makes note of folders that
|
// listenForUpdates subscribes to the event bus and makes note of folders that
|
||||||
// need their data recalculated.
|
// need their data recalculated.
|
||||||
func (c *folderSummaryService) listenForUpdates(stop chan struct{}) {
|
func (c *folderSummaryService) listenForUpdates(ctx context.Context) {
|
||||||
sub := c.evLogger.Subscribe(events.LocalIndexUpdated | events.RemoteIndexUpdated | events.StateChanged | events.RemoteDownloadProgress | events.DeviceConnected | events.FolderWatchStateChanged | events.DownloadProgress)
|
sub := c.evLogger.Subscribe(events.LocalIndexUpdated | events.RemoteIndexUpdated | events.StateChanged | events.RemoteDownloadProgress | events.DeviceConnected | events.FolderWatchStateChanged | events.DownloadProgress)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
@ -155,7 +156,7 @@ func (c *folderSummaryService) listenForUpdates(stop chan struct{}) {
|
|||||||
select {
|
select {
|
||||||
case ev := <-sub.C():
|
case ev := <-sub.C():
|
||||||
c.processUpdate(ev)
|
c.processUpdate(ev)
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +235,7 @@ func (c *folderSummaryService) processUpdate(ev events.Event) {
|
|||||||
|
|
||||||
// calculateSummaries periodically recalculates folder summaries and
|
// calculateSummaries periodically recalculates folder summaries and
|
||||||
// completion percentage, and sends the results on the event bus.
|
// completion percentage, and sends the results on the event bus.
|
||||||
func (c *folderSummaryService) calculateSummaries(stop chan struct{}) {
|
func (c *folderSummaryService) calculateSummaries(ctx context.Context) {
|
||||||
const pumpInterval = 2 * time.Second
|
const pumpInterval = 2 * time.Second
|
||||||
pump := time.NewTimer(pumpInterval)
|
pump := time.NewTimer(pumpInterval)
|
||||||
|
|
||||||
@ -255,7 +256,7 @@ func (c *folderSummaryService) calculateSummaries(stop chan struct{}) {
|
|||||||
case folder := <-c.immediate:
|
case folder := <-c.immediate:
|
||||||
c.sendSummary(folder)
|
c.sendSummary(folder)
|
||||||
|
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1227,7 +1227,7 @@ func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
|||||||
dropSymlinks: dropSymlinks,
|
dropSymlinks: dropSymlinks,
|
||||||
evLogger: m.evLogger,
|
evLogger: m.evLogger,
|
||||||
}
|
}
|
||||||
is.Service = util.AsService(is.serve)
|
is.Service = util.AsService(is.serve, is.String())
|
||||||
// The token isn't tracked as the service stops when the connection
|
// The token isn't tracked as the service stops when the connection
|
||||||
// terminates and is automatically removed from supervisor (by
|
// terminates and is automatically removed from supervisor (by
|
||||||
// implementing suture.IsCompletable).
|
// implementing suture.IsCompletable).
|
||||||
@ -1970,7 +1970,7 @@ type indexSender struct {
|
|||||||
connClosed chan struct{}
|
connClosed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *indexSender) serve(stop chan struct{}) {
|
func (s *indexSender) serve(ctx context.Context) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
l.Debugf("Starting indexSender for %s to %s at %s (slv=%d)", s.folder, s.dev, s.conn, s.prevSequence)
|
l.Debugf("Starting indexSender for %s to %s at %s (slv=%d)", s.folder, s.dev, s.conn, s.prevSequence)
|
||||||
@ -1991,7 +1991,7 @@ func (s *indexSender) serve(stop chan struct{}) {
|
|||||||
|
|
||||||
for err == nil {
|
for err == nil {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case <-s.connClosed:
|
case <-s.connClosed:
|
||||||
return
|
return
|
||||||
@ -2004,7 +2004,7 @@ func (s *indexSender) serve(stop chan struct{}) {
|
|||||||
// sending for.
|
// sending for.
|
||||||
if s.fset.Sequence(protocol.LocalDeviceID) <= s.prevSequence {
|
if s.fset.Sequence(protocol.LocalDeviceID) <= s.prevSequence {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case <-s.connClosed:
|
case <-s.connClosed:
|
||||||
return
|
return
|
||||||
@ -2037,7 +2037,7 @@ func (s *indexSender) sendIndexTo() error {
|
|||||||
initial := s.prevSequence == 0
|
initial := s.prevSequence == 0
|
||||||
batch := newFileInfoBatch(nil)
|
batch := newFileInfoBatch(nil)
|
||||||
batch.flushFn = func(fs []protocol.FileInfo) error {
|
batch.flushFn = func(fs []protocol.FileInfo) error {
|
||||||
l.Debugf("Sending indexes for %s to %s at %s: %d files (<%d bytes)", s.folder, s.dev, s.conn, len(batch.infos), batch.size)
|
l.Debugf("%v: Sending %d files (<%d bytes)", s, len(batch.infos), batch.size)
|
||||||
if initial {
|
if initial {
|
||||||
initial = false
|
initial = false
|
||||||
return s.conn.Index(s.folder, fs)
|
return s.conn.Index(s.folder, fs)
|
||||||
@ -2099,6 +2099,10 @@ func (s *indexSender) sendIndexTo() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *indexSender) String() string {
|
||||||
|
return fmt.Sprintf("indexSender@%p for %s to %s at %s", s, s.folder, s.dev, s.conn)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *model) requestGlobal(ctx context.Context, deviceID protocol.DeviceID, folder, name string, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
|
func (m *model) requestGlobal(ctx context.Context, deviceID protocol.DeviceID, folder, name string, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
|
||||||
m.pmut.RLock()
|
m.pmut.RLock()
|
||||||
nc, ok := m.conn[deviceID]
|
nc, ok := m.conn[deviceID]
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ func NewProgressEmitter(cfg config.Wrapper, evLogger events.Logger) *ProgressEmi
|
|||||||
evLogger: evLogger,
|
evLogger: evLogger,
|
||||||
mut: sync.NewMutex(),
|
mut: sync.NewMutex(),
|
||||||
}
|
}
|
||||||
t.Service = util.AsService(t.serve)
|
t.Service = util.AsService(t.serve, t.String())
|
||||||
|
|
||||||
t.CommitConfiguration(config.Configuration{}, cfg.RawCopy())
|
t.CommitConfiguration(config.Configuration{}, cfg.RawCopy())
|
||||||
cfg.Subscribe(t)
|
cfg.Subscribe(t)
|
||||||
@ -57,12 +58,12 @@ func NewProgressEmitter(cfg config.Wrapper, evLogger events.Logger) *ProgressEmi
|
|||||||
|
|
||||||
// serve starts the progress emitter which starts emitting DownloadProgress
|
// serve starts the progress emitter which starts emitting DownloadProgress
|
||||||
// events as the progress happens.
|
// events as the progress happens.
|
||||||
func (t *ProgressEmitter) serve(stop chan struct{}) {
|
func (t *ProgressEmitter) serve(ctx context.Context) {
|
||||||
var lastUpdate time.Time
|
var lastUpdate time.Time
|
||||||
var lastCount, newCount int
|
var lastCount, newCount int
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
l.Debugln("progress emitter: stopping")
|
l.Debugln("progress emitter: stopping")
|
||||||
return
|
return
|
||||||
case <-t.timer.C:
|
case <-t.timer.C:
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package nat
|
package nat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -19,7 +20,7 @@ func Register(provider DiscoverFunc) {
|
|||||||
providers = append(providers, provider)
|
providers = append(providers, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverAll(renewal, timeout time.Duration, stop chan struct{}) map[string]Device {
|
func discoverAll(ctx context.Context, renewal, timeout time.Duration) map[string]Device {
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
wg.Add(len(providers))
|
wg.Add(len(providers))
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ func discoverAll(renewal, timeout time.Duration, stop chan struct{}) map[string]
|
|||||||
for _, dev := range f(renewal, timeout) {
|
for _, dev := range f(renewal, timeout) {
|
||||||
select {
|
select {
|
||||||
case c <- dev:
|
case c <- dev:
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,7 +51,7 @@ func discoverAll(renewal, timeout time.Duration, stop chan struct{}) map[string]
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
nats[dev.ID()] = dev
|
nats[dev.ID()] = dev
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package nat
|
package nat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@ -43,11 +44,11 @@ func NewService(id protocol.DeviceID, cfg config.Wrapper) *Service {
|
|||||||
timer: time.NewTimer(0),
|
timer: time.NewTimer(0),
|
||||||
mut: sync.NewRWMutex(),
|
mut: sync.NewRWMutex(),
|
||||||
}
|
}
|
||||||
s.Service = util.AsService(s.serve)
|
s.Service = util.AsService(s.serve, s.String())
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) serve(stop chan struct{}) {
|
func (s *Service) serve(ctx context.Context) {
|
||||||
announce := stdsync.Once{}
|
announce := stdsync.Once{}
|
||||||
|
|
||||||
s.mut.Lock()
|
s.mut.Lock()
|
||||||
@ -57,7 +58,7 @@ func (s *Service) serve(stop chan struct{}) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-s.timer.C:
|
case <-s.timer.C:
|
||||||
if found := s.process(stop); found != -1 {
|
if found := s.process(ctx); found != -1 {
|
||||||
announce.Do(func() {
|
announce.Do(func() {
|
||||||
suffix := "s"
|
suffix := "s"
|
||||||
if found == 1 {
|
if found == 1 {
|
||||||
@ -66,7 +67,7 @@ func (s *Service) serve(stop chan struct{}) {
|
|||||||
l.Infoln("Detected", found, "NAT service"+suffix)
|
l.Infoln("Detected", found, "NAT service"+suffix)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
s.timer.Stop()
|
s.timer.Stop()
|
||||||
s.mut.RLock()
|
s.mut.RLock()
|
||||||
for _, mapping := range s.mappings {
|
for _, mapping := range s.mappings {
|
||||||
@ -78,7 +79,7 @@ func (s *Service) serve(stop chan struct{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) process(stop chan struct{}) int {
|
func (s *Service) process(ctx context.Context) int {
|
||||||
// toRenew are mappings which are due for renewal
|
// toRenew are mappings which are due for renewal
|
||||||
// toUpdate are the remaining mappings, which will only be updated if one of
|
// toUpdate are the remaining mappings, which will only be updated if one of
|
||||||
// the old IGDs has gone away, or a new IGD has appeared, but only if we
|
// the old IGDs has gone away, or a new IGD has appeared, but only if we
|
||||||
@ -120,14 +121,14 @@ func (s *Service) process(stop chan struct{}) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
nats := discoverAll(time.Duration(s.cfg.Options().NATRenewalM)*time.Minute, time.Duration(s.cfg.Options().NATTimeoutS)*time.Second, stop)
|
nats := discoverAll(ctx, time.Duration(s.cfg.Options().NATRenewalM)*time.Minute, time.Duration(s.cfg.Options().NATTimeoutS)*time.Second)
|
||||||
|
|
||||||
for _, mapping := range toRenew {
|
for _, mapping := range toRenew {
|
||||||
s.updateMapping(mapping, nats, true, stop)
|
s.updateMapping(ctx, mapping, nats, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mapping := range toUpdate {
|
for _, mapping := range toUpdate {
|
||||||
s.updateMapping(mapping, nats, false, stop)
|
s.updateMapping(ctx, mapping, nats, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(nats)
|
return len(nats)
|
||||||
@ -177,17 +178,17 @@ func (s *Service) RemoveMapping(mapping *Mapping) {
|
|||||||
// acquire mappings for natds which the mapping was unaware of before.
|
// acquire mappings for natds which the mapping was unaware of before.
|
||||||
// Optionally takes renew flag which indicates whether or not we should renew
|
// Optionally takes renew flag which indicates whether or not we should renew
|
||||||
// mappings with existing natds
|
// mappings with existing natds
|
||||||
func (s *Service) updateMapping(mapping *Mapping, nats map[string]Device, renew bool, stop chan struct{}) {
|
func (s *Service) updateMapping(ctx context.Context, mapping *Mapping, nats map[string]Device, renew bool) {
|
||||||
var added, removed []Address
|
var added, removed []Address
|
||||||
|
|
||||||
renewalTime := time.Duration(s.cfg.Options().NATRenewalM) * time.Minute
|
renewalTime := time.Duration(s.cfg.Options().NATRenewalM) * time.Minute
|
||||||
mapping.expires = time.Now().Add(renewalTime)
|
mapping.expires = time.Now().Add(renewalTime)
|
||||||
|
|
||||||
newAdded, newRemoved := s.verifyExistingMappings(mapping, nats, renew, stop)
|
newAdded, newRemoved := s.verifyExistingMappings(ctx, mapping, nats, renew)
|
||||||
added = append(added, newAdded...)
|
added = append(added, newAdded...)
|
||||||
removed = append(removed, newRemoved...)
|
removed = append(removed, newRemoved...)
|
||||||
|
|
||||||
newAdded, newRemoved = s.acquireNewMappings(mapping, nats, stop)
|
newAdded, newRemoved = s.acquireNewMappings(ctx, mapping, nats)
|
||||||
added = append(added, newAdded...)
|
added = append(added, newAdded...)
|
||||||
removed = append(removed, newRemoved...)
|
removed = append(removed, newRemoved...)
|
||||||
|
|
||||||
@ -196,14 +197,14 @@ func (s *Service) updateMapping(mapping *Mapping, nats map[string]Device, renew
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) verifyExistingMappings(mapping *Mapping, nats map[string]Device, renew bool, stop chan struct{}) ([]Address, []Address) {
|
func (s *Service) verifyExistingMappings(ctx context.Context, mapping *Mapping, nats map[string]Device, renew bool) ([]Address, []Address) {
|
||||||
var added, removed []Address
|
var added, removed []Address
|
||||||
|
|
||||||
leaseTime := time.Duration(s.cfg.Options().NATLeaseM) * time.Minute
|
leaseTime := time.Duration(s.cfg.Options().NATLeaseM) * time.Minute
|
||||||
|
|
||||||
for id, address := range mapping.addressMap() {
|
for id, address := range mapping.addressMap() {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@ -225,7 +226,7 @@ func (s *Service) verifyExistingMappings(mapping *Mapping, nats map[string]Devic
|
|||||||
|
|
||||||
l.Debugf("Renewing %s -> %s mapping on %s", mapping, address, id)
|
l.Debugf("Renewing %s -> %s mapping on %s", mapping, address, id)
|
||||||
|
|
||||||
addr, err := s.tryNATDevice(nat, mapping.address.Port, address.Port, leaseTime, stop)
|
addr, err := s.tryNATDevice(ctx, nat, mapping.address.Port, address.Port, leaseTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugf("Failed to renew %s -> mapping on %s", mapping, address, id)
|
l.Debugf("Failed to renew %s -> mapping on %s", mapping, address, id)
|
||||||
mapping.removeAddress(id)
|
mapping.removeAddress(id)
|
||||||
@ -247,7 +248,7 @@ func (s *Service) verifyExistingMappings(mapping *Mapping, nats map[string]Devic
|
|||||||
return added, removed
|
return added, removed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) acquireNewMappings(mapping *Mapping, nats map[string]Device, stop chan struct{}) ([]Address, []Address) {
|
func (s *Service) acquireNewMappings(ctx context.Context, mapping *Mapping, nats map[string]Device) ([]Address, []Address) {
|
||||||
var added, removed []Address
|
var added, removed []Address
|
||||||
|
|
||||||
leaseTime := time.Duration(s.cfg.Options().NATLeaseM) * time.Minute
|
leaseTime := time.Duration(s.cfg.Options().NATLeaseM) * time.Minute
|
||||||
@ -255,7 +256,7 @@ func (s *Service) acquireNewMappings(mapping *Mapping, nats map[string]Device, s
|
|||||||
|
|
||||||
for id, nat := range nats {
|
for id, nat := range nats {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@ -274,7 +275,7 @@ func (s *Service) acquireNewMappings(mapping *Mapping, nats map[string]Device, s
|
|||||||
|
|
||||||
l.Debugf("Acquiring %s mapping on %s", mapping, id)
|
l.Debugf("Acquiring %s mapping on %s", mapping, id)
|
||||||
|
|
||||||
addr, err := s.tryNATDevice(nat, mapping.address.Port, 0, leaseTime, stop)
|
addr, err := s.tryNATDevice(ctx, nat, mapping.address.Port, 0, leaseTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugf("Failed to acquire %s mapping on %s", mapping, id)
|
l.Debugf("Failed to acquire %s mapping on %s", mapping, id)
|
||||||
continue
|
continue
|
||||||
@ -291,7 +292,7 @@ func (s *Service) acquireNewMappings(mapping *Mapping, nats map[string]Device, s
|
|||||||
|
|
||||||
// tryNATDevice tries to acquire a port mapping for the given internal address to
|
// tryNATDevice tries to acquire a port mapping for the given internal address to
|
||||||
// the given external port. If external port is 0, picks a pseudo-random port.
|
// the given external port. If external port is 0, picks a pseudo-random port.
|
||||||
func (s *Service) tryNATDevice(natd Device, intPort, extPort int, leaseTime time.Duration, stop chan struct{}) (Address, error) {
|
func (s *Service) tryNATDevice(ctx context.Context, natd Device, intPort, extPort int, leaseTime time.Duration) (Address, error) {
|
||||||
var err error
|
var err error
|
||||||
var port int
|
var port int
|
||||||
|
|
||||||
@ -313,7 +314,7 @@ func (s *Service) tryNATDevice(natd Device, intPort, extPort int, leaseTime time
|
|||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return Address{}, nil
|
return Address{}, nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@ -343,6 +344,10 @@ findIP:
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) String() string {
|
||||||
|
return fmt.Sprintf("nat.Service@%p", s)
|
||||||
|
}
|
||||||
|
|
||||||
func hash(input string) int64 {
|
func hash(input string) int64 {
|
||||||
h := fnv.New64a()
|
h := fnv.New64a()
|
||||||
h.Write([]byte(input))
|
h.Write([]byte(input))
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -51,16 +52,16 @@ type commonClient struct {
|
|||||||
mut sync.RWMutex
|
mut sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCommonClient(invitations chan protocol.SessionInvitation, serve func(chan struct{}) error) commonClient {
|
func newCommonClient(invitations chan protocol.SessionInvitation, serve func(context.Context) error, creator string) commonClient {
|
||||||
c := commonClient{
|
c := commonClient{
|
||||||
invitations: invitations,
|
invitations: invitations,
|
||||||
mut: sync.NewRWMutex(),
|
mut: sync.NewRWMutex(),
|
||||||
}
|
}
|
||||||
newServe := func(stop chan struct{}) error {
|
newServe := func(ctx context.Context) error {
|
||||||
defer c.cleanup()
|
defer c.cleanup()
|
||||||
return serve(stop)
|
return serve(ctx)
|
||||||
}
|
}
|
||||||
c.ServiceWithError = util.AsServiceWithError(newServe)
|
c.ServiceWithError = util.AsServiceWithError(newServe, creator)
|
||||||
if c.invitations == nil {
|
if c.invitations == nil {
|
||||||
c.closeInvitationsOnFinish = true
|
c.closeInvitationsOnFinish = true
|
||||||
c.invitations = make(chan protocol.SessionInvitation)
|
c.invitations = make(chan protocol.SessionInvitation)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -32,11 +33,11 @@ func newDynamicClient(uri *url.URL, certs []tls.Certificate, invitations chan pr
|
|||||||
certs: certs,
|
certs: certs,
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
}
|
}
|
||||||
c.commonClient = newCommonClient(invitations, c.serve)
|
c.commonClient = newCommonClient(invitations, c.serve, c.String())
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicClient) serve(stop chan struct{}) error {
|
func (c *dynamicClient) serve(ctx context.Context) error {
|
||||||
uri := *c.pooladdr
|
uri := *c.pooladdr
|
||||||
|
|
||||||
// Trim off the `dynamic+` prefix
|
// Trim off the `dynamic+` prefix
|
||||||
@ -69,9 +70,9 @@ func (c *dynamicClient) serve(stop chan struct{}) error {
|
|||||||
addrs = append(addrs, ruri.String())
|
addrs = append(addrs, ruri.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range relayAddressesOrder(addrs, stop) {
|
for _, addr := range relayAddressesOrder(ctx, addrs) {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
l.Debugln(c, "stopping")
|
l.Debugln(c, "stopping")
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
@ -148,7 +149,7 @@ type dynamicAnnouncement struct {
|
|||||||
// the closest 50ms, and puts them in buckets of 50ms latency ranges. Then
|
// the closest 50ms, and puts them in buckets of 50ms latency ranges. Then
|
||||||
// shuffles each bucket, and returns all addresses starting with the ones from
|
// shuffles each bucket, and returns all addresses starting with the ones from
|
||||||
// the lowest latency bucket, ending with the highest latency buceket.
|
// the lowest latency bucket, ending with the highest latency buceket.
|
||||||
func relayAddressesOrder(input []string, stop chan struct{}) []string {
|
func relayAddressesOrder(ctx context.Context, input []string) []string {
|
||||||
buckets := make(map[int][]string)
|
buckets := make(map[int][]string)
|
||||||
|
|
||||||
for _, relay := range input {
|
for _, relay := range input {
|
||||||
@ -162,7 +163,7 @@ func relayAddressesOrder(input []string, stop chan struct{}) []string {
|
|||||||
buckets[id] = append(buckets[id], relay)
|
buckets[id] = append(buckets[id], relay)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@ -39,11 +40,11 @@ func newStaticClient(uri *url.URL, certs []tls.Certificate, invitations chan pro
|
|||||||
messageTimeout: time.Minute * 2,
|
messageTimeout: time.Minute * 2,
|
||||||
connectTimeout: timeout,
|
connectTimeout: timeout,
|
||||||
}
|
}
|
||||||
c.commonClient = newCommonClient(invitations, c.serve)
|
c.commonClient = newCommonClient(invitations, c.serve, c.String())
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *staticClient) serve(stop chan struct{}) error {
|
func (c *staticClient) serve(ctx context.Context) error {
|
||||||
if err := c.connect(); err != nil {
|
if err := c.connect(); err != nil {
|
||||||
l.Infof("Could not connect to relay %s: %s", c.uri, err)
|
l.Infof("Could not connect to relay %s: %s", c.uri, err)
|
||||||
return err
|
return err
|
||||||
@ -72,7 +73,7 @@ func (c *staticClient) serve(stop chan struct{}) error {
|
|||||||
messages := make(chan interface{})
|
messages := make(chan interface{})
|
||||||
errors := make(chan error, 1)
|
errors := make(chan error, 1)
|
||||||
|
|
||||||
go messageReader(c.conn, messages, errors, stop)
|
go messageReader(ctx, c.conn, messages, errors)
|
||||||
|
|
||||||
timeout := time.NewTimer(c.messageTimeout)
|
timeout := time.NewTimer(c.messageTimeout)
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ func (c *staticClient) serve(stop chan struct{}) error {
|
|||||||
return fmt.Errorf("protocol error: unexpected message %v", msg)
|
return fmt.Errorf("protocol error: unexpected message %v", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
l.Debugln(c, "stopping")
|
l.Debugln(c, "stopping")
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
@ -241,7 +242,7 @@ func performHandshakeAndValidation(conn *tls.Conn, uri *url.URL) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func messageReader(conn net.Conn, messages chan<- interface{}, errors chan<- error, stop chan struct{}) {
|
func messageReader(ctx context.Context, conn net.Conn, messages chan<- interface{}, errors chan<- error) {
|
||||||
for {
|
for {
|
||||||
msg, err := protocol.ReadMessage(conn)
|
msg, err := protocol.ReadMessage(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -250,7 +251,7 @@ func messageReader(conn net.Conn, messages chan<- interface{}, errors chan<- err
|
|||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case messages <- msg:
|
case messages <- msg:
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package stun
|
package stun
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -104,7 +105,7 @@ func New(cfg config.Wrapper, subscriber Subscriber, conn net.PacketConn) (*Servi
|
|||||||
natType: NATUnknown,
|
natType: NATUnknown,
|
||||||
addr: nil,
|
addr: nil,
|
||||||
}
|
}
|
||||||
s.Service = util.AsService(s.serve)
|
s.Service = util.AsService(s.serve, s.String())
|
||||||
return s, otherDataConn
|
return s, otherDataConn
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +114,7 @@ func (s *Service) Stop() {
|
|||||||
s.Service.Stop()
|
s.Service.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) serve(stop chan struct{}) {
|
func (s *Service) serve(ctx context.Context) {
|
||||||
for {
|
for {
|
||||||
disabled:
|
disabled:
|
||||||
s.setNATType(NATUnknown)
|
s.setNATType(NATUnknown)
|
||||||
@ -121,7 +122,7 @@ func (s *Service) serve(stop chan struct{}) {
|
|||||||
|
|
||||||
if s.cfg.Options().IsStunDisabled() {
|
if s.cfg.Options().IsStunDisabled() {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
continue
|
continue
|
||||||
@ -134,12 +135,12 @@ func (s *Service) serve(stop chan struct{}) {
|
|||||||
// This blocks until we hit an exit condition or there are issues with the STUN server.
|
// This blocks until we hit an exit condition or there are issues with the STUN server.
|
||||||
// This returns a boolean signifying if a different STUN server should be tried (oppose to the whole thing
|
// This returns a boolean signifying if a different STUN server should be tried (oppose to the whole thing
|
||||||
// shutting down and this winding itself down.
|
// shutting down and this winding itself down.
|
||||||
if !s.runStunForServer(addr, stop) {
|
if !s.runStunForServer(ctx, addr) {
|
||||||
// Check exit conditions.
|
// Check exit conditions.
|
||||||
|
|
||||||
// Have we been asked to stop?
|
// Have we been asked to stop?
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@ -165,13 +166,13 @@ func (s *Service) serve(stop chan struct{}) {
|
|||||||
// Chillout for a while.
|
// Chillout for a while.
|
||||||
select {
|
select {
|
||||||
case <-time.After(stunRetryInterval):
|
case <-time.After(stunRetryInterval):
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) runStunForServer(addr string, stop chan struct{}) (tryNext bool) {
|
func (s *Service) runStunForServer(ctx context.Context, addr string) (tryNext bool) {
|
||||||
l.Debugf("Running stun for %s via %s", s, addr)
|
l.Debugf("Running stun for %s via %s", s, addr)
|
||||||
|
|
||||||
// Resolve the address, so that in case the server advertises two
|
// Resolve the address, so that in case the server advertises two
|
||||||
@ -209,10 +210,10 @@ func (s *Service) runStunForServer(addr string, stop chan struct{}) (tryNext boo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.stunKeepAlive(addr, extAddr, stop)
|
return s.stunKeepAlive(ctx, addr, extAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) stunKeepAlive(addr string, extAddr *Host, stop chan struct{}) (tryNext bool) {
|
func (s *Service) stunKeepAlive(ctx context.Context, addr string, extAddr *Host) (tryNext bool) {
|
||||||
var err error
|
var err error
|
||||||
nextSleep := time.Duration(s.cfg.Options().StunKeepaliveStartS) * time.Second
|
nextSleep := time.Duration(s.cfg.Options().StunKeepaliveStartS) * time.Second
|
||||||
|
|
||||||
@ -255,7 +256,7 @@ func (s *Service) stunKeepAlive(addr string, extAddr *Host, stop chan struct{})
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(sleepFor):
|
case <-time.After(sleepFor):
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
l.Debugf("%s stopping, aborting stun", s)
|
l.Debugf("%s stopping, aborting stun", s)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
package syncthing
|
package syncthing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/thejerf/suture"
|
"github.com/thejerf/suture"
|
||||||
@ -29,19 +31,19 @@ func newAuditService(w io.Writer, evLogger events.Logger) *auditService {
|
|||||||
w: w,
|
w: w,
|
||||||
sub: evLogger.Subscribe(events.AllEvents),
|
sub: evLogger.Subscribe(events.AllEvents),
|
||||||
}
|
}
|
||||||
s.Service = util.AsService(s.serve)
|
s.Service = util.AsService(s.serve, s.String())
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// serve runs the audit service.
|
// serve runs the audit service.
|
||||||
func (s *auditService) serve(stop chan struct{}) {
|
func (s *auditService) serve(ctx context.Context) {
|
||||||
enc := json.NewEncoder(s.w)
|
enc := json.NewEncoder(s.w)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case ev := <-s.sub.C():
|
case ev := <-s.sub.C():
|
||||||
enc.Encode(ev)
|
enc.Encode(ev)
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,3 +54,7 @@ func (s *auditService) Stop() {
|
|||||||
s.Service.Stop()
|
s.Service.Stop()
|
||||||
s.sub.Unsubscribe()
|
s.sub.Unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *auditService) String() string {
|
||||||
|
return fmt.Sprintf("auditService@%p", s)
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package syncthing
|
package syncthing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/thejerf/suture"
|
"github.com/thejerf/suture"
|
||||||
@ -26,12 +27,12 @@ func newVerboseService(evLogger events.Logger) *verboseService {
|
|||||||
s := &verboseService{
|
s := &verboseService{
|
||||||
sub: evLogger.Subscribe(events.AllEvents),
|
sub: evLogger.Subscribe(events.AllEvents),
|
||||||
}
|
}
|
||||||
s.Service = util.AsService(s.serve)
|
s.Service = util.AsService(s.serve, s.String())
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// serve runs the verbose logging service.
|
// serve runs the verbose logging service.
|
||||||
func (s *verboseService) serve(stop chan struct{}) {
|
func (s *verboseService) serve(ctx context.Context) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case ev := <-s.sub.C():
|
case ev := <-s.sub.C():
|
||||||
@ -39,7 +40,7 @@ func (s *verboseService) serve(stop chan struct{}) {
|
|||||||
if formatted != "" {
|
if formatted != "" {
|
||||||
l.Verboseln(formatted)
|
l.Verboseln(formatted)
|
||||||
}
|
}
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,3 +188,7 @@ func (s *verboseService) formatEvent(ev events.Event) string {
|
|||||||
|
|
||||||
return fmt.Sprintf("%s %#v", ev.Type, ev)
|
return fmt.Sprintf("%s %#v", ev.Type, ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *verboseService) String() string {
|
||||||
|
return fmt.Sprintf("verboseService@%p", s)
|
||||||
|
}
|
||||||
|
@ -57,7 +57,7 @@ func New(cfg config.Wrapper, m model.Model, connectionsService connections.Servi
|
|||||||
noUpgrade: noUpgrade,
|
noUpgrade: noUpgrade,
|
||||||
forceRun: make(chan struct{}, 1), // Buffered to prevent locking
|
forceRun: make(chan struct{}, 1), // Buffered to prevent locking
|
||||||
}
|
}
|
||||||
svc.Service = util.AsService(svc.serve)
|
svc.Service = util.AsService(svc.serve, svc.String())
|
||||||
cfg.Subscribe(svc)
|
cfg.Subscribe(svc)
|
||||||
return svc
|
return svc
|
||||||
}
|
}
|
||||||
@ -384,11 +384,11 @@ func (s *Service) sendUsageReport() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) serve(stop chan struct{}) {
|
func (s *Service) serve(ctx context.Context) {
|
||||||
t := time.NewTimer(time.Duration(s.cfg.Options().URInitialDelayS) * time.Second)
|
t := time.NewTimer(time.Duration(s.cfg.Options().URInitialDelayS) * time.Second)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case <-s.forceRun:
|
case <-s.forceRun:
|
||||||
t.Reset(0)
|
t.Reset(0)
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -178,11 +178,11 @@ func Address(network, host string) string {
|
|||||||
|
|
||||||
// AsService wraps the given function to implement suture.Service by calling
|
// AsService wraps the given function to implement suture.Service by calling
|
||||||
// that function on serve and closing the passed channel when Stop is called.
|
// that function on serve and closing the passed channel when Stop is called.
|
||||||
func AsService(fn func(stop chan struct{})) suture.Service {
|
func AsService(fn func(ctx context.Context), creator string) suture.Service {
|
||||||
return asServiceWithError(func(stop chan struct{}) error {
|
return asServiceWithError(func(ctx context.Context) error {
|
||||||
fn(stop)
|
fn(ctx)
|
||||||
return nil
|
return nil
|
||||||
})
|
}, creator)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceWithError interface {
|
type ServiceWithError interface {
|
||||||
@ -194,25 +194,18 @@ type ServiceWithError interface {
|
|||||||
|
|
||||||
// AsServiceWithError does the same as AsService, except that it keeps track
|
// AsServiceWithError does the same as AsService, except that it keeps track
|
||||||
// of an error returned by the given function.
|
// of an error returned by the given function.
|
||||||
func AsServiceWithError(fn func(stop chan struct{}) error) ServiceWithError {
|
func AsServiceWithError(fn func(ctx context.Context) error, creator string) ServiceWithError {
|
||||||
return asServiceWithError(fn)
|
return asServiceWithError(fn, creator)
|
||||||
}
|
}
|
||||||
|
|
||||||
// caller retrieves information about the creator of the service, i.e. the stack
|
func asServiceWithError(fn func(ctx context.Context) error, creator string) ServiceWithError {
|
||||||
// two levels up from itself.
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
func caller() string {
|
|
||||||
pc := make([]uintptr, 1)
|
|
||||||
_ = runtime.Callers(4, pc)
|
|
||||||
f, _ := runtime.CallersFrames(pc).Next()
|
|
||||||
return f.Function
|
|
||||||
}
|
|
||||||
|
|
||||||
func asServiceWithError(fn func(stop chan struct{}) error) ServiceWithError {
|
|
||||||
s := &service{
|
s := &service{
|
||||||
caller: caller(),
|
|
||||||
serve: fn,
|
serve: fn,
|
||||||
stop: make(chan struct{}),
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
stopped: make(chan struct{}),
|
stopped: make(chan struct{}),
|
||||||
|
creator: creator,
|
||||||
mut: sync.NewMutex(),
|
mut: sync.NewMutex(),
|
||||||
}
|
}
|
||||||
close(s.stopped) // not yet started, don't block on Stop()
|
close(s.stopped) // not yet started, don't block on Stop()
|
||||||
@ -220,9 +213,10 @@ func asServiceWithError(fn func(stop chan struct{}) error) ServiceWithError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
caller string
|
creator string
|
||||||
serve func(stop chan struct{}) error
|
serve func(ctx context.Context) error
|
||||||
stop chan struct{}
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
stopped chan struct{}
|
stopped chan struct{}
|
||||||
err error
|
err error
|
||||||
mut sync.Mutex
|
mut sync.Mutex
|
||||||
@ -231,7 +225,7 @@ type service struct {
|
|||||||
func (s *service) Serve() {
|
func (s *service) Serve() {
|
||||||
s.mut.Lock()
|
s.mut.Lock()
|
||||||
select {
|
select {
|
||||||
case <-s.stop:
|
case <-s.ctx.Done():
|
||||||
s.mut.Unlock()
|
s.mut.Unlock()
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
@ -247,16 +241,16 @@ func (s *service) Serve() {
|
|||||||
close(s.stopped)
|
close(s.stopped)
|
||||||
s.mut.Unlock()
|
s.mut.Unlock()
|
||||||
}()
|
}()
|
||||||
err = s.serve(s.stop)
|
err = s.serve(s.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Stop() {
|
func (s *service) Stop() {
|
||||||
s.mut.Lock()
|
s.mut.Lock()
|
||||||
select {
|
select {
|
||||||
case <-s.stop:
|
case <-s.ctx.Done():
|
||||||
panic(fmt.Sprintf("Stop called more than once on %v", s))
|
panic(fmt.Sprintf("Stop called more than once on %v", s))
|
||||||
default:
|
default:
|
||||||
close(s.stop)
|
s.cancel()
|
||||||
}
|
}
|
||||||
s.mut.Unlock()
|
s.mut.Unlock()
|
||||||
<-s.stopped
|
<-s.stopped
|
||||||
@ -275,5 +269,5 @@ func (s *service) SetError(err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) String() string {
|
func (s *service) String() string {
|
||||||
return fmt.Sprintf("Service@%p created by %v", s, s.caller)
|
return fmt.Sprintf("Service@%p created by %v", s, s.creator)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -227,17 +228,17 @@ func TestCopyMatching(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUtilStopTwicePanic(t *testing.T) {
|
func TestUtilStopTwicePanic(t *testing.T) {
|
||||||
s := AsService(func(stop chan struct{}) {
|
name := "foo"
|
||||||
<-stop
|
s := AsService(func(ctx context.Context) {
|
||||||
})
|
<-ctx.Done()
|
||||||
|
}, name)
|
||||||
|
|
||||||
go s.Serve()
|
go s.Serve()
|
||||||
s.Stop()
|
s.Stop()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
expected := "lib/util.TestUtilStopTwicePanic"
|
if r := recover(); r == nil || !strings.Contains(r.(string), name) {
|
||||||
if r := recover(); r == nil || !strings.Contains(r.(string), expected) {
|
t.Fatalf(`expected panic containing "%v", got "%v"`, name, r)
|
||||||
t.Fatalf(`expected panic containing "%v", got "%v"`, expected, r)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
s.Stop()
|
s.Stop()
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
package versioner
|
package versioner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
@ -65,13 +67,13 @@ func NewStaggered(folderID string, folderFs fs.Filesystem, params map[string]str
|
|||||||
},
|
},
|
||||||
mutex: sync.NewMutex(),
|
mutex: sync.NewMutex(),
|
||||||
}
|
}
|
||||||
s.Service = util.AsService(s.serve)
|
s.Service = util.AsService(s.serve, s.String())
|
||||||
|
|
||||||
l.Debugf("instantiated %#v", s)
|
l.Debugf("instantiated %#v", s)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Staggered) serve(stop chan struct{}) {
|
func (v *Staggered) serve(ctx context.Context) {
|
||||||
v.clean()
|
v.clean()
|
||||||
if v.testCleanDone != nil {
|
if v.testCleanDone != nil {
|
||||||
close(v.testCleanDone)
|
close(v.testCleanDone)
|
||||||
@ -83,7 +85,7 @@ func (v *Staggered) serve(stop chan struct{}) {
|
|||||||
select {
|
select {
|
||||||
case <-tck.C:
|
case <-tck.C:
|
||||||
v.clean()
|
v.clean()
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,3 +232,7 @@ func (v *Staggered) GetVersions() (map[string][]FileVersion, error) {
|
|||||||
func (v *Staggered) Restore(filepath string, versionTime time.Time) error {
|
func (v *Staggered) Restore(filepath string, versionTime time.Time) error {
|
||||||
return restoreFile(v.versionsFs, v.folderFs, filepath, versionTime, TagFilename)
|
return restoreFile(v.versionsFs, v.folderFs, filepath, versionTime, TagFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Staggered) String() string {
|
||||||
|
return fmt.Sprintf("Staggered/@%p", v)
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package versioner
|
package versioner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
@ -38,7 +39,7 @@ func NewTrashcan(folderID string, folderFs fs.Filesystem, params map[string]stri
|
|||||||
versionsFs: fsFromParams(folderFs, params),
|
versionsFs: fsFromParams(folderFs, params),
|
||||||
cleanoutDays: cleanoutDays,
|
cleanoutDays: cleanoutDays,
|
||||||
}
|
}
|
||||||
s.Service = util.AsService(s.serve)
|
s.Service = util.AsService(s.serve, s.String())
|
||||||
|
|
||||||
l.Debugf("instantiated %#v", s)
|
l.Debugf("instantiated %#v", s)
|
||||||
return s
|
return s
|
||||||
@ -52,7 +53,7 @@ func (t *Trashcan) Archive(filePath string) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Trashcan) serve(stop chan struct{}) {
|
func (t *Trashcan) serve(ctx context.Context) {
|
||||||
l.Debugln(t, "starting")
|
l.Debugln(t, "starting")
|
||||||
defer l.Debugln(t, "stopping")
|
defer l.Debugln(t, "stopping")
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ func (t *Trashcan) serve(stop chan struct{}) {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
|
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
|
@ -109,7 +109,7 @@ type aggregator struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAggregator(folderCfg config.FolderConfiguration, ctx context.Context) *aggregator {
|
func newAggregator(ctx context.Context, folderCfg config.FolderConfiguration) *aggregator {
|
||||||
a := &aggregator{
|
a := &aggregator{
|
||||||
folderID: folderCfg.ID,
|
folderID: folderCfg.ID,
|
||||||
folderCfgUpdate: make(chan config.FolderConfiguration),
|
folderCfgUpdate: make(chan config.FolderConfiguration),
|
||||||
@ -125,8 +125,8 @@ func newAggregator(folderCfg config.FolderConfiguration, ctx context.Context) *a
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func Aggregate(in <-chan fs.Event, out chan<- []string, folderCfg config.FolderConfiguration, cfg config.Wrapper, evLogger events.Logger, ctx context.Context) {
|
func Aggregate(ctx context.Context, in <-chan fs.Event, out chan<- []string, folderCfg config.FolderConfiguration, cfg config.Wrapper, evLogger events.Logger) {
|
||||||
a := newAggregator(folderCfg, ctx)
|
a := newAggregator(ctx, folderCfg)
|
||||||
|
|
||||||
// Necessary for unit tests where the backend is mocked
|
// Necessary for unit tests where the backend is mocked
|
||||||
go a.mainLoop(in, out, cfg, evLogger)
|
go a.mainLoop(in, out, cfg, evLogger)
|
||||||
|
@ -67,7 +67,7 @@ func TestAggregate(t *testing.T) {
|
|||||||
folderCfg.ID = "Aggregate"
|
folderCfg.ID = "Aggregate"
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
a := newAggregator(folderCfg, ctx)
|
a := newAggregator(ctx, folderCfg)
|
||||||
|
|
||||||
// checks whether maxFilesPerDir events in one dir are kept as is
|
// checks whether maxFilesPerDir events in one dir are kept as is
|
||||||
for i := 0; i < maxFilesPerDir; i++ {
|
for i := 0; i < maxFilesPerDir; i++ {
|
||||||
@ -95,7 +95,7 @@ func TestAggregate(t *testing.T) {
|
|||||||
compareBatchToExpectedDirect(t, getEventPaths(a.root, ".", a), []string{"parent"})
|
compareBatchToExpectedDirect(t, getEventPaths(a.root, ".", a), []string{"parent"})
|
||||||
|
|
||||||
// again test aggregation in "parent" but with event in subdirs
|
// again test aggregation in "parent" but with event in subdirs
|
||||||
a = newAggregator(folderCfg, ctx)
|
a = newAggregator(ctx, folderCfg)
|
||||||
for i := 0; i < maxFilesPerDir; i++ {
|
for i := 0; i < maxFilesPerDir; i++ {
|
||||||
a.newEvent(fs.Event{
|
a.newEvent(fs.Event{
|
||||||
Name: filepath.Join("parent", strconv.Itoa(i)),
|
Name: filepath.Join("parent", strconv.Itoa(i)),
|
||||||
@ -109,7 +109,7 @@ func TestAggregate(t *testing.T) {
|
|||||||
compareBatchToExpectedDirect(t, getEventPaths(a.root, ".", a), []string{"parent"})
|
compareBatchToExpectedDirect(t, getEventPaths(a.root, ".", a), []string{"parent"})
|
||||||
|
|
||||||
// test aggregation in root
|
// test aggregation in root
|
||||||
a = newAggregator(folderCfg, ctx)
|
a = newAggregator(ctx, folderCfg)
|
||||||
for i := 0; i < maxFiles; i++ {
|
for i := 0; i < maxFiles; i++ {
|
||||||
a.newEvent(fs.Event{
|
a.newEvent(fs.Event{
|
||||||
Name: strconv.Itoa(i),
|
Name: strconv.Itoa(i),
|
||||||
@ -132,7 +132,7 @@ func TestAggregate(t *testing.T) {
|
|||||||
}, inProgress)
|
}, inProgress)
|
||||||
compareBatchToExpectedDirect(t, getEventPaths(a.root, ".", a), []string{"."})
|
compareBatchToExpectedDirect(t, getEventPaths(a.root, ".", a), []string{"."})
|
||||||
|
|
||||||
a = newAggregator(folderCfg, ctx)
|
a = newAggregator(ctx, folderCfg)
|
||||||
filesPerDir := maxFilesPerDir / 2
|
filesPerDir := maxFilesPerDir / 2
|
||||||
dirs := make([]string, maxFiles/filesPerDir+1)
|
dirs := make([]string, maxFiles/filesPerDir+1)
|
||||||
for i := 0; i < maxFiles/filesPerDir+1; i++ {
|
for i := 0; i < maxFiles/filesPerDir+1; i++ {
|
||||||
@ -293,7 +293,7 @@ func testScenario(t *testing.T, name string, testCase func(c chan<- fs.Event), e
|
|||||||
|
|
||||||
folderCfg := defaultFolderCfg.Copy()
|
folderCfg := defaultFolderCfg.Copy()
|
||||||
folderCfg.ID = name
|
folderCfg.ID = name
|
||||||
a := newAggregator(folderCfg, ctx)
|
a := newAggregator(ctx, folderCfg)
|
||||||
a.notifyTimeout = testNotifyTimeout
|
a.notifyTimeout = testNotifyTimeout
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
Loading…
Reference in New Issue
Block a user