package com.netifera.platform.tasks.internal; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import com.netifera.platform.api.dispatcher.DispatchException; import com.netifera.platform.api.dispatcher.DispatchMismatchException; import com.netifera.platform.api.dispatcher.IMessageDispatcher; import com.netifera.platform.api.dispatcher.IMessageDispatcherService; import com.netifera.platform.api.dispatcher.IMessageHandler; import com.netifera.platform.api.dispatcher.IMessenger; import com.netifera.platform.api.dispatcher.IProbeMessage; import com.netifera.platform.api.dispatcher.MessengerException; import com.netifera.platform.api.log.ILogManager; import com.netifera.platform.api.log.ILogger; import com.netifera.platform.api.model.IModelService; import com.netifera.platform.api.tasks.ITask; import com.netifera.platform.api.tasks.ITaskManagerService; import com.netifera.platform.api.tasks.ITaskStatus; import com.netifera.platform.api.tasks.ITaskRunnable; import com.netifera.platform.tasks.TaskStatus; import com.netifera.platform.tasks.messages.TaskCancelMessage; import com.netifera.platform.tasks.messages.TaskListMessage; import com.netifera.platform.tasks.messages.TaskStartMessage; import com.netifera.platform.tasks.messages.TasksSubscribeMessage; public class TaskManager implements ITaskManagerService { private static final ThreadPoolExecutor exec = (ThreadPoolExecutor)Executors.newFixedThreadPool(10); private static final Map<Long,Task> tasks = new HashMap<Long,Task>(); private IModelService model; private ILogger logger; /* * TaskCancelMessage --> taskCancelHandler * TaskListMessage --> taskListHandler * TaskSubscribeMessage --> subscribeToTasks */ private void registerHandlers(IMessageDispatcher dispatcher) { IMessageHandler handler = new IMessageHandler() { public void call(IMessenger messenger, IProbeMessage message) throws DispatchException { if(message instanceof TaskCancelMessage) { taskCancelHandler((TaskCancelMessage) message); } else if(message instanceof TaskListMessage) { taskListHandler(messenger, (TaskListMessage) message); } else if(message instanceof TasksSubscribeMessage) { subscribeToTasks( ((TasksSubscribeMessage)message).getTaskList(), messenger); } else if(message instanceof TaskStartMessage) { startTask(messenger, (TaskStartMessage)message); } else { throw new DispatchMismatchException(message); } } }; dispatcher.registerMessageHandler(TaskCancelMessage.ID, handler); dispatcher.registerMessageHandler(TaskListMessage.ID, handler); dispatcher.registerMessageHandler(TasksSubscribeMessage.ID, handler); dispatcher.registerMessageHandler(TaskStartMessage.ID, handler); } public ITask createTask(ITaskRunnable runnable, IMessenger messenger) { synchronized(this) { long newTaskId = model.getCurrentWorkspace().generateTaskId(); TaskStatus record = new TaskStatus(runnable.getClassName(), newTaskId); Task task = new Task(record, runnable, messenger, this, logger); tasks.put(newTaskId,task); return task; } } void runTask(Task t) { exec.execute(t); } private void taskCancelHandler(TaskCancelMessage message) { long taskIdList[] = message.getTaskList(); if(taskIdList == null) { return; } for(long taskId : taskIdList) { if(tasks.containsKey(taskId)) { Task task = tasks.get(taskId); if(task.getStatus().isWaiting()) { synchronized(tasks) { exec.remove(task); task.cancel(); tasks.remove(taskId); } } else if(task.getStatus().isRunning()) { task.cancel(); } } } } private void taskListHandler(IMessenger messenger, TaskListMessage message) { synchronized(tasks) { ITaskStatus[] tasksArray = new ITaskStatus[tasks.size()]; int i = 0; for(Task t : tasks.values()) { tasksArray[i] = t.getStatus(); i++; } sendResponse(messenger, message.createResponse(tasksArray)); } } private void sendResponse(IMessenger messenger, IProbeMessage message) { try { messenger.emitMessage(message); } catch (MessengerException e) { logger.error("Failed to send message response", e); } } private void subscribeToTasks(List<Long> tasksIds, IMessenger messenger) { /* if list null or empty subscribe to every task */ if(tasksIds == null || tasksIds.size() == 0) { for(Task task : tasks.values()) { task.setMessenger(messenger); } } else { for(Long taskId : tasksIds) { if(tasks.containsKey(taskId)) { tasks.get(taskId).setMessenger(messenger); } } } } private void startTask(IMessenger messenger, TaskStartMessage message) { final long id = message.getTaskId(); final Task task = tasks.get(id); if(task == null) { sendError(messenger, message, "No such task exists"); return; } if(task.isStarted()) { sendError(messenger, message, "Task is already started"); return; } sendOk(messenger, message); task.start(); } private void sendError(IMessenger messenger, IProbeMessage message, String errorMsg) { try { messenger.respondError(message, errorMsg); } catch (MessengerException e) { logger.warning("Failed to send error response", e); } } private void sendOk(IMessenger messenger, IProbeMessage message) { try { messenger.respondOk(message); } catch (MessengerException e) { logger.warning("Failed to send Ok response", e); } } // OSGi DS protected void setDispatcher(IMessageDispatcherService dispatcherService) { registerHandlers(dispatcherService.getServerDispatcher()); } protected void unsetDispatcher(IMessageDispatcherService dispatcherService) { } protected void setModelService(IModelService model) { this.model = model; } protected void unsetModelService(IModelService model) { } protected void setLogManager(ILogManager logManager) { logger = logManager.getLogger("Task Manager"); } protected void unsetLogManager(ILogManager logManager) { logger = null; } }