-
Notifications
You must be signed in to change notification settings - Fork 72
/
config.go
100 lines (83 loc) · 3.09 KB
/
config.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
/*
Copyright (c) Facebook, Inc. and its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package daemon
import (
"fmt"
"os"
"time"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
yaml "gopkg.in/yaml.v2"
)
// Config represents configuration we expect to read from file
type Config struct {
PTPClientAddress string // where should fbclock connect to
RingSize int // must be at least the size of N samples we use in expressions
Math Math // configuration for calculation we'll be doing
Interval time.Duration // how often do we poll ptp4l and update data in shm
Iface string // network interface to use
LinearizabilityTestInterval time.Duration // perform the linearizability test every so often
SPTP bool // denotes whether we are running in sptp or ptp4l mode
LinearizabilityTestMaxGMOffset time.Duration // max offset between GMs before linearizability test considered failed
BootDelay time.Duration // postpone startup by this time after boot
}
// EvalAndValidate makes sure config is valid and evaluates expressions for further use.
func (c *Config) EvalAndValidate() error {
if c.PTPClientAddress == "" {
return fmt.Errorf("bad config: 'ptpclientaddress'")
}
if c.RingSize <= 0 {
return fmt.Errorf("bad config: 'ringsize' must be >0")
}
if c.Interval <= 0 || c.Interval > time.Minute {
return fmt.Errorf("bad config: 'interval' must be between 0 and 1 minute")
}
if c.LinearizabilityTestInterval < 0 {
return fmt.Errorf("bad config: 'test interval' must be positive")
}
if c.LinearizabilityTestMaxGMOffset < 0 {
return fmt.Errorf("bad config: 'offset' must be positive")
}
return c.Math.Prepare()
}
// PostponeStart postpones startup by BootDelay
func (c *Config) PostponeStart() error {
uptime, err := uptime()
if err != nil {
return err
}
log.Debugf("system uptime: %s", uptime)
if uptime < c.BootDelay {
log.Infof("postponing startup by %s", c.BootDelay-uptime)
time.Sleep(c.BootDelay - uptime)
}
return nil
}
// uptime returns system boot time
func uptime() (time.Duration, error) {
var ts unix.Timespec
if err := unix.ClockGettime(unix.CLOCK_BOOTTIME, &ts); err != nil {
return 0, err
}
return time.Duration(ts.Nano()), nil
}
// ReadConfig reads config and unmarshals it from yaml into Config
func ReadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
c := Config{}
err = yaml.UnmarshalStrict(data, &c)
return &c, err
}