QueueBean.java
6.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package fi.codecrew.moya.beans.map;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Asynchronous;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Lock;
import javax.ejb.LockType;
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;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEventPropertyKey;
import fi.codecrew.moya.model.PlaceSlot;
import fi.codecrew.moya.model.map.MapReservationQueueEntry;
/**
* Session Bean implementation class QueueBean
*/
@Singleton
@LocalBean
@Lock(LockType.READ)
@DeclareRoles({ MapPermission.S_MANAGE_MAPS })
public class QueueBean implements QueueBeanLocal {
private static final Logger logger = LoggerFactory.getLogger(QueueBean.class);
/**
* Default constructor.
*/
public QueueBean() {
logger.info("Initialized2 QueueBean, {}", mapqueues);
}
@EJB
private PlaceBeanLocal placebean;
private final ConcurrentHashMap<Integer, MapQueue> mapqueues = new ConcurrentHashMap<Integer, MapQueue>();
@EJB
private EventBeanLocal eventbean;
private AtomicLong nextReservingTimeoutCheck = new AtomicLong();
@EJB
private PlaceSlotFacade slotfacade;
@EJB
private PermissionBeanLocal permbean;
@Lock(LockType.READ)
@Override
public boolean isReserving(EventMap map, EventUser user) {
// If queue is not enabled, user can always reserve
if (!isQueueEnabled())
return true;
if (!permbean.isCurrentUser(user) && !permbean.hasPermission(MapPermission.MANAGE_OTHERS))
throw new RuntimeException("Use " + permbean.getCurrentUser() + "tried to enter to queue in behalf of another user: " + user);
if (map == null || user == null) {
logger.warn("Can not check map {}, user {}", map, user);
return false;
}
boolean ret = getMapque(map).isReserving(user);
// Do some housekeeping, but only on each 120
long now = System.currentTimeMillis();
long nextTime = nextReservingTimeoutCheck.get();
// Update next checktime to 120 seconds in to the future, so we should have plenty of time
// to do the checks we need..
if (now > nextTime && nextReservingTimeoutCheck.compareAndSet(nextTime, now + 1000 * 120)) {
logger.info("Launcing reservingTimeout check ");
checkReservingTimeouts();
logger.info("Done launching reservingTimeoutCheck");
}
return ret;
}
@Lock(LockType.READ)
@Asynchronous
private void checkReservingTimeouts() {
try {
final long oldTime = nextReservingTimeoutCheck.get();
for (MapQueue m : mapqueues.values()) {
m.timeoutEntries();
}
// DO housekeeping every 10 seconds.
nextReservingTimeoutCheck.compareAndSet(oldTime, System.currentTimeMillis() + 1000 * 10);
} catch (Exception t) {
logger.warn("Exception while checking reservingTimeouts", t);
}
}
@Lock(LockType.READ)
private MapQueue getMapque(EventMap map) {
if (map == null) {
return null;
}
MapQueue ret = mapqueues.get(map.getId());
if (ret == null) {
ret = new MapQueue(map);
MapQueue nret = mapqueues.putIfAbsent(map.getId(), ret);
if (nret != null) {
ret = nret;
}
}
logger.info("returning queue {} for map {}", ret, map);
return ret;
}
@Lock(LockType.READ)
@Override
public Date getReservationTimeout(EventMap map)
{
Date d = null;
MapReservationQueueEntry ret = getMapque(map).getEntry(permbean.getCurrentUser());
if (ret != null)
d = ret.getReservationTimeout();
return d;
}
public Date getReservingTimeout(EventMap map)
{
MapReservationQueueEntry ret = getMapque(map).getEntry(permbean.getCurrentUser());
Date time = null;
if (ret != null)
time = ret.getReservationTimeout();
return time;
}
@Lock(LockType.READ)
@Override
public Integer getQueuePosition(EventMap map, EventUser user)
{
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);
return getMapque(map).getPosition(permbean.getCurrentUser());
}
@Lock(LockType.READ)
@Override
public boolean isQueueEnabled() {
return eventbean.getPropertyBoolean(LanEventPropertyKey.MAP_QUEUE);
}
@Lock(LockType.READ)
@Override
public MapReservationQueueEntry remove(EventMap map, EventUser user) {
if (!permbean.isCurrentUser(user) && !permbean.hasPermission(MapPermission.MANAGE_OTHERS))
throw new RuntimeException("Use " + permbean.getCurrentUser() + "tried to enter to queue in behalf of another user: " + user);
MapQueue queue = getMapque(map);
return queue.remove(user);
}
@Override
@Lock(LockType.READ)
@RolesAllowed(MapPermission.S_MANAGE_MAPS)
public void forceAddToReserving(EventMap map, EventUser u, Date time) {
MapQueue q = getMapque(map);
List<PlaceSlot> slots = slotfacade.findFreePlaceSlots(u, map);
q.forceAdd(u, time, slots);
}
@Override
@Lock(LockType.READ)
public MapReservationQueueEntry enterQueue(EventMap map, EventUser user) {
if (!isQueueEnabled()) {
return null;
}
if (!permbean.isCurrentUser(user) && !permbean.hasPermission(MapPermission.MANAGE_OTHERS))
throw new RuntimeException("Use " + permbean.getCurrentUser() + "tried to enter to queue in behalf of another user: " + user);
if (user == null || user.isAnonymous()) {
return null;
}
MapQueue queue = getMapque(map);
MapReservationQueueEntry ret = null;
if (queue.isInQueue(user)) {
logger.info("User {} already in queue");
ret = queue.getEntry(user);
} else {
List<PlaceSlot> slots = slotfacade.findFreePlaceSlots(user, map);
logger.info("User {} not yet in queue. User has {} slots", user, slots.size());
if (!slots.isEmpty() && slots.size() >= queue.getMinimumSlotsInQueue()) {
ret = queue.enter(user, slots);
}
}
return ret;
}
@Lock(LockType.READ)
@RolesAllowed({MapPermission.S_MANAGE_MAPS, MapPermission.S_BUY_PLACES})
@Override
public MapQueue getMapQueue(EventMap map) {
return getMapque(map);
}
@Override
@Lock(LockType.READ)
@RolesAllowed(MapPermission.S_MANAGE_MAPS)
public void forceRemove(EventMap e, EventUser u) {
MapQueue q = getMapque(e);
q.remove(u);
}
}