Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
jenkins
提交
edb9bc5a
J
jenkins
项目概览
xxadev
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
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,发现更多精彩内容 >>
提交
edb9bc5a
编写于
6月 20, 2013
作者:
K
Kohsuke Kawaguchi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[JENKINS-17247] Refactored a bit to extract the SCC computation into a reusable code
上级
8d0f7f56
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
175 addition
and
98 deletion
+175
-98
core/src/main/java/hudson/model/DependencyGraph.java
core/src/main/java/hudson/model/DependencyGraph.java
+20
-98
core/src/main/java/jenkins/util/DirectedGraph.java
core/src/main/java/jenkins/util/DirectedGraph.java
+155
-0
未找到文件。
core/src/main/java/hudson/model/DependencyGraph.java
浏览文件 @
edb9bc5a
...
...
@@ -28,12 +28,12 @@ import jenkins.model.DependencyDeclarer;
import
com.google.common.collect.ImmutableList
;
import
hudson.security.ACL
;
import
jenkins.model.Jenkins
;
import
jenkins.util.DirectedGraph
;
import
jenkins.util.DirectedGraph.SCC
;
import
org.acegisecurity.context.SecurityContext
;
import
org.acegisecurity.context.SecurityContextHolder
;
import
org.apache.commons.collections.map.HashedMap
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Comparator
;
...
...
@@ -110,106 +110,31 @@ public class DependencyGraph implements Comparator<AbstractProject> {
* See http://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm
*/
private
void
topologicalDagSort
()
{
/**
* Node of the cyclic graph, which is primarily {@link AbstractProject} but with additional
* data structures needed for the Tarjan's algorithm.
*/
class
Node
{
final
AbstractProject
project
;
/**
* DFS visit order.
*/
int
index
=
-
1
;
/**
* The smallest index of any nodes reachable from this node transitively.
*/
int
lowlink
;
/**
* Strongly connected component index.
* All the {@link Node}s that have the same SCC number belongs to the same strongly-connected
* component, and more over, the Tarjan's algorithm is such that the scc index constitutes
* the reverse topological order of the topological sort of the SCC DAG.
*
* Smallest SCC# means everyone depends on you.
*/
int
scc
=
-
1
;
Node
(
AbstractProject
project
)
{
this
.
project
=
project
;
}
Collection
<
AbstractProject
>
edges
()
{
return
getDownstream
(
project
);
}
}
final
Map
<
AbstractProject
,
Node
>
nodes
=
new
HashMap
<
AbstractProject
,
Node
>();
for
(
AbstractProject
p
:
forward
.
keySet
())
{
if
(!
nodes
.
containsKey
(
p
))
nodes
.
put
(
p
,
new
Node
(
p
));
}
for
(
AbstractProject
p
:
backward
.
keySet
())
{
if
(!
nodes
.
containsKey
(
p
))
nodes
.
put
(
p
,
new
Node
(
p
));
}
class
Tarjan
{
int
index
=
0
;
int
scc
=
0
;
/**
* Nodes not yet classified for the strongly connected components
*/
Stack
<
Node
>
pending
=
new
Stack
<
Node
>();
void
traverse
()
{
for
(
Node
n
:
nodes
.
values
())
{
if
(
n
.
index
==-
1
)
visit
(
n
);
}
}
void
visit
(
Node
v
)
{
v
.
index
=
v
.
lowlink
=
index
++;
pending
.
push
(
v
);
for
(
AbstractProject
q
:
v
.
edges
())
{
Node
w
=
nodes
.
get
(
q
);
if
(
w
.
index
==-
1
)
{
visit
(
w
);
v
.
lowlink
=
Math
.
min
(
v
.
lowlink
,
w
.
lowlink
);
}
else
if
(
pending
.
contains
(
w
))
{
v
.
lowlink
=
Math
.
min
(
v
.
lowlink
,
w
.
index
);
}
}
if
(
v
.
lowlink
==
v
.
index
)
{
Node
w
;
do
{
w
=
pending
.
pop
();
w
.
scc
=
scc
;
}
while
(
w
!=
v
);
scc
++;
}
DirectedGraph
<
AbstractProject
>
g
=
new
DirectedGraph
<
AbstractProject
>()
{
@Override
protected
Collection
<
AbstractProject
>
nodes
()
{
final
Set
<
AbstractProject
>
nodes
=
new
HashSet
<
AbstractProject
>();
nodes
.
addAll
(
forward
.
keySet
());
nodes
.
addAll
(
backward
.
keySet
());
return
nodes
;
}
}
new
Tarjan
().
traverse
();
// sort nodes in the topological order
Node
[]
a
=
nodes
.
values
().
toArray
(
new
Node
[
nodes
.
size
()]);
Arrays
.
sort
(
a
,
new
Comparator
<
Node
>()
{
@Override
p
ublic
int
compare
(
Node
o1
,
Node
o2
)
{
return
o2
.
scc
-
o1
.
scc
;
// Tarjan finds them backward, so the order is swapped here
p
rotected
Collection
<
AbstractProject
>
forward
(
AbstractProject
node
)
{
return
getDownstream
(
node
);
}
});
};
List
<
SCC
<
AbstractProject
>>
sccs
=
g
.
getStronglyConnectedComponents
();
final
Map
<
AbstractProject
,
Integer
>
topoOrder
=
new
HashMap
<
AbstractProject
,
Integer
>();
topologicallySorted
=
new
ArrayList
<
AbstractProject
<?,?>>();
int
idx
=
0
;
for
(
Node
n
:
a
)
{
topoOrder
.
put
(
n
.
project
,
idx
++);
for
(
SCC
<
AbstractProject
>
scc
:
sccs
)
{
for
(
AbstractProject
n
:
scc
)
{
topoOrder
.
put
(
n
,
idx
++);
topologicallySorted
.
add
(
n
);
}
}
topologicalOrder
=
new
Comparator
<
AbstractProject
<?,
?>>()
{
...
...
@@ -219,9 +144,6 @@ public class DependencyGraph implements Comparator<AbstractProject> {
}
};
topologicallySorted
=
new
ArrayList
<
AbstractProject
<?,?>>(
a
.
length
);
for
(
Node
n
:
a
)
topologicallySorted
.
add
(
n
.
project
);
topologicallySorted
=
Collections
.
unmodifiableList
(
topologicallySorted
);
}
...
...
core/src/main/java/jenkins/util/DirectedGraph.java
0 → 100644
浏览文件 @
edb9bc5a
package
jenkins.util
;
import
java.util.AbstractSet
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Stack
;
/**
* A possible cyclic directed graph.
*
* This class defines various algorithms on a directed graph that's not necessarily acyclic.
*
* @author Kohsuke Kawaguchi
*/
public
abstract
class
DirectedGraph
<
N
>
{
/**
* All the vertices of the nodes.
*/
protected
abstract
Collection
<
N
>
nodes
();
/**
* Forward traversal of the edges.
*/
protected
abstract
Collection
<
N
>
forward
(
N
node
);
/**
* Strongly connected component (SCC) of a graph.
*/
public
static
class
SCC
<
N
>
extends
AbstractSet
<
N
>
{
/**
* The Tarjan's algorithm is such that this index constitutes
* the reverse topological order of the topological sort of the SCC DAG.
*
* <p>
* That is, if you think about a derived graph where nodes are SCCs of the original directed graph,
* it will always form a DAG even when the original graph has cycles.
*
* Smallest SCC# means it's more of a sink, and larger SCC# means it's more of a source.
*/
public
final
int
index
;
private
final
List
<
N
>
members
=
new
ArrayList
<
N
>();
public
SCC
(
int
index
)
{
this
.
index
=
index
;
}
@Override
public
Iterator
<
N
>
iterator
()
{
return
members
.
iterator
();
}
@Override
public
int
size
()
{
return
members
.
size
();
}
}
/**
* Performs the Tarjan's algorithm and computes strongly-connected components from the
* sink to source order.
*
* See http://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm
*/
public
List
<
SCC
<
N
>>
getStronglyConnectedComponents
()
{
/**
* Node of the cyclic graph, which is primarily {@link N} but with additional
* data structures needed for the Tarjan's algorithm.
*/
class
Node
{
final
N
n
;
/**
* DFS visit order.
*/
int
index
=
-
1
;
/**
* The smallest index of any nodes reachable from this node transitively.
*/
int
lowlink
;
SCC
scc
;
Node
(
N
n
)
{
this
.
n
=
n
;
}
Collection
<
N
>
edges
()
{
return
forward
(
n
);
}
}
final
Map
<
N
,
Node
>
nodes
=
new
HashMap
<
N
,
Node
>();
for
(
N
n
:
nodes
())
{
nodes
.
put
(
n
,
new
Node
(
n
));
}
final
List
<
SCC
<
N
>>
sccs
=
new
ArrayList
<
SCC
<
N
>>();
class
Tarjan
{
int
index
=
0
;
int
sccIndex
=
0
;
/**
* Nodes not yet classified for the strongly connected components
*/
Stack
<
Node
>
pending
=
new
Stack
<
Node
>();
void
traverse
()
{
for
(
Node
n
:
nodes
.
values
())
{
if
(
n
.
index
==-
1
)
visit
(
n
);
}
}
void
visit
(
Node
v
)
{
v
.
index
=
v
.
lowlink
=
index
++;
pending
.
push
(
v
);
for
(
N
q
:
v
.
edges
())
{
Node
w
=
nodes
.
get
(
q
);
if
(
w
.
index
==-
1
)
{
visit
(
w
);
v
.
lowlink
=
Math
.
min
(
v
.
lowlink
,
w
.
lowlink
);
}
else
if
(
pending
.
contains
(
w
))
{
v
.
lowlink
=
Math
.
min
(
v
.
lowlink
,
w
.
index
);
}
}
if
(
v
.
lowlink
==
v
.
index
)
{
// found a new SCC
SCC
<
N
>
scc
=
new
SCC
<
N
>(
sccIndex
++);
sccs
.
add
(
scc
);
Node
w
;
do
{
w
=
pending
.
pop
();
w
.
scc
=
scc
;
scc
.
members
.
add
(
w
.
n
);
}
while
(
w
!=
v
);
}
}
}
new
Tarjan
().
traverse
();
Collections
.
reverse
(
sccs
);
return
sccs
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录