Skip to content

Commit

Permalink
all: upd golibs, imp fswatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
EugeneOne1 committed Feb 9, 2024
1 parent 7f83707 commit 3afbbcb
Show file tree
Hide file tree
Showing 17 changed files with 88 additions and 86 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.21.7

require (
github.com/AdguardTeam/dnsproxy v0.65.0
github.com/AdguardTeam/golibs v0.20.0
github.com/AdguardTeam/golibs v0.20.1
github.com/AdguardTeam/urlfilter v0.17.3
github.com/NYTimes/gziphandler v1.1.1
github.com/ameshkov/dnscrypt/v2 v2.2.7
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/AdguardTeam/dnsproxy v0.65.0 h1:mqJjVSkqoqPwThY3tTvnLHQ/AYBYrfWmK2ER91fu4FE=
github.com/AdguardTeam/dnsproxy v0.65.0/go.mod h1:AGYMLPk2zX+I3NIUYS12KUI296mkCyfoMF/luy2uqdk=
github.com/AdguardTeam/golibs v0.20.0 h1:A9FIdYq7wUKhFYy3z+YZ/Aw5oFUYgW+xgaVAJ0pnnPY=
github.com/AdguardTeam/golibs v0.20.0/go.mod h1:3WunclLLfrVAq7fYQRhd6f168FHOEMssnipVXCxDL/w=
github.com/AdguardTeam/golibs v0.20.1 h1:ol8qLjWGZhU9paMMwN+OLWVTUigGsXa29iVTyd62VKY=
github.com/AdguardTeam/golibs v0.20.1/go.mod h1:bgcMgRviCKyU6mkrX+RtT/OsKPFzyppelfRsksMG3KU=
github.com/AdguardTeam/urlfilter v0.17.3 h1:fg/ObbnO0Cv6aw0tW6N/ETDMhhNvmcUUOZ7HlmKC3rw=
github.com/AdguardTeam/urlfilter v0.17.3/go.mod h1:Jru7jFfeH2CoDf150uDs+rRYcZBzHHBz05r9REyDKyE=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
Expand Down
4 changes: 4 additions & 0 deletions internal/aghnet/hostscontainer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func TestNewHostsContainer(t *testing.T) {
}

hc, err := aghnet.NewHostsContainer(testFS, &aghtest.FSWatcher{
OnStart: func() (_ error) { panic("not implemented") },
OnEvents: onEvents,
OnAdd: onAdd,
OnClose: func() (err error) { return nil },
Expand All @@ -93,6 +94,7 @@ func TestNewHostsContainer(t *testing.T) {
t.Run("nil_fs", func(t *testing.T) {
require.Panics(t, func() {
_, _ = aghnet.NewHostsContainer(nil, &aghtest.FSWatcher{
OnStart: func() (_ error) { panic("not implemented") },
// Those shouldn't panic.
OnEvents: func() (e <-chan struct{}) { return nil },
OnAdd: func(name string) (err error) { return nil },
Expand All @@ -111,6 +113,7 @@ func TestNewHostsContainer(t *testing.T) {
const errOnAdd errors.Error = "error"

errWatcher := &aghtest.FSWatcher{
OnStart: func() (_ error) { panic("not implemented") },
OnEvents: func() (e <-chan struct{}) { panic("not implemented") },
OnAdd: func(name string) (err error) { return errOnAdd },
OnClose: func() (err error) { return nil },
Expand Down Expand Up @@ -155,6 +158,7 @@ func TestHostsContainer_refresh(t *testing.T) {
t.Cleanup(func() { close(eventsCh) })

w := &aghtest.FSWatcher{
OnStart: func() (_ error) { panic("not implemented") },
OnEvents: func() (e <-chan event) { return eventsCh },
OnAdd: func(name string) (err error) {
assert.Equal(t, "dir", name)
Expand Down
3 changes: 2 additions & 1 deletion internal/aghnet/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/osutil"
)

// DialContextFunc is the semantic alias for dialing functions, such as
Expand All @@ -32,7 +33,7 @@ var (
netInterfaceAddrs = net.InterfaceAddrs

// rootDirFS is the filesystem pointing to the root directory.
rootDirFS = aghos.RootDirFS()
rootDirFS = osutil.RootDirFS()
)

// ErrNoStaticIPInfo is returned by IfaceHasStaticIP when no information about
Expand Down
89 changes: 55 additions & 34 deletions internal/aghos/fswatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (

"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/osutil"
"github.com/AdguardTeam/golibs/stringutil"
"github.com/fsnotify/fsnotify"
)

Expand All @@ -19,30 +21,34 @@ type event = struct{}
//
// TODO(e.burkov, a.garipov): Move into another package like aghfs.
type FSWatcher interface {
// Start starts watching the added files.
Start() (err error)

io.Closer

// Events should return a read-only channel which notifies about events.
// Events returns the channel to notify about the file system events.
Events() (e <-chan event)

// Add should check if the file named name is accessible and starts tracking
// it.
// Add starts tracking the file. It returns an error if the file can't be
// tracked. It must not be called after Start.
Add(name string) (err error)
}

// osWatcher tracks the file system provided by the OS.
type osWatcher struct {
// w is the actual notifier that is handled by osWatcher.
w *fsnotify.Watcher
// watcher is the actual notifier that is handled by osWatcher.
watcher *fsnotify.Watcher

// events is the channel to notify.
events chan event

// files is the set of tracked files.
files *stringutil.Set
}

const (
// osWatcherPref is a prefix for logging and wrapping errors in osWathcer's
// methods.
osWatcherPref = "os watcher"
)
// osWatcherPref is a prefix for logging and wrapping errors in osWathcer's
// methods.
const osWatcherPref = "os watcher"

// NewOSWritesWatcher creates FSWatcher that tracks the real file system of the
// OS and notifies only about writing events.
Expand All @@ -55,48 +61,53 @@ func NewOSWritesWatcher() (w FSWatcher, err error) {
return nil, fmt.Errorf("creating watcher: %w", err)
}

fsw := &osWatcher{
w: watcher,
events: make(chan event, 1),
}
return &osWatcher{
watcher: watcher,
events: make(chan event, 1),
files: stringutil.NewSet(),
}, nil
}

go fsw.handleErrors()
go fsw.handleEvents()
// type check
var _ FSWatcher = (*osWatcher)(nil)

return fsw, nil
}
// Start implements the FSWatcher interface for *osWatcher.
func (w *osWatcher) Start() (err error) {
go w.handleErrors()
go w.handleEvents()

// handleErrors handles accompanying errors. It used to be called in a separate
// goroutine.
func (w *osWatcher) handleErrors() {
defer log.OnPanic(fmt.Sprintf("%s: handling errors", osWatcherPref))
return nil
}

for err := range w.w.Errors {
log.Error("%s: %s", osWatcherPref, err)
}
// Close implements the FSWatcher interface for *osWatcher.
func (w *osWatcher) Close() (err error) {
return w.watcher.Close()
}

// Events implements the FSWatcher interface for *osWatcher.
func (w *osWatcher) Events() (e <-chan event) {
return w.events
}

// Add implements the FSWatcher interface for *osWatcher.
// Add implements the [FSWatcher] interface for *osWatcher.
//
// TODO(e.burkov): Make it accept non-existing files to detect it's creating.
func (w *osWatcher) Add(name string) (err error) {
defer func() { err = errors.Annotate(err, "%s: %w", osWatcherPref) }()

if _, err = fs.Stat(RootDirFS(), name); err != nil {
fi, err := fs.Stat(osutil.RootDirFS(), name)
if err != nil {
return fmt.Errorf("checking file %q: %w", name, err)
}

return w.w.Add(filepath.Join("/", name))
}
name = filepath.Join("/", name)
w.files.Add(name)

// Close implements the FSWatcher interface for *osWatcher.
func (w *osWatcher) Close() (err error) {
return w.w.Close()
if !fi.IsDir() {
name = filepath.Dir(name)
}

return w.watcher.Add(name)
}

// handleEvents notifies about the received file system's event if needed. It
Expand All @@ -106,9 +117,9 @@ func (w *osWatcher) handleEvents() {

defer close(w.events)

ch := w.w.Events
ch := w.watcher.Events
for e := range ch {
if e.Op&fsnotify.Write == 0 {
if e.Op&fsnotify.Write == 0 || !w.files.Has(e.Name) {
continue
}

Expand All @@ -131,3 +142,13 @@ func (w *osWatcher) handleEvents() {
}
}
}

// handleErrors handles accompanying errors. It used to be called in a separate
// goroutine.
func (w *osWatcher) handleErrors() {
defer log.OnPanic(fmt.Sprintf("%s: handling errors", osWatcherPref))

for err := range w.watcher.Errors {
log.Error("%s: %s", osWatcherPref, err)
}
}
13 changes: 2 additions & 11 deletions internal/aghos/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"bufio"
"fmt"
"io"
"io/fs"
"os"
"os/exec"
"path"
Expand All @@ -18,7 +17,6 @@ import (

"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/mathutil"
)

// UnsupportedError is returned by functions and methods when a particular
Expand Down Expand Up @@ -63,7 +61,7 @@ func RunCommand(command string, arguments ...string) (code int, output []byte, e
cmd := exec.Command(command, arguments...)
out, err := cmd.Output()

out = out[:mathutil.Min(len(out), MaxCmdOutputSize)]
out = out[:min(len(out), MaxCmdOutputSize)]

if err != nil {
if eerr := new(exec.ExitError); errors.As(err, &eerr) {
Expand Down Expand Up @@ -142,7 +140,7 @@ func parsePSOutput(r io.Reader, cmdName string, ignore []int) (largest, instNum
}

instNum++
largest = mathutil.Max(largest, cur)
largest = max(largest, cur)
}
if err = s.Err(); err != nil {
return 0, 0, fmt.Errorf("scanning stdout: %w", err)
Expand All @@ -156,13 +154,6 @@ func IsOpenWrt() (ok bool) {
return isOpenWrt()
}

// RootDirFS returns the [fs.FS] rooted at the operating system's root. On
// Windows it returns the fs.FS rooted at the volume of the system directory
// (usually, C:).
func RootDirFS() (fsys fs.FS) {
return rootDirFS()
}

// NotifyReconfigureSignal notifies c on receiving reconfigure signals.
func NotifyReconfigureSignal(c chan<- os.Signal) {
notifyReconfigureSignal(c)
Expand Down
3 changes: 2 additions & 1 deletion internal/aghos/os_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"syscall"

"github.com/AdguardTeam/golibs/osutil"
"github.com/AdguardTeam/golibs/stringutil"
)

Expand Down Expand Up @@ -40,7 +41,7 @@ func isOpenWrt() (ok bool) {
}

return nil, !stringutil.ContainsFold(string(data), osNameData), nil
}).Walk(RootDirFS(), etcReleasePattern)
}).Walk(osutil.RootDirFS(), etcReleasePattern)

return err == nil && ok
}
5 changes: 0 additions & 5 deletions internal/aghos/os_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,12 @@
package aghos

import (
"io/fs"
"os"
"os/signal"

"golang.org/x/sys/unix"
)

func rootDirFS() (fsys fs.FS) {
return os.DirFS("/")
}

func notifyReconfigureSignal(c chan<- os.Signal) {
signal.Notify(c, unix.SIGHUP)
}
Expand Down
16 changes: 0 additions & 16 deletions internal/aghos/os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,13 @@
package aghos

import (
"io/fs"
"os"
"os/signal"
"path/filepath"
"syscall"

"github.com/AdguardTeam/golibs/log"
"golang.org/x/sys/windows"
)

func rootDirFS() (fsys fs.FS) {
// TODO(a.garipov): Use a better way if golang/go#44279 is ever resolved.
sysDir, err := windows.GetSystemDirectory()
if err != nil {
log.Error("aghos: getting root filesystem: %s; using C:", err)

// Assume that C: is the safe default.
return os.DirFS("C:")
}

return os.DirFS(filepath.VolumeName(sysDir))
}

func setRlimit(val uint64) (err error) {
return Unsupported("setrlimit")
}
Expand Down
18 changes: 12 additions & 6 deletions internal/aghtest/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,25 @@ import (

// FSWatcher is a fake [aghos.FSWatcher] implementation for tests.
type FSWatcher struct {
OnStart func() (err error)
OnClose func() (err error)
OnEvents func() (e <-chan struct{})
OnAdd func(name string) (err error)
OnClose func() (err error)
}

// type check
var _ aghos.FSWatcher = (*FSWatcher)(nil)

// Start implements the [aghos.FSWatcher] interface for *FSWatcher.
func (w *FSWatcher) Start() (err error) {
return w.OnStart()
}

// Close implements the [aghos.FSWatcher] interface for *FSWatcher.
func (w *FSWatcher) Close() (err error) {
return w.OnClose()
}

// Events implements the [aghos.FSWatcher] interface for *FSWatcher.
func (w *FSWatcher) Events() (e <-chan struct{}) {
return w.OnEvents()
Expand All @@ -44,11 +55,6 @@ func (w *FSWatcher) Add(name string) (err error) {
return w.OnAdd(name)
}

// Close implements the [aghos.FSWatcher] interface for *FSWatcher.
func (w *FSWatcher) Close() (err error) {
return w.OnClose()
}

// Package agh

// ServiceWithConfig is a fake [agh.ServiceWithConfig] implementation for tests.
Expand Down
3 changes: 2 additions & 1 deletion internal/arpdb/arpdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/osutil"
)

// Variables and functions to substitute in tests.
Expand All @@ -22,7 +23,7 @@ var (
aghosRunCommand = aghos.RunCommand

// rootDirFS is the filesystem pointing to the root directory.
rootDirFS = aghos.RootDirFS()
rootDirFS = osutil.RootDirFS()
)

// Interface stores and refreshes the network neighborhood reported by ARP
Expand Down

0 comments on commit 3afbbcb

Please sign in to comment.