Skip to content

Commit

Permalink
Dead rooms now get deleted.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kait0u committed Jun 18, 2024
1 parent 6652035 commit d6df3c2
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,74 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import wit.pap.multidraw.shared.communication.ClientMessage;
import wit.pap.multidraw.shared.globals.Globals;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

public class MultiDrawServer {
public static final Logger log = LogManager.getLogger(MultiDrawServer.class.getName());

private final int port;
private final ServerSocket serverSocket;
private boolean isRunning = false;
private final AtomicBoolean isRunning;

private final Thread userAssigner, deadRoomCleaner;


// private final Set<User> users;
private final Set<Room> rooms;
private final Map<String, Room> nameRoomMap;
private final Map<Room, Thread> roomThreadMap;
private final Queue<Socket> toBeUsers;

Instant lastDeadRoomCheck;

public MultiDrawServer(int port) {
this.port = port;
try {
this.serverSocket = new ServerSocket(this.port);
} catch (IOException e) {
throw new RuntimeException(e);
}
this.isRunning = new AtomicBoolean(false);
this.rooms = new HashSet<>();
this.nameRoomMap = new HashMap<>();
this.roomThreadMap = new HashMap<>();
// this.users = new HashSet<>();
this.toBeUsers = new ConcurrentLinkedQueue<>();

this.lastDeadRoomCheck = Instant.now();

this.userAssigner = new Thread(() -> {
while (isRunning.get())
assignUsers();
});

this.deadRoomCleaner = new Thread(() -> {
while (isRunning.get()) {
clearDeadRooms();
}
});
}

public void start() {
isRunning = true;
isRunning.set(true);
log.info(new StringBuilder("Server started on port ").append(port));
run();
}

public void run() {
while (isRunning) {
userAssigner.start();
deadRoomCleaner.start();

while (isRunning.get()) {
waitForUser();
assignUser();
}
}

Expand All @@ -62,8 +85,8 @@ private void waitForUser() {
}
}

private void assignUser() {
if (!toBeUsers.isEmpty()) {
private void assignUsers() {
while (!toBeUsers.isEmpty()) {
Socket socket = toBeUsers.poll();

User user = new User(socket, null, null);
Expand Down Expand Up @@ -93,9 +116,7 @@ private void assignUser() {
try {
user.setNickname(nickname);
user.setRoom(room);
// synchronized (users) {
// users.add(user);
// }

log.info(new StringBuilder(socket.getInetAddress().toString())
.append(" became User ").append(nickname).append(" in room ").append(roomName));
} catch (DuplicateNicknameException e) {
Expand Down Expand Up @@ -130,6 +151,35 @@ private Room createRoom(String name) {
return room;
}

private void clearDeadRooms() {
if (Duration.between(lastDeadRoomCheck, Instant.now()).toSeconds() < Globals.DEAD_ROOM_CHECK_INTERVAL_SECONDS)
return;

log.info("Searching for dead rooms...");

synchronized (rooms) {
Iterator<Room> deadRoomIterator = rooms.iterator();

while (deadRoomIterator.hasNext()) {
Room r = deadRoomIterator.next();

if (!r.isRunning()){
synchronized (roomThreadMap) {
Thread thread = roomThreadMap.getOrDefault(r, null);
if (thread != null && !thread.isAlive()) {
roomThreadMap.remove(r);
}
}

deadRoomIterator.remove();
log.info(new StringBuilder("Dead Room \"").append(r.getName()).append("\" removed!"));
}
}
}
lastDeadRoomCheck = Instant.now();
log.info("Searching for dead rooms complete!");
}

private void logClientMessage(ClientMessage message) {
log.info(new StringBuilder("Message received: ").append(message.getClientCommand().name()).append(" ")
.append(new String(message.getPayload())));
Expand Down
56 changes: 37 additions & 19 deletions multidraw-server/src/main/java/wit/pap/multidraw/server/Room.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
import wit.pap.multidraw.shared.communication.ClientMessage;
import wit.pap.multidraw.shared.communication.ServerCommands;
import wit.pap.multidraw.shared.communication.ServerMessage;
import wit.pap.multidraw.shared.globals.Globals;

import java.net.SocketException;
import java.security.InvalidParameterException;
import java.time.Duration;
import java.time.Instant;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

Expand All @@ -19,6 +20,7 @@ public class Room implements Runnable {
private final String name;
private final Set<User> users;
private final AtomicBoolean isRunning;
private Instant lastUserRemoval, lastDeadUserCheck;

public Room(String name) {
if (name == null)
Expand All @@ -27,6 +29,19 @@ public Room(String name) {
this.name = name;
this.users = new LinkedHashSet<>();
this.isRunning = new AtomicBoolean(false);
this.lastDeadUserCheck = Instant.now();
this.lastUserRemoval = Instant.now();
}

@Override
public void run() {
isRunning.set(true);
while (isRunning.get()) {
catchDeadUsers();
preventLinger();
}

log.info(new StringBuilder("Room \"").append(name).append("\" ceases to operate!"));
}

public void addUser(User user) throws DuplicateNicknameException {
Expand All @@ -45,6 +60,7 @@ public void addUser(User user) throws DuplicateNicknameException {
.append(". Current user count: ")
.append(users.size())
);
user.sendMessage(new ServerMessage(ServerCommands.ACCEPT_INT0_ROOM, null));
}

}
Expand All @@ -61,29 +77,18 @@ public void removeUser(User user) {
.append(users.size())
);
}
}

@Override
public void run() {
isRunning.set(true);
while (isRunning.get()) {
catchDeadUsers();
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
log.error(e);
}

}
lastUserRemoval = Instant.now();
}

private void catchDeadUsers() {
if (Duration.between(lastDeadUserCheck, Instant.now()).toSeconds() < Globals.DEAD_USERS_CHECK_INTERVAL_SECONDS)
return;

synchronized (users) {
Iterator<User> uIt = users.iterator();
while (uIt.hasNext()) {
User u = uIt.next();
boolean shouldDelete = false;
shouldDelete = u.isDead();
boolean shouldDelete = u.isDead();

if (!shouldDelete) {
try {
Expand All @@ -98,6 +103,8 @@ private void catchDeadUsers() {
removeUser(u);
}
}

lastDeadUserCheck = Instant.now();
}

private void receiveMessages() {
Expand All @@ -114,8 +121,19 @@ private void handleMessage(User sender, ClientMessage message) {
switch (message.getClientCommand()) {
case POKE, SET_NICKNAME, JOIN_CREATE_ROOM -> {}
case SEND_IMAGE -> {}
case DISCONNECT -> { removeUser(sender); }
case DISCONNECT -> removeUser(sender);
}
}

private void preventLinger() {
Instant now = Instant.now();
Duration timeSinceLastRemoval = Duration.between(lastUserRemoval, now);

if (users.isEmpty() && timeSinceLastRemoval.toMinutes() >= Globals.MAX_ROOM_LINGER_MINUTES) {
isRunning.set(false);
log.info(new StringBuilder("Room \"").append(name).append("\" set to stop"));
}

}

// Getters & Setters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class Globals {
public static final int WINDOW_MIN_W = 960;
public static final int WINDOW_MIN_H = 512;

public static final int MAX_DATAGRAM_LENGTH_KB = 16;
public static final int MAX_DATAGRAM_LENGTH_B = MAX_DATAGRAM_LENGTH_KB * 1024;

public static final int DEAD_USERS_CHECK_INTERVAL_SECONDS = 20;
public static final int DEAD_ROOM_CHECK_INTERVAL_SECONDS = 20;
public static final int MAX_ROOM_LINGER_MINUTES = 1;
}

0 comments on commit d6df3c2

Please sign in to comment.