Skip to content
Snippets Groups Projects
Commit 4cabe61a authored by Daniel Hornung's avatar Daniel Hornung
Browse files

DOC: Documentation in the source code.

parent 5b86d55f
No related branches found
No related tags found
2 merge requests!21Release v0.4.0,!15Document server code structure
Pipeline #8190 passed
......@@ -145,6 +145,9 @@ public abstract class BackendTransaction implements Undoable {
protected abstract void execute();
/**
* Like execute(), but with benchmarking measurement.
*/
public final void executeTransaction() {
final long t1 = System.currentTimeMillis();
execute();
......
......
......@@ -60,12 +60,19 @@ import org.reflections.Reflections;
* @todo Describe me.
*/
public abstract class Job {
/**
* All known Job classes, by name (actually lowercase getSimpleName()).
*/
static HashMap<String, Class<? extends Job>> allClasses = null;
private static List<Class<? extends Job>> loadAlways;
private Transaction<? extends TransactionContainer> transaction = null;
private Mode mode = null;
private final JobExecutionTime time;
private EntityInterface entity = null;
public abstract JobTarget getTarget();
private EntityInterface entity = null;
public abstract JobTarget getTarget();
protected <S, T> HashMap<S, T> getCache(final String name) {
return getTransaction().getCache(name);
......@@ -230,22 +237,33 @@ public abstract class Job {
}
}
static HashMap<String, Class<? extends Job>> allClasses = null;
private static List<Class<? extends Job>> loadAlways;
/**
* Create a Job object with the given parameters.
* <p>
* This static method is used by other classes to create Job objects, instead of the private
* constructor.
*
* @return The generated Job object.
*/
public static Job getJob(
final String job,
final Mode mode,
final EntityInterface entity,
final Transaction<? extends TransactionContainer> transaction) {
// Fill `allClasses` with available subclasses
scanJobClasspath();
// Get matching class for Job and generate it.
final Class<? extends Job> jobClass = allClasses.get(job.toLowerCase());
return getJob(jobClass, mode, entity, transaction);
}
/**
* Initialize {@code allClasses} with all {@code Job} classes found in the classpath.
*
* @todo Details when this has any effect.
*/
private static void scanJobClasspath() {
if (allClasses == null || loadAlways == null) {
allClasses = new HashMap<>();
loadAlways = new ArrayList<>();
......@@ -452,15 +470,18 @@ public abstract class Job {
System.out.println(toString());
}
private final JobExecutionTime time;
public JobExecutionTime getExecutionTime() {
return this.time;
}
/**
* @todo What is a permanent Job? What does "load" mean?
*
* @return A list with the jobs.
*/
public static List<Job> loadPermanentContainerJobs(Transaction<?> transaction) {
final ArrayList<Job> jobs = new ArrayList<>();
// load permanent jobs
// load permanent jobs: ContainerJob classes with the correct transaction
for (Class<? extends Job> j : loadAlways) {
if (ContainerJob.class.isAssignableFrom(j)
&& j.getAnnotation(JobAnnotation.class).transaction().isInstance(transaction)) {
......
......
......@@ -26,6 +26,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.caosdb.server.transaction.TransactionInterface;
/**
* Jobs may be annotated with @JobAnnotation(...).
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface JobAnnotation {
JobExecutionTime time() default JobExecutionTime.CHECK;
......
......
......@@ -22,6 +22,9 @@
*/
package org.caosdb.server.jobs;
/**
* Not really a time (measured in seconds), but rather the executaion state.
*/
public enum JobExecutionTime {
INIT,
PRE_CHECK,
......
......
......@@ -30,6 +30,9 @@ import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import org.caosdb.server.entity.EntityInterface;
/**
* Keeps track of Jobs, ordered by "time".
*/
public class Schedule {
private final Map<Integer, List<ScheduledJob>> jobLists = new HashMap<>();
......@@ -54,6 +57,9 @@ public class Schedule {
return ret;
}
/**
* Run all Jobs with the specified JobExecutionTime.
*/
public void runJobs(final JobExecutionTime time) {
List<ScheduledJob> jobs = this.jobLists.get(time.ordinal());
if (jobs != null) {
......@@ -81,6 +87,11 @@ public class Schedule {
}
}
/**
* Run all scheduled Jobs for the given entity.
*
* Execution time: Either CHECK or what is given as jobclass annotation.
*/
public void runJob(final EntityInterface entity, final Class<? extends Job> jobclass) {
List<ScheduledJob> jobs =
jobclass.isAnnotationPresent(JobAnnotation.class)
......
......
......@@ -54,10 +54,16 @@ public class ScheduledJob {
return this.job.toString();
}
/**
* Does not actually start the job, but only sets the startTime.
*/
private void start() {
this.startTime = System.currentTimeMillis();
}
/**
* Calculate and set the runtime, and add the measurement.
*/
private void finish() {
this.runtime += System.currentTimeMillis() - this.startTime;
this.job
......@@ -78,6 +84,9 @@ public class ScheduledJob {
return this.startTime != -1;
}
/**
* Return the state of the inner Job.
*/
public JobExecutionTime getExecutionTime() {
return this.job.getExecutionTime();
}
......
......
......@@ -86,6 +86,11 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
return this.container;
}
/**
* Implementation note: Not called in this class, but may be used by subclasses.
* <p>
* E.g. in {@link Retrieve} and {@link WriteTransaction}.
*/
protected void makeSchedule() throws Exception {
// load flag jobs
final Job loadContainerFlags = Job.getJob("LoadContainerFlagJobs", Mode.MUST, null, this);
......@@ -115,6 +120,31 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
}
}
/**
* The main transaction execution method.
* <p>
* This method calls the following other internal methods and scheduled jobs stored in the {@link
* getSchedule() internal Schedule object}:
* <ul>
* <li> {@link init}
* <li> {@link Schedule.runJobs(INIT)}
* <li> {@link preCheck}
* <li> {@link Schedule.runJobs(PRE_CHECK)}
* <li> {@link check}
* <li> {@link Schedule.runJobs(POST_CHECK)}
* <li> {@link postCheck}
* <li> {@link preTransaction}
* <li> {@link Schedule.runJobs(PRE_TRANSACTION)}
* <li> {@link transaction}: This is typically the main method of a Transaction.
* <li> {@link Schedule.runJobs(POST_TRANSACTION)}
* <li> {@link postTransaction}
* <li> {@link writeHistory}
* <li> {@link commit}
* <li> {@link rollBack}: Only in the case of errors.
* <li> {@link cleanUp}: Always.
* <li> {@link notifyObservers(CLEAN_UP)}: Also always.
*
*/
@Override
public final void execute() throws Exception {
long t1 = System.currentTimeMillis();
......
......
......@@ -35,6 +35,11 @@ public interface TransactionInterface {
return TransactionBenchmark.getRootInstance().getBenchmark(getClass());
}
/**
* Append the BackendTransaction t to a RollBackHandler before basically calling {@code
* t.execute()}. Except for benchmarking, this method does not interact directly with this
* object.
*/
public default <K extends BackendTransaction> K execute(K t, Access access) {
final RollBackHandler handler = (RollBackHandler) access.getHelper("RollBack");
handler.append(t);
......
......
......@@ -76,8 +76,7 @@ public class WriteTransaction extends Transaction<WritableContainer>
@Override
protected final void preTransaction() throws InterruptedException {
// acquire strong access. No other thread can have access until
// it this strong access is released.
// Acquire strong access. No other thread can have access until this strong access is released.
setAccess(getAccessManager().acquireWriteAccess(this));
}
......
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment