@@ -32,12 +32,12 @@ import (
32
32
)
33
33
34
34
const (
35
- // updatePeriod is the period which condition manager checks update.
35
+ // updatePeriod is the period at which condition manager checks update.
36
36
updatePeriod = 1 * time .Second
37
- // updateTimeout is the timeout of condition update operation .
38
- updateTimeout = 10 * time .Second
39
- // resyncPeriod is the period which condition manager does resync no matter whether these is any update .
40
- resyncPeriod = 30 * time .Second
37
+ // resyncPeriod is the period at which condition manager does resync, only updates when needed .
38
+ resyncPeriod = 10 * time .Second
39
+ // heartbeatPeriod is the period at which condition manager does forcibly sync with apiserver .
40
+ heartbeatPeriod = 1 * time .Minute
41
41
)
42
42
43
43
// ConditionManager synchronizes node conditions with the apiserver with problem client.
@@ -52,17 +52,21 @@ const (
52
52
type ConditionManager interface {
53
53
// Start starts the condition manager.
54
54
Start ()
55
- // UpdateCondition update specific condition.
55
+ // UpdateCondition updates a specific condition.
56
56
UpdateCondition (types.Condition )
57
57
}
58
58
59
59
type conditionManager struct {
60
- sync.Mutex
61
- clock clock.Clock
62
- latest time.Time
63
- client problemclient.Client
64
- updates map [string ]types.Condition
65
- conditions map [string ]types.Condition
60
+ clock clock.Clock
61
+ latestTry time.Time
62
+ resyncNeeded bool
63
+ client problemclient.Client
64
+ // updatesLock is the lock protecting updates. Only the field `updates`
65
+ // will be accessed by random caller and the sync routine, so only it
66
+ // needs to be protected.
67
+ updatesLock sync.Mutex
68
+ updates map [string ]types.Condition
69
+ conditions map [string ]types.Condition
66
70
}
67
71
68
72
// NewConditionManager creates a condition manager.
@@ -80,8 +84,8 @@ func (c *conditionManager) Start() {
80
84
}
81
85
82
86
func (c * conditionManager ) UpdateCondition (condition types.Condition ) {
83
- c .Lock ()
84
- defer c .Unlock ()
87
+ c .updatesLock . Lock ()
88
+ defer c .updatesLock . Unlock ()
85
89
// New node condition will override the old condition, because we only need the newest
86
90
// condition for each condition type.
87
91
c .updates [condition .Type ] = condition
@@ -92,17 +96,17 @@ func (c *conditionManager) syncLoop() {
92
96
for {
93
97
select {
94
98
case <- updateCh :
95
- if c .checkUpdates () || c .checkResync () {
99
+ if c .needUpdates () || c .needResync () || c . needHeartbeat () {
96
100
c .sync ()
97
101
}
98
102
}
99
103
}
100
104
}
101
105
102
- // checkUpdates checks whether there are recent updates.
103
- func (c * conditionManager ) checkUpdates () bool {
104
- c .Lock ()
105
- defer c .Unlock ()
106
+ // needUpdates checks whether there are recent updates.
107
+ func (c * conditionManager ) needUpdates () bool {
108
+ c .updatesLock . Lock ()
109
+ defer c .updatesLock . Unlock ()
106
110
needUpdate := false
107
111
for t , update := range c .updates {
108
112
if ! reflect .DeepEqual (c .conditions [t ], update ) {
@@ -114,21 +118,29 @@ func (c *conditionManager) checkUpdates() bool {
114
118
return needUpdate
115
119
}
116
120
117
- // checkResync checks whether a resync is needed.
118
- func (c * conditionManager ) checkResync () bool {
119
- return c .clock .Now ().Sub (c .latest ) >= resyncPeriod
121
+ // needResync checks whether a resync is needed.
122
+ func (c * conditionManager ) needResync () bool {
123
+ // Only update when resync is needed.
124
+ return c .clock .Now ().Sub (c .latestTry ) >= resyncPeriod && c .resyncNeeded
125
+ }
126
+
127
+ // needHeartbeat checks whether a forcible heartbeat is needed.
128
+ func (c * conditionManager ) needHeartbeat () bool {
129
+ return c .clock .Now ().Sub (c .latestTry ) >= heartbeatPeriod
120
130
}
121
131
122
132
// sync synchronizes node conditions with the apiserver.
123
133
func (c * conditionManager ) sync () {
134
+ c .latestTry = c .clock .Now ()
135
+ c .resyncNeeded = false
124
136
conditions := []api.NodeCondition {}
125
137
for i := range c .conditions {
126
138
conditions = append (conditions , problemutil .ConvertToAPICondition (c .conditions [i ]))
127
139
}
128
140
if err := c .client .SetConditions (conditions ); err != nil {
129
141
// The conditions will be updated again in future sync
130
142
glog .Errorf ("failed to update node conditions: %v" , err )
143
+ c .resyncNeeded = true
131
144
return
132
145
}
133
- c .latest = c .clock .Now ()
134
146
}
0 commit comments