Search in sources :

Example 1 with Reactor

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));
                }
            });
        }
    });
}
Also used : TaskBuilder(org.jvnet.hudson.reactor.TaskBuilder) InitializerFinder(hudson.init.InitializerFinder) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) CycleDetectedException(hudson.util.CyclicGraphDetector.CycleDetectedException) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) IOException(java.io.IOException) Dependency(hudson.PluginWrapper.Dependency) ServletException(javax.servlet.ServletException) CycleDetectedException(hudson.util.CyclicGraphDetector.CycleDetectedException) IOException(java.io.IOException) TaskGraphBuilder(org.jvnet.hudson.reactor.TaskGraphBuilder) List(java.util.List) PersistedList(hudson.util.PersistedList) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) Executable(org.jvnet.hudson.reactor.Executable) Reactor(org.jvnet.hudson.reactor.Reactor) CyclicGraphDetector(hudson.util.CyclicGraphDetector) File(java.io.File)

Example 2 with Reactor

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();
    }
}
Also used : Task(org.jvnet.hudson.reactor.Task) DaemonThreadFactory(hudson.util.DaemonThreadFactory) ExecutorService(java.util.concurrent.ExecutorService) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) Reactor(org.jvnet.hudson.reactor.Reactor) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) UDPBroadcastThread(hudson.UDPBroadcastThread)

Example 3 with Reactor

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;
}
Also used : FullControlOnceLoggedInAuthorizationStrategy(hudson.security.FullControlOnceLoggedInAuthorizationStrategy) XmlFile(hudson.XmlFile) NodeList(hudson.slaves.NodeList) IOException(java.io.IOException) ExtensionListView(hudson.ExtensionListView) FormException(hudson.model.Descriptor.FormException) RestartNotSupportedException(hudson.lifecycle.RestartNotSupportedException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ServletException(javax.servlet.ServletException) ReactorException(org.jvnet.hudson.reactor.ReactorException) TimeoutException(java.util.concurrent.TimeoutException) ParseException(java.text.ParseException) JellyException(org.apache.commons.jelly.JellyException) ANTLRException(antlr.ANTLRException) AcegiSecurityException(org.acegisecurity.AcegiSecurityException) BindException(java.net.BindException) AccessDeniedException(org.acegisecurity.AccessDeniedException) TaskGraphBuilder(org.jvnet.hudson.reactor.TaskGraphBuilder) Handle(org.jvnet.hudson.reactor.TaskGraphBuilder.Handle) LegacySecurityRealm(hudson.security.LegacySecurityRealm) FileFilter(java.io.FileFilter) Executable(org.jvnet.hudson.reactor.Executable) Reactor(org.jvnet.hudson.reactor.Reactor) TextFile(hudson.util.TextFile) XmlFile(hudson.XmlFile) File(java.io.File)

Aggregations

Reactor (org.jvnet.hudson.reactor.Reactor)3 File (java.io.File)2 IOException (java.io.IOException)2 ServletException (javax.servlet.ServletException)2 Executable (org.jvnet.hudson.reactor.Executable)2 TaskGraphBuilder (org.jvnet.hudson.reactor.TaskGraphBuilder)2 ANTLRException (antlr.ANTLRException)1 ExtensionListView (hudson.ExtensionListView)1 Dependency (hudson.PluginWrapper.Dependency)1 UDPBroadcastThread (hudson.UDPBroadcastThread)1 XmlFile (hudson.XmlFile)1 InitializerFinder (hudson.init.InitializerFinder)1 RestartNotSupportedException (hudson.lifecycle.RestartNotSupportedException)1 FormException (hudson.model.Descriptor.FormException)1 FullControlOnceLoggedInAuthorizationStrategy (hudson.security.FullControlOnceLoggedInAuthorizationStrategy)1 LegacySecurityRealm (hudson.security.LegacySecurityRealm)1 NodeList (hudson.slaves.NodeList)1 CyclicGraphDetector (hudson.util.CyclicGraphDetector)1 CycleDetectedException (hudson.util.CyclicGraphDetector.CycleDetectedException)1 DaemonThreadFactory (hudson.util.DaemonThreadFactory)1