/*
* Copyright 2012 dominictootell
*
* 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.greencheek.processio.service.scheduler;
import org.greencheek.processio.domain.CurrentProcessIO;
import org.greencheek.processio.service.io.ProcessIOReader;
import org.greencheek.processio.service.persistence.ProcessIOUsagePersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
* <p>
* Uses a single threaded executor service the contains a runnable task that simply:
* <ul>
* <li>calls {@link org.greencheek.processio.service.io.ProcessIOReader#getCurrentProcessIO()}</li>
* <li>asks for the resulting {@link CurrentProcessIO} to be persisted by the implementation of {@link ProcessIOUsagePersistence}</li>
* <li>The {@link CurrentProcessIO} is only requested to be persisted if is not the {@link ProcessIOReader#NON_READABLE_PROCESS_IO} instance</li>
* </ul>
* </p>
* <p>
* User: dominictootell
* Date: 22/04/2012
* Time: 18:38
* </p>
*/
public class ScheduledExecutorServiceProcessIOScheduler implements ProcessIOScheduler {
private static final Logger log = LoggerFactory.getLogger(ScheduledExecutorServiceProcessIOScheduler.class);
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
private final ProcessIOReader reader;
private final ProcessIOUsagePersistence persistence;
private final long frequencyInMillis;
private volatile ScheduledFuture<?> submittedTask;
private volatile boolean stopped = false;
public ScheduledExecutorServiceProcessIOScheduler(ProcessIOReader ioReader, ProcessIOUsagePersistence persistence) {
this(ioReader,persistence,DEFAULT_FREQUENCY_IN_MILLIS);
}
public ScheduledExecutorServiceProcessIOScheduler(ProcessIOReader ioReader, ProcessIOUsagePersistence persistence, long frequencyInMillis) {
this.reader = ioReader;
this.persistence = persistence;
this.frequencyInMillis = frequencyInMillis;
}
/**
* Can only be called once. This stops the executor from running; shutting it down
* In order for the executor to re-run, and new instance of the class should be created.
*/
@Override
public synchronized void stop() {
if(stopped) return;
try {
if(submittedTask!=null) {
submittedTask.cancel(true);
}
submittedTask = null;
scheduler.shutdownNow();
} finally {
stopped = true;
}
}
/**
* Starts the process of periodically obtaining the io usage of the current jvm processing, and
* asking for that to be persisted.
*
* @param frequencyInMillis The frequency in millis to run the process of obtaining process io info
*/
public synchronized void start(long frequencyInMillis) {
if(!stopped) {
submittedTask = scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
log.info("Obtaining process io");
CurrentProcessIO io = reader.getCurrentProcessIO();
if(io != ProcessIOReader.NON_READABLE_PROCESS_IO) persistence.persist(io);
else log.warn("Unable to read process io");
} catch (Exception e) {
log.error("Exception occurred whilst reading current process io",e);
}
}
},0,frequencyInMillis, TimeUnit.MILLISECONDS);
}
}
@Override
public void start() {
start(this.frequencyInMillis);
}
/**
* Makes sure that the thread in the Scheduled Executor don't stop the JVM from exiting
*/
private static class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
}
}