/*
* Copyright (c) 2001 - 2012 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.bkprst;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
import org.geoserver.config.GeoServerDataDirectory;
import org.geotools.util.logging.Logging;
import com.thoughtworks.xstream.XStream;
/**
* Class managing queud backuo/restore tasks
*
* @author Luca Morandini lmorandini@ieee.org
*
*/
public class BrManager {
private List<BrTask> tasks;
private ExecutorService exec;
private int taskRetentionTime; // Time (in ms) of completed tasks retention
private BRLockDispatcherCallback writeLocker;
private final static Logger LOGGER = Logging.getLogger(BrManager.class.toString());
private final GeoServerDataDirectory dataRoot;
private XStream xstream;
// ReST paths
public static final String REST_ID = "id";
public static final String REST_MAINPATH = "bkprst";
public static final String REST_TASKPATH = "/task/path";
public static final String REST_INCLUDEDATAPATH = "/task/includedata";
public static final String REST_INCLUDEGWCPATH = "/task/includegwc";
public static final String REST_INCLUDELOGPATH = "/task/includelog";
public BrManager(BRLockDispatcherCallback writeLocker, int taskRetentionTime,
final GeoServerDataDirectory dataRoot) {
this.taskRetentionTime = taskRetentionTime;
this.exec = Executors.newSingleThreadExecutor();
this.tasks = new ArrayList<BrTask>();
this.writeLocker = writeLocker;
this.dataRoot = dataRoot;
// Register XML serialization using XStream
this.xstream = new XStream();
this.xstream.alias("bkprst", BrManager.class);
this.xstream.omitField(BrManager.class, "exec");
this.xstream.omitField(BrManager.class, "taskRetentionTime");
this.xstream.omitField(BrManager.class, "writeLocker");
this.xstream.omitField(BrManager.class, "LOGGER");
this.xstream.omitField(BrManager.class, "dataRoot");
this.xstream.omitField(BrManager.class, "xstream");
this.xstream.omitField(BrManager.class, "test");
this.xstream.aliasField("id", BrTask.class, "id");
this.xstream.aliasField("state", BrTask.class, "state");
this.xstream.aliasField("startTime", BrTask.class, "startTime");
this.xstream.aliasField("endTime", BrTask.class, "endTime");
this.xstream.aliasField("path", BrTask.class, "path");
this.xstream.aliasField("progress", BrTask.class, "progress");
this.xstream.omitField(BrTask.class, "br");
this.xstream.omitField(BrTask.class, "locker");
this.xstream.omitField(BrTask.class, "LOGGER");
this.xstream.omitField(BrTask.class, "dataRoot");
this.xstream.omitField(BrTask.class, "act");
this.xstream.omitField(BrTask.class, "dataFilter");
this.xstream.omitField(BrTask.class, "gwcFilter");
this.xstream.omitField(BrTask.class, "logFilter");
this.xstream.omitField(BackupTask.class, "trans");
this.xstream.omitField(RestoreTask.class, "trans");
this.xstream.alias("backup", BackupTask.class);
this.xstream.alias("restore", RestoreTask.class);
}
/**
* Retutns a new task UUID
*/
public UUID generateId() {
return UUID.randomUUID();
}
/**
* Adds a given task to the execution queue after cleanuo
*/
synchronized public UUID addTask(BrTask task) {
this.cleanupTasks();
task.setDataRoot(this.dataRoot);
task.setBrManager(this);
this.tasks.add(task);
this.exec.execute(task);
LOGGER.finest("Added backup task " + task.id.toString());
return task.getId();
}
/**
* Adds a backup task to the execution queue after cleanuo
*
* @param path
* Path to backup configuraiton to
*/
synchronized public UUID addBackupTask(String path, boolean includeData, boolean includeGwc,
boolean includeLog) {
BackupTask task = new BackupTask(this.generateId(), path, this.writeLocker, this.dataRoot);
task.setBrManager(this);
task.setIncludeData(includeData);
task.setIncludeGwc(includeGwc);
task.setIncludeLog(includeLog);
return this.addTask(task);
}
/**
* Adds a restore task to the execution queue after cleanup
*
* @param path
* Path from which restor the configuraiton from
*/
synchronized public UUID addRestoreTask(String path) {
RestoreTask task = new RestoreTask(this.generateId(), path, this.writeLocker, this.dataRoot);
task.setBrManager(this);
return this.addTask(task);
}
/**
* Attempts to stop a given task after cleanup
*
* @param id
* ID of task to stop
*/
public void stopBackupTask(UUID id) throws UnallowedOperationException, TaskNotFoundException {
BrTask task = this.getTask(id);
if (task == null) {
throw new TaskNotFoundException("Task " + id + " was not found");
}
if (task.isBackup()) {
this.cleanupTasks();
((BackupTask) (task)).stop();
} else {
throw new UnallowedOperationException("Stopping a restore task is not allowed");
}
}
/**
* Returns an tasks as a Collection
*/
public Collection<BrTask> getAllTasks() {
return this.tasks;
}
/**
* Returns a given task after deleting stale ones
*
* @param id
* ID of task to stop
*/
public BrTask getTask(UUID id) {
this.cleanupTasks();
Iterator<BrTask> iter = this.tasks.iterator();
while (iter.hasNext()) {
BrTask nextTask = iter.next();
if (nextTask.getId().equals(id)) {
return nextTask;
}
}
return null;
}
/**
* Checks if a task has completed and its life after completion has surpassed the retention time
*
* @param task
* Task to check
*/
private boolean isStale(BrTask task) {
if (task.getState().completed()
&& ((new Date()).getTime() - task.getEndTime().getTime()) > this.taskRetentionTime) {
return true;
} else {
return false;
}
}
/**
* Deletes stale tasks
*/
synchronized public void cleanupTasks() {
Iterator<BrTask> iter = this.tasks.iterator();
while (iter.hasNext()) {
BrTask entry = iter.next();
if (this.isStale(entry)) {
LOGGER.finest("Removed task " + entry.getId().toString());
iter.remove();
}
}
}
public int getTaskRetentionTime() {
return taskRetentionTime;
}
public void setTaskRetentionTime(int taskRetentionTime) {
this.taskRetentionTime = taskRetentionTime;
}
public BRLockDispatcherCallback getWriteLocker() {
return writeLocker;
}
public void setWriteLocker(BRLockDispatcherCallback writeLocker) {
this.writeLocker = writeLocker;
}
/**
* Serializes an object to XML
*
* @param obj
* Object to serialize
*/
public String toXML(Object obj) {
return this.xstream.toXML(obj);
}
/**
* De-erializes an object from XML
*
* @param xml
* XML to get the object from
*
* @param obj
* Object to populate
*/
public void fromXML(String xml, Object obj) {
this.xstream.fromXML(xml, obj);
}
}