Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
940cc283
Commit
940cc283
authored
Aug 25, 2015
by
Clayton Coleman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Review comments
parent
8a62f182
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
163 additions
and
57 deletions
+163
-57
nodecontroller.go
pkg/controller/node/nodecontroller.go
+69
-39
nodecontroller_test.go
pkg/controller/node/nodecontroller_test.go
+1
-1
rate_limited_queue.go
pkg/controller/node/rate_limited_queue.go
+45
-15
rate_limited_queue_test.go
pkg/controller/node/rate_limited_queue_test.go
+48
-2
No files found.
pkg/controller/node/nodecontroller.go
View file @
940cc283
This diff is collapsed.
Click to expand it.
pkg/controller/node/nodecontroller_test.go
View file @
940cc283
...
@@ -347,7 +347,7 @@ func TestMonitorNodeStatusEvictPods(t *testing.T) {
...
@@ -347,7 +347,7 @@ func TestMonitorNodeStatusEvictPods(t *testing.T) {
return
true
,
0
return
true
,
0
})
})
nodeController
.
podEvictor
.
Try
(
func
(
value
TimedValue
)
(
bool
,
time
.
Duration
)
{
nodeController
.
podEvictor
.
Try
(
func
(
value
TimedValue
)
(
bool
,
time
.
Duration
)
{
nodeController
.
terminatePods
(
value
.
Value
,
value
.
Added
)
nodeController
.
terminatePods
(
value
.
Value
,
value
.
Added
At
)
return
true
,
0
return
true
,
0
})
})
podEvicted
:=
false
podEvicted
:=
false
...
...
pkg/controller/node/rate_limited_queue.go
View file @
940cc283
...
@@ -26,19 +26,19 @@ import (
...
@@ -26,19 +26,19 @@ import (
// TimedValue is a value that should be processed at a designated time.
// TimedValue is a value that should be processed at a designated time.
type
TimedValue
struct
{
type
TimedValue
struct
{
Value
string
Value
string
Added
time
.
Time
Added
At
time
.
Time
Next
time
.
Time
ProcessAt
time
.
Time
}
}
// now is used to test time
// now is used to test time
var
now
func
()
time
.
Time
=
time
.
Now
var
now
func
()
time
.
Time
=
time
.
Now
// TimedQueue is a priority heap where the lowest
Nex
t is at the front of the queue
// TimedQueue is a priority heap where the lowest
ProcessA
t is at the front of the queue
type
TimedQueue
[]
*
TimedValue
type
TimedQueue
[]
*
TimedValue
func
(
h
TimedQueue
)
Len
()
int
{
return
len
(
h
)
}
func
(
h
TimedQueue
)
Len
()
int
{
return
len
(
h
)
}
func
(
h
TimedQueue
)
Less
(
i
,
j
int
)
bool
{
return
h
[
i
]
.
Next
.
Before
(
h
[
j
]
.
Nex
t
)
}
func
(
h
TimedQueue
)
Less
(
i
,
j
int
)
bool
{
return
h
[
i
]
.
ProcessAt
.
Before
(
h
[
j
]
.
ProcessA
t
)
}
func
(
h
TimedQueue
)
Swap
(
i
,
j
int
)
{
h
[
i
],
h
[
j
]
=
h
[
j
],
h
[
i
]
}
func
(
h
TimedQueue
)
Swap
(
i
,
j
int
)
{
h
[
i
],
h
[
j
]
=
h
[
j
],
h
[
i
]
}
func
(
h
*
TimedQueue
)
Push
(
x
interface
{})
{
func
(
h
*
TimedQueue
)
Push
(
x
interface
{})
{
...
@@ -75,6 +75,23 @@ func (q *UniqueQueue) Add(value TimedValue) bool {
...
@@ -75,6 +75,23 @@ func (q *UniqueQueue) Add(value TimedValue) bool {
return
true
return
true
}
}
// Replace replaces an existing value in the queue if it already exists, otherwise it does nothing.
// Returns true if the item was found.
func
(
q
*
UniqueQueue
)
Replace
(
value
TimedValue
)
bool
{
q
.
lock
.
Lock
()
defer
q
.
lock
.
Unlock
()
for
i
:=
range
q
.
queue
{
if
q
.
queue
[
i
]
.
Value
!=
value
.
Value
{
continue
}
heap
.
Remove
(
&
q
.
queue
,
i
)
heap
.
Push
(
&
q
.
queue
,
&
value
)
return
true
}
return
false
}
// Removes the value from the queue, so Get() call won't return it, and allow subsequent addition
// Removes the value from the queue, so Get() call won't return it, and allow subsequent addition
// of the given value. If the value is not present does nothing and returns false.
// of the given value. If the value is not present does nothing and returns false.
func
(
q
*
UniqueQueue
)
Remove
(
value
string
)
bool
{
func
(
q
*
UniqueQueue
)
Remove
(
value
string
)
bool
{
...
@@ -103,6 +120,17 @@ func (q *UniqueQueue) Get() (TimedValue, bool) {
...
@@ -103,6 +120,17 @@ func (q *UniqueQueue) Get() (TimedValue, bool) {
return
*
result
,
true
return
*
result
,
true
}
}
// Head returns the oldest added value that wasn't returned yet without removing it.
func
(
q
*
UniqueQueue
)
Head
()
(
TimedValue
,
bool
)
{
q
.
lock
.
Lock
()
defer
q
.
lock
.
Unlock
()
if
len
(
q
.
queue
)
==
0
{
return
TimedValue
{},
false
}
result
:=
q
.
queue
[
0
]
return
*
result
,
true
}
// RateLimitedTimedQueue is a unique item priority queue ordered by the expected next time
// RateLimitedTimedQueue is a unique item priority queue ordered by the expected next time
// of execution. It is also rate limited.
// of execution. It is also rate limited.
type
RateLimitedTimedQueue
struct
{
type
RateLimitedTimedQueue
struct
{
...
@@ -133,7 +161,7 @@ type ActionFunc func(TimedValue) (bool, time.Duration)
...
@@ -133,7 +161,7 @@ type ActionFunc func(TimedValue) (bool, time.Duration)
// otherwise it is added back to the queue. The returned remaining is used to identify the minimum
// otherwise it is added back to the queue. The returned remaining is used to identify the minimum
// time to execute the next item in the queue.
// time to execute the next item in the queue.
func
(
q
*
RateLimitedTimedQueue
)
Try
(
fn
ActionFunc
)
{
func
(
q
*
RateLimitedTimedQueue
)
Try
(
fn
ActionFunc
)
{
val
,
ok
:=
q
.
queue
.
Get
()
val
,
ok
:=
q
.
queue
.
Head
()
for
ok
{
for
ok
{
// rate limit the queue checking
// rate limit the queue checking
if
q
.
leak
{
if
q
.
leak
{
...
@@ -145,18 +173,20 @@ func (q *RateLimitedTimedQueue) Try(fn ActionFunc) {
...
@@ -145,18 +173,20 @@ func (q *RateLimitedTimedQueue) Try(fn ActionFunc) {
}
}
now
:=
now
()
now
:=
now
()
if
now
.
Before
(
val
.
Nex
t
)
{
if
now
.
Before
(
val
.
ProcessA
t
)
{
q
.
queue
.
Add
(
val
)
q
.
queue
.
Replace
(
val
)
val
,
ok
=
q
.
queue
.
Get
()
val
,
ok
=
q
.
queue
.
Head
()
// we do not sleep here because other values may be added at the front of the queue
// we do not sleep here because other values may be added at the front of the queue
continue
continue
}
}
if
ok
,
wait
:=
fn
(
val
);
!
ok
{
if
ok
,
wait
:=
fn
(
val
);
!
ok
{
val
.
Next
=
now
.
Add
(
wait
+
1
)
val
.
ProcessAt
=
now
.
Add
(
wait
+
1
)
q
.
queue
.
Add
(
val
)
q
.
queue
.
Replace
(
val
)
}
else
{
q
.
queue
.
Remove
(
val
.
Value
)
}
}
val
,
ok
=
q
.
queue
.
Get
()
val
,
ok
=
q
.
queue
.
Head
()
}
}
}
}
...
@@ -165,9 +195,9 @@ func (q *RateLimitedTimedQueue) Try(fn ActionFunc) {
...
@@ -165,9 +195,9 @@ func (q *RateLimitedTimedQueue) Try(fn ActionFunc) {
func
(
q
*
RateLimitedTimedQueue
)
Add
(
value
string
)
bool
{
func
(
q
*
RateLimitedTimedQueue
)
Add
(
value
string
)
bool
{
now
:=
now
()
now
:=
now
()
return
q
.
queue
.
Add
(
TimedValue
{
return
q
.
queue
.
Add
(
TimedValue
{
Value
:
value
,
Value
:
value
,
Added
:
now
,
Added
At
:
now
,
Next
:
now
,
ProcessAt
:
now
,
})
})
}
}
...
...
pkg/controller/node/rate_limited_queue_test.go
View file @
940cc283
...
@@ -161,10 +161,10 @@ func TestTryOrdering(t *testing.T) {
...
@@ -161,10 +161,10 @@ func TestTryOrdering(t *testing.T) {
queued
:=
false
queued
:=
false
evictor
.
Try
(
func
(
value
TimedValue
)
(
bool
,
time
.
Duration
)
{
evictor
.
Try
(
func
(
value
TimedValue
)
(
bool
,
time
.
Duration
)
{
count
++
count
++
if
value
.
Added
.
IsZero
()
{
if
value
.
Added
At
.
IsZero
()
{
t
.
Fatalf
(
"added should not be zero"
)
t
.
Fatalf
(
"added should not be zero"
)
}
}
if
value
.
Nex
t
.
IsZero
()
{
if
value
.
ProcessA
t
.
IsZero
()
{
t
.
Fatalf
(
"next should not be zero"
)
t
.
Fatalf
(
"next should not be zero"
)
}
}
if
!
queued
&&
value
.
Value
==
"second"
{
if
!
queued
&&
value
.
Value
==
"second"
{
...
@@ -181,3 +181,49 @@ func TestTryOrdering(t *testing.T) {
...
@@ -181,3 +181,49 @@ func TestTryOrdering(t *testing.T) {
t
.
Fatalf
(
"unexpected iterations: %d"
,
count
)
t
.
Fatalf
(
"unexpected iterations: %d"
,
count
)
}
}
}
}
func
TestTryRemovingWhileTry
(
t
*
testing
.
T
)
{
evictor
:=
NewRateLimitedTimedQueue
(
util
.
NewFakeRateLimiter
(),
false
)
evictor
.
Add
(
"first"
)
evictor
.
Add
(
"second"
)
evictor
.
Add
(
"third"
)
processing
:=
make
(
chan
struct
{})
wait
:=
make
(
chan
struct
{})
order
:=
[]
string
{}
count
:=
0
queued
:=
false
// while the Try function is processing "second", remove it from the queue
// we should not see "second" retried.
go
func
()
{
<-
processing
evictor
.
Remove
(
"second"
)
close
(
wait
)
}()
evictor
.
Try
(
func
(
value
TimedValue
)
(
bool
,
time
.
Duration
)
{
count
++
if
value
.
AddedAt
.
IsZero
()
{
t
.
Fatalf
(
"added should not be zero"
)
}
if
value
.
ProcessAt
.
IsZero
()
{
t
.
Fatalf
(
"next should not be zero"
)
}
if
!
queued
&&
value
.
Value
==
"second"
{
queued
=
true
close
(
processing
)
<-
wait
return
false
,
time
.
Millisecond
}
order
=
append
(
order
,
value
.
Value
)
return
true
,
0
})
if
!
reflect
.
DeepEqual
(
order
,
[]
string
{
"first"
,
"third"
})
{
t
.
Fatalf
(
"order was wrong: %v"
,
order
)
}
if
count
!=
3
{
t
.
Fatalf
(
"unexpected iterations: %d"
,
count
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment