Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
LinuxSuRen
jenkins
提交
d5167025
J
jenkins
项目概览
LinuxSuRen
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
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,发现更多精彩内容 >>
提交
d5167025
编写于
1月 18, 2016
作者:
J
Jesse Glick
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[FIXED JENKINS-22767] Make sure only one thread actually loads a given build.
上级
8f426002
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
79 addition
and
3 deletion
+79
-3
core/src/main/java/jenkins/model/lazy/AbstractLazyLoadRunMap.java
.../main/java/jenkins/model/lazy/AbstractLazyLoadRunMap.java
+17
-3
core/src/test/java/jenkins/model/lazy/AbstractLazyLoadRunMapTest.java
...t/java/jenkins/model/lazy/AbstractLazyLoadRunMapTest.java
+62
-0
未找到文件。
core/src/main/java/jenkins/model/lazy/AbstractLazyLoadRunMap.java
浏览文件 @
d5167025
...
...
@@ -353,7 +353,19 @@ public abstract class AbstractLazyLoadRunMap<R> extends AbstractMap<Integer,R> i
if
(
v
!=
null
)
return
v
;
// already in memory
// otherwise fall through to load
}
return
load
(
n
,
null
);
synchronized
(
this
)
{
if
(
index
.
byNumber
.
containsKey
(
n
))
{
// JENKINS-22767: recheck inside lock
BuildReference
<
R
>
ref
=
index
.
byNumber
.
get
(
n
);
if
(
ref
==
null
)
{
return
null
;
}
R
v
=
unwrap
(
ref
);
if
(
v
!=
null
)
{
return
v
;
}
}
return
load
(
n
,
null
);
}
}
protected
final
synchronized
void
proposeNewNumber
(
int
number
)
throws
IllegalStateException
{
...
...
@@ -443,7 +455,8 @@ public abstract class AbstractLazyLoadRunMap<R> extends AbstractMap<Integer,R> i
*
* @return null if the data failed to load.
*/
protected
R
load
(
int
n
,
Index
editInPlace
)
{
private
R
load
(
int
n
,
Index
editInPlace
)
{
assert
Thread
.
holdsLock
(
this
);
assert
dir
!=
null
;
R
v
=
load
(
new
File
(
dir
,
String
.
valueOf
(
n
)),
editInPlace
);
if
(
v
==
null
&&
editInPlace
!=
null
)
{
...
...
@@ -460,7 +473,8 @@ public abstract class AbstractLazyLoadRunMap<R> extends AbstractMap<Integer,R> i
* If non-null, update this data structure.
* Otherwise do a copy-on-write of {@link #index}
*/
protected
synchronized
R
load
(
File
dataDir
,
Index
editInPlace
)
{
private
R
load
(
File
dataDir
,
Index
editInPlace
)
{
assert
Thread
.
holdsLock
(
this
);
try
{
R
r
=
retrieve
(
dataDir
);
if
(
r
==
null
)
return
null
;
...
...
core/src/test/java/jenkins/model/lazy/AbstractLazyLoadRunMapTest.java
浏览文件 @
d5167025
...
...
@@ -23,6 +23,7 @@
*/
package
jenkins.model.lazy
;
import
java.io.File
;
import
static
org
.
junit
.
Assert
.*;
import
jenkins.model.lazy.AbstractLazyLoadRunMap.Direction
;
...
...
@@ -31,13 +32,19 @@ import org.junit.Rule;
import
org.junit.Test
;
import
java.io.IOException
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.NoSuchElementException
;
import
java.util.Set
;
import
java.util.SortedMap
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.Semaphore
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.logging.Level
;
import
jenkins.util.Timer
;
import
org.junit.BeforeClass
;
import
org.jvnet.hudson.test.Issue
;
...
...
@@ -72,6 +79,29 @@ public class AbstractLazyLoadRunMapTest {
}
};
private
final
Map
<
Integer
,
Semaphore
>
slowBuilderStartSemaphores
=
new
HashMap
<>();
private
final
Map
<
Integer
,
Semaphore
>
slowBuilderEndSemaphores
=
new
HashMap
<>();
private
final
Map
<
Integer
,
AtomicInteger
>
slowBuilderLoadCount
=
new
HashMap
<>();
@Rule
public
FakeMapBuilder
slowBuilder
=
new
FakeMapBuilder
()
{
@Override
public
FakeMap
make
()
{
return
new
FakeMap
(
getDir
())
{
@Override
protected
Build
retrieve
(
File
dir
)
throws
IOException
{
Build
b
=
super
.
retrieve
(
dir
);
slowBuilderStartSemaphores
.
get
(
b
.
n
).
release
();
try
{
slowBuilderEndSemaphores
.
get
(
b
.
n
).
acquire
();
}
catch
(
InterruptedException
x
)
{
throw
new
IOException
(
x
);
}
slowBuilderLoadCount
.
get
(
b
.
n
).
incrementAndGet
();
return
b
;
}
};
}
};
@BeforeClass
public
static
void
setUpClass
()
{
...
...
@@ -358,4 +388,36 @@ public class AbstractLazyLoadRunMapTest {
assertTrue
(
a
.
entrySet
().
contains
(
e
));
}
}
@Issue
(
"JENKINS-22767"
)
@Test
public
void
slowRetrieve
()
throws
Exception
{
for
(
int
i
=
1
;
i
<=
3
;
i
++)
{
slowBuilder
.
add
(
i
);
slowBuilderStartSemaphores
.
put
(
i
,
new
Semaphore
(
0
));
slowBuilderEndSemaphores
.
put
(
i
,
new
Semaphore
(
0
));
slowBuilderLoadCount
.
put
(
i
,
new
AtomicInteger
());
}
final
FakeMap
m
=
slowBuilder
.
make
();
Future
<
Build
>
firstLoad
=
Timer
.
get
().
submit
(
new
Callable
<
Build
>()
{
@Override
public
Build
call
()
throws
Exception
{
return
m
.
getByNumber
(
2
);
}
});
Future
<
Build
>
secondLoad
=
Timer
.
get
().
submit
(
new
Callable
<
Build
>()
{
@Override
public
Build
call
()
throws
Exception
{
return
m
.
getByNumber
(
2
);
}
});
slowBuilderStartSemaphores
.
get
(
2
).
acquire
(
1
);
// now one of them is inside retrieve(…); the other is waiting for the lock
slowBuilderEndSemaphores
.
get
(
2
).
release
(
2
);
// allow both to proceed
Build
first
=
firstLoad
.
get
();
Build
second
=
secondLoad
.
get
();
assertEquals
(
1
,
slowBuilderLoadCount
.
get
(
2
).
get
());
assertSame
(
second
,
first
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录