Fix: Server Persistence
This commit is contained in:
@@ -42,6 +42,7 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
|||||||
BlockingQueue<NetworkEvent> actionQueue;
|
BlockingQueue<NetworkEvent> actionQueue;
|
||||||
private LimitedMap<String, Boolean> playerList;
|
private LimitedMap<String, Boolean> playerList;
|
||||||
|
|
||||||
|
private boolean serverCrashed;
|
||||||
|
|
||||||
public RMIServer(GameController controller, int nPort,
|
public RMIServer(GameController controller, int nPort,
|
||||||
BlockingQueue<NetworkEvent> actionQueue,
|
BlockingQueue<NetworkEvent> actionQueue,
|
||||||
@@ -71,6 +72,28 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
|||||||
if (preferredInt < 2 || preferredInt > 5) return false;
|
if (preferredInt < 2 || preferredInt > 5) return false;
|
||||||
|
|
||||||
synchronized (controller) {
|
synchronized (controller) {
|
||||||
|
if(serverCrashed)
|
||||||
|
{
|
||||||
|
if(controller.getModel().getPlayers().stream().anyMatch(p -> p.getUserName().equals(username))&& !playerList.containsKey(username)) {
|
||||||
|
clients.put(username, callback);
|
||||||
|
playerList.put(username, true);
|
||||||
|
startWatchdog(username);
|
||||||
|
System.out.println("(After crash)Reconnected player: " + username);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (playerList.containsKey(username) && !playerList.get(username)) {
|
||||||
|
playerList.put(username, true);
|
||||||
|
clients.put(username, callback);
|
||||||
|
System.out.println("Reconnected player: " + username);
|
||||||
|
startWatchdog(username);
|
||||||
|
callback.onGameInit(model);
|
||||||
|
System.out.println("Model sent: " + username);
|
||||||
|
actionQueue.add(new ReconnectPlayer(username));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (playerList.isEmpty()) {
|
if (playerList.isEmpty()) {
|
||||||
model = new Game(preferredInt);
|
model = new Game(preferredInt);
|
||||||
controller.setModel(model);
|
controller.setModel(model);
|
||||||
@@ -94,6 +117,7 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
|||||||
actionQueue.add(new ReconnectPlayer(username));
|
actionQueue.add(new ReconnectPlayer(username));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,7 +287,8 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
|||||||
* Starts the RMI server.
|
* Starts the RMI server.
|
||||||
* @return true if the server starts successfully, false otherwise
|
* @return true if the server starts successfully, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean start() {
|
public boolean start(boolean serverCrashed) {
|
||||||
|
this.serverCrashed = serverCrashed;
|
||||||
try {
|
try {
|
||||||
System.setProperty("java.rmi.server.hostname", host);
|
System.setProperty("java.rmi.server.hostname", host);
|
||||||
registry = LocateRegistry.createRegistry(nPort);
|
registry = LocateRegistry.createRegistry(nPort);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class TCPServer {
|
|||||||
LimitedMap<String, Boolean> playerList;
|
LimitedMap<String, Boolean> playerList;
|
||||||
List<ClientHandler> clientHandlers;
|
List<ClientHandler> clientHandlers;
|
||||||
|
|
||||||
|
boolean serverCrashed;
|
||||||
// Mappa temporanea: username → ClientHandler
|
// Mappa temporanea: username → ClientHandler
|
||||||
// Serve per associare il socket heartbeat al giusto ClientHandler
|
// Serve per associare il socket heartbeat al giusto ClientHandler
|
||||||
private final Map<String, ClientHandler> pendingHeartbeat = new ConcurrentHashMap<>();
|
private final Map<String, ClientHandler> pendingHeartbeat = new ConcurrentHashMap<>();
|
||||||
@@ -50,7 +51,8 @@ public class TCPServer {
|
|||||||
this.clientHandlers = new ArrayList<>();
|
this.clientHandlers = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start(boolean serverCrashed) {
|
||||||
|
this.serverCrashed = serverCrashed;
|
||||||
try {
|
try {
|
||||||
socketTCP = new ServerSocket(port);
|
socketTCP = new ServerSocket(port);
|
||||||
heartbeatSocketTCP = new ServerSocket(heartbeatPort);
|
heartbeatSocketTCP = new ServerSocket(heartbeatPort);
|
||||||
@@ -90,23 +92,55 @@ public class TCPServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (controller) {
|
synchronized (controller) {
|
||||||
|
|
||||||
|
String username = eventAddPlayer.getUsername();
|
||||||
|
if(serverCrashed){
|
||||||
|
if(controller.getModel().getPlayers().stream().anyMatch(p -> p.getUserName().equals(username))&& !playerList.containsKey(username)){
|
||||||
|
playerList.put(username, true);
|
||||||
|
System.out.println("(After crash)Reconnected player: " + username);
|
||||||
|
ClientHandler handler = new ClientHandler(
|
||||||
|
username, clientSocket, clientSend, clientReceive,
|
||||||
|
clientHandlers,playerList, actionQueue
|
||||||
|
);
|
||||||
|
clientSocket.getOutputStream().write(1);
|
||||||
|
pendingHeartbeat.put(username, handler);
|
||||||
|
Thread thread = new Thread(handler);
|
||||||
|
thread.start();
|
||||||
|
clientHandlers.add(handler);
|
||||||
|
connectedPlayers++;
|
||||||
|
}
|
||||||
|
else if(playerList.containsKey(username) && !playerList.get(username)){
|
||||||
|
// riconnessione
|
||||||
|
playerList.put(username, true);
|
||||||
|
System.out.println("Reconnected player: " + username);
|
||||||
|
|
||||||
|
ClientHandler handler = new ClientHandler(
|
||||||
|
username, clientSocket, clientSend, clientReceive,
|
||||||
|
clientHandlers, playerList, actionQueue
|
||||||
|
);
|
||||||
|
clientSocket.getOutputStream().write(1);
|
||||||
|
pendingHeartbeat.put(username, handler);
|
||||||
|
handler.notifyModel(controller.getModel());
|
||||||
|
Thread thread = new Thread(handler);
|
||||||
|
thread.start();
|
||||||
|
clientHandlers.add(handler);
|
||||||
|
connectedPlayers++;
|
||||||
|
actionQueue.add(new ReconnectPlayer(username));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clientSocket.getOutputStream().write(-1);
|
||||||
|
clientSocket.close();
|
||||||
|
System.out.println("Player could not be added. Connection terminated.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (playerList.isEmpty()) {
|
if (playerList.isEmpty()) {
|
||||||
if(controller.getModel() == null){
|
|
||||||
Game model = new Game(eventAddPlayer.getProposedNPlayer());
|
Game model = new Game(eventAddPlayer.getProposedNPlayer());
|
||||||
controller.setModel(model);
|
controller.setModel(model);
|
||||||
playerList.setLimit(eventAddPlayer.getProposedNPlayer());
|
playerList.setLimit(eventAddPlayer.getProposedNPlayer());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
for(Player p:controller.getModel().getPlayers()) {
|
|
||||||
playerList.put(p.getUserName(),false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String username = eventAddPlayer.getUsername();
|
|
||||||
|
|
||||||
if (controller.addPlayer(username)) {
|
if (controller.addPlayer(username)) {
|
||||||
// nuovo giocatore
|
// nuovo giocatore
|
||||||
playerList.put(username, true);
|
playerList.put(username, true);
|
||||||
@@ -122,8 +156,6 @@ public class TCPServer {
|
|||||||
clientHandlers.add(handler);
|
clientHandlers.add(handler);
|
||||||
connectedPlayers++;
|
connectedPlayers++;
|
||||||
// metti in attesa del socket heartbeat
|
// metti in attesa del socket heartbeat
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(playerList.containsKey(username) && !playerList.get(username)){
|
else if(playerList.containsKey(username) && !playerList.get(username)){
|
||||||
// riconnessione
|
// riconnessione
|
||||||
@@ -150,6 +182,8 @@ public class TCPServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(IOException | ClassNotFoundException e){
|
catch(IOException | ClassNotFoundException e){
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package it.polimi.ingsw.gc14;
|
|||||||
import it.polimi.ingsw.gc14.Controller.GameController;
|
import it.polimi.ingsw.gc14.Controller.GameController;
|
||||||
import it.polimi.ingsw.gc14.Model.Game;
|
import it.polimi.ingsw.gc14.Model.Game;
|
||||||
import it.polimi.ingsw.gc14.Model.GamePackage.GameStages;
|
import it.polimi.ingsw.gc14.Model.GamePackage.GameStages;
|
||||||
|
import it.polimi.ingsw.gc14.Model.Player;
|
||||||
import it.polimi.ingsw.gc14.Network.NetworkEvent;
|
import it.polimi.ingsw.gc14.Network.NetworkEvent;
|
||||||
import it.polimi.ingsw.gc14.Network.NetworkEvents.DisconnectedPlayer;
|
import it.polimi.ingsw.gc14.Network.NetworkEvents.DisconnectedPlayer;
|
||||||
import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer;
|
import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer;
|
||||||
@@ -126,7 +127,7 @@ public class ServerLauncher {
|
|||||||
BlockingQueue<NetworkEvent> actionQueue = new LinkedBlockingQueue<>();
|
BlockingQueue<NetworkEvent> actionQueue = new LinkedBlockingQueue<>();
|
||||||
GameController gameController = new GameController();
|
GameController gameController = new GameController();
|
||||||
String IP;
|
String IP;
|
||||||
|
boolean serverCrashed;
|
||||||
try {
|
try {
|
||||||
IP=chooseNetworkInterface(new Scanner(System.in));
|
IP=chooseNetworkInterface(new Scanner(System.in));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -136,7 +137,12 @@ public class ServerLauncher {
|
|||||||
RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue, playerList,IP);
|
RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue, playerList,IP);
|
||||||
TCPServer serverTCP = new TCPServer(gameController, 8080, 8081,actionQueue, playerList);
|
TCPServer serverTCP = new TCPServer(gameController, 8080, 8081,actionQueue, playerList);
|
||||||
ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP);
|
ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP);
|
||||||
|
if(gameController.getModel() != null){
|
||||||
|
playerList.setLimit(gameController.getModel().getNPlayers());
|
||||||
|
serverCrashed = true;
|
||||||
|
} else {
|
||||||
|
serverCrashed = false;
|
||||||
|
}
|
||||||
playerList.setAction(()->{
|
playerList.setAction(()->{
|
||||||
new Thread(()->{
|
new Thread(()->{
|
||||||
try {
|
try {
|
||||||
@@ -149,8 +155,8 @@ public class ServerLauncher {
|
|||||||
}).start();
|
}).start();
|
||||||
});
|
});
|
||||||
|
|
||||||
serverRMI.start();
|
serverRMI.start(serverCrashed);
|
||||||
new Thread(()->{serverTCP.start();}).start();
|
new Thread(()->{serverTCP.start(serverCrashed);}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user