Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
FIY695
jenkins
提交
7ab81687
J
jenkins
项目概览
FIY695
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7ab81687
编写于
8月 10, 2015
作者:
S
Stephen Connolly
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1785 from stephenc/pr-1777-is-better-when-lockfree
[FIXES PR#1777] Make accessing pendingLaunches lock free
上级
4b9318f5
030793f0
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
43 addition
and
27 deletion
+43
-27
core/src/main/java/hudson/slaves/NodeProvisioner.java
core/src/main/java/hudson/slaves/NodeProvisioner.java
+43
-27
未找到文件。
core/src/main/java/hudson/slaves/NodeProvisioner.java
浏览文件 @
7ab81687
...
...
@@ -42,6 +42,7 @@ import java.util.Collection;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicReference
;
import
java.util.concurrent.locks.Lock
;
import
java.util.concurrent.locks.ReentrantLock
;
import
java.util.logging.Logger
;
...
...
@@ -122,8 +123,8 @@ public class NodeProvisioner {
*/
private
final
Label
label
;
@GuardedBy
(
"provisioningLock"
)
private
final
List
<
PlannedNode
>
pendingLaunches
=
new
ArrayList
<
PlannedNode
>(
);
private
final
AtomicReference
<
List
<
PlannedNode
>>
pendingLaunches
=
new
AtomicReference
<
List
<
PlannedNode
>>(
new
ArrayList
<
PlannedNode
>()
);
private
final
Lock
provisioningLock
=
new
ReentrantLock
();
...
...
@@ -155,12 +156,7 @@ public class NodeProvisioner {
* @since 1.401
*/
public
List
<
PlannedNode
>
getPendingLaunches
()
{
provisioningLock
.
lock
();
try
{
return
new
ArrayList
<
PlannedNode
>(
pendingLaunches
);
}
finally
{
provisioningLock
.
unlock
();
}
return
new
ArrayList
<
PlannedNode
>(
pendingLaunches
.
get
());
}
/**
...
...
@@ -214,7 +210,8 @@ public class NodeProvisioner {
int
plannedCapacitySnapshot
=
0
;
for
(
Iterator
<
PlannedNode
>
itr
=
pendingLaunches
.
iterator
();
itr
.
hasNext
();
)
{
List
<
PlannedNode
>
snapPendingLaunches
=
new
ArrayList
<
PlannedNode
>(
pendingLaunches
.
get
());
for
(
Iterator
<
PlannedNode
>
itr
=
snapPendingLaunches
.
iterator
();
itr
.
hasNext
();
)
{
PlannedNode
f
=
itr
.
next
();
if
(
f
.
future
.
isDone
())
{
try
{
...
...
@@ -249,7 +246,29 @@ public class NodeProvisioner {
LOGGER
.
log
(
Level
.
SEVERE
,
"Unexpected uncaught exception encountered while "
+
"processing provisioned slave "
+
f
.
displayName
,
e
);
}
finally
{
itr
.
remove
();
while
(
true
)
{
List
<
PlannedNode
>
orig
=
pendingLaunches
.
get
();
List
<
PlannedNode
>
repl
=
new
ArrayList
<
PlannedNode
>(
orig
);
// the contract for List.remove(o) is that the first element i where
// (o==null ? get(i)==null : o.equals(get(i)))
// is true will be removed from the list
// since PlannedNode.equals(o) is not final and we cannot assume
// that subclasses do not override with an equals which does not
// assure object identity comparison, we need to manually
// do the removal based on instance identity not equality
boolean
changed
=
false
;
for
(
Iterator
<
PlannedNode
>
iterator
=
repl
.
iterator
();
iterator
.
hasNext
();
)
{
PlannedNode
p
=
iterator
.
next
();
if
(
p
==
f
)
{
iterator
.
remove
();
changed
=
true
;
break
;
}
}
if
(!
changed
||
pendingLaunches
.
compareAndSet
(
orig
,
repl
))
{
break
;
}
}
f
.
spent
();
}
}
else
{
...
...
@@ -355,7 +374,6 @@ public class NodeProvisioner {
* The current statistics snapshot for this {@link #label}.
*/
private
final
LoadStatistics
.
LoadStatisticsSnapshot
snapshot
;
private
final
List
<
PlannedNode
>
pendingLaunches
;
/**
* The additional planned capacity for this {@link #label} and provisioned by previous strategies during the
* current updating of the {@link NodeProvisioner}.
...
...
@@ -372,7 +390,6 @@ public class NodeProvisioner {
this
.
snapshot
=
snapshot
;
this
.
label
=
label
;
this
.
plannedCapacitySnapshot
=
plannedCapacitySnapshot
;
pendingLaunches
=
NodeProvisioner
.
this
.
pendingLaunches
;
}
/**
...
...
@@ -428,13 +445,8 @@ public class NodeProvisioner {
* The additional planned capacity for this {@link #getLabel()} and provisioned by previous strategies during
* the current updating of the {@link NodeProvisioner}.
*/
public
int
getAdditionalPlannedCapacity
()
{
provisioningLock
.
lock
();
try
{
return
additionalPlannedCapacity
;
}
finally
{
provisioningLock
.
unlock
();
}
public
synchronized
int
getAdditionalPlannedCapacity
()
{
return
additionalPlannedCapacity
;
}
/**
...
...
@@ -544,7 +556,7 @@ public class NodeProvisioner {
additionalPlannedCapacity
+=
node
.
getNumExecutors
();
}
}
catch
(
InterruptedException
e
)
{
//
ignore, this will be caught by others later
//
should never happen as we were told the future was done
}
catch
(
ExecutionException
e
)
{
// ignore, this will be caught by others later
}
...
...
@@ -552,14 +564,18 @@ public class NodeProvisioner {
additionalPlannedCapacity
+=
f
.
numExecutors
;
}
}
provisioningLock
.
lock
();
try
{
pendingLaunches
.
addAll
(
plannedNodes
);
if
(
additionalPlannedCapacity
>
0
)
{
this
.
additionalPlannedCapacity
+=
additionalPlannedCapacity
;
while
(!
plannedNodes
.
isEmpty
())
{
List
<
PlannedNode
>
orig
=
pendingLaunches
.
get
();
List
<
PlannedNode
>
repl
=
new
ArrayList
<
PlannedNode
>(
orig
);
repl
.
addAll
(
plannedNodes
);
if
(
pendingLaunches
.
compareAndSet
(
orig
,
repl
))
{
if
(
additionalPlannedCapacity
>
0
)
{
synchronized
(
this
)
{
this
.
additionalPlannedCapacity
+=
additionalPlannedCapacity
;
}
}
break
;
}
}
finally
{
provisioningLock
.
unlock
();
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录