blob: bb5f6599fc8030cf3b392c47a94e1af6d8fd8995 [file] [log] [blame]
sslobodrd046be82019-01-16 10:02:22 -05001package probing
2
3import (
4 "sync"
5 "time"
6)
7
8var (
9 // weight factor
10 α = 0.125
11)
12
13type Status interface {
14 Total() int64
15 Loss() int64
16 Health() bool
17 Err() error
18 // Estimated smoothed round trip time
19 SRTT() time.Duration
20 // Estimated clock difference
21 ClockDiff() time.Duration
22 StopNotify() <-chan struct{}
23}
24
25type status struct {
26 mu sync.Mutex
27 srtt time.Duration
28 total int64
29 loss int64
30 health bool
31 err error
32 clockdiff time.Duration
33 stopC chan struct{}
34}
35
36// SRTT = (1-α) * SRTT + α * RTT
37func (s *status) SRTT() time.Duration {
38 s.mu.Lock()
39 defer s.mu.Unlock()
40 return s.srtt
41}
42
43func (s *status) Total() int64 {
44 s.mu.Lock()
45 defer s.mu.Unlock()
46 return s.total
47}
48
49func (s *status) Loss() int64 {
50 s.mu.Lock()
51 defer s.mu.Unlock()
52 return s.loss
53}
54
55func (s *status) Health() bool {
56 s.mu.Lock()
57 defer s.mu.Unlock()
58 return s.health
59}
60
61func (s *status) Err() error {
62 s.mu.Lock()
63 defer s.mu.Unlock()
64 return s.err
65}
66
67func (s *status) ClockDiff() time.Duration {
68 s.mu.Lock()
69 defer s.mu.Unlock()
70 return s.clockdiff
71}
72
73func (s *status) StopNotify() <-chan struct{} {
74 return s.stopC
75}
76
77func (s *status) record(rtt time.Duration, when time.Time) {
78 s.mu.Lock()
79 defer s.mu.Unlock()
80
81 s.total += 1
82 s.health = true
83 s.srtt = time.Duration((1-α)*float64(s.srtt) + α*float64(rtt))
84 s.clockdiff = time.Now().Sub(when) - s.srtt/2
85 s.err = nil
86}
87
88func (s *status) recordFailure(err error) {
89 s.mu.Lock()
90 defer s.mu.Unlock()
91
92 s.total++
93 s.health = false
94 s.loss += 1
95 s.err = err
96}
97
98func (s *status) reset() {
99 s.mu.Lock()
100 defer s.mu.Unlock()
101
102 s.srtt = 0
103 s.total = 0
104 s.loss = 0
105 s.health = false
106 s.clockdiff = 0
107 s.err = nil
108}