package com.destinationradiodenver.mobileStreaming.application;
import java.io.Serializable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.ejb.AccessTimeout;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import org.jboss.logging.Logger;
import com.destinationradiodenver.mobileConsole.tasks.StopEncoderTask;
import com.destinationradiodenver.mobileStreaming.messages.EncoderDispatchMessage;
import com.destinationradiodenver.mobileStreaming.messages.EncoderDispatchMessage.Task;
import com.destinationradiodenver.mobileStreaming.web.entity.Encoder;
import com.destinationradiodenver.mobileStreaming.web.entity.Stream;
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@AccessTimeout(value = 10, unit = TimeUnit.SECONDS)
@Named
public class Encoders extends CopyOnWriteArrayList<Encoder> implements Serializable {
/**
* @author cpenhale
*/
private static final long serialVersionUID = -5411315964008656521L;
private static final Logger log = Logger.getLogger(Encoders.class);
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
@PersistenceContext
private EntityManager entityManager;
private static ConcurrentHashMap<String,Future<StopEncoderTask>> running = new ConcurrentHashMap<String,Future<StopEncoderTask>>();
@Inject
EncoderDispatcher encoderDispatcher;
public Encoders() {
}
@Override
public boolean add(Encoder o){
if(super.contains(o)){
if(o.getStream()!=null){
log.infof("Encoders was asked to add an Encoder that already exists (%s). Stopping/removing existing Encoder before continuing", o.getStream()+"_"+o.getMobileProfile().getName());
remove(o);
}
}
log.info("Adding encoder");
boolean status = super.add(o);
Stream stream = o.getStream();
if(stream!=null){
if(stream.getRestartEncodersEveryMinutes()>0){
ScheduledFuture<StopEncoderTask> task = (ScheduledFuture<StopEncoderTask>) scheduler.scheduleAtFixedRate(new StopEncoderTask(o), stream.getRestartEncodersEveryMinutes(), stream.getRestartEncodersEveryMinutes(), TimeUnit.MINUTES);
running.put(o.getStream()+"_"+o.getMobileProfile().getName(),task);
log.infof("scheduled encoder restart %s minutes from now ad infinitum", stream.getRestartEncodersEveryMinutes());
}else{
log.info("not scheduling encoder restart");
}
}else{
log.info("failed to get stream");
log.info("not scheduling encoder restart");
}
return status;
}
@Override
public boolean remove(Object o){
log.info("Removing encoder");
boolean status = super.remove(o);
if(o instanceof Encoder){
Encoder encoder = (Encoder) o;
Stream stream = encoder.getStream();
if(stream!=null){
if(stream.getAutomaticallyStartEncoders()){
log.info("got stream");
EncoderDispatchMessage edm = EncoderDispatchMessage.generateEncoderDispatchMessage(encoder);
edm.setTask(Task.START_ENCODING);
encoderDispatcher.dispatch(edm);
log.info("dispatched automatic restart message");
}else{
log.info("not automatically restarting encoder");
if(stream.getRestartEncodersEveryMinutes()>0){
log.info("Cancelling auto restart encoder task");
Future<StopEncoderTask> task = running.get(stream+"_"+encoder.getMobileProfile().getName());
task.cancel(false);
running.remove(encoder.getStream()+"_"+encoder.getMobileProfile().getName());
}
}
}else{
log.info("failed to get stream");
}
}else{
log.info("not an encoder");
}
return status;
}
}