org.grouter.core.util.SchedulerService.java Source code

Java tutorial

Introduction

Here is the source code for org.grouter.core.util.SchedulerService.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.grouter.core.util;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.log4j.Logger;
import org.grouter.core.command.AbstractCommand;
import org.grouter.core.command.CommandConsumerJob;
import org.grouter.core.readers.FileReaderJob;
import org.grouter.core.readers.FtpReaderJob;
import org.grouter.core.readers.HttpReaderJob;
import org.grouter.core.readers.JmsReaderJob;
import org.grouter.domain.entities.EndPointType;
import org.grouter.domain.entities.Node;
import org.grouter.domain.entities.NodeStatus;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.List;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * What's the right size for a thread pool, assuming the goal is to keep the
 * processors fully utilized? Amdahl's law gives us a good approximate formula, if
 * we know how many processors our system has and the approximate ratio of
 * compute time to wait time for the tasks.
 * Let WT represent the average wait time per task, and ST the average service
 * time (computation time) per task. Then WT/ST is the percentage of time a task
 * spends waiting. For an N processor system, we would want to have
 * approximately N*(1+WT/ST) threads in the pool.
 * <p/>
 * <p/>
 * We are using a Fascade round the Quartz scheduler framework.
 *
 * @author Georges Polyzois
 */
public class SchedulerService {
    private static Logger logger = Logger.getLogger(SchedulerService.class);
    private static final int QUEUE_CAPACITY = 1000;
    Scheduler scheduler;
    private Set<Node> nodes;
    private static final String GROUTER = "grouter";

    /**
     * Consturctor
     */
    public SchedulerService(Set<Node> nodes) {
        Validate.noNullElements(nodes, "Can not handle null nodes!!");

        this.nodes = nodes;
        for (Node node : nodes) {
            node.setNodeStatus(NodeStatus.NOTSTARTED);
        }

        try {
            scheduler = StdSchedulerFactory.getDefaultScheduler();
        } catch (SchedulerException e) {
            logger.error("Could not create scheduler frm SchedulerFactory", e);
            throw new RuntimeException("Could not create scheduler from SchedulerFactory", e);
        }

    }

    /**
     * Start the scheduler using all available nodes.
     *
     * @throws Exception
     */
    public void startAllNodes() throws Exception {
        for (Node node : this.nodes) {
            logger.info("Scheduling node : " + node.getDisplayName());
            BlockingQueue<AbstractCommand> blockingQueue = new ArrayBlockingQueue<AbstractCommand>(QUEUE_CAPACITY);
            if (node.getInBound().getEndPointType().getId() == EndPointType.FILE_READER.getId()) {
                JobDetail jobDetail = new JobDetail(node.getInBound().getId().toString(), getTriggerGroup(node),
                        FileReaderJob.class);
                jobDetail.getJobDataMap().put("node", node);
                jobDetail.getJobDataMap().put("queue", blockingQueue);
                CronTrigger cronTrigger = new CronTrigger(getTriggerName(node, true), getTriggerGroup(node),
                        node.getInBound().getCron());
                scheduler.scheduleJob(jobDetail, cronTrigger);
            }
            if (node.getInBound().getEndPointType().getId() == EndPointType.FTP_READER.getId()) {

                JobDetail jobDetail = new JobDetail(node.getInBound().getId().toString(), getTriggerGroup(node),
                        FtpReaderJob.class);
                jobDetail.getJobDataMap().put("node", node);
                jobDetail.getJobDataMap().put("queue", blockingQueue);
                CronTrigger cronTrigger = new CronTrigger(getTriggerName(node, true), getTriggerGroup(node),
                        node.getInBound().getCron());
                scheduler.scheduleJob(jobDetail, cronTrigger);
            }
            if (node.getInBound().getEndPointType().getId() == EndPointType.JMS_READER.getId()) {
                JobDetail jobDetail = new JobDetail(node.getInBound().getId().toString(), getTriggerGroup(node),
                        JmsReaderJob.class);
                jobDetail.getJobDataMap().put("node", node);
                jobDetail.getJobDataMap().put("queue", blockingQueue);
                CronTrigger cronTrigger = new CronTrigger(getTriggerName(node, true), getTriggerGroup(node),
                        node.getInBound().getCron());
                scheduler.scheduleJob(jobDetail, cronTrigger);

            }

            if (node.getInBound().getEndPointType().getId() == EndPointType.HTTP_READER.getId()) {
                JobDetail jobDetail = new JobDetail(node.getInBound().getId().toString(), getTriggerGroup(node),
                        HttpReaderJob.class);
                jobDetail.getJobDataMap().put("node", node);
                jobDetail.getJobDataMap().put("queue", blockingQueue);
                CronTrigger cronTrigger = new CronTrigger(getTriggerName(node, true), getTriggerGroup(node),
                        node.getInBound().getCron());
                scheduler.scheduleJob(jobDetail, cronTrigger);

            }

            // For all WRITERS we need only create this
            if (node.getOutBound().getEndPointType().getId() == EndPointType.FILE_WRITER.getId()
                    || node.getOutBound().getEndPointType().getId() == EndPointType.JMS_WRITER.getId()
                    || node.getOutBound().getEndPointType().getId() == EndPointType.FTP_WRITER.getId()) {
                JobDetail jobDetail = new JobDetail(node.getOutBound().getId().toString(), getTriggerGroup(node),
                        CommandConsumerJob.class);
                jobDetail.getJobDataMap().put("node", node);
                jobDetail.getJobDataMap().put("queue", blockingQueue);
                CronTrigger cronTrigger = new CronTrigger(getTriggerName(node, false), getTriggerGroup(node),
                        node.getOutBound().getCron());
                scheduler.scheduleJob(jobDetail, cronTrigger);
            }
            node.setNodeStatus(NodeStatus.SCHEDULED_TO_START);
        }

        // Start the Scheduler
        scheduler.start();
    }

    private String getTriggerGroup(Node node) {
        String group = GROUTER + "_" + node.getId();
        logger.debug("Trigger group :" + group);
        return group;
    }

    private String getTriggerName(Node node, boolean inbound) {
        String triggerName;
        if (inbound) {
            triggerName = node.getId() + "_" + node.getInBound().getId();
        } else {
            triggerName = node.getId() + "_" + node.getOutBound().getId();
        }
        logger.debug("Trigger name:" + triggerName);
        return triggerName;
    }

    /**
     * Shudtowns the scheduler.
     */
    public void shutdown() throws Exception {
        scheduler.shutdown();
    }

    /**
     * Stop a node from running - both inbound and outbound endpoints of the Node are stopped.  In Quartz this
     * means that we remove the job from the scheduler.
     *
     * @param node the node which we want to stop
     */
    public void stop(Node node) throws Exception {
        //scheduler.interrupt(getTriggerName(node, true), getTriggerGroup(node));  -> callback to job implmeenting Interruptable.. interface for gracefully stoping
        //scheduler.interrupt(getTriggerName(node, false), getTriggerGroup(node));
        scheduler.unscheduleJob(getTriggerName(node, true), getTriggerGroup(node));
        scheduler.unscheduleJob(getTriggerName(node, false), getTriggerGroup(node));

        logStatus();
    }

    /**
     * Reschedules a job.
     * @param node node to be rescheduled
     * @throws Exception
     */
    public void rescheduleNode(Node node) throws Exception {
        logger.info("Rescheduling node : " + node.getDisplayName());
        CronTrigger cronTriggerIn = (CronTrigger) scheduler.getTrigger(getTriggerName(node, true),
                getTriggerGroup(node));
        cronTriggerIn.setCronExpression(node.getInBound().getCron());
        scheduler.rescheduleJob(getTriggerName(node, true), getTriggerGroup(node), cronTriggerIn);

        CronTrigger cronTriggerOut = (CronTrigger) scheduler.getTrigger(getTriggerName(node, false),
                getTriggerGroup(node));
        cronTriggerOut.setCronExpression(node.getOutBound().getCron());
        scheduler.rescheduleJob(getTriggerName(node, false), getTriggerGroup(node), cronTriggerOut);
    }

    /**
     * Util for printing out some statistics.
     */
    private void logStatus() {
        try {
            logger.info("Scheduler meta info :" + scheduler.getMetaData());
            List<JobExecutionContext> list = scheduler.getCurrentlyExecutingJobs();
            logger.info("Currently number of running jobs:" + list.size());
            for (JobExecutionContext jobExecutionContext : list) {
                logger.info("Job running :" + jobExecutionContext.getJobDetail().getFullName());
            }

            String[] groups = scheduler.getJobGroupNames();
            logger.info("Registered groups and jobs for each group");
            for (String group : groups) {
                String[] jobnames = scheduler.getJobNames(group);
                logger.info("Jobnames for group :" + group + " -> " + ToStringBuilder.reflectionToString(jobnames));
            }
        } catch (SchedulerException e) {
            //ignore
        }
    }

    public void setNodes(Set<Node> nodes) {
        this.nodes = nodes;
    }
}