⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ramjobstore.java

📁 Quartz is a full-featured, open source job scheduling system that can be integrated with, or used al
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/* 
 * Copyright 2004-2005 OpenSymphony 
 * 
 * Licensed 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.
 * 
 */

/*
 * Previously Copyright (c) 2001-2004 James House
 */
package org.quartz.simpl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Calendar;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobPersistenceException;
import org.quartz.ObjectAlreadyExistsException;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.core.SchedulingContext;
import org.quartz.spi.ClassLoadHelper;
import org.quartz.spi.JobStore;
import org.quartz.spi.SchedulerSignaler;
import org.quartz.spi.TriggerFiredBundle;

/**
 * <p>
 * This class implements a <code>{@link org.quartz.spi.JobStore}</code> that
 * utilizes RAM as its storage device.
 * </p>
 * 
 * <p>
 * As you should know, the ramification of this is that access is extrememly
 * fast, but the data is completely volatile - therefore this <code>JobStore</code>
 * should not be used if true persistence between program shutdowns is
 * required.
 * </p>
 * 
 * @author James House
 * @author Sharada Jambula
 * @author Eric Mueller
 */
public class RAMJobStore implements JobStore {

    /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * 
     * Data members.
     * 
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */

    protected HashMap jobsByFQN = new HashMap(1000);

    protected HashMap triggersByFQN = new HashMap(1000);

    protected HashMap jobsByGroup = new HashMap(25);

    protected HashMap triggersByGroup = new HashMap(25);

    protected TreeSet timeTriggers = new TreeSet(new TriggerComparator());

    protected HashMap calendarsByName = new HashMap(25);

    protected ArrayList triggers = new ArrayList(1000);

    protected final Object triggerLock = new Object();

    protected HashSet pausedTriggerGroups = new HashSet();

    protected HashSet pausedJobGroups = new HashSet();

    protected HashSet blockedJobs = new HashSet();
    
    protected long misfireThreshold = 5000l;

    protected SchedulerSignaler signaler;

    private final Log log = LogFactory.getLog(getClass());

    /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * 
     * Constructors.
     * 
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */

    /**
     * <p>
     * Create a new <code>RAMJobStore</code>.
     * </p>
     */
    public RAMJobStore() {
    }

    /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * 
     * Interface.
     * 
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */

    protected Log getLog() {
        return log;
    }

    /**
     * <p>
     * Called by the QuartzScheduler before the <code>JobStore</code> is
     * used, in order to give the it a chance to initialize.
     * </p>
     */
    public void initialize(ClassLoadHelper loadHelper,
            SchedulerSignaler signaler) {

        this.signaler = signaler;

        getLog().info("RAMJobStore initialized.");
    }

    public void schedulerStarted() throws SchedulerException {
        // nothing to do
    }

    public long getMisfireThreshold() {
        return misfireThreshold;
    }

    /**
     * The number of milliseconds by which a trigger must have missed its
     * next-fire-time, in order for it to be considered "misfired" and thus
     * have its misfire instruction applied.
     * 
     * @param misfireThreshold
     */
    public void setMisfireThreshold(long misfireThreshold) {
        if (misfireThreshold < 1) {
            throw new IllegalArgumentException("Misfirethreashold must be larger than 0");
        }
        this.misfireThreshold = misfireThreshold;
    }

    /**
     * <p>
     * Called by the QuartzScheduler to inform the <code>JobStore</code> that
     * it should free up all of it's resources because the scheduler is
     * shutting down.
     * </p>
     */
    public void shutdown() {
    }

    public boolean supportsPersistence() {
        return false;
    }

    /**
     * <p>
     * Store the given <code>{@link org.quartz.JobDetail}</code> and <code>{@link org.quartz.Trigger}</code>.
     * </p>
     * 
     * @param newJob
     *          The <code>JobDetail</code> to be stored.
     * @param newTrigger
     *          The <code>Trigger</code> to be stored.
     * @throws ObjectAlreadyExistsException
     *           if a <code>Job</code> with the same name/group already
     *           exists.
     */
    public void storeJobAndTrigger(SchedulingContext ctxt, JobDetail newJob,
            Trigger newTrigger) throws JobPersistenceException {
        storeJob(ctxt, newJob, false);
        storeTrigger(ctxt, newTrigger, false);
    }

    /**
     * <p>
     * Store the given <code>{@link org.quartz.Job}</code>.
     * </p>
     * 
     * @param newJob
     *          The <code>Job</code> to be stored.
     * @param replaceExisting
     *          If <code>true</code>, any <code>Job</code> existing in the
     *          <code>JobStore</code> with the same name & group should be
     *          over-written.
     * @throws ObjectAlreadyExistsException
     *           if a <code>Job</code> with the same name/group already
     *           exists, and replaceExisting is set to false.
     */
    public void storeJob(SchedulingContext ctxt, JobDetail newJob,
            boolean replaceExisting) throws ObjectAlreadyExistsException {
        JobWrapper jw = new JobWrapper((JobDetail)newJob.clone());

        boolean repl = false;

        if (jobsByFQN.get(jw.key) != null) {
            if (!replaceExisting) {
                throw new ObjectAlreadyExistsException(newJob);
            }
            repl = true;
        }

        synchronized (triggerLock) {
            if (!repl) {
                // get job group
                HashMap grpMap = (HashMap) jobsByGroup.get(newJob.getGroup());
                if (grpMap == null) {
                    grpMap = new HashMap(100);
                    jobsByGroup.put(newJob.getGroup(), grpMap);
                }
                // add to jobs by group
                grpMap.put(newJob.getName(), jw);
                // add to jobs by FQN map
                jobsByFQN.put(jw.key, jw);
            } else {
                // update job detail
                JobWrapper orig = (JobWrapper) jobsByFQN.get(jw.key);
                orig.jobDetail = jw.jobDetail; // already cloned
            }
        }
    }

    /**
     * <p>
     * Remove (delete) the <code>{@link org.quartz.Job}</code> with the given
     * name, and any <code>{@link org.quartz.Trigger}</code> s that reference
     * it.
     * </p>
     *
     * @param jobName
     *          The name of the <code>Job</code> to be removed.
     * @param groupName
     *          The group name of the <code>Job</code> to be removed.
     * @return <code>true</code> if a <code>Job</code> with the given name &
     *         group was found and removed from the store.
     */
    public boolean removeJob(SchedulingContext ctxt, String jobName,
            String groupName) {
        String key = JobWrapper.getJobNameKey(jobName, groupName);

        boolean found = false;

        Trigger[] trigger = getTriggersForJob(ctxt, jobName,
                groupName);
        for (int i = 0; i < trigger.length; i++) {
            Trigger trig = trigger[i];
            this.removeTrigger(ctxt, trig.getName(), trig.getGroup());
            found = true;
        }
        synchronized (triggerLock) {
            found = (jobsByFQN.remove(key) != null) | found;
            if (found) {

                HashMap grpMap = (HashMap) jobsByGroup.get(groupName);
                if (grpMap != null) {
                    grpMap.remove(jobName);
                    if (grpMap.size() == 0) {
                        jobsByGroup.remove(groupName);
                    }
                }
            }
        }

        return found;
    }

    /**
     * <p>
     * Store the given <code>{@link org.quartz.Trigger}</code>.
     * </p>
     *
     * @param newTrigger
     *          The <code>Trigger</code> to be stored.
     * @param replaceExisting
     *          If <code>true</code>, any <code>Trigger</code> existing in
     *          the <code>JobStore</code> with the same name & group should
     *          be over-written.
     * @throws ObjectAlreadyExistsException
     *           if a <code>Trigger</code> with the same name/group already
     *           exists, and replaceExisting is set to false.
     *
     * @see #pauseTriggerGroup(SchedulingContext, String)
     */
    public void storeTrigger(SchedulingContext ctxt, Trigger newTrigger,
            boolean replaceExisting) throws JobPersistenceException {
        TriggerWrapper tw = new TriggerWrapper((Trigger)newTrigger.clone());

        if (triggersByFQN.get(tw.key) != null) {
            if (!replaceExisting) {
                throw new ObjectAlreadyExistsException(newTrigger);
            }

            removeTrigger(ctxt, newTrigger.getName(), newTrigger.getGroup(), false);
        }

        if (retrieveJob(ctxt, newTrigger.getJobName(), newTrigger.getJobGroup()) == null) {
            throw new JobPersistenceException("The job ("
                    + newTrigger.getFullJobName()
                    + ") referenced by the trigger does not exist.");
        }

        synchronized (triggerLock) {
            // add to triggers array
            triggers.add(tw);
            // add to triggers by group
            HashMap grpMap = (HashMap) triggersByGroup.get(newTrigger
                    .getGroup());
            if (grpMap == null) {
                grpMap = new HashMap(100);
                triggersByGroup.put(newTrigger.getGroup(), grpMap);
            }
            grpMap.put(newTrigger.getName(), tw);
            // add to triggers by FQN map
            triggersByFQN.put(tw.key, tw);

            if (pausedTriggerGroups.contains(newTrigger.getGroup())
            		|| pausedJobGroups.contains(newTrigger.getJobGroup())) {
                tw.state = TriggerWrapper.STATE_PAUSED;
                if (blockedJobs.contains(tw.jobKey)) {
                    tw.state = TriggerWrapper.STATE_PAUSED_BLOCKED;
                }
            } else if (blockedJobs.contains(tw.jobKey)) {
                tw.state = TriggerWrapper.STATE_BLOCKED;
            } else {
                timeTriggers.add(tw);
            }
        }
    }

    /**
     * <p>
     * Remove (delete) the <code>{@link org.quartz.Trigger}</code> with the
     * given name.
     * </p>
     *
     * @param triggerName
     *          The name of the <code>Trigger</code> to be removed.
     * @param groupName
     *          The group name of the <code>Trigger</code> to be removed.
     * @return <code>true</code> if a <code>Trigger</code> with the given
     *         name & group was found and removed from the store.
     */
    public boolean removeTrigger(SchedulingContext ctxt, String triggerName,
            String groupName) {
        return removeTrigger(ctxt, triggerName, groupName, true);
    }
    private boolean removeTrigger(SchedulingContext ctxt, String triggerName,
            String groupName, boolean removeOrphanedJob) {
        String key = TriggerWrapper.getTriggerNameKey(triggerName, groupName);

        boolean found = false;

        synchronized (triggerLock) {
            // remove from triggers by FQN map
            found = (triggersByFQN.remove(key) == null) ? false : true;
            if (found) {
                TriggerWrapper tw = null;
                // remove from triggers by group
                HashMap grpMap = (HashMap) triggersByGroup.get(groupName);
                if (grpMap != null) {
                    grpMap.remove(triggerName);
                    if (grpMap.size() == 0) {
                        triggersByGroup.remove(groupName);
                    }
                }
                // remove from triggers array
                Iterator tgs = triggers.iterator();
                while (tgs.hasNext()) {
                    tw = (TriggerWrapper) tgs.next();
                    if (key.equals(tw.key)) {
                        tgs.remove();
                        break;
                    }
                }
                timeTriggers.remove(tw);

                if (removeOrphanedJob) {
                    JobWrapper jw = (JobWrapper) jobsByFQN.get(JobWrapper
                            .getJobNameKey(tw.trigger.getJobName(), tw.trigger
                                    .getJobGroup()));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -