/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.maven.server.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* Executor for {@link MavenProjectTask}. Uses {@link MavenExecutorService} as executor service.
*
* @author Evgen Vidolob
*/
public class MavenTaskExecutor {
private static final Logger LOG = LoggerFactory.getLogger(MavenTaskExecutor.class);
private final MavenExecutorService service;
private final MavenProgressNotifier notifier;
private final Queue<MavenProjectTask> queue = new LinkedList<>();
private boolean isWorking;
public MavenTaskExecutor(MavenExecutorService service, MavenProgressNotifier notifier) {
this.service = service;
this.notifier = notifier;
}
public void submitTask(MavenProjectTask task) {
synchronized (queue) {
//if no running tasks, start immediately
if (!isWorking) {
isWorking = true;
runTask(task);
} else {
if (!queue.contains(task)) {
queue.add(task);
}
}
}
}
public void removeTask(MavenProjectTask task) {
synchronized (queue) {
queue.remove(task);
}
}
public void stop() {
synchronized (queue) {
queue.clear();
}
}
private void runTask(MavenProjectTask task) {
service.submit(() -> doRunTasks(task));
}
private void doRunTasks(MavenProjectTask task) {
int taskDone = 0;
notifier.start();
while (true) {
taskDone++;
int restTasks;
synchronized (queue) {
restTasks = queue.size();
}
notifier.setPercent((double)taskDone / (double)(restTasks + taskDone));
try {
task.perform();
} catch (Throwable throwable) {
LOG.error(throwable.getMessage(), throwable);
//TODO need to notify user some how
}
synchronized (queue) {
task = queue.poll();
if (task == null) {
isWorking = false;
notifier.stop();
return;
}
}
}
}
public void waitForEndAllTasks() {
if(!isWorking){
return;
}
Semaphore semaphore = new Semaphore(1);
try {
semaphore.acquire();
submitTask(semaphore::release);
while (true) {
if (!isWorking || semaphore.tryAcquire(1, TimeUnit.SECONDS)) {
return;
}
}
} catch (InterruptedException e) {
LOG.debug(e.getMessage(), e);
}
}
}