109 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |