Added ReadWriteLock instead of synchronize for Rooms

This commit is contained in:
Andrey Terentev 2024-03-13 16:31:24 +07:00 committed by Andrey Terentev
parent bdf9616062
commit c998da9792

View File

@ -11,8 +11,9 @@ import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository; import ru.dragonestia.picker.repository.UserRepository;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@Repository @Repository
@RequiredArgsConstructor @RequiredArgsConstructor
@ -20,13 +21,15 @@ public class RoomRepositoryImpl implements RoomRepository {
private final UserRepository userRepository; private final UserRepository userRepository;
private final PickerRepository pickerRepository; private final PickerRepository pickerRepository;
private final Map<Node, Rooms> node2roomsMap = new ConcurrentHashMap<>(); private final Map<Node, Rooms> node2roomsMap = new HashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
@Override @Override
public void create(Room room) throws RoomAlreadyExistException { public void create(Room room) throws RoomAlreadyExistException {
var nodeId = room.getNodeIdentifier(); var nodeId = room.getNodeIdentifier();
synchronized (node2roomsMap) { lock.writeLock().lock();
try {
var node = node2roomsMap.keySet().stream() var node = node2roomsMap.keySet().stream()
.filter(n -> room.getNodeIdentifier().equals(n.getIdentifier())) .filter(n -> room.getNodeIdentifier().equals(n.getIdentifier()))
.findFirst(); .findFirst();
@ -41,6 +44,8 @@ public class RoomRepositoryImpl implements RoomRepository {
} }
rooms.put(room.getIdentifier(), new RoomContainer(room, new AtomicInteger(0))); rooms.put(room.getIdentifier(), new RoomContainer(room, new AtomicInteger(0)));
pickerRepository.find(room.getNodeIdentifier()).add(room); pickerRepository.find(room.getNodeIdentifier()).add(room);
} finally {
lock.writeLock().unlock();
} }
} }
@ -51,44 +56,54 @@ public class RoomRepositoryImpl implements RoomRepository {
.filter(n -> room.getNodeIdentifier().equals(n.getIdentifier())) .filter(n -> room.getNodeIdentifier().equals(n.getIdentifier()))
.findFirst(); .findFirst();
synchronized (node2roomsMap) { lock.writeLock().lock();
try {
if (node.isEmpty()) { if (node.isEmpty()) {
throw new NodeNotFoundException("Node '" + nodeId + "' does not exist"); throw new NodeNotFoundException("Node '" + nodeId + "' does not exist");
} }
node2roomsMap.get(node.get()).remove(room.getIdentifier()); node2roomsMap.get(node.get()).remove(room.getIdentifier());
pickerRepository.find(room.getNodeIdentifier()).remove(room); pickerRepository.find(room.getNodeIdentifier()).remove(room);
}
userRepository.onRemoveRoom(room); userRepository.onRemoveRoom(room);
} finally {
lock.writeLock().unlock();
}
} }
@Override @Override
public Optional<Room> find(Node node, String identifier) { public Optional<Room> find(Node node, String identifier) {
synchronized (node2roomsMap) { lock.readLock().lock();
try {
if (!node2roomsMap.containsKey(node)) { if (!node2roomsMap.containsKey(node)) {
throw new NodeNotFoundException("Node '" + node.getIdentifier() + "' does not exist"); throw new NodeNotFoundException("Node '" + node.getIdentifier() + "' does not exist");
} }
var result = node2roomsMap.get(node).getOrDefault(identifier, null); var result = node2roomsMap.get(node).getOrDefault(identifier, null);
return result == null? Optional.empty() : Optional.of(result.room()); return result == null? Optional.empty() : Optional.of(result.room());
} finally {
lock.readLock().unlock();
} }
} }
@Override @Override
public List<Room> all(Node node) { public List<Room> all(Node node) {
synchronized (node2roomsMap) { lock.readLock().lock();
try {
if (!node2roomsMap.containsKey(node)) { if (!node2roomsMap.containsKey(node)) {
throw new NodeNotFoundException("Node '%s' does not exists".formatted(node.getIdentifier())); throw new NodeNotFoundException("Node '%s' does not exists".formatted(node.getIdentifier()));
} }
return node2roomsMap.get(node).values().stream().map(RoomContainer::room).toList(); return node2roomsMap.get(node).values().stream().map(RoomContainer::room).toList();
} finally {
lock.readLock().unlock();
} }
} }
@Override @Override
public Optional<Room> pickFree(Node node, Collection<User> users) { public Optional<Room> pickFree(Node node, Collection<User> users) {
synchronized (node2roomsMap) { lock.writeLock().lock();
try {
if (!node2roomsMap.containsKey(node)) { if (!node2roomsMap.containsKey(node)) {
throw new NodeNotFoundException("Node '" + node.getIdentifier() + "' does not exist"); throw new NodeNotFoundException("Node '" + node.getIdentifier() + "' does not exist");
} }
@ -109,24 +124,32 @@ public class RoomRepositoryImpl implements RoomRepository {
} }
return container.map(RoomContainer::room); return container.map(RoomContainer::room);
} finally {
lock.writeLock().unlock();
} }
} }
@Override @Override
public void onCreateNode(Node node) { public void onCreateNode(Node node) {
synchronized (node2roomsMap) { lock.writeLock().lock();
try {
node2roomsMap.put(node, new Rooms()); node2roomsMap.put(node, new Rooms());
} finally {
lock.writeLock().unlock();
} }
} }
@Override @Override
public List<Room> onRemoveNode(Node node) { public List<Room> onRemoveNode(Node node) {
List<Room> deleted; lock.writeLock().lock();
synchronized (node2roomsMap) { try {
deleted = node2roomsMap.get(node).values().stream().map(container -> container.room).toList(); var deleted = node2roomsMap.get(node).values().stream().map(container -> container.room).toList();
node2roomsMap.remove(node); node2roomsMap.remove(node);
return deleted;
} finally {
lock.writeLock().unlock();
} }
return deleted;
} }
private record RoomContainer(Room room, AtomicInteger used) { private record RoomContainer(Room room, AtomicInteger used) {