5
5
"time"
6
6
7
7
"github.com/golang/glog"
8
- "github.com/google/btree"
9
8
10
9
apierrors "k8s.io/apimachinery/pkg/api/errors"
11
10
"k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -16,30 +15,27 @@ import (
16
15
oauthclient "github.com/openshift/origin/pkg/oauth/generated/internalclientset/typed/oauth/internalversion"
17
16
oauthclientlister "github.com/openshift/origin/pkg/oauth/generated/listers/oauth/internalversion"
18
17
"github.com/openshift/origin/pkg/user/apis/user"
18
+ "github.com/openshift/origin/pkg/util/rankedset"
19
19
)
20
20
21
21
var errTimedout = errors .New ("token timed out" )
22
22
23
+ // Implements rankedset.Item
23
24
type tokenData struct {
24
25
token * oauth.OAuthAccessToken
25
26
seen time.Time
26
27
}
27
28
28
- func (a * tokenData ) timeout () time.Time {
29
+ func (a tokenData ) timeout () time.Time {
29
30
return a .token .CreationTimestamp .Time .Add (time .Duration (a .token .TimeoutsIn ) * time .Second )
30
31
}
31
32
32
- type tokenDataRef struct {
33
- name string
34
- timeout time.Time
33
+ func (a tokenData ) Key () string {
34
+ return a .token .Name
35
35
}
36
36
37
- func (a * tokenDataRef ) Less (than btree.Item ) bool {
38
-
39
- if a .timeout .Equal (than .(* tokenDataRef ).timeout ) {
40
- return a .name < than .(* tokenDataRef ).name
41
- }
42
- return a .timeout .Before (than .(* tokenDataRef ).timeout )
37
+ func (a tokenData ) Rank () int64 {
38
+ return a .timeout ().Unix ()
43
39
}
44
40
45
41
func timeoutAsDuration (timeout int32 ) time.Duration {
@@ -50,8 +46,7 @@ type TimeoutValidator struct {
50
46
oauthClients oauthclientlister.OAuthClientLister
51
47
tokens oauthclient.OAuthAccessTokenInterface
52
48
tokenChannel chan tokenData
53
- data map [string ]tokenData
54
- tree * btree.BTree
49
+ data * rankedset.RankedSet
55
50
minValidTimeout int32
56
51
maxFlushTimeout int32
57
52
defaultTimeout time.Duration
@@ -61,12 +56,10 @@ type TimeoutValidator struct {
61
56
62
57
func NewTimeoutValidator (tokens oauthclient.OAuthAccessTokenInterface , oauthClients oauthclientlister.OAuthClientLister , defaultTimeout int32 , minValidTimeout int32 , maxFlushTimeout int32 ) * TimeoutValidator {
63
58
a := & TimeoutValidator {
64
- oauthClients : oauthClients ,
65
- tokens : tokens ,
66
- tokenChannel : make (chan tokenData ),
67
- data : make (map [string ]tokenData ),
68
- // FIXME: what is the right degree for the btree
69
- tree : btree .New (32 ),
59
+ oauthClients : oauthClients ,
60
+ tokens : tokens ,
61
+ tokenChannel : make (chan tokenData ),
62
+ data : rankedset .New (),
70
63
minValidTimeout : minValidTimeout ,
71
64
maxFlushTimeout : maxFlushTimeout ,
72
65
}
@@ -163,21 +156,6 @@ func (a *TimeoutValidator) updateTimeouts() {
163
156
}
164
157
}
165
158
166
- func (a * TimeoutValidator ) insert (td tokenData ) {
167
- // if there is a token we have to remove it first
168
- oldtd , exists := a .data [td .token .Name ]
169
- if exists {
170
- a .delete (oldtd , & tokenDataRef {oldtd .token .Name , oldtd .timeout ()})
171
- }
172
- a .data [td .token .Name ] = td
173
- a .tree .ReplaceOrInsert (& tokenDataRef {td .token .Name , td .timeout ()})
174
- }
175
-
176
- func (a * TimeoutValidator ) delete (td tokenData , tdr * tokenDataRef ) {
177
- a .tree .Delete (tdr )
178
- delete (a .data , td .token .Name )
179
- }
180
-
181
159
func (a * TimeoutValidator ) update (td tokenData ) error {
182
160
// Obtain the timeout interval for this client
183
161
delta := a .clientTimeout (td .token .ClientName )
@@ -207,37 +185,34 @@ func (a *TimeoutValidator) update(td tokenData) error {
207
185
}
208
186
209
187
func (a * TimeoutValidator ) flush (flushHorizon time.Time ) {
210
- flushedTokens := 0
211
- totalTokens := len (a .data )
212
- var retrylist []tokenData
213
-
214
188
glog .V (5 ).Infof ("Flushing tokens timing out before %s" , flushHorizon )
215
189
216
- for item := a .tree .Min (); item != nil ; item = a .tree .Min () {
217
- tdr := item .(* tokenDataRef )
218
- if tdr .timeout .After (flushHorizon ) {
219
- // out of items within the flush Horizon
220
- break
221
- }
222
- td := a .data [tdr .name ]
190
+ // grab all tokens that need to be update in this flush interval
191
+ // and remove them from the stored data, they either flush now or never
192
+ tokenList := a .data .LessThan (flushHorizon .Unix (), true )
193
+
194
+ var retryList []tokenData
195
+ flushedTokens := 0
196
+
197
+ for _ , item := range tokenList {
198
+ td := item .(tokenData )
223
199
err := a .update (td )
224
200
switch {
225
201
case err == nil :
226
202
flushedTokens ++
227
203
case apierrors .IsConflict (err ) || apierrors .IsServerTimeout (err ):
228
204
glog .V (5 ).Infof ("Token update deferred for token=%q, retriable error: %v" ,
229
205
td .token .Name , err )
230
- retrylist = append (retrylist , td )
206
+ retryList = append (retryList , td )
231
207
default :
232
208
glog .V (5 ).Infof ("Token timeout for user=%q client=%q scopes=%v was not updated: %v" ,
233
209
td .token .UserName , td .token .ClientName , td .token .Scopes , err )
234
210
}
235
- // In all cases we remove the token from the data set
236
- a .delete (td , tdr )
237
211
}
238
212
239
- // we try once more and if it still fails we stop trying here and defer to a future regular update
240
- for _ , td := range retrylist {
213
+ // we try once more and if it still fails we stop trying here and defer
214
+ // to a future regular update if the token is used again
215
+ for _ , td := range retryList {
241
216
err := a .update (td )
242
217
if err != nil {
243
218
glog .V (5 ).Infof ("Token timeout for user=%q client=%q scopes=%v was not updated: %v" ,
@@ -247,7 +222,8 @@ func (a *TimeoutValidator) flush(flushHorizon time.Time) {
247
222
}
248
223
}
249
224
250
- glog .V (5 ).Infof ("Flushed %d tokens out of %d in bucket" , flushedTokens , totalTokens )
225
+ glog .V (5 ).Infof ("Successfully flushed %d tokens out of %d" ,
226
+ flushedTokens , len (tokenList ))
251
227
}
252
228
253
229
func (a * TimeoutValidator ) Run (stopCh <- chan struct {}) {
@@ -284,7 +260,7 @@ func (a *TimeoutValidator) Run(stopCh <-chan struct{}) {
284
260
// if channel closes terminate
285
261
return
286
262
case td := <- a .tokenChannel :
287
- a .insert (td )
263
+ a .data . Insert (td )
288
264
// if this token is going to time out before the timer, fire
289
265
// immediately (safety margin is added to avoid racing too close)
290
266
tokenTimeout := td .timeout ()
0 commit comments