-
Notifications
You must be signed in to change notification settings - Fork 191
/
status_file.go
154 lines (131 loc) · 2.8 KB
/
status_file.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package health
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"path"
"strings"
"sync"
"time"
)
type StatusFile struct {
filename string
mu sync.RWMutex
m StatusFileData
}
type StatusFileData map[string]*Service
func NewStatusFile(filename string) *StatusFile {
return &StatusFile{
m: make(StatusFileData),
filename: filename,
}
}
// DirectoryReader loads (and regularly re-loads) health
// .json files from the specified files into the default
// health registry.
func DirectoryReader(dir string) {
for {
err := reloadDirectory(dir)
if err != nil {
log.Printf("loading health data: %s", err)
}
time.Sleep(1 * time.Second)
}
}
func reloadDirectory(dir string) error {
dirlist, err := ioutil.ReadDir(dir)
if err != nil {
return fmt.Errorf("could not read '%s': %s", dir, err)
}
seen := map[string]bool{}
var parseErr error
for _, file := range dirlist {
fileName := file.Name()
if !strings.HasSuffix(strings.ToLower(fileName), ".json") ||
strings.HasPrefix(path.Base(fileName), ".") ||
file.IsDir() {
continue
}
statusName := fileName[0:strings.LastIndex(fileName, ".")]
registry.mu.Lock()
s, ok := registry.m[statusName]
registry.mu.Unlock()
seen[statusName] = true
if ok {
s.Reload()
} else {
s := NewStatusFile(path.Join(dir, fileName))
err := s.Reload()
if err != nil {
log.Printf("error loading '%s': %s", fileName, err)
parseErr = err
}
registry.Add(statusName, s)
}
}
registry.mu.Lock()
for n, _ := range registry.m {
if !seen[n] {
registry.m[n].Close()
delete(registry.m, n)
}
}
registry.mu.Unlock()
return parseErr
}
func (s *StatusFile) Reload() error {
if len(s.filename) > 0 {
return s.Load(s.filename)
}
return nil
}
// Load imports the data atomically into the status map. If there's
// a JSON error the old data is preserved.
func (s *StatusFile) Load(filename string) error {
n := StatusFileData{}
b, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
err = json.Unmarshal(b, &n)
if err != nil {
return err
}
s.mu.Lock()
s.m = n
s.mu.Unlock()
return nil
}
func (s *StatusFile) Close() error {
s.mu.Lock()
s.m = nil
s.mu.Unlock()
return nil
}
func (s *StatusFile) GetStatus(check string) StatusType {
s.mu.RLock()
defer s.mu.RUnlock()
if s.m == nil {
return StatusUnknown
}
st, ok := s.m[check]
if !ok {
log.Printf("Not found '%s'", check)
return StatusUnknown
}
return st.Status
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (srv *Service) UnmarshalJSON(b []byte) error {
var i int64
if err := json.Unmarshal(b, &i); err != nil {
return err
}
*srv = Service{Status: StatusType(i)}
return nil
}
// UnmarshalJSON implements the json.Marshaler interface.
// func (srv *Service) MarshalJSON() ([]byte, error) {
// return
// }