All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.red5.server.scheduling.JDKSchedulingService Maven / Gradle / Ivy

There is a newer version: 2.0.12
Show newest version
/*
 * RED5 Open Source Media Server - https://github.com/Red5/ Copyright 2006-2023 by respective authors (see below). All rights reserved. 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.
 */

package org.red5.server.scheduling;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.scheduling.IScheduledJob;
import org.red5.server.api.scheduling.ISchedulingService;
import org.red5.server.jmx.mxbeans.JDKSchedulingServiceMXBean;
import org.slf4j.Logger;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jmx.export.annotation.ManagedResource;

/**
 * Scheduling service that uses JDK ScheduledExecutor as backend.
 *
 * @author The Red5 Project
 * @author Paul Gregoire ([email protected])
 */
@ManagedResource(objectName = "org.red5.server:name=schedulingService,type=JDKSchedulingService")
public class JDKSchedulingService implements ISchedulingService, JDKSchedulingServiceMXBean, InitializingBean, DisposableBean {

    private static Logger log = Red5LoggerFactory.getLogger(JDKSchedulingService.class);

    /**
     * Service scheduler
     */
    protected ScheduledExecutorService scheduler;

    protected int threadCount = Runtime.getRuntime().availableProcessors() * 2;

    /**
     * Storage for job futures keyed by name
     */
    protected ConcurrentMap> keyMap = new ConcurrentHashMap<>();

    protected AtomicInteger jobDetailCounter = new AtomicInteger();

    private boolean interruptOnRemove = true;

    /** Constructs a new JDKSchedulingService. */
    public void afterPropertiesSet() throws Exception {
        log.debug("Initializing...");
        scheduler = Executors.newScheduledThreadPool(threadCount);
    }

    /**
     * @return the threadCount
     */
    public int getThreadCount() {
        return threadCount;
    }

    /**
     * @param threadCount
     *            the threadCount to set
     */
    public void setThreadCount(int threadCount) {
        this.threadCount = threadCount;
    }

    /** {@inheritDoc} */
    public String addScheduledJob(int interval, IScheduledJob job) {
        String name = getJobName();
        // Store reference to applications job and service
        Map jobData = new HashMap<>();
        jobData.put(ISchedulingService.SCHEDULING_SERVICE, this);
        jobData.put(ISchedulingService.SCHEDULED_JOB, job);
        // runnable task with false to prevent removal after it runs, since this job is meant to iterate
        JDKSchedulingServiceJob schedJob = new JDKSchedulingServiceJob(name, jobData, false);
        // schedule it to run at interval
        ScheduledFuture future = scheduler.scheduleAtFixedRate(schedJob, interval, interval, TimeUnit.MILLISECONDS);
        // add to the key map
        keyMap.put(name, future);
        return name;
    }

    /** {@inheritDoc} */
    public String addScheduledOnceJob(Date date, IScheduledJob job) {
        String name = getJobName();
        // Store reference to applications job and service
        Map jobData = new HashMap<>();
        jobData.put(ISchedulingService.SCHEDULING_SERVICE, this);
        jobData.put(ISchedulingService.SCHEDULED_JOB, job);
        // runnable task
        JDKSchedulingServiceJob schedJob = new JDKSchedulingServiceJob(name, jobData);
        // calculate the delay
        long delay = date.getTime() - System.currentTimeMillis();
        // schedule it to run once after the specified delay
        ScheduledFuture future = scheduler.schedule(schedJob, delay, TimeUnit.MILLISECONDS);
        // add to the key map
        keyMap.put(name, future);
        return name;
    }

    /** {@inheritDoc} */
    public String addScheduledOnceJob(long timeDelta, IScheduledJob job) {
        // Create trigger that fires once in  milliseconds
        String name = getJobName();
        // Store reference to applications job and service
        Map jobData = new HashMap<>();
        jobData.put(ISchedulingService.SCHEDULING_SERVICE, this);
        jobData.put(ISchedulingService.SCHEDULED_JOB, job);
        // runnable task
        JDKSchedulingServiceJob schedJob = new JDKSchedulingServiceJob(name, jobData);
        // schedule it to run once after the specified delay
        ScheduledFuture future = scheduler.schedule(schedJob, timeDelta, TimeUnit.MILLISECONDS);
        // add to the key map
        keyMap.put(name, future);
        return name;
    }

    /** {@inheritDoc} */
    public String addScheduledJobAfterDelay(int interval, IScheduledJob job, int delay) {
        String name = getJobName();
        // Store reference to applications job and service
        Map jobData = new HashMap<>();
        jobData.put(ISchedulingService.SCHEDULING_SERVICE, this);
        jobData.put(ISchedulingService.SCHEDULED_JOB, job);
        // runnable task with false to prevent removal after it runs, since this job is meant to iterate
        JDKSchedulingServiceJob schedJob = new JDKSchedulingServiceJob(name, jobData, false);
        // schedule it to run at interval
        ScheduledFuture future = scheduler.scheduleAtFixedRate(schedJob, delay, interval, TimeUnit.MILLISECONDS);
        // add to the key map
        keyMap.put(name, future);
        return name;
    }

    /**
     * Getter for job name.
     *
     * @return Job name
     */
    public String getJobName() {
        return String.format("ScheduledJob_%d", jobDetailCounter.getAndIncrement());
    }

    /** {@inheritDoc} */
    public List getScheduledJobNames() {
        if (scheduler != null) {
            return new ArrayList<>(keyMap.keySet());
        } else {
            log.warn("No scheduler is available");
        }
        return Collections.emptyList();
    }

    /** {@inheritDoc} */
    public void pauseScheduledJob(String name) {
        throw new RuntimeException("Pause is not supported for ScheduledFuture");
    }

    /** {@inheritDoc} */
    public void resumeScheduledJob(String name) {
        throw new RuntimeException("Pause/resume is not supported for ScheduledFuture");
    }

    /** {@inheritDoc} */
    public void removeScheduledJob(String name) {
        try {
            ScheduledFuture future = keyMap.remove(name);
            // check done before we attempt cancelling
            if (future != null && !future.isDone()) {
                future.cancel(interruptOnRemove);
            } else {
                log.debug("No key found for job: {} or the job was done", name);
            }
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public void destroy() throws Exception {
        if (scheduler != null) {
            log.debug("Destroying...");
            scheduler.shutdownNow();
        }
        keyMap.clear();
    }

    public boolean isInterruptOnRemove() {
        return interruptOnRemove;
    }

    public void setInterruptOnRemove(boolean interruptOnRemove) {
        this.interruptOnRemove = interruptOnRemove;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy