Refactor simulation and net example tests to use builder pattern for ServerNode and improve arrival handling logic

This commit is contained in:
2025-02-07 17:33:27 +01:00
parent 5aedd25c5f
commit fbc9aeac2c
8 changed files with 329 additions and 99 deletions

View File

@@ -74,12 +74,12 @@ public class NetBuilderInteractive {
var limit = ask("Arrivals limit (0 for Int.Max): ", Integer::parseInt, 1);
if (limit <= 0)
limit = Integer.MAX_VALUE;
yield ServerNode.createLimitedSource(name, distribution, limit);
yield ServerNode.Builder.sourceLimited(name, limit, distribution);
}
case 2 -> {
var servers = ask("Number of servers: ", Integer::parseInt, 1);
var unavailable = askDistribution("Unavailable distribution");
yield ServerNode.createQueue(name, servers, distribution, unavailable);
yield ServerNode.Builder.queue(name, servers, distribution, unavailable);
}
default -> null;
};

View File

@@ -15,84 +15,36 @@ public class ServerNode {
public final Distribution service;
public final Distribution unavailable;
/**
* Creates a source node with the given name and distribution.
* It swpawns infinite arrivals (Integer.MAX_VALUE) that are served by infinite
* servers (Integer.MAX_VALUE).
*
* @param name The name of the node.
* @param distribution The distribution of the inter-arrival times.
* @return The created source node.
*/
public static ServerNode createSource(String name, Distribution distribution) {
return new ServerNode(name, Integer.MAX_VALUE, distribution, null, Integer.MAX_VALUE);
}
/**
* Creates a source node with the given name, distribution, and number of
* arrivals to spawn that are served by infinite servers (Integer.MAX_VALUE).
*
* @param name The name of the node.
* @param service The distribution of the inter-arrival times.
* @param spawnArrivals The number of arrivals to spawn.
* @return The created source node.
*/
public static ServerNode createLimitedSource(String name, Distribution service, int spawnArrivals) {
return new ServerNode(name, Integer.MAX_VALUE, service, null, spawnArrivals);
}
/**
* Creates a queue node with the given name, maximum number of servers, and
* distribution.
*
* @param name The name of the node.
* @param maxServers The maximum number of servers in the queue.
* @param service The distribution of the service times.
* @return The created queue node.
*/
public static ServerNode createQueue(String name, int maxServers, Distribution service) {
return new ServerNode(name, maxServers, service, null, 0);
}
/**
* Creates a queue node with the given name, maximum number of servers, and
* distribution.
*
* @param name The name of the node.
* @param maxServers The maximum number of servers in the queue.
* @param service The distribution of the service times.
* @param unavailable The distribution of the unavailable times after service.
* @return The created queue node.
*/
public static ServerNode createQueue(String name, int maxServers, Distribution service, Distribution unavailable) {
return new ServerNode(name, maxServers, service, unavailable, 0);
}
/**
* Creates a generic node with the given name and distribution.
* The servers number must be 1 or higher; if lower will be put to 1.
* The spawn number must be 0 or higher; if lower will be put to 0.
* The distribution can't be null, otherwise an exception is thrown.
* The queue number must be equal or higher than the servers number; if lower
* will be put to the servers number.
* The service distribution can't be null, otherwise an exception is thrown.
*
* @param name The name of the node.
* @param maxServers The maximum number of servers in the queue.
* @param service The distribution of the service times.
* @param unavailable The distribution of the unavailable times after service.
* @param spawnArrivals The number of arrivals to spawn.
* @param name The name of the node.
* @param servers The maximum number of servers in the queue.
* @param spawn The number of arrivals to spawn.
* @param queue The maximum number of requests in the queue.
* @param service The distribution of the service times.
* @param unavailable The distribution of the unavailable times after service.
* @throws NullPointerException if the distribution is null
*/
private ServerNode(String name, int maxServers, Distribution service, Distribution unavailable, int spawnArrivals) {
private ServerNode(String name, int servers, int spawn, int queue, Distribution service, Distribution unavailable) {
if (service == null)
throw new NullPointerException("Service distribution can't be null");
if (maxServers <= 0)
maxServers = 1;
if (spawnArrivals < 0)
spawnArrivals = 0;
if (servers <= 0)
servers = 1;
if (spawn < 0)
spawn = 0;
if (queue < servers)
queue = servers;
this.name = name;
this.maxQueue = 100; // TODO change to runtime
this.maxServers = maxServers;
this.spawnArrivals = spawnArrivals;
this.maxQueue = queue;
this.maxServers = servers;
this.spawnArrivals = spawn;
this.service = service;
this.unavailable = unavailable;
}
@@ -131,4 +83,114 @@ public class ServerNode {
public int hashCode() {
return this.name.hashCode();
}
/**
* Creates a new builder for the node.
* It is useful to create a node with a more readable syntax and a in a more
* flexible way.
*/
public static class Builder {
private String name;
private int maxQueue;
private int maxServers;
private int spawnArrivals;
private Distribution service;
private Distribution unavailable;
/**
* Creates a new builder for the node with the given name and distribution.
* The maximum number of servers is set to 1, the maximum number of requests in
* the queue is set to 100, the number of arrivals to spawn is set to 0, and
* the unavailable time is set to null.
*
* @param name The name of the node.
* @param service The distribution of the service times.
* @return The created sink node.
*/
public Builder(String name, Distribution service) {
this.name = name;
this.service = service;
this.maxQueue = 100; // default value
this.maxServers = 1;
this.spawnArrivals = 0;
this.unavailable = null;
}
public Builder queue(int maxQueue) {
this.maxQueue = maxQueue;
return this;
}
public Builder servers(int maxServers) {
this.maxServers = maxServers;
return this;
}
public Builder spawn(int spawnArrivals) {
this.spawnArrivals = spawnArrivals;
return this;
}
public Builder unavailable(Distribution unavailable) {
this.unavailable = unavailable;
return this;
}
public ServerNode build() {
return new ServerNode(name, maxServers, spawnArrivals, maxQueue, service, unavailable);
}
/**
* Creates a source node with the given name and distribution.
* It swpawns infinite arrivals (Integer.MAX_VALUE) that are served by infinite
* servers (Integer.MAX_VALUE).
*
* @param name The name of the node.
* @param distribution The distribution of the inter-arrival times.
* @return The created source node.
*/
public static ServerNode source(String name, Distribution distribution) {
return new Builder(name, distribution).spawn(Integer.MAX_VALUE).build();
}
/**
* Creates a source node with the given name, distribution, and number of
* arrivals to spawn that are served by infinite servers (Integer.MAX_VALUE).
*
* @param name The name of the node.
* @param service The distribution of the inter-arrival times.
* @param spawnArrivals The number of arrivals to spawn.
* @return The created source node.
*/
public static ServerNode sourceLimited(String name, int spawnArrivals, Distribution service) {
return new Builder(name, service).spawn(spawnArrivals).build();
}
/**
* Creates a queue node with the given name, maximum number of servers, and
* distribution.
*
* @param name The name of the node.
* @param maxServers The maximum number of servers in the queue.
* @param service The distribution of the service times.
* @return The created queue node.
*/
public static ServerNode queue(String name, int maxServers, Distribution service) {
return new Builder(name, service).servers(maxServers).build();
}
/**
* Creates a queue node with the given name, maximum number of servers, and
* distribution.
*
* @param name The name of the node.
* @param maxServers The maximum number of servers in the queue.
* @param service The distribution of the service times.
* @param unavailable The distribution of the unavailable times after service.
* @return The created queue node.
*/
public static ServerNode queue(String name, int maxServers, Distribution service, Distribution unavailable) {
return new Builder(name, service).unavailable(unavailable).servers(maxServers).build();
}
}
}

View File

@@ -97,8 +97,12 @@ public final class Simulation {
this.addToFel(state.spawnUnavailableIfPossible(time, this.rng));
this.addToFel(state.spawnDepartureIfPossible(time, this.rng));
this.addToFel(state.spawnArrivalToChild(time, this.rng));
this.addToFel(state.spawnArrivalIfPossilbe(time));
// Spawn arrival to child node if queue is not full otherwise drop
var ev = state.spawnArrivalToChild(time, this.rng);
if (ev != null && !this.states[ev.nodeIndex].isQueueFull())
this.addToFel(ev);
}
}
}