Commit 21d04081 by Tuomas Riihimäki

Split MapQueue away from QUeueBean. It is getting a bit too big in there.

1 parent 7731bff9
package fi.codecrew.moya.beans.map;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.map.QueueBeanLocal.MapQueueI;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.PlaceSlot;
import fi.codecrew.moya.model.map.MapReservationQueueEntry;
public class MapQueue implements MapQueueI {
private int defaultTimeoutMin = 10;
private int minimumSlotsInQueue = 1;
private int reservingSize = 5;
// private final Set<MapReservationQueueEntry> reserving = new HashSet<>();
private volatile Set<EventUser> reserving = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final PriorityQueue<MapReservationQueueEntry> queue = new PriorityQueue<>();
private final ConcurrentMap<EventUser, MapReservationQueueEntry> queEntries = new ConcurrentHashMap<>();
private final Integer mapId;
private static final Logger logger = LoggerFactory.getLogger(MapQueue.class);
public MapQueue(EventMap map) {
this.mapId = map.getId();
}
void timeoutEntries() {
logger.info("Timeouting entries");
// give 10 seconds mercy ( and give us some time to go through all entries)
Date now = new Date(System.currentTimeMillis() + 1000 * 15);
for (EventUser r : reserving) {
MapReservationQueueEntry entry = queEntries.get(r);
logger.info("Checking if should remove user from queue {}, timeout {}", r, entry.getReservationTimeout());
if (entry.getReservationTimeout() == null || now.after(entry.getReservationTimeout())) {
logger.info("Removing Eventuser {} from reserving queue due to reservationTimeout: {}", r, entry.getReservationTimeout());
this.remove(r);
}
}
// Set idle time to the past.
// Idle timeout after 60 seconds
Date idleTimeout = new Date(System.currentTimeMillis() - 1000 * 60);
for (MapReservationQueueEntry entry : queue) {
if (entry.getSeenTime() == null) {
entry.setSeenTime(new Date());
continue;
}
if (idleTimeout.after(entry.getSeenTime())) {
remove(entry.getUser());
}
}
}
public boolean isReserving(EventUser e) {
// Check queue size and add entry to queue
checkReservingEntry();
MapReservationQueueEntry que = queEntries.get(e);
if (que != null) {
que.setSeenTime(new Date());
}
return reserving.contains(e);
}
private final Object reservingLock = new Object();
private void checkReservingEntry() {
if (reserving.size() < getReservingSize()) {
synchronized (reservingLock) {
if (reserving.size() < getReservingSize()) {
MapReservationQueueEntry queEntry = queue.poll();
if (queEntry != null) {
reserving.add(queEntry.getUser());
queEntry.setReservationTimeout(new Date(System.currentTimeMillis() + getDefaultTimeoutMin() * 60 * 1000));
}
}
}
}
}
public MapReservationQueueEntry remove(EventUser user)
{
if (user == null) {
return null;
}
MapReservationQueueEntry ret = null;
reserving.remove(user);
MapReservationQueueEntry entry = queEntries.remove(user);
if (entry != null) {
// There should neve be more than one instance, but make sure
while (queue.remove(entry)) {
}
}
checkReservingEntry();
return ret;
}
public MapReservationQueueEntry enter(EventUser user, List<PlaceSlot> slots) {
MapReservationQueueEntry ret = initEntry(user, slots);
if (!reserving.contains(user) && !queue.contains(ret)) {
queue.add(ret);
// Check if the user can be put to reservation queue immediately
checkReservingEntry();
} else {
ret = queEntries.get(user);
logger.info("User {} already in queue. Not entering again {}", user, ret);
}
return ret;
}
public void forceAdd(EventUser u, Date time, List<PlaceSlot> slots) {
MapReservationQueueEntry entry = initEntry(u, slots);
entry.setReservationTimeout(time);
queue.remove(entry);
reserving.add(u);
}
private MapReservationQueueEntry initEntry(EventUser user, List<PlaceSlot> slots) {
MapReservationQueueEntry ret = queEntries.get(user);
if (ret == null) {
ret = new MapReservationQueueEntry();
ret.setUser(user);
ret.setSeenTime(new Date());
ret.setPlaceslotcount(slots.size());
MapReservationQueueEntry old = queEntries.putIfAbsent(user, ret);
if (old != null) {
ret = old;
}
}
queEntries.put(user, ret);
return ret;
}
public Integer getPosition(EventUser user) {
Integer ret = null;
MapReservationQueueEntry entry = queEntries.get(user);
if (reserving.contains(user)) {
ret = 0;
logger.info("User in reserving queue {}", user);
} else if (entry != null && queue.contains(entry)) {
ret = 1;
for (Iterator<MapReservationQueueEntry> iterator = queue.iterator(); iterator.hasNext();) {
if (iterator.next().getUser().equals(user)) {
break;
}
++ret;
}
} else {
logger.info("Not in queue, while checking position");
}
return ret;
}
public boolean isInQueue(EventUser user) {
MapReservationQueueEntry entry = queEntries.get(user);
return reserving.contains(user) || (entry != null && queue.contains(entry));
}
public MapReservationQueueEntry getEntry(EventUser user) {
return queEntries.get(user);
}
public Collection<EventUser> getReserving() {
return reserving;
}
@Override
public PriorityQueue<MapReservationQueueEntry> getQueue() {
return queue;
}
public int getMinimumSlotsInQueue() {
return minimumSlotsInQueue;
}
public void setMinimumSlotsInQueue(int minimumSlotsInQueue) {
this.minimumSlotsInQueue = minimumSlotsInQueue;
}
public int getDefaultTimeoutMin() {
return defaultTimeoutMin;
}
public void setDefaultTimeoutMin(int defaultTimeoutMin) {
this.defaultTimeoutMin = defaultTimeoutMin;
}
public int getReservingSize() {
return reservingSize;
}
public void setReservingSize(int reservingSize) {
this.reservingSize = reservingSize;
}
}
package fi.codecrew.moya.beans;
package fi.codecrew.moya.beans.map;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.security.DeclareRoles;
......@@ -23,6 +17,9 @@ import javax.ejb.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.facade.PlaceSlotFacade;
import fi.codecrew.moya.model.EventMap;
......@@ -51,209 +48,9 @@ public class QueueBean implements QueueBeanLocal {
@EJB
private PlaceBeanLocal placebean;
private final ConcurrentHashMap<Integer, MapQueue> mapqueues = new ConcurrentHashMap<Integer, QueueBean.MapQueue>();
private static class MapQueue implements MapQueueI {
private int defaultTimeoutMin = 10;
private int minimumSlotsInQueue = 1;
private int reservingSize = 5;
// private final Set<MapReservationQueueEntry> reserving = new HashSet<>();
private volatile Set<EventUser> reserving = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final PriorityQueue<MapReservationQueueEntry> queue = new PriorityQueue<>();
private final ConcurrentMap<EventUser, MapReservationQueueEntry> queEntries = new ConcurrentHashMap<>();
private final Integer mapId;
private static final Logger logger = LoggerFactory.getLogger(MapQueue.class);
public MapQueue(EventMap map) {
this.mapId = map.getId();
}
void timeoutEntries() {
logger.info("Timeouting entries");
// give 10 seconds mercy ( and give us some time to go through all entries)
Date now = new Date(System.currentTimeMillis() + 1000 * 15);
for (EventUser r : reserving) {
MapReservationQueueEntry entry = queEntries.get(r);
logger.info("Checking if should remove user from queue {}, timeout {}", r, entry.getReservationTimeout());
if (entry.getReservationTimeout() == null || now.after(entry.getReservationTimeout())) {
logger.info("Removing Eventuser {} from reserving queue due to reservationTimeout: {}", r, entry.getReservationTimeout());
this.remove(r);
}
}
// Set idle time to the past.
// Idle timeout after 60 seconds
Date idleTimeout = new Date(System.currentTimeMillis() - 1000 * 60);
for (MapReservationQueueEntry entry : queue) {
if (entry.getSeenTime() == null) {
entry.setSeenTime(new Date());
continue;
}
if (idleTimeout.after(entry.getSeenTime())) {
remove(entry.getUser());
}
}
}
public boolean isReserving(EventUser e) {
// Check queue size and add entry to queue
checkReservingEntry();
MapReservationQueueEntry que = queEntries.get(e);
if (que != null) {
que.setSeenTime(new Date());
}
return reserving.contains(e);
}
private final Object reservingLock = new Object();
private void checkReservingEntry() {
if (reserving.size() < getReservingSize()) {
synchronized (reservingLock) {
if (reserving.size() < getReservingSize()) {
MapReservationQueueEntry queEntry = queue.poll();
if (queEntry != null) {
reserving.add(queEntry.getUser());
queEntry.setReservationTimeout(new Date(System.currentTimeMillis() + getDefaultTimeoutMin() * 60 * 1000));
}
}
}
}
}
public MapReservationQueueEntry remove(EventUser user)
{
if (user == null) {
return null;
}
MapReservationQueueEntry ret = null;
reserving.remove(user);
MapReservationQueueEntry entry = queEntries.remove(user);
if (entry != null) {
// There should neve be more than one instance, but make sure
while (queue.remove(entry)) {
}
}
checkReservingEntry();
return ret;
}
public MapReservationQueueEntry enter(EventUser user, List<PlaceSlot> slots) {
MapReservationQueueEntry ret = initEntry(user, slots);
if (!reserving.contains(user) && !queue.contains(ret)) {
queue.add(ret);
// Check if the user can be put to reservation queue immediately
checkReservingEntry();
} else {
ret = queEntries.get(user);
logger.info("User {} already in queue. Not entering again {}", user, ret);
}
return ret;
}
public void forceAdd(EventUser u, Date time, List<PlaceSlot> slots) {
MapReservationQueueEntry entry = initEntry(u, slots);
entry.setReservationTimeout(time);
queue.remove(entry);
reserving.add(u);
}
private MapReservationQueueEntry initEntry(EventUser user, List<PlaceSlot> slots) {
MapReservationQueueEntry ret = queEntries.get(user);
if (ret == null) {
ret = new MapReservationQueueEntry();
ret.setUser(user);
ret.setSeenTime(new Date());
ret.setPlaceslotcount(slots.size());
MapReservationQueueEntry old = queEntries.putIfAbsent(user, ret);
if (old != null) {
ret = old;
}
}
queEntries.put(user, ret);
return ret;
}
public Integer getPosition(EventUser user) {
Integer ret = null;
MapReservationQueueEntry entry = queEntries.get(user);
if (reserving.contains(user)) {
ret = 0;
logger.info("User in reserving queue {}", user);
} else if (entry != null && queue.contains(entry)) {
ret = 1;
for (Iterator<MapReservationQueueEntry> iterator = queue.iterator(); iterator.hasNext();) {
if (iterator.next().getUser().equals(user)) {
break;
}
++ret;
}
} else {
logger.info("Not in queue, while checking position");
}
return ret;
}
public boolean isInQueue(EventUser user) {
MapReservationQueueEntry entry = queEntries.get(user);
return reserving.contains(user) || (entry != null && queue.contains(entry));
}
public MapReservationQueueEntry getEntry(EventUser user) {
return queEntries.get(user);
}
public Collection<EventUser> getReserving() {
return reserving;
}
@Override
public PriorityQueue<MapReservationQueueEntry> getQueue() {
return queue;
}
public int getMinimumSlotsInQueue() {
return minimumSlotsInQueue;
}
public void setMinimumSlotsInQueue(int minimumSlotsInQueue) {
this.minimumSlotsInQueue = minimumSlotsInQueue;
}
public int getDefaultTimeoutMin() {
return defaultTimeoutMin;
}
public void setDefaultTimeoutMin(int defaultTimeoutMin) {
this.defaultTimeoutMin = defaultTimeoutMin;
}
public int getReservingSize() {
return reservingSize;
}
public void setReservingSize(int reservingSize) {
this.reservingSize = reservingSize;
}
}
private final ConcurrentHashMap<Integer, MapQueue> mapqueues = new ConcurrentHashMap<Integer, MapQueue>();
@EJB
private EventBeanLocal eventbean;
private AtomicLong nextReservingTimeoutCheck = new AtomicLong();
......
......@@ -14,8 +14,8 @@ import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.QueueBeanLocal;
import fi.codecrew.moya.beans.QueueBeanLocal.MapQueueI;
import fi.codecrew.moya.beans.map.QueueBeanLocal;
import fi.codecrew.moya.beans.map.QueueBeanLocal.MapQueueI;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.model.EventMap;
......@@ -38,7 +38,7 @@ public class QueueManageView extends GenericCDIView {
private EventMap map;
private fi.codecrew.moya.beans.QueueBeanLocal.MapQueueI queue;
private fi.codecrew.moya.beans.map.QueueBeanLocal.MapQueueI queue;
private String username;
private Date time = new Date(System.currentTimeMillis() + 1000 * 60 * 60);
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!