Commit c8ffa521 by Tuukka Kivilahti

Merge branch 'mapque' into 'master'

Minor mapqueue fix

MapQUueue is fully thread safe, don't bother container for thread management.
Also. We don't want to use synchronized..

See merge request !318
2 parents 3fc2964a 5ea99194
...@@ -9,6 +9,7 @@ import java.util.PriorityQueue; ...@@ -9,6 +9,7 @@ import java.util.PriorityQueue;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -24,10 +25,11 @@ public class MapQueue implements MapQueueI { ...@@ -24,10 +25,11 @@ public class MapQueue implements MapQueueI {
private int minimumSlotsInQueue = 1; private int minimumSlotsInQueue = 1;
private int reservingSize = 5; private int reservingSize = 5;
// private final Set<MapReservationQueueEntry> reserving = new HashSet<>(); // private final Set<MapReservationQueueEntry> reserving = new HashSet<>();
private volatile Set<EventUser> reserving = Collections.newSetFromMap(new ConcurrentHashMap<>()); private final Set<EventUser> reserving = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final PriorityQueue<MapReservationQueueEntry> queue = new PriorityQueue<>(); private final PriorityQueue<MapReservationQueueEntry> queue = new PriorityQueue<>();
private final ConcurrentMap<EventUser, MapReservationQueueEntry> queEntries = new ConcurrentHashMap<>(); private final ConcurrentMap<EventUser, MapReservationQueueEntry> queEntries = new ConcurrentHashMap<>();
private final Integer mapId; private final Integer mapId;
//private final Object reservingLock = new Object();
private static final Logger logger = LoggerFactory.getLogger(MapQueue.class); private static final Logger logger = LoggerFactory.getLogger(MapQueue.class);
...@@ -50,8 +52,8 @@ public class MapQueue implements MapQueueI { ...@@ -50,8 +52,8 @@ public class MapQueue implements MapQueueI {
} }
// Set idle time to the past. // Set idle time to the past.
// Idle timeout after 60 seconds // Idle timeout after 12 seconds
Date idleTimeout = new Date(System.currentTimeMillis() - 1000 * 60); Date idleTimeout = new Date(System.currentTimeMillis() - 1000 * 120);
for (MapReservationQueueEntry entry : queue) { for (MapReservationQueueEntry entry : queue) {
if (entry.getSeenTime() == null) { if (entry.getSeenTime() == null) {
...@@ -77,12 +79,13 @@ public class MapQueue implements MapQueueI { ...@@ -77,12 +79,13 @@ public class MapQueue implements MapQueueI {
} }
private final Object reservingLock = new Object(); private final AtomicBoolean modifyReservers = new AtomicBoolean(false);
private void checkReservingEntry() { private void checkReservingEntry() {
if (reserving.size() < getReservingSize()) { if (reserving.size() < getReservingSize() && modifyReservers.compareAndSet(false, true)) {
synchronized (reservingLock) {
try {
if (reserving.size() < getReservingSize()) { if (reserving.size() < getReservingSize()) {
MapReservationQueueEntry queEntry = queue.poll(); MapReservationQueueEntry queEntry = queue.poll();
if (queEntry != null) { if (queEntry != null) {
...@@ -90,12 +93,14 @@ public class MapQueue implements MapQueueI { ...@@ -90,12 +93,14 @@ public class MapQueue implements MapQueueI {
queEntry.setReservationTimeout(new Date(System.currentTimeMillis() + getDefaultTimeoutMin() * 60 * 1000)); queEntry.setReservationTimeout(new Date(System.currentTimeMillis() + getDefaultTimeoutMin() * 60 * 1000));
} }
} }
} finally {
modifyReservers.set(false);
} }
} }
} }
public MapReservationQueueEntry remove(EventUser user) public MapReservationQueueEntry remove(EventUser user) {
{
if (user == null) { if (user == null) {
return null; return null;
} }
......
...@@ -13,6 +13,8 @@ import javax.ejb.LocalBean; ...@@ -13,6 +13,8 @@ import javax.ejb.LocalBean;
import javax.ejb.Lock; import javax.ejb.Lock;
import javax.ejb.LockType; import javax.ejb.LockType;
import javax.ejb.Singleton; import javax.ejb.Singleton;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -34,6 +36,8 @@ import fi.codecrew.moya.model.map.MapReservationQueueEntry; ...@@ -34,6 +36,8 @@ import fi.codecrew.moya.model.map.MapReservationQueueEntry;
@Singleton @Singleton
@LocalBean @LocalBean
@Lock(LockType.READ) @Lock(LockType.READ)
@TransactionManagement(value = TransactionManagementType.BEAN)
@DeclareRoles({ MapPermission.S_MANAGE_MAPS }) @DeclareRoles({ MapPermission.S_MANAGE_MAPS })
public class QueueBean implements QueueBeanLocal { public class QueueBean implements QueueBeanLocal {
private static final Logger logger = LoggerFactory.getLogger(QueueBean.class); private static final Logger logger = LoggerFactory.getLogger(QueueBean.class);
...@@ -45,15 +49,13 @@ public class QueueBean implements QueueBeanLocal { ...@@ -45,15 +49,13 @@ public class QueueBean implements QueueBeanLocal {
logger.info("Initialized2 QueueBean, {}", mapqueues); logger.info("Initialized2 QueueBean, {}", mapqueues);
} }
@EJB
private PlaceBeanLocal placebean;
private final ConcurrentHashMap<Integer, MapQueue> mapqueues = new ConcurrentHashMap<Integer, MapQueue>(); private final ConcurrentHashMap<Integer, MapQueue> mapqueues = new ConcurrentHashMap<Integer, MapQueue>();
private final AtomicLong nextReservingTimeoutCheck = new AtomicLong();
@EJB
private PlaceBeanLocal placebean;
@EJB @EJB
private EventBeanLocal eventbean; private EventBeanLocal eventbean;
private AtomicLong nextReservingTimeoutCheck = new AtomicLong();
@EJB @EJB
private PlaceSlotFacade slotfacade; private PlaceSlotFacade slotfacade;
@EJB @EJB
...@@ -79,6 +81,7 @@ public class QueueBean implements QueueBeanLocal { ...@@ -79,6 +81,7 @@ public class QueueBean implements QueueBeanLocal {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
long nextTime = nextReservingTimeoutCheck.get(); long nextTime = nextReservingTimeoutCheck.get();
// Update next checktime to 120 seconds in to the future, so we should have plenty of time // Update next checktime to 120 seconds in to the future, so we should have plenty of time
// to do the checks we need.. // to do the checks we need..
if (now > nextTime && nextReservingTimeoutCheck.compareAndSet(nextTime, now + 1000 * 120)) { if (now > nextTime && nextReservingTimeoutCheck.compareAndSet(nextTime, now + 1000 * 120)) {
...@@ -127,8 +130,7 @@ public class QueueBean implements QueueBeanLocal { ...@@ -127,8 +130,7 @@ public class QueueBean implements QueueBeanLocal {
@Lock(LockType.READ) @Lock(LockType.READ)
@Override @Override
public Date getReservationTimeout(EventMap map) public Date getReservationTimeout(EventMap map) {
{
Date d = null; Date d = null;
MapReservationQueueEntry ret = getMapque(map).getEntry(permbean.getCurrentUser()); MapReservationQueueEntry ret = getMapque(map).getEntry(permbean.getCurrentUser());
if (ret != null) if (ret != null)
...@@ -136,8 +138,7 @@ public class QueueBean implements QueueBeanLocal { ...@@ -136,8 +138,7 @@ public class QueueBean implements QueueBeanLocal {
return d; return d;
} }
public Date getReservingTimeout(EventMap map) public Date getReservingTimeout(EventMap map) {
{
MapReservationQueueEntry ret = getMapque(map).getEntry(permbean.getCurrentUser()); MapReservationQueueEntry ret = getMapque(map).getEntry(permbean.getCurrentUser());
Date time = null; Date time = null;
if (ret != null) if (ret != null)
...@@ -147,8 +148,7 @@ public class QueueBean implements QueueBeanLocal { ...@@ -147,8 +148,7 @@ public class QueueBean implements QueueBeanLocal {
@Lock(LockType.READ) @Lock(LockType.READ)
@Override @Override
public Integer getQueuePosition(EventMap map, EventUser user) public Integer getQueuePosition(EventMap map, EventUser user) {
{
if (!permbean.isCurrentUser(user) && !permbean.hasPermission(MapPermission.MANAGE_OTHERS)) if (!permbean.isCurrentUser(user) && !permbean.hasPermission(MapPermission.MANAGE_OTHERS))
throw new RuntimeException("Use " + permbean.getCurrentUser() + "tried to get queuepos in behalf of another user: " + user); throw new RuntimeException("Use " + permbean.getCurrentUser() + "tried to get queuepos in behalf of another user: " + user);
...@@ -215,7 +215,7 @@ public class QueueBean implements QueueBeanLocal { ...@@ -215,7 +215,7 @@ public class QueueBean implements QueueBeanLocal {
} }
@Lock(LockType.READ) @Lock(LockType.READ)
@RolesAllowed({MapPermission.S_MANAGE_MAPS, MapPermission.S_BUY_PLACES}) @RolesAllowed({ MapPermission.S_MANAGE_MAPS, MapPermission.S_BUY_PLACES })
@Override @Override
public MapQueue getMapQueue(EventMap map) { public MapQueue getMapQueue(EventMap map) {
return getMapque(map); return getMapque(map);
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!