source: src/main/java/geniusweb/partiesserver/repository/RunningPartiesRepo.java

Last change on this file was 46, checked in by ruud, 20 months ago

Fixed small issues in domaineditor.

File size: 4.1 KB
Line 
1package geniusweb.partiesserver.repository;
2
3import java.util.Collection;
4import java.util.Collections;
5import java.util.Date;
6import java.util.Map;
7import java.util.concurrent.ConcurrentHashMap;
8import java.util.logging.Level;
9
10import geniusweb.actions.PartyId;
11import tudelft.utilities.listener.DefaultListenable;
12import tudelft.utilities.logging.ReportToLogger;
13import tudelft.utilities.logging.Reporter;
14import tudelft.utilities.repository.NoResourcesNowException;
15import tudelft.utilities.repository.Repository;
16
17/**
18 * RunningPartiesRepo stores all currently running parties. Listeners are
19 * notified when a party is added or removed.
20 */
21public class RunningPartiesRepo extends DefaultListenable<PartyId>
22 implements Repository<PartyId, RunningParty> {
23 /**
24 * List of currently running parties.
25 */
26 public static final int MAX_SLOTS = 16;
27 private static final RunningPartiesRepo instance = new RunningPartiesRepo(
28 new ReportToLogger("partiesserver"));
29 private static final long MAXWAIT_MS = 600000; // 10 minutes
30 private final Reporter log;
31
32 // not static to facilitate testing.
33 private final Map<PartyId, RunningParty> runningParties = new ConcurrentHashMap<>();
34
35 /**
36 * singleton pattern. Do not call this but use {@link #instance()}. Testers
37 * can still use this (instead of {@link #instance()) to get a fresn empty
38 * runningParties map. We need singleton pattern because tomcat acts as a
39 * black box calling us from "nowhere" (it works with annotations).
40 */
41 RunningPartiesRepo(Reporter reporter) {
42 this.log = reporter;
43 }
44
45 public static RunningPartiesRepo instance() {
46 return instance;
47 }
48
49 @Override
50 public Collection<RunningParty> list() {
51 return Collections.unmodifiableCollection(runningParties.values());
52 }
53
54 @Override
55 public RunningParty get(PartyId id) {
56 return runningParties.get(id);
57 }
58
59 @Override
60 public void put(RunningParty newParty) throws NoResourcesNowException {
61 PartyId id = newParty.getID();
62 synchronized (runningParties) {
63 if (runningParties.containsKey(id)) {
64 throw new IllegalArgumentException(
65 "Party " + newParty + " already in the repository");
66 }
67 if (availableSlots() <= 0) {
68 Date date = estimateCleanupTime();
69 System.out.println("AAGHG!!" + runningParties.size());
70 throw new NoResourcesNowException(
71 "There are currently no free slots to register party "
72 + newParty,
73 date);
74 }
75 runningParties.put(id, newParty);
76 }
77 notifyListeners(id);
78 }
79
80 @Override
81 public void replace(RunningParty newParty) {
82 PartyId id = newParty.getID();
83 synchronized (runningParties) {
84 if (!runningParties.containsKey(id)) {
85 throw new IllegalArgumentException(
86 "Party " + newParty + " is not in the repository");
87 }
88 runningParties.put(id, newParty);
89 }
90 notifyListeners(id);
91
92 }
93
94 /**
95 * @return an estimate of when the repo will be cleaned up (party gets
96 * terminated). Returns at most {@link #MAXWAIT_MS}. May return time
97 * before NOW if party is was expected to be already terminated.
98 */
99 public Date estimateCleanupTime() {
100 long now = System.currentTimeMillis();
101 Date date = new Date(now + MAXWAIT_MS);
102 synchronized (runningParties) {
103 for (RunningParty party : runningParties.values()) {
104 if (party.getEndDate().before(date)) {
105 date = party.getEndDate();
106 }
107 }
108 }
109 return date;
110 }
111
112 @Override
113 public void remove(PartyId id) {
114 synchronized (runningParties) {
115 RunningParty party = runningParties.get(id);
116 if (party == null) {
117 return; // no such party is there right now.
118 }
119 runningParties.remove(id);
120 try {
121 party.getParty().terminate();
122 } catch (Throwable e) {
123 log.log(Level.WARNING,
124 "Party " + id + " did not terminate properly", e);
125
126 }
127 }
128 notifyListeners(id);
129 }
130
131 /**
132 * @return the maximum number of slots in this factory. Each slot can run
133 * one party.
134 */
135
136 public int maximumSlots() {
137 return MAX_SLOTS;
138 }
139
140 /**
141 *
142 * @return the currently available number of slots in this factory. Each
143 * slot can run one party.
144 */
145
146 public int availableSlots() {
147 synchronized (runningParties) {
148 return MAX_SLOTS - runningParties.size();
149 }
150 }
151
152}
Note: See TracBrowser for help on using the repository browser.