diff --git a/src/main/java/com/flowpowered/plugins/artifact/Artifact.java b/src/main/java/com/flowpowered/plugins/artifact/Artifact.java new file mode 100644 index 0000000..31b6ed9 --- /dev/null +++ b/src/main/java/com/flowpowered/plugins/artifact/Artifact.java @@ -0,0 +1,33 @@ +package com.flowpowered.plugins.artifact; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class Artifact { + private Queue jobQueue = new ConcurrentLinkedQueue<>(); + private ArtifactState state = ArtifactState.UNDEFINED; + private volatile boolean gone = false; + + public ArtifactState getState() { + return state; + } + + /** + * Should be only called from the thread that is currently executing {@link ArtifactManager#pulse(String)} + */ + public void setState(ArtifactState state) { + this.state = state; + } + + public Queue getJobQueue() { + return jobQueue; + } + + public boolean isGone() { + return gone; + } + + protected void makeGone() { + this.gone = true; + } +} diff --git a/src/main/java/com/flowpowered/plugins/artifact/ArtifactJob.java b/src/main/java/com/flowpowered/plugins/artifact/ArtifactJob.java new file mode 100644 index 0000000..6deeebc --- /dev/null +++ b/src/main/java/com/flowpowered/plugins/artifact/ArtifactJob.java @@ -0,0 +1,10 @@ +package com.flowpowered.plugins.artifact; + +import com.flowpowered.commons.SimpleFuture; + +public interface ArtifactJob { + + SimpleFuture getFuture(); + + void run(Artifact artifact); +} diff --git a/src/main/java/com/flowpowered/plugins/artifact/ArtifactManager.java b/src/main/java/com/flowpowered/plugins/artifact/ArtifactManager.java new file mode 100644 index 0000000..81632f3 --- /dev/null +++ b/src/main/java/com/flowpowered/plugins/artifact/ArtifactManager.java @@ -0,0 +1,78 @@ +package com.flowpowered.plugins.artifact; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Future; + +import com.flowpowered.plugins.artifact.jobs.LocateJob; +import com.flowpowered.plugins.artifact.jobs.RemoveJob; + +public class ArtifactManager { + private ConcurrentMap byName = new ConcurrentHashMap<>(); + + + /** + * Makes the Manager try to find the artifact and start tracking it. + * @return some Future, whose type will be specified once I figure out what I want it to be + */ + public Future locate(String artifactName) { + LocateJob job = new LocateJob(); + + Artifact newArtifact = new Artifact(); + newArtifact.getJobQueue().add(job); + + Artifact artifact = byName.putIfAbsent(artifactName, newArtifact); + if (artifact == null) { + enqueuePulse(artifactName); + } else { + artifact.getJobQueue().add(job); + + if (artifact.isGone()) { + // Our job might be never processed, so let's try again. Better have 2 jobs than none. + // FIXME: Convert this to iteration, or we might get StackOverflows. + return locate(artifactName); + } + } + return job.getFuture(); + } + + /** + * In any given moment this method can be running at most once per artifact + */ + public void pulse(String artifactName) { + Artifact artifact = byName.get(artifactName); + if (artifact == null) { + // Should not happen, only we're allowed to set it to null and wouldn't pulse after that + throw new IllegalStateException("pulsed on nonexistent artifact"); + } + ArtifactJob job = artifact.getJobQueue().poll(); + if (job != null) { + // TODO: Job merging + job.run(artifact); + + if (job instanceof RemoveJob) { + byName.remove(artifactName); + artifact.makeGone(); + + for (ArtifactJob j : artifact.getJobQueue()) { + if (j instanceof LocateJob) { + locate(artifactName); + // TODO: add the rest of the queue to the new artifact? + break; + } + } + + return; // Don't requeue ourselves; + } + } + enqueuePulse(artifactName); + } + + /** + * Makes some thread call {@link #pulse(String)} for the given artifact soon. + * The definition of "soon" is implementation-specific. + */ + protected void enqueuePulse(String artifactName) { + + } +} diff --git a/src/main/java/com/flowpowered/plugins/artifact/ArtifactState.java b/src/main/java/com/flowpowered/plugins/artifact/ArtifactState.java new file mode 100644 index 0000000..cd123a4 --- /dev/null +++ b/src/main/java/com/flowpowered/plugins/artifact/ArtifactState.java @@ -0,0 +1,5 @@ +package com.flowpowered.plugins.artifact; + +public enum ArtifactState { + UNDEFINED, LOCATED, LOADING, LOADED, WAITING_FOR_DEPS, MISSING_DEPS, RESOLVED, UNLOADING, UNLOADED +} diff --git a/src/main/java/com/flowpowered/plugins/artifact/jobs/AbstractJob.java b/src/main/java/com/flowpowered/plugins/artifact/jobs/AbstractJob.java new file mode 100644 index 0000000..4d03988 --- /dev/null +++ b/src/main/java/com/flowpowered/plugins/artifact/jobs/AbstractJob.java @@ -0,0 +1,15 @@ +package com.flowpowered.plugins.artifact.jobs; + +import com.flowpowered.commons.SimpleFuture; + +import com.flowpowered.plugins.artifact.ArtifactJob; + +public abstract class AbstractJob implements ArtifactJob { + protected SimpleFuture future = new SimpleFuture<>(); + + @Override + public SimpleFuture getFuture() { + return future; + } + +} \ No newline at end of file diff --git a/src/main/java/com/flowpowered/plugins/artifact/jobs/LocateJob.java b/src/main/java/com/flowpowered/plugins/artifact/jobs/LocateJob.java new file mode 100644 index 0000000..a0e80ad --- /dev/null +++ b/src/main/java/com/flowpowered/plugins/artifact/jobs/LocateJob.java @@ -0,0 +1,14 @@ +package com.flowpowered.plugins.artifact.jobs; + +import com.flowpowered.plugins.artifact.Artifact; +import com.flowpowered.plugins.artifact.ArtifactState; + +public class LocateJob extends AbstractJob { + @Override + public void run(Artifact artifact) { + // TODO Auto-generated method stub + artifact.setState(ArtifactState.LOCATED); + future.setResult(null); + } + +} diff --git a/src/main/java/com/flowpowered/plugins/artifact/jobs/RemoveJob.java b/src/main/java/com/flowpowered/plugins/artifact/jobs/RemoveJob.java new file mode 100644 index 0000000..9032474 --- /dev/null +++ b/src/main/java/com/flowpowered/plugins/artifact/jobs/RemoveJob.java @@ -0,0 +1,13 @@ +package com.flowpowered.plugins.artifact.jobs; + +import com.flowpowered.plugins.artifact.Artifact; + +public class RemoveJob extends AbstractJob { + + @Override + public void run(Artifact artifact) { + // TODO Auto-generated method stub + future.setResult(null); + } + +}