/*
* Copyright 2013 Eediom Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.araqne.logdb;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* physical plan
*
* @author xeraph
*
*/
public abstract class QueryTask implements Runnable {
private final Logger logger = LoggerFactory.getLogger(QueryTask.class);
public enum TaskStatus {
INIT, RUNNING, FINALIZING, COMPLETED, CANCELED
}
private CountDownLatch latch;
private TaskStatus status = TaskStatus.INIT;
private Throwable failure;
private QueryTask parentTask;
private CopyOnWriteArraySet<QueryTask> subTasks = new CopyOnWriteArraySet<QueryTask>();
private CopyOnWriteArraySet<QueryTask> dependencies = new CopyOnWriteArraySet<QueryTask>();
private CopyOnWriteArraySet<QueryTaskListener> listeners = new CopyOnWriteArraySet<QueryTaskListener>();
private static AtomicLong l = new AtomicLong(1);
private long id = l.incrementAndGet();
private Object statusLock = new Object();
public TaskStatus getStatus() {
return status;
}
public void await() {
if(this.latch != null)
try {
this.latch.await();
} catch (InterruptedException e) {
}
}
public void done() {
if (latch != null)
latch.countDown();
}
public void setStatus(TaskStatus status) {
synchronized (statusLock) {
if (this.status.ordinal() >= status.ordinal())
return;
if (status == TaskStatus.RUNNING)
latch = new CountDownLatch(1);
this.status = status;
}
}
public Throwable getFailure() {
return failure;
}
public void setFailure(Throwable failure) {
this.failure = failure;
}
public Collection<QueryTask> getSubTasks() {
return new ArrayList<QueryTask>(subTasks);
}
public QueryTask getParentTask() {
return parentTask;
}
public void setParentTask(QueryTask parentTask) {
this.parentTask = parentTask;
}
public void addSubTask(QueryTask task) {
if (task == null)
throw new IllegalArgumentException("null task is not allowed");
task.setParentTask(this);
subTasks.add(task);
}
public void removeSubTask(QueryTask task) {
if (task == null)
throw new IllegalArgumentException("null task is not allowed");
subTasks.remove(task);
}
public boolean isStopped() {
return (this.status == TaskStatus.CANCELED || this.status == TaskStatus.COMPLETED);
}
public boolean isRunnable() {
for (QueryTask t : dependencies)
if (!t.isStopped())
return false;
return status == TaskStatus.INIT;
}
// invoked when task is started
public void onStart() {
}
// like finally block, regardless of normal complete or cancel
public void onCleanUp() {
}
public Collection<QueryTask> getDependencies() {
return dependencies;
}
public void addDependency(QueryTask task) {
checkNotNull(task, "task");
if (logger.isDebugEnabled())
logger.debug("araqne logdb: [{}] depends on [{}] task", this, task);
dependencies.add(task);
}
public void removeDependency(QueryTask task) {
checkNotNull(task, "task");
dependencies.remove(task);
}
public Collection<QueryTaskListener> getListeners() {
return listeners;
}
public void addListener(QueryTaskListener listener) {
checkNotNull(listener, "listener");
listeners.add(listener);
}
public void removeListener(QueryTaskListener listener) {
checkNotNull(listener, "listener");
listeners.remove(listener);
}
private void checkNotNull(Object o, String name) {
if (o == null)
throw new IllegalArgumentException("null " + name + " is not allowed");
}
public long getID() {
return id;
}
}