diff --git a/README.md b/README.md index 4ff0176f026f8274aa364524eac4f1fe4de3a9d1..c16a2ea0b74002593551d4964db050e790eaf72d 100644 --- a/README.md +++ b/README.md @@ -10,5 +10,4 @@ sur les nœuds de manière à maximiser l'utilisation de la mémoire et du nombr ## Membres du projet -- NOM, prénom, numéro de groupe, du premier participant -- NOM, prénom, numéro de groupe, du deuxième participant \ No newline at end of file +- LABOUREL, Arnaud \ No newline at end of file diff --git a/src/main/java/cluster/App.java b/src/main/java/cluster/App.java index 5ef810084425acc7cc0fd902102b1f3d6f083289..f0dbb57ac50d11aec8a2dfa7d706952f156ddaee 100644 --- a/src/main/java/cluster/App.java +++ b/src/main/java/cluster/App.java @@ -4,14 +4,11 @@ public class App { public static void main(String[] args) throws Exception{ - // TODO : décommenter pour tester le main. - /* Job job1 = new Job(1000, 1000); Job job2 = new Job(3000, 1000); Node node = new Node("Calcul", 10000, 3000); - node.acceptJob(job1); - node.acceptJob(job2); + node.accept(job1); + node.accept(job2); node.printJobs(); - */ } } diff --git a/src/main/java/cluster/Controller.java b/src/main/java/cluster/Controller.java new file mode 100644 index 0000000000000000000000000000000000000000..b519c63cf962e8ed0022cd13534aa4c0108012f4 --- /dev/null +++ b/src/main/java/cluster/Controller.java @@ -0,0 +1,53 @@ +package cluster; + +import java.util.ArrayList; +import java.util.List; + +public class Controller<J extends Job> { + private List<J> nonScheduledJobs = new ArrayList<>(); + private final List<Node> nodes = new ArrayList<>(); + private final String name; + private final Scheduler<J> scheduler; + + void addNode(Node node){ + nodes.add(node); + } + + void submitJob(J job){ + nonScheduledJobs.add(job); + } + + Controller(String name, Scheduler<J> scheduler){ + this.name = name; + this.scheduler = scheduler; + } + + void printNodesAndNonScheduledJobs(){ + System.out.println(this); + printNodes(); + System.out.println("Non scheduled jobs"); + printNonScheduledJobs(); + } + + private void printNodes(){ + for (Node node : nodes){ + node.printJobs(); + System.out.println(); + } + } + + private void printNonScheduledJobs(){ + for (Job job : nonScheduledJobs){ + System.out.println(job); + } + } + + public void scheduleJobs(){ + nonScheduledJobs = scheduler.scheduleJobs(nonScheduledJobs, nodes); + } + + @Override + public String toString() { + return "Controller " + name; + } +} diff --git a/src/main/java/cluster/Job.java b/src/main/java/cluster/Job.java new file mode 100644 index 0000000000000000000000000000000000000000..848c7a04e0be279b7bc88ca8054ed0dc263be956 --- /dev/null +++ b/src/main/java/cluster/Job.java @@ -0,0 +1,46 @@ +package cluster; + +public class Job { + private final int memory; + private final int flop; + private final int id; + private static int jobCount = 0; + + public Job(int memory, int flop) { + if (memory <= 0){ + throw new IllegalArgumentException("Cannot create a job with negative memory : " + getMemory()); + } + if (flop <= 0){ + throw new IllegalArgumentException("Cannot create a job with a negative number of operations : " + getMemory()); + } + this.memory = memory; + this.flop = flop; + id = jobCount++; + } + + public int getFlop() { + return flop; + } + + public int getMemory() { + return memory; + } + + public int getId() { + return id; + } + + public static void resetJobCount() { + jobCount = 0; + } + + public static int getJobCount() { + return jobCount; + } + + public String toString(){ + return "Job "+ getId() + + " (" + getFlop() + "FLOP, " + + getMemory() + "o)"; + } +} diff --git a/src/main/java/cluster/JobGenerator.java b/src/main/java/cluster/JobGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..ffd564abafbef3436189469a6604b4df8cd0fcc9 --- /dev/null +++ b/src/main/java/cluster/JobGenerator.java @@ -0,0 +1,5 @@ +package cluster; + +public interface JobGenerator { + Job generateJob(); +} diff --git a/src/main/java/cluster/Main.java b/src/main/java/cluster/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..d729e9b06105231e20c735890ecaa40d398bb798 --- /dev/null +++ b/src/main/java/cluster/Main.java @@ -0,0 +1,30 @@ +package cluster; + +public class Main { + public static void main(String[] args){ + JobGenerator randomJobGenerator = new RandomJobGenerator(10, 100, 10, 11, 0); + Node node = new Node("Calcul", 10000, 3000); + for(int i = 0; i<10; i++){ + try { + node.accept(randomJobGenerator.generateJob()); + } + catch (NotEnoughResourceException e){ + e.printStackTrace(); + } + } + node.printJobs(); + /* + Job job1 = new Job(1000, 1000); + Job job2 = new Job(3000, 1000); + Node node = new Node("Calcul", 10000, 3000); + Scheduler<Job> randomScheduler = new RandomScheduler(); + Controller<Job> controller = new Controller<>("Pharo", randomScheduler); + controller.addNode(node); + controller.submitJob(job1); + controller.submitJob(job2); + controller.scheduleJobs(); + controller.printNodesAndNonScheduledJobs(); + */ + + } +} \ No newline at end of file diff --git a/src/main/java/cluster/Node.java b/src/main/java/cluster/Node.java new file mode 100644 index 0000000000000000000000000000000000000000..11dafeb8a1e5ebffb4824e079bf86945893e3c17 --- /dev/null +++ b/src/main/java/cluster/Node.java @@ -0,0 +1,69 @@ +package cluster; + +import java.util.ArrayList; +import java.util.List; + +public class Node { + private final String name; + private final int memoryCapacity; + private final int flopCapacity; + + private int availableMemory; + private int availableFlop; + private final List<Job> assignedJobs = new ArrayList<>(); + + Node(String name, int memoryCapacity, int flopCapacity) { + this.name = name; + this.memoryCapacity = memoryCapacity; + this.flopCapacity = flopCapacity; + availableMemory = memoryCapacity; + availableFlop = flopCapacity; + } + + boolean canAccept(Job job){ + return availableMemory >= job.getMemory() && + availableFlop >= job.getFlop(); + } + + boolean canHandle(Job job){ + return memoryCapacity >= job.getMemory() && + flopCapacity >= job.getFlop(); + } + + void accept(Job job) throws NotEnoughResourceException{ + if(memoryCapacity < job.getMemory()){ + throw new NotEnoughTotalMemoryException(this, job); + } + if(availableMemory < job.getMemory()){ + throw new NotEnoughRemainingMemoryException(this, job); + } + if(flopCapacity < job.getFlop()){ + throw new NotEnoughTotalFlopException(this, job); + } + if(availableFlop < job.getFlop()){ + throw new NotEnoughRemainingFlopException(this, job); + } + assignedJobs.add(job); + availableMemory -= job.getMemory(); + availableFlop -= job.getFlop(); + } + + int usedMemory(){ + return memoryCapacity - availableMemory; + } + + int usedFlop(){ + return flopCapacity - availableFlop; + } + + public String toString(){ + return "Node " + name + " (" + usedFlop() + "/" + flopCapacity + "FLOP, " + usedMemory() + "/" + memoryCapacity +"o)"; + } + + void printJobs(){ + System.out.println(this); + for(Job job : assignedJobs){ + System.out.println(job); + } + } +} diff --git a/src/main/java/cluster/NotEnoughRemainingFlopException.java b/src/main/java/cluster/NotEnoughRemainingFlopException.java new file mode 100644 index 0000000000000000000000000000000000000000..bb0f015de03eb2f9161231b99a06e5aeef70cc31 --- /dev/null +++ b/src/main/java/cluster/NotEnoughRemainingFlopException.java @@ -0,0 +1,12 @@ +package cluster; + +public class NotEnoughRemainingFlopException extends NotEnoughResourceException { + public NotEnoughRemainingFlopException(Node node, Job job) { + super(node, job); + } + + @Override + public String getSentenceMessage() { + return " has not enough remaining FLOP to handle "; + } +} diff --git a/src/main/java/cluster/NotEnoughRemainingMemoryException.java b/src/main/java/cluster/NotEnoughRemainingMemoryException.java new file mode 100644 index 0000000000000000000000000000000000000000..40818f7f8082a77a7c12d485b524491c40768a06 --- /dev/null +++ b/src/main/java/cluster/NotEnoughRemainingMemoryException.java @@ -0,0 +1,12 @@ +package cluster; + +public class NotEnoughRemainingMemoryException extends NotEnoughResourceException{ + public NotEnoughRemainingMemoryException(Node node, Job job) { + super(node, job); + } + + @Override + public String getSentenceMessage() { + return " has not enough remaining memory to handle "; + } +} diff --git a/src/main/java/cluster/NotEnoughResourceException.java b/src/main/java/cluster/NotEnoughResourceException.java new file mode 100644 index 0000000000000000000000000000000000000000..4edcb224d6deff38fc983c9e61dc0e118c41acc6 --- /dev/null +++ b/src/main/java/cluster/NotEnoughResourceException.java @@ -0,0 +1,18 @@ +package cluster; + +public abstract class NotEnoughResourceException extends Exception { + private final Node node; + private final Job job; + + public NotEnoughResourceException(Node node, Job job) { + this.node = node; + this.job = job; + } + + @Override + public String getMessage() { + return node + getSentenceMessage() + job; + } + + public abstract String getSentenceMessage(); +} diff --git a/src/main/java/cluster/NotEnoughTotalFlopException.java b/src/main/java/cluster/NotEnoughTotalFlopException.java new file mode 100644 index 0000000000000000000000000000000000000000..0a36b251cde4db879161aa127df4714717b689f7 --- /dev/null +++ b/src/main/java/cluster/NotEnoughTotalFlopException.java @@ -0,0 +1,12 @@ +package cluster; + +public class NotEnoughTotalFlopException extends NotEnoughResourceException{ + public NotEnoughTotalFlopException(Node node, Job job) { + super(node, job); + } + + @Override + public String getSentenceMessage() { + return " has not enough total number of operations to handle "; + } +} diff --git a/src/main/java/cluster/NotEnoughTotalMemoryException.java b/src/main/java/cluster/NotEnoughTotalMemoryException.java new file mode 100644 index 0000000000000000000000000000000000000000..23d8d3764aaca4d856a39a4a860c0e4e670bb1b2 --- /dev/null +++ b/src/main/java/cluster/NotEnoughTotalMemoryException.java @@ -0,0 +1,12 @@ +package cluster; + +public class NotEnoughTotalMemoryException extends NotEnoughResourceException { + public NotEnoughTotalMemoryException(Node node, Job job) { + super(node, job); + } + + @Override + public String getSentenceMessage() { + return " has not enough total memory to handle "; + } +} diff --git a/src/main/java/cluster/PriorityJob.java b/src/main/java/cluster/PriorityJob.java new file mode 100644 index 0000000000000000000000000000000000000000..92877796fb06d311c5637b9dbbbcccb07094db8d --- /dev/null +++ b/src/main/java/cluster/PriorityJob.java @@ -0,0 +1,15 @@ +package cluster; + +public class PriorityJob extends Job implements Comparable<PriorityJob>{ + private final int priority; + + public PriorityJob(int memory, int flop, int priority) { + super(memory, flop); + this.priority = priority; + } + + @Override + public int compareTo(PriorityJob job) { + return job.priority - this.priority; + } +} diff --git a/src/main/java/cluster/PriorityScheduler.java b/src/main/java/cluster/PriorityScheduler.java new file mode 100644 index 0000000000000000000000000000000000000000..cf1d5fdd79362b623d7500a6700a7083ad8521d5 --- /dev/null +++ b/src/main/java/cluster/PriorityScheduler.java @@ -0,0 +1,31 @@ +package cluster; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class PriorityScheduler implements Scheduler<PriorityJob> { + @Override + public List<PriorityJob> scheduleJobs(List<PriorityJob> jobs, List<Node> nodes) { + List<PriorityJob> nonScheduledJobs = new ArrayList<>(); + Collections.sort(jobs); + for (PriorityJob job : jobs) { + if(!scheduleJob(job, nodes)){ + nonScheduledJobs.add(job); + } + } + return nonScheduledJobs; + } + + + private boolean scheduleJob(Job job, List<Node> nodes){ + for (Node node : nodes) { + try { + node.accept(job); + return true; + } + catch (NotEnoughResourceException e){} + } + return false; + } +} diff --git a/src/main/java/cluster/RandomJobGenerator.java b/src/main/java/cluster/RandomJobGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..69ee89a2bcc9bee515bb440a028bb28cd09e2fa2 --- /dev/null +++ b/src/main/java/cluster/RandomJobGenerator.java @@ -0,0 +1,27 @@ +package cluster; + +import java.util.Random; + +public class RandomJobGenerator implements JobGenerator{ + private final int minMemory; + private final int maxMemory; + private final int minFlop; + private final int maxFlop; + private final Random random; + + public RandomJobGenerator(int minMemory, int maxMemory, int minFlop, int maxFlop, long seed) { + this.minMemory = minMemory; + this.maxMemory = maxMemory; + this.minFlop = minFlop; + this.maxFlop = maxFlop; + this.random = new Random(seed); + } + + private int nextInt(int min, int max){ + return min + random.nextInt(max - min + 1); + } + + public Job generateJob(){ + return new Job(nextInt(minMemory, maxMemory), nextInt(minFlop, maxFlop)); + } +} diff --git a/src/main/java/cluster/RandomScheduler.java b/src/main/java/cluster/RandomScheduler.java new file mode 100644 index 0000000000000000000000000000000000000000..c8571bbc472afdf2af1aaea86fcb8a13939197e4 --- /dev/null +++ b/src/main/java/cluster/RandomScheduler.java @@ -0,0 +1,27 @@ +package cluster; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class RandomScheduler implements Scheduler<Job>{ + private Random random = new Random(); + + public Node randomNode(List<Node> nodes){ + return nodes.get(random.nextInt(nodes.size())); + } + + @Override + public List<Job> scheduleJobs(List<Job> jobs, List<Node> nodes) { + List<Job> nonScheduledJobs = new ArrayList<>(); + for(Job job : jobs){ + try{ + randomNode(nodes).accept(job); + } + catch (NotEnoughResourceException e){ + nonScheduledJobs.add(job); + } + } + return nonScheduledJobs ; + } +} diff --git a/src/main/java/cluster/Scheduler.java b/src/main/java/cluster/Scheduler.java new file mode 100644 index 0000000000000000000000000000000000000000..9111ad2e4e09d3a530a2e634f7e423141013b39a --- /dev/null +++ b/src/main/java/cluster/Scheduler.java @@ -0,0 +1,7 @@ +package cluster; + +import java.util.List; + +public interface Scheduler<J extends Job> { + List<J> scheduleJobs(List<J> jobs, List<Node> nodes); +} diff --git a/src/main/java/cluster/UniformJobGenerator.java b/src/main/java/cluster/UniformJobGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..0260cf76f2cdf3e258cc28826aab9fffa7eb10ab --- /dev/null +++ b/src/main/java/cluster/UniformJobGenerator.java @@ -0,0 +1,16 @@ +package cluster; + +public class UniformJobGenerator implements JobGenerator{ + private final int memory; + private final int flop; + + public UniformJobGenerator(int memory, int flop) { + this.memory = memory; + this.flop = flop; + } + + @Override + public Job generateJob() { + return new Job(memory, flop); + } +} diff --git a/src/test/java/cluster/JobTest.java b/src/test/java/cluster/JobTest.java index 1b87f8360ee34b5627e9abf3e98cf73616de2d6d..820e28e0ca816e7d1b4b53748f2d5dc9f7cdd854 100644 --- a/src/test/java/cluster/JobTest.java +++ b/src/test/java/cluster/JobTest.java @@ -5,8 +5,7 @@ import static org.junit.jupiter.api.Assertions.*; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; public class JobTest { - //TODO : décommenter pour tester la classe Job -/* + @Test void testToString(){ // Test with Junit @@ -44,6 +43,6 @@ public class JobTest { assertThat(Job.getJobCount()).isEqualTo(jobCount); } } - */ + }