-
Notifications
You must be signed in to change notification settings - Fork 1
/
watchdog.go
125 lines (103 loc) · 3.37 KB
/
watchdog.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"fmt"
"time"
log "github.com/sirupsen/logrus"
)
// watchdogWorker holds information for every watchdog worker
type watchdogWorker struct {
dnsStream *dnsStream
exit chan bool
stopped bool
ticker *time.Ticker
}
// newWatchdog creates a watchdog worker struct
func newWatchdogWorker(d *dnsStream) *watchdogWorker {
return &watchdogWorker{
dnsStream: d,
exit: make(chan bool, 1),
ticker: time.NewTicker(time.Duration(d.interval) * time.Second),
stopped: true,
}
}
// watch starts a loop with a periodic check of the DNS request
// and it doesn't stop until it get a exit signal.
func (ww *watchdogWorker) watch() {
ww.stopped = false
dnsClient := newDNSClient()
log.Infof("Entering watchdog's worker(%s) internal loop", ww)
for {
select {
case <-ww.exit:
log.Infof("Got message in watchdog's worker(%s) exit channel, exiting watchdog's loop", ww)
return
case <-ww.ticker.C:
log.Debugf("Starting new watchdog's worker(%s) interval check", ww)
log.Debugf("Start query for domain:<%s> and DNS query type:<%s>", ww.dnsStream.request.domain, ww.dnsStream.request.queryType)
err := ww.dnsStream.query(dnsClient)
if err != nil {
log.Error(err)
}
log.Debugf("Finished query for domain:<%s> and DNS query type:<%s> with verification status:<%.f>", ww.dnsStream.request.domain, ww.dnsStream.request.queryType, ww.dnsStream.verificationStatus)
ww.dnsStream.updateStats()
log.Debugf("Finished watchdog's worker(%s) interval check", ww)
}
}
}
// stop sends a message to exit channel so worker can exit its internal loop
func (ww *watchdogWorker) stop() {
if ww.stopped {
log.Infof("Watchdog's worker(%s) already stopped", ww)
return
}
ww.exit <- true
ww.stopped = true
log.Debugf("Sent message to watchdog's worker(%s) exit channel", ww)
}
func (ww *watchdogWorker) String() string {
return fmt.Sprintf("Domain:<%s> - Query Type:<%s> - interval:<%d>", ww.dnsStream.request.domain, ww.dnsStream.request.queryType, ww.dnsStream.interval)
}
// watchdow is the struct that encapsulates information for the watchdog loop
// that makes the DNS queries.
type watchdog struct {
exit chan bool
workers []*watchdogWorker
}
// newWatchdog creates a watchdog struct.
func newWatchdog(requests []*dnsStream) *watchdog {
workers := []*watchdogWorker{}
for _, r := range requests {
w := newWatchdogWorker(r)
workers = append(workers, w)
}
return &watchdog{
exit: make(chan bool, 1),
workers: workers,
}
}
// watchdog starts all the workers that are needed in separate go routines
// and waits forever for an exit signal
func (w *watchdog) watch() {
for _, worker := range w.workers {
log.Info(w.workers)
go worker.watch()
}
log.Debug("Blocking on the watchdog's exit channel")
<-w.exit
log.Debug("Exiting watchdog watch function.")
}
// stop is responsible to send exit signal to all workers and
// exit its watch blocking function by sending another exit signal
// in it's exit channel.
func (w *watchdog) stop() {
log.Debug("Sending message to main watchdog's exit channel")
w.exit <- true
log.Info("Sending message to all watchdog's workers exit channels")
for _, worker := range w.workers {
worker.stop()
}
log.Debug("Waiting couple of seconds for all watchdog workers to exit")
// Wait couple of seconds workers to finish
time.Sleep(2 * time.Second)
log.Debug("Exiting watchdog stop now.")
}