package org.server;
/*
*The server has an array of 3 Ports called comm_ports: comm_ports[0] receives requests from clients belonging to setA
comm_ports[1] receives requests from clients belonging to setA
comm_ports[2] receives requests from clients belonging to both setA and setB wishing to release a resource
When requesting a resource, a client sends data of type Message which contains a reference to the port to be used for the reply and the data to be send.
For request messages, the data part of the message is null while for release messages the data part contains an integer of the resource to be released.
The server checks for messages from each port by calling the isEmpty function of the Port class which returns true if a message has been send to the port
and is waiting to be received. If a message if available, method receiveRequest() returns an integer corresponding to the index in comm_ports array which
has a message. The message is then read from the port. If the message is a request message from either setA or setB and a free resource is available,
one is allocated, the reply port is read from the message and a reply is send back to the client. If no resource is free, the client is blocked and the
request is queued either to waiting_setA or waiting_setB for setA and setB requests respectively.
On the other hand if the received message was a release message, a reply signal is send back to the client releasing the resource then if setA has blocked messages,
one of then is picked and the resource is allocated to it and a reply is send. if no setA clients have been but there are setB clients blocked,
the resource if allocated to one of them and its removed from the queue. Finally, if no client has been blocked, the resource is marked as free.
*/
import java.util.ArrayList;
import java.util.List;
import org.port.Port;
import org.port.Ports;
public class Server extends Thread {
public static final int SET_A = 0;
public static final int SET_B = 1;
public static final int RELEASE = 2;
public Ports resources;
public Port[] comm_ports;
private boolean[] free;
private int available;
private List<Message> waiting_setA;
private List<Message> waiting_setB;
public Server() {
resources = new Ports(5);
comm_ports = new Port[3];
free = new boolean[5];
available = 5;
waiting_setA = new ArrayList<Message>();
waiting_setB = new ArrayList<Message>();
for (int i = 0; i < 5; i++)
free[i] = true;
for (int i = 0; i < 3; i++)
comm_ports[i] = new Port<>();
}
public void run() {
while (true) {
int req = receiveRequest();
Message m;
Message msg = new Message<>();
switch (req) {
case SET_A:
m = (Message) comm_ports[SET_A].receive();
if (available == 0) {
waiting_setA.add(m);
} else {
int r = 0;
while (!free[r])
r++;
free[r] = false;
available--;
msg.data = (Integer) r;
msg.reply_port = null;
m.reply_port.send(msg);
}
break;
case SET_B:
m = (Message) comm_ports[SET_B].receive();
if (available == 0) {
waiting_setB.add(m);
} else {
int r = 0;
while (!free[r])
r++;
free[r] = false;
available--;
msg.data = (Integer) r;
msg.reply_port = null;
m.reply_port.send(msg);
}
break;
case RELEASE:
m = (Message) comm_ports[RELEASE].receive();
int r = (Integer) m.data;
Port reply = (Port) m.reply_port;
reply.send(null); // sends a signal to client releasing the
// resource
if (!waiting_setA.isEmpty()) {
m = waiting_setA.get(0);
msg.reply_port = null;
msg.data = (Integer) r;
waiting_setA.remove(0);
m.reply_port.send(msg);
} else if (!waiting_setB.isEmpty()) {
m = waiting_setB.get(0);
msg.reply_port = null;
msg.data = r;
waiting_setB.remove(0);
m.reply_port.send(msg);
} else {
free[r] = true;
available++;
}
break;
}
}
}
private int receiveRequest() {
while (true) {
for (int i = 0; i < 2; i++)
if (!comm_ports[i].isEmpty())
return i;
}
}
}