123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- // Copyright 2016 The go-ethereum Authors
- // This file is part of the go-ethereum library.
- //
- // The go-ethereum library is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // The go-ethereum library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public License
- // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
- // +build darwin,!ios freebsd linux,!arm64 netbsd solaris
- package keystore
- import (
- "time"
- "github.com/ethereum/go-ethereum/log"
- "github.com/rjeczalik/notify"
- )
- type watcher struct {
- ac *accountCache
- starting bool
- running bool
- ev chan notify.EventInfo
- quit chan struct{}
- }
- func newWatcher(ac *accountCache) *watcher {
- return &watcher{
- ac: ac,
- ev: make(chan notify.EventInfo, 10),
- quit: make(chan struct{}),
- }
- }
- // starts the watcher loop in the background.
- // Start a watcher in the background if that's not already in progress.
- // The caller must hold w.ac.mu.
- func (w *watcher) start() {
- if w.starting || w.running {
- return
- }
- w.starting = true
- go w.loop()
- }
- func (w *watcher) close() {
- close(w.quit)
- }
- func (w *watcher) loop() {
- defer func() {
- w.ac.mu.Lock()
- w.running = false
- w.starting = false
- w.ac.mu.Unlock()
- }()
- logger := log.New("path", w.ac.keydir)
- if err := notify.Watch(w.ac.keydir, w.ev, notify.All); err != nil {
- logger.Trace("Failed to watch keystore folder", "err", err)
- return
- }
- defer notify.Stop(w.ev)
- logger.Trace("Started watching keystore folder")
- defer logger.Trace("Stopped watching keystore folder")
- w.ac.mu.Lock()
- w.running = true
- w.ac.mu.Unlock()
- // Wait for file system events and reload.
- // When an event occurs, the reload call is delayed a bit so that
- // multiple events arriving quickly only cause a single reload.
- var (
- debounceDuration = 500 * time.Millisecond
- rescanTriggered = false
- debounce = time.NewTimer(0)
- )
- // Ignore initial trigger
- if !debounce.Stop() {
- <-debounce.C
- }
- defer debounce.Stop()
- for {
- select {
- case <-w.quit:
- return
- case <-w.ev:
- // Trigger the scan (with delay), if not already triggered
- if !rescanTriggered {
- debounce.Reset(debounceDuration)
- rescanTriggered = true
- }
- case <-debounce.C:
- w.ac.scanAccounts()
- rescanTriggered = false
- }
- }
- }
|