/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Arne Kepp / The Open Planning Project 2008
*/
package org.geowebcache.seed;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geowebcache.GeoWebCacheException;
/**
*
*/
public abstract class GWCTask {
private static final Log log = LogFactory.getLog(GWCTask.class);
public static enum TYPE {
UNSET, SEED, RESEED, TRUNCATE
};
public static enum STATE {
UNSET, READY, RUNNING, DONE, DEAD
};
/**
* Value shared between all the threads in the group, is incremented each time a task starts
* working and decremented each time one task finishes (either normally or abnormally)
*/
protected AtomicInteger sharedThreadCount = new AtomicInteger();
protected int threadOffset = 0;
long taskId = -1;
protected TYPE parsedType = TYPE.UNSET;
protected STATE state = STATE.UNSET;
protected String layerName = null;
protected long timeSpent = -1;
protected long timeRemaining = -1;
protected long tilesDone = -1;
protected long tilesTotal = -1;
protected boolean terminate = false;
private long groupStartTime;
/**
* Marks this task as active in the group by incrementing the shared counter, delegates to
* {@link #doActionInternal()}, and makes sure to remove this task from the group count.
*/
public final void doAction() throws GeoWebCacheException, InterruptedException {
this.sharedThreadCount.incrementAndGet();
this.groupStartTime = System.currentTimeMillis();
try {
doActionInternal();
} finally {
dispose();
int membersRemaining = this.sharedThreadCount.decrementAndGet();
if (0 == membersRemaining) {
double groupTotalTimeSecs = (System.currentTimeMillis() - (double) groupStartTime) / 1000;
log.info("Thread group finished " + parsedType + " task after "
+ groupTotalTimeSecs + " seconds");
}
}
}
protected abstract void dispose();
/**
* Extension point for subclasses to do what they do
*/
protected abstract void doActionInternal() throws GeoWebCacheException, InterruptedException;
/**
* @param sharedThreadCount
* a counter of number of active tasks in the task group, incremented when this task
* starts working and decremented when it stops
* @param threadOffset
* REVISIT: may not be needed anymore. Just check if sharedThreadCount == 1?
*/
public void setThreadInfo(AtomicInteger sharedThreadCount, int threadOffset) {
this.sharedThreadCount = sharedThreadCount;
this.threadOffset = threadOffset;
}
public void setTaskId(long taskId) {
this.taskId = taskId;
}
public long getTaskId() {
return taskId;
}
public int getThreadCount() {
return sharedThreadCount.get();
}
public int getThreadOffset() {
return threadOffset;
}
public String getLayerName() {
return layerName;
}
/**
* @return total number of tiles (in the whole task group), or < 0 if too many to count
*/
public long getTilesTotal() {
return tilesTotal;
}
public long getTilesDone() {
return tilesDone;
}
/**
* @return estimated remaining time in seconds, or {@code -2} if unknown
*/
public long getTimeRemaining() {
if (tilesTotal > 0) {
return timeRemaining;
} else {
return -2;
}
}
/**
* @return task time spent in seconds
*/
public long getTimeSpent() {
return timeSpent;
}
public void terminateNicely() {
this.terminate = true;
}
public TYPE getType() {
return parsedType;
}
public STATE getState() {
return state;
}
protected void checkInterrupted() throws InterruptedException {
if (Thread.interrupted()) {
this.state = STATE.DEAD;
throw new InterruptedException();
}
}
@Override
public String toString() {
return new StringBuilder("[").append(getTaskId()).append(": ").append(getLayerName())
.append(", ").append(getType()).append(", ").append(getState()).append("]")
.toString();
}
}