001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.objectserver.api;
006:
007: import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
008:
009: import com.tc.exception.ImplementMe;
010: import com.tc.object.ObjectID;
011: import com.tc.objectserver.core.api.Filter;
012: import com.tc.objectserver.core.api.GarbageCollector;
013: import com.tc.text.PrettyPrinter;
014: import com.tc.util.Assert;
015: import com.tc.util.concurrent.LifeCycleState;
016: import com.tc.util.concurrent.NullLifeCycleState;
017: import com.tc.util.concurrent.StoppableThread;
018:
019: import java.util.ArrayList;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.HashSet;
023: import java.util.List;
024: import java.util.Set;
025:
026: public class TestGarbageCollector implements GarbageCollector {
027: public Set collectedObjects = new HashSet();
028: private boolean collected = false;
029: private boolean isPausing = false;
030: private boolean isPaused = false;
031:
032: private LinkedQueue collectCalls;
033: private LinkedQueue notifyReadyToGCCalls;
034: private LinkedQueue notifyGCCompleteCalls;
035: private LinkedQueue requestGCCalls;
036: private LinkedQueue blockUntilReadyToGCCalls;
037: private LinkedQueue blockUntilReadyToGCQueue;
038: private ObjectManager objectProvider;
039:
040: public TestGarbageCollector(ObjectManager objectProvider) {
041: initQueues();
042: this .objectProvider = objectProvider;
043: }
044:
045: private void initQueues() {
046: collectCalls = new LinkedQueue();
047: notifyReadyToGCCalls = new LinkedQueue();
048: notifyGCCompleteCalls = new LinkedQueue();
049: requestGCCalls = new LinkedQueue();
050: blockUntilReadyToGCCalls = new LinkedQueue();
051: blockUntilReadyToGCQueue = new LinkedQueue();
052: }
053:
054: private List drainQueue(LinkedQueue queue) {
055: List rv = new ArrayList();
056: while (queue.peek() != null) {
057: try {
058: rv.add(queue.take());
059: } catch (InterruptedException e) {
060: throw new AssertionError(e);
061: }
062: }
063: return rv;
064: }
065:
066: public synchronized void reset() {
067: collectedObjects.clear();
068: collected = false;
069: isPausing = false;
070: initQueues();
071: }
072:
073: public Set collect(Filter filter, Collection rootIds,
074: Set managedObjectIds) {
075: try {
076: collectCalls.put(new CollectCallContext(filter, rootIds,
077: managedObjectIds, objectProvider));
078: } catch (InterruptedException e) {
079: throw new AssertionError(e);
080: }
081: this .collected = true;
082: return collectedObjects;
083: }
084:
085: public boolean collectWasCalled() {
086: return collectCalls.peek() != null;
087: }
088:
089: public boolean waitForCollectToBeCalled(long timeout) {
090: try {
091: return collectCalls.poll(timeout) != null;
092: } catch (InterruptedException e) {
093: throw new AssertionError(e);
094: }
095: }
096:
097: public CollectCallContext getNextCollectCall() {
098: try {
099: return (CollectCallContext) collectCalls.take();
100: } catch (InterruptedException e) {
101: throw new AssertionError(e);
102: }
103: }
104:
105: public List getCollectCalls() {
106: return drainQueue(collectCalls);
107: }
108:
109: public static class CollectCallContext {
110: public final Filter filter;
111: public final Collection roots;
112: public final Set managedObjectIds;
113: public final ManagedObjectProvider objectProvider;
114:
115: private CollectCallContext(Filter filter, Collection roots,
116: Set managedObjectIds,
117: ManagedObjectProvider objectProvider) {
118: this .filter = filter;
119: this .roots = Collections.unmodifiableCollection(roots);
120: this .managedObjectIds = Collections
121: .unmodifiableSet(managedObjectIds);
122: this .objectProvider = objectProvider;
123: }
124: }
125:
126: public boolean isCollected() {
127: return this .collected;
128: }
129:
130: public synchronized boolean isPausingOrPaused() {
131: return isPausing || isPaused;
132: }
133:
134: public synchronized boolean isPaused() {
135: return isPaused;
136: }
137:
138: public void notifyReadyToGC() {
139: try {
140: isPaused = true;
141: notifyReadyToGCCalls.put(new Object());
142: } catch (InterruptedException e) {
143: throw new AssertionError(e);
144: }
145: }
146:
147: public boolean notifyReadyToGC_WasCalled() {
148: return notifyReadyToGCCalls.peek() != null;
149: }
150:
151: public boolean waitFor_notifyReadyToGC_ToBeCalled(long timeout) {
152: try {
153: return notifyReadyToGCCalls.poll(timeout) != null;
154: } catch (InterruptedException e) {
155: throw new AssertionError(e);
156: }
157: }
158:
159: public void blockUntilReadyToGC() {
160: try {
161: blockUntilReadyToGCCalls.put(new Object());
162: blockUntilReadyToGCQueue.take();
163: } catch (InterruptedException e) {
164: throw new AssertionError(e);
165: }
166: }
167:
168: public void allow_blockUntilReadyToGC_ToProceed() {
169: try {
170: Assert.eval("queue was not empty!",
171: blockUntilReadyToGCQueue.peek() == null);
172: blockUntilReadyToGCQueue.put(new Object());
173: } catch (InterruptedException e) {
174: throw new AssertionError(e);
175: }
176: }
177:
178: public void waitUntil_blockUntilReadyToGC_IsCalled() {
179: try {
180: blockUntilReadyToGCCalls.take();
181: } catch (InterruptedException e) {
182: throw new AssertionError(e);
183: }
184: }
185:
186: public boolean waitFor_blockUntilReadyToGC_ToBeCalled(int timeout) {
187: try {
188: return blockUntilReadyToGCCalls.poll(timeout) != null;
189: } catch (InterruptedException e) {
190: throw new AssertionError(e);
191: }
192: }
193:
194: public boolean blockUntilReadyToGC_WasCalled() {
195: return blockUntilReadyToGCCalls.peek() != null;
196: }
197:
198: public void notifyGCDeleteStarted() {
199: return;
200: }
201:
202: public void notifyGCComplete() {
203: try {
204: isPausing = false;
205: isPaused = false;
206: notifyGCCompleteCalls.put(new Object());
207: } catch (InterruptedException e) {
208: throw new AssertionError(e);
209: }
210: return;
211: }
212:
213: public void waitUntil_notifyGCComplete_IsCalled() {
214: try {
215: notifyGCCompleteCalls.take();
216: } catch (InterruptedException e) {
217: throw new AssertionError(e);
218: }
219: }
220:
221: public boolean waitFor_notifyGCComplete_ToBeCalled(long timeout) {
222: try {
223: return notifyGCCompleteCalls.poll(timeout) != null;
224: } catch (InterruptedException e) {
225: throw new AssertionError(e);
226: }
227: }
228:
229: public void requestGCPause() {
230: try {
231: isPausing = true;
232: isPaused = false;
233: requestGCCalls.put(new Object());
234: } catch (InterruptedException e) {
235: throw new AssertionError(e);
236: }
237: return;
238: }
239:
240: public PrettyPrinter prettyPrint(PrettyPrinter out) {
241: return out.print(getClass().getName());
242: }
243:
244: public Set collect(Filter traverser, Collection roots,
245: Set managedObjectIds, LifeCycleState state) {
246: return collect(traverser, roots, managedObjectIds);
247: }
248:
249: public void changed(ObjectID changedObject, ObjectID oldReference,
250: ObjectID newReference) {
251: throw new ImplementMe();
252:
253: }
254:
255: // This test is kind of messed up now that I refactored. Needs evaluating.
256: public void gc() {
257: collect(null, objectProvider.getRootIDs(), objectProvider
258: .getAllObjectIDs(), new NullLifeCycleState());
259: this .requestGCPause();
260: this .blockUntilReadyToGC();
261: this .notifyGCComplete();
262: }
263:
264: public void addNewReferencesTo(Set rescueIds) {
265: throw new ImplementMe();
266:
267: }
268:
269: public void start() {
270: // Nop
271: }
272:
273: public void stop() {
274: throw new ImplementMe();
275:
276: }
277:
278: public void setState(StoppableThread st) {
279: throw new ImplementMe();
280:
281: }
282:
283: public void addListener(ObjectManagerEventListener listener) {
284: throw new ImplementMe();
285:
286: }
287:
288: public GCStats[] getGarbageCollectorStats() {
289: return null;
290: }
291:
292: public boolean disableGC() {
293: return false;
294: }
295:
296: public void enableGC() {
297: throw new ImplementMe();
298:
299: }
300:
301: public boolean isDisabled() {
302: return false;
303: }
304:
305: public boolean isStarted() {
306: return false;
307: }
308: }
|