package cz.cuni.mff.d3s.been.objectrepository.janitor;
import cz.cuni.mff.d3s.been.cluster.Names;
import cz.cuni.mff.d3s.been.core.persistence.Entities;
import cz.cuni.mff.d3s.been.core.task.TaskContextState;
import cz.cuni.mff.d3s.been.core.task.TaskState;
import cz.cuni.mff.d3s.been.persistence.QueryAnswer;
import cz.cuni.mff.d3s.been.persistence.QueryBuilder;
import cz.cuni.mff.d3s.been.persistence.task.PersistentContextState;
import cz.cuni.mff.d3s.been.persistence.task.PersistentTaskState;
import cz.cuni.mff.d3s.been.storage.Storage;
import cz.cuni.mff.d3s.been.util.JSONUtils;
import cz.cuni.mff.d3s.been.util.JsonException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
/**
* Looks up trash that needs taking out
*
* @author darklight
*/
class TrashSeeker {
private static final Logger log = LoggerFactory.getLogger(TrashSeeker.class);
private final Storage storage;
private final JSONUtils jsonUtils;
private final Collection<PersistentTaskState> dummyFailTaskStateCollection;
private final Collection<PersistentContextState> dummyFailContextStateCollection;
TrashSeeker(Storage storage) {
this.storage = storage;
this.jsonUtils = JSONUtils.newInstance();
this.dummyFailTaskStateCollection = new ArrayList<PersistentTaskState>(0);
this.dummyFailContextStateCollection = new ArrayList<PersistentContextState>(0);
}
/**
* Lookup failed tasks that need cleanup
*
* @param when Timestamp past which the tasks need to be cleaned up
*
* @return A list of failed tasks
*/
Collection<PersistentTaskState> getFailedTasksPastDue(Long when) {
final QueryAnswer qAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_TASK.getId())
.with("taskState").equal(TaskState.ABORTED.name())
.with("contextId").differentFrom(Names.BENCHMARKS_CONTEXT_ID)
.with("created").below(when)
.fetch());
if (checkDataAnswer(qAnswer)) {
return dummyFailTaskStateCollection;
}
try {
return jsonUtils.deserialize(qAnswer.getData(), PersistentTaskState.class);
} catch (JsonException e) {
log.warn("Cannot deserialize task list for cleanup", e);
return dummyFailTaskStateCollection;
}
}
/**
* Lookup finished tasks that need cleanup
*
* @param when Timestamp past which the tasks need to be cleaned up
*
* @return A list of finished tasks
*/
Collection<PersistentTaskState> getFinishedTasksPastDue(Long when) {
final QueryAnswer qAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_TASK.getId())
.with("taskState").equal(TaskState.FINISHED.name())
.with("contextId").differentFrom(Names.BENCHMARKS_CONTEXT_ID)
.with("created").below(when)
.fetch());
if (checkDataAnswer(qAnswer)) {
return dummyFailTaskStateCollection;
}
try {
return jsonUtils.deserialize(qAnswer.getData(), PersistentTaskState.class);
} catch (JsonException e) {
log.warn("Cannot load finished task list for cleanup", e);
return dummyFailTaskStateCollection;
}
}
/**
* Lookup starting states to tasks past due, which helps find tasks in zombie state
*
* @param when Timestamp past which to load starting states of tasks
*
* @return A list of started tasks
*/
Collection<PersistentTaskState> getStartedTasksPastDue(Long when) {
final QueryAnswer queryAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_TASK.getId())
.with("taskState").equal(TaskState.RUNNING.name())
.with("contextId").differentFrom(Names.BENCHMARKS_CONTEXT_ID)
.with("created").below(when)
.fetch());
if (!checkDataAnswer(queryAnswer)) {
return dummyFailTaskStateCollection;
}
try {
return jsonUtils.deserialize(queryAnswer.getData(), PersistentTaskState.class);
} catch (JsonException e) {
log.warn("Cannot load started task list for zombie detection");
return dummyFailTaskStateCollection;
}
}
/**
* Lookup failed task contexts that need cleanup
*
* @param when Timestamp pas which the contexts need to be cleaned up
*
* @return A list of failed contexts
*/
Collection<PersistentContextState> getFailedContextsPastDue(Long when) {
final QueryAnswer qAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_CONTEXT.getId())
.with("contextState").equal(TaskContextState.FAILED.name())
.with("created").below(when)
.fetch());
if (!checkDataAnswer(qAnswer)) {
return dummyFailContextStateCollection;
}
try {
return jsonUtils.deserialize(qAnswer.getData(), PersistentContextState.class);
} catch (JsonException e) {
log.warn("Cannot load failed task context list for cleanup", e);
return dummyFailContextStateCollection;
}
}
/**
* Lookup finished task contexts that need cleanup
*
* @param when Timestamp pas which the contexts need to be cleaned up
*
* @return A list of finished contexts
*/
Collection<PersistentContextState> getFinishedContextsPastDue(Long when) {
final QueryAnswer qAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_CONTEXT.getId())
.with("contextState").equal(TaskContextState.FINISHED.name())
.with("created").below(when)
.fetch());
if (!checkDataAnswer(qAnswer)) {
return dummyFailContextStateCollection;
}
try {
return jsonUtils.deserialize(qAnswer.getData(), PersistentContextState.class);
} catch (JsonException e) {
log.warn("Cannot load finished task context list for cleanup", e);
return dummyFailContextStateCollection;
}
}
/**
* Lookup started contexts past a timestamp. Helps zombie context detection.
*
* @param when Timestamp past which to look for started contexts
*
* @return A list of started contexts
*/
Collection<PersistentContextState> getStartedContextsPastDue(Long when) {
final QueryAnswer qAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_CONTEXT.getId())
.with("contextState").equal(TaskContextState.RUNNING.name())
.with("created").below(when)
.fetch());
if (!checkDataAnswer(qAnswer)) {
return dummyFailContextStateCollection;
}
try {
return jsonUtils.deserialize(qAnswer.getData(), PersistentContextState.class);
} catch (JsonException e) {
log.warn("Cannot load started task context list for cleanup", e);
return dummyFailContextStateCollection;
}
}
/**
* Lookup failed benchmarks that need cleanup
*
* @param when Timestamp past which the benchmarks need to be cleaned up
*
* @return A list of failed benchmarks
*/
Collection<PersistentTaskState> getFailedBenchmarksPastDue(Long when) {
final QueryAnswer qAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_TASK.getId())
.with("taskState").equal(TaskState.ABORTED.name())
.with("contextId").equal(Names.BENCHMARKS_CONTEXT_ID)
.with("created").below(when)
.fetch());
if (!checkDataAnswer(qAnswer)) {
return dummyFailTaskStateCollection;
}
try {
return jsonUtils.deserialize(qAnswer.getData(), PersistentTaskState.class);
} catch (JsonException e) {
log.warn("Cannot load failed benchmark list for cleanup", e);
return dummyFailTaskStateCollection;
}
}
/**
* Lookup finished benchmarks that need cleanup
*
* @param when Timestamp past which the benchmarks need to be cleaned up
*
* @return A list of finished benchmarks
*/
Collection<PersistentTaskState> getFinishedBenchmarksPastDue(Long when) {
final QueryAnswer qAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_TASK.getId())
.with("taskState").equal(TaskState.FINISHED.name())
.with("contextId").equal(Names.BENCHMARKS_CONTEXT_ID)
.with("created").below(when)
.fetch());
if (!checkDataAnswer(qAnswer)) {
return dummyFailTaskStateCollection;
}
try {
return jsonUtils.deserialize(qAnswer.getData(), PersistentTaskState.class);
} catch (JsonException e) {
log.warn("Cannot load finished benchmark list for cleanup", e);
return dummyFailTaskStateCollection;
}
}
/**
* Get started benchmarks past a certain timestamp. Helps with zombie benchmark detection
*
* @param when Timestamp past which the benchmarks need t obe cleaned up
*
* @return A list of started benchmarks
*/
Collection<PersistentTaskState> getStartedBenchmarksPastDue(Long when) {
final QueryAnswer qAnswer = storage.query(new QueryBuilder()
.on(Entities.OUTCOME_TASK.getId())
.with("taskState").equal(TaskState.RUNNING.name())
.with("contextId").equal(Names.BENCHMARKS_CONTEXT_ID)
.with("created").below(when)
.fetch());
if (!checkDataAnswer(qAnswer)) {
return dummyFailTaskStateCollection;
}
try {
return jsonUtils.deserialize(qAnswer.getData(), PersistentTaskState.class);
} catch (JsonException e) {
log.warn("Cannot load started benchmark list for cleanup", e);
return dummyFailTaskStateCollection;
}
}
private boolean checkDataAnswer(QueryAnswer qAnswer) {
if (!qAnswer.getStatus().isOk()) {
log.warn("Cannot refresh failed event list: {}", qAnswer.getStatus().getDescription());
return false;
}
if (!qAnswer.isCarryingData()) {
// should never get here, but just in case something changes in the future...
log.warn("Loaded failed event list carries no data: {}", qAnswer.getStatus().getDescription());
return false;
}
return true;
}
}