use of org.jvnet.hudson.reactor.Reactor in project hudson-2.x by hudson.
the class PluginManager method initTasks.
/**
* Called immediately after the construction.
* This is a separate method so that code executed from here will see a valid value in
* {@link Hudson#pluginManager}.
*/
public TaskBuilder initTasks(final InitStrategy initStrategy) {
TaskBuilder builder;
if (!pluginListed) {
builder = new TaskGraphBuilder() {
List<File> archives;
Collection<String> bundledPlugins;
{
Handle loadBundledPlugins = add("Loading bundled plugins", new Executable() {
public void run(Reactor session) throws Exception {
bundledPlugins = loadBundledPlugins();
}
});
Handle listUpPlugins = requires(loadBundledPlugins).add("Listing up plugins", new Executable() {
public void run(Reactor session) throws Exception {
archives = initStrategy.listPluginArchives(PluginManager.this);
}
});
requires(listUpPlugins).attains(PLUGINS_LISTED).add("Preparing plugins", new Executable() {
public void run(Reactor session) throws Exception {
// once we've listed plugins, we can fill in the reactor with plugin-specific initialization tasks
TaskGraphBuilder g = new TaskGraphBuilder();
final Map<String, File> inspectedShortNames = new HashMap<String, File>();
for (final File arc : archives) {
g.followedBy().notFatal().attains(PLUGINS_LISTED).add("Inspecting plugin " + arc, new Executable() {
public void run(Reactor session1) throws Exception {
try {
PluginWrapper p = strategy.createPluginWrapper(arc);
if (isDuplicate(p))
return;
p.isBundled = bundledPlugins.contains(arc.getName());
plugins.add(p);
if (p.isActive())
activePlugins.add(p);
} catch (IOException e) {
failedPlugins.add(new FailedPlugin(arc.getName(), e));
throw e;
}
}
/**
* Inspects duplication. this happens when you run hpi:run on a bundled plugin,
* as well as putting numbered hpi files, like "cobertura-1.0.hpi" and "cobertura-1.1.hpi"
*/
private boolean isDuplicate(PluginWrapper p) {
String shortName = p.getShortName();
if (inspectedShortNames.containsKey(shortName)) {
LOGGER.info("Ignoring " + arc + " because " + inspectedShortNames.get(shortName) + " is already loaded");
return true;
}
inspectedShortNames.put(shortName, arc);
return false;
}
});
}
g.requires(PLUGINS_PREPARED).add("Checking cyclic dependencies", new Executable() {
/**
* Makes sure there's no cycle in dependencies.
*/
public void run(Reactor reactor) throws Exception {
try {
new CyclicGraphDetector<PluginWrapper>() {
@Override
protected List<PluginWrapper> getEdges(PluginWrapper p) {
List<PluginWrapper> next = new ArrayList<PluginWrapper>();
addTo(p.getDependencies(), next);
addTo(p.getOptionalDependencies(), next);
return next;
}
private void addTo(List<Dependency> dependencies, List<PluginWrapper> r) {
for (Dependency d : dependencies) {
PluginWrapper p = getPlugin(d.shortName);
if (p != null)
r.add(p);
}
}
}.run(getPlugins());
} catch (CycleDetectedException e) {
// disable all plugins since classloading from them can lead to StackOverflow
stop();
// let Hudson fail
throw e;
}
Collections.sort(plugins);
}
});
session.addAll(g.discoverTasks(session));
// technically speaking this is still too early, as at this point tasks are merely scheduled, not necessarily executed.
pluginListed = true;
}
});
}
};
} else {
builder = TaskBuilder.EMPTY_BUILDER;
}
// misc. stuff
final InitializerFinder initializerFinder = new InitializerFinder(uberClassLoader);
// lists up initialization tasks about loading plugins.
return // this scans @Initializer in the core once
TaskBuilder.union(// this scans @Initializer in the core once
initializerFinder, builder, new TaskGraphBuilder() {
{
requires(PLUGINS_LISTED).attains(PLUGINS_PREPARED).add("Loading plugins", new Executable() {
/**
* Once the plugins are listed, schedule their initialization.
*/
public void run(Reactor session) throws Exception {
Hudson.getInstance().lookup.set(PluginInstanceStore.class, new PluginInstanceStore());
TaskGraphBuilder g = new TaskGraphBuilder();
// schedule execution of loading plugins
for (final PluginWrapper p : activePlugins.toArray(new PluginWrapper[activePlugins.size()])) {
g.followedBy().notFatal().attains(PLUGINS_PREPARED).add("Loading plugin " + p.getShortName(), new Executable() {
public void run(Reactor session) throws Exception {
try {
p.resolvePluginDependencies();
strategy.load(p);
} catch (IOException e) {
failedPlugins.add(new FailedPlugin(p.getShortName(), e));
activePlugins.remove(p);
plugins.remove(p);
throw e;
}
}
});
}
// schedule execution of initializing plugins
for (final PluginWrapper p : activePlugins.toArray(new PluginWrapper[activePlugins.size()])) {
g.followedBy().notFatal().attains(PLUGINS_STARTED).add("Initializing plugin " + p.getShortName(), new Executable() {
public void run(Reactor session) throws Exception {
try {
p.getPlugin().postInitialize();
} catch (Exception e) {
failedPlugins.add(new FailedPlugin(p.getShortName(), e));
activePlugins.remove(p);
plugins.remove(p);
throw e;
}
}
});
}
g.followedBy().attains(PLUGINS_STARTED).add("Discovering plugin initialization tasks", new Executable() {
public void run(Reactor reactor) throws Exception {
// rescan to find plugin-contributed @Initializer
reactor.addAll(initializerFinder.discoverTasks(reactor));
}
});
// register them all
session.addAll(g.discoverTasks(session));
}
});
}
});
}
use of org.jvnet.hudson.reactor.Reactor in project hudson-2.x by hudson.
the class Hudson method executeReactor.
/**
* Executes a reactor.
*
* @param is
* If non-null, this can be consulted for ignoring some tasks. Only used during the initialization of Hudson.
*/
private void executeReactor(final InitStrategy is, TaskBuilder... builders) throws IOException, InterruptedException, ReactorException {
Reactor reactor = new Reactor(builders) {
/**
* Sets the thread name to the task for better diagnostics.
*/
@Override
protected void runTask(Task task) throws Exception {
if (is != null && is.skipInitTask(task)) {
return;
}
// full access in the initialization thread
SecurityContextHolder.getContext().setAuthentication(ACL.SYSTEM);
String taskName = task.getDisplayName();
Thread t = Thread.currentThread();
String name = t.getName();
if (taskName != null) {
t.setName(taskName);
}
try {
long start = System.currentTimeMillis();
super.runTask(task);
if (LOG_STARTUP_PERFORMANCE) {
LOGGER.info(String.format("Took %dms for %s by %s", System.currentTimeMillis() - start, taskName, name));
}
} finally {
t.setName(name);
SecurityContextHolder.clearContext();
}
}
};
ExecutorService es;
if (PARALLEL_LOAD) {
es = new ThreadPoolExecutor(TWICE_CPU_NUM, TWICE_CPU_NUM, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new DaemonThreadFactory());
} else {
es = Executors.newSingleThreadExecutor(new DaemonThreadFactory());
}
try {
reactor.execute(es, buildReactorListener());
} finally {
// upon a successful return the executor queue should be empty. Upon an exception, we want to cancel all pending tasks
es.shutdownNow();
}
}
use of org.jvnet.hudson.reactor.Reactor in project hudson-2.x by hudson.
the class Hudson method loadTasks.
private synchronized TaskBuilder loadTasks() throws IOException {
File projectsDir = new File(root, "jobs");
if (!projectsDir.isDirectory() && !projectsDir.mkdirs()) {
if (projectsDir.exists()) {
throw new IOException(projectsDir + " is not a directory");
}
throw new IOException("Unable to create " + projectsDir + "\nPermission issue? Please create this directory manually.");
}
File[] subdirs = projectsDir.listFiles(new FileFilter() {
public boolean accept(File child) {
return child.isDirectory() && Items.getConfigFile(child).exists();
}
});
TaskGraphBuilder g = new TaskGraphBuilder();
Handle loadHudson = g.requires(InitMilestone.EXTENSIONS_AUGMENTED).attains(InitMilestone.JOB_LOADED).add("Loading global config", new Executable() {
public void run(Reactor session) throws Exception {
XmlFile cfg = getConfigFile();
if (cfg.exists()) {
// reset some data that may not exist in the disk file
// so that we can take a proper compensation action later.
primaryView = null;
views.clear();
// load from disk
cfg.unmarshal(Hudson.this);
}
// if we are loading old data that doesn't have this field
if (slaves == null) {
slaves = new NodeList();
}
clouds.setOwner(Hudson.this);
items.clear();
}
});
for (final File subdir : subdirs) {
g.requires(loadHudson).attains(InitMilestone.JOB_LOADED).notFatal().add("Loading job " + subdir.getName(), new Executable() {
public void run(Reactor session) throws Exception {
TopLevelItem item = (TopLevelItem) Items.load(Hudson.this, subdir);
items.put(item.getName(), item);
}
});
}
g.requires(InitMilestone.JOB_LOADED).add("Finalizing set up", new Executable() {
public void run(Reactor session) throws Exception {
rebuildDependencyGraph();
{
// recompute label objects - populates the labels mapping.
for (// Note that not all labels are visible until the slaves have connected.
Node slave : // Note that not all labels are visible until the slaves have connected.
slaves) {
slave.getAssignedLabels();
}
getAssignedLabels();
}
// this is both for clean Hudson and for backward compatibility.
if (views.size() == 0 || primaryView == null) {
View v = new AllView(Messages.Hudson_ViewName());
v.owner = Hudson.this;
views.add(0, v);
primaryView = v.getViewName();
}
// read in old data that doesn't have the security field set
if (authorizationStrategy == null) {
if (useSecurity == null || !useSecurity) {
authorizationStrategy = AuthorizationStrategy.UNSECURED;
} else {
authorizationStrategy = new FullControlOnceLoggedInAuthorizationStrategy();
}
}
if (securityRealm == null) {
if (useSecurity == null || !useSecurity) {
setSecurityRealm(SecurityRealm.NO_AUTHENTICATION);
} else {
setSecurityRealm(new LegacySecurityRealm());
}
} else {
// force the set to proxy
setSecurityRealm(securityRealm);
}
if (useSecurity != null && !useSecurity) {
// forced reset to the unsecure mode.
// this works as an escape hatch for people who locked themselves out.
authorizationStrategy = AuthorizationStrategy.UNSECURED;
setSecurityRealm(SecurityRealm.NO_AUTHENTICATION);
}
// Initialize the filter with the crumb issuer
setCrumbIssuer(crumbIssuer);
// auto register root actions
for (Action a : getExtensionList(RootAction.class)) {
if (!actions.contains(a)) {
actions.add(a);
}
}
}
});
return g;
}
Aggregations