use of cz.metacentrum.perun.taskslib.model.TaskSchedule in project perun by CESNET.
the class TaskScheduler method run.
// ----- methods -------------------------------------
/**
* This method runs in separate thread perpetually trying to take tasks from delay queue, blocking if none are available.
* If there is Task ready, we check if it source was updated. If it was, we put the task back to the queue (This
* can happen only limited number of times). If on the other hand it was not updated we perform additional checks using
* method sendToEngine.
*/
@Override
public void run() {
try {
initPerunSession();
} catch (InternalErrorException e1) {
String message = "Dispatcher was unable to initialize Perun session.";
log.error(message, e1);
throw new RuntimeException(message, e1);
}
log.debug("Pool contains {} tasks in total", schedulingPool.getSize());
TaskSchedule schedule;
while (!shouldStop()) {
try {
if (tasksManagerBl.isSuspendedTasksPropagation()) {
// do not continue sending tasks to the engine until propagation is set to resume
waitForResumingPropagation();
}
schedule = getWaitingTaskSchedule();
} catch (InterruptedException e) {
String message = "Thread was interrupted, cannot continue.";
log.error(message, e);
throw new RuntimeException(message, e);
}
Task task = schedule.getTask();
if (task.isSourceUpdated() && schedule.getDelayCount() > 0 && !task.isPropagationForced()) {
// source data changed before sending, wait for more changes to come -> reschedule
log.warn("[{}] Task was not allowed to be sent to Engine now: {}.", task.getId(), task);
schedulingPool.scheduleTask(task, schedule.getDelayCount() - 1);
} else {
// send it to engine
TaskScheduled reason = sendToEngine(task);
switch(reason) {
case QUEUE_ERROR:
log.warn("[{}] Task dispatcherQueue could not be set, so it is rescheduled: {}.", task.getId(), task);
schedulingPool.scheduleTask(task, -1);
break;
case DENIED:
// Task is lost from waiting queue, since somebody blocked service on facility, all destinations or globally
log.info("[{}] Execution was denied for Task before sending to Engine: {}.", task.getId(), task);
break;
case ERROR:
log.error("[{}] Unexpected error when scheduling Task, so it is rescheduled: {}.", task.getId(), task);
schedulingPool.scheduleTask(task, -1);
break;
case SUCCESS:
log.info("[{}] Task was successfully sent to Engine: {}.", task.getId(), task);
break;
case DB_ERROR:
// Task is lost from waiting queue, will be cleared from pool by propagation maintainer
log.warn("[{}] Facility, Service or Destination could not be found in DB for Task {}.", task.getId(), task);
break;
}
// update task status in DB
tasksManagerBl.updateTask(perunSession, task);
}
}
log.debug("TaskScheduler has stopped.");
}
use of cz.metacentrum.perun.taskslib.model.TaskSchedule in project perun by CESNET.
the class SchedulingPoolImpl method scheduleTask.
@Override
public void scheduleTask(Task task, int delayCount) {
// check if service/facility exists
boolean removeTask = false;
try {
Service service = perun.getServicesManager().getServiceById(sess, task.getServiceId());
Facility facility = perun.getFacilitiesManager().getFacilityById(sess, task.getFacilityId());
task.setService(service);
task.setFacility(facility);
} catch (ServiceNotExistsException e) {
log.error("[{}] Task NOT added to waiting queue, service not exists: {}.", task.getId(), task);
removeTask = true;
} catch (FacilityNotExistsException e) {
log.error("[{}] Task NOT added to waiting queue, facility not exists: {}.", task.getId(), task);
removeTask = true;
} catch (InternalErrorException | PrivilegeException e) {
log.error("[{}] {}", task.getId(), e);
}
if (!task.getService().isEnabled() || ((PerunBl) perun).getServicesManagerBl().isServiceBlockedOnFacility(task.getService(), task.getFacility())) {
log.error("[{}] Task NOT added to waiting queue, service is blocked: {}.", task.getId(), task);
// do not change Task status or any other data !
if (!removeTask)
return;
}
try {
List<Destination> destinations = perun.getServicesManager().getDestinations(sess, task.getService(), task.getFacility());
if (destinations != null && !destinations.isEmpty()) {
Iterator<Destination> iter = destinations.iterator();
while (iter.hasNext()) {
Destination dest = iter.next();
if (((PerunBl) perun).getServicesManagerBl().isServiceBlockedOnDestination(task.getService(), dest.getId())) {
iter.remove();
}
}
if (destinations.isEmpty()) {
// All service destinations were blocked -> Task is denied to be sent to engine just like
// when service is blocked globally in Perun or on facility as a whole.
log.debug("[{}] Task NOT added to waiting queue, all its destinations are blocked.", task.getId());
if (!removeTask)
return;
}
}
} catch (ServiceNotExistsException e) {
log.error("[{}] Task NOT added to waiting queue, service not exists: {}.", task.getId(), task);
removeTask = true;
} catch (FacilityNotExistsException e) {
log.error("[{}] Task NOT added to waiting queue, facility not exists: {}.", task.getId(), task);
removeTask = true;
} catch (InternalErrorException | PrivilegeException e) {
log.error("[{}] {}", task.getId(), e);
}
try {
List<Service> assignedServices = perun.getServicesManager().getAssignedServices(sess, task.getFacility());
if (!assignedServices.contains(task.getService())) {
log.debug("[{}] Task NOT added to waiting queue, service is not assigned to facility any more: {}.", task.getId(), task);
if (!removeTask)
return;
}
} catch (FacilityNotExistsException e) {
removeTask = true;
log.error("[{}] Task removed from database, facility no longer exists: {}.", task.getId(), task);
} catch (InternalErrorException | PrivilegeException e) {
log.error("[{}] Unable to check Service assignment to Facility: {}", task.getId(), e.getMessage());
}
if (removeTask) {
// in memory task belongs to non existent facility/service - remove it and return
try {
removeTask(task);
return;
} catch (TaskStoreException e) {
log.error("[{}] Unable to remove Task from pool: {}.", task.getId(), e);
return;
}
}
// Task is eligible for running - create new schedule
task.setSourceUpdated(false);
long newTaskDelay = 0;
if (!task.isPropagationForced()) {
// normal tasks are delayed
try {
newTaskDelay = Long.parseLong(dispatcherProperties.getProperty("dispatcher.task.delay.time"));
} catch (NumberFormatException e) {
log.warn("Could not parse value of dispatcher.task.delay.time property. Using default.");
newTaskDelay = 30000;
}
}
if (task.isPropagationForced()) {
delayCount = 0;
}
if (delayCount < 0) {
try {
delayCount = Integer.parseInt(dispatcherProperties.getProperty("dispatcher.task.delay.count"));
} catch (NumberFormatException e) {
log.warn("Could not parse value of dispatcher.task.delay.count property. Using default.");
delayCount = 4;
}
}
TaskSchedule schedule = new TaskSchedule(newTaskDelay, task);
schedule.setBase(System.currentTimeMillis());
schedule.setDelayCount(delayCount);
// Task was newly planned for propagation, switch state.
if (!task.getStatus().equals(TaskStatus.WAITING)) {
task.setStatus(TaskStatus.WAITING);
task.setSchedule(LocalDateTime.now());
// clear previous timestamps
task.setSentToEngine((LocalDateTime) null);
task.setStartTime((LocalDateTime) null);
task.setGenStartTime((LocalDateTime) null);
task.setSendStartTime((LocalDateTime) null);
task.setEndTime((LocalDateTime) null);
task.setGenEndTime((LocalDateTime) null);
task.setSendEndTime((LocalDateTime) null);
tasksManagerBl.updateTask(sess, task);
}
boolean added = false;
if (schedule.getTask().isPropagationForced()) {
added = waitingForcedTasksQueue.add(schedule);
} else {
added = waitingTasksQueue.add(schedule);
}
if (!added) {
log.error("[{}] Task could not be added to waiting queue. Shouldn't ever happen. Look to javadoc of DelayQueue. {}", task.getId(), schedule);
} else {
log.debug("[{}] Task was added to waiting queue: {}", task.getId(), schedule);
}
}
use of cz.metacentrum.perun.taskslib.model.TaskSchedule in project perun by CESNET.
the class TaskScheduler method getWaitingTaskSchedule.
/**
* Internal method which chooses next Task that will be processed, we try to take forced Task first,
* and if none is available, then we wait for a normal Task for a few seconds.
*
* @return Once one of the Queues returns non null TaskSchedule, we return it.
* @throws InterruptedException When blocking queue polling was interrupted.
*/
private TaskSchedule getWaitingTaskSchedule() throws InterruptedException {
TaskSchedule taskSchedule = null;
while (!shouldStop()) {
log.debug(schedulingPool.getReport());
log.debug("WaitingTasksQueue has {} normal Tasks and {} forced Tasks.", waitingTasksQueue.size(), waitingForcedTasksQueue.size());
taskSchedule = waitingForcedTasksQueue.poll();
if (taskSchedule == null) {
taskSchedule = waitingTasksQueue.poll(10, TimeUnit.SECONDS);
}
if (taskSchedule != null) {
break;
}
}
log.trace("[{}] Returning Task schedule {}.", taskSchedule.getTask().getId(), taskSchedule);
return taskSchedule;
}
Aggregations