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.core.impl;
006:
007: import com.tc.exception.ImplementMe;
008: import com.tc.net.groups.NodeID;
009: import com.tc.object.ObjectID;
010: import com.tc.objectserver.api.ObjectManager;
011: import com.tc.objectserver.api.ObjectManagerStatsListener;
012: import com.tc.objectserver.context.ObjectManagerResultsContext;
013: import com.tc.objectserver.core.api.Filter;
014: import com.tc.objectserver.core.api.GarbageCollector;
015: import com.tc.objectserver.core.api.ManagedObject;
016: import com.tc.objectserver.impl.ManagedObjectReference;
017: import com.tc.objectserver.l1.api.TestClientStateManager;
018: import com.tc.objectserver.persistence.api.PersistenceTransaction;
019: import com.tc.objectserver.persistence.api.PersistenceTransactionProvider;
020: import com.tc.objectserver.persistence.impl.NullPersistenceTransactionProvider;
021: import com.tc.text.PrettyPrinter;
022: import com.tc.util.ObjectIDSet2;
023:
024: import java.util.Arrays;
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.HashSet;
028: import java.util.Iterator;
029: import java.util.List;
030: import java.util.Map;
031: import java.util.Set;
032:
033: import junit.framework.TestCase;
034:
035: /**
036: * @author steve
037: */
038: public class MarkAndSweepGarbageCollectorTest extends TestCase
039: implements ObjectManager {
040: private long objectIDCounter = 0;
041: private TestManagedObject root1;
042: private TestManagedObject root2;
043: private Set roots = new HashSet();
044: private Map managed; // = new
045: // HashMap();
046: private GarbageCollector collector; // = new
047: // MarkAndSweepGarbageCollector();
048: private Set lookedUp;
049: private Set released;
050: private PersistenceTransactionProvider transactionProvider = new NullPersistenceTransactionProvider();
051:
052: private Filter filter = new Filter() {
053: public boolean shouldVisit(ObjectID referencedObject) {
054: return true;
055: }
056: };
057:
058: /**
059: * Constructor for MarkAndSweepGarbageCollectorTest.
060: *
061: * @param arg0
062: */
063: public MarkAndSweepGarbageCollectorTest(String arg0) {
064: super (arg0);
065: }
066:
067: /*
068: * @see TestCase#setUp()
069: */
070: protected void setUp() throws Exception {
071: super .setUp();
072: this .managed = new HashMap();
073:
074: this .collector = new MarkAndSweepGarbageCollector(this ,
075: new TestClientStateManager(), false);
076: this .lookedUp = new HashSet();
077: this .released = new HashSet();
078: this .root1 = createObject(8);
079: this .root2 = createObject(8);
080: this .roots = new HashSet();
081: roots.add(root1);
082: roots.add(root2);
083: }
084:
085: public Object getLock() {
086: return this ;
087: }
088:
089: public Set getRootIds() {
090: HashSet rv = new HashSet();
091: for (Iterator i = roots.iterator(); i.hasNext();) {
092: rv.add(((TestManagedObject) i.next()).getID());
093: }
094: return rv;
095: }
096:
097: public void testEmptyRoots() {
098: // System.out.println("running: testEmptyRoots");
099:
100: Set toDelete = collector.collect(filter, getRootIds(),
101: new HashSet(managed.keySet()));
102: // System.out.println(toDelete);
103: assertTrue(toDelete.size() == 0);
104: }
105:
106: public void testOneLevelNoGarbage() {
107: // System.out.println("running: testOneLevelNoGarbage");
108: TestManagedObject tmo = createObject(3);
109: root1.setReference(0, tmo.getID());
110: Set toDelete = collector.collect(filter, getRootIds(),
111: new HashSet(managed.keySet()));
112: // System.out.println(toDelete);
113: assertTrue(toDelete.size() == 0);
114: }
115:
116: public void testSharedBetweenRootsNoGarbage() {
117: // System.out.println("running: testSharedBetweenRootsNoGarbage");
118: TestManagedObject tmo = createObject(3);
119: root1.setReference(0, tmo.getID());
120: root2.setReference(0, tmo.getID());
121: Set toDelete = collector.collect(filter, getRootIds(),
122: new HashSet(managed.keySet()));
123: // System.out.println(toDelete);
124: // System.out.println(managed);
125: assertTrue(toDelete.size() == 0);
126: }
127:
128: public void testObjectCycleNoGarbage() {
129: TestManagedObject tmo1 = createObject(3);
130: TestManagedObject tmo2 = createObject(3);
131: tmo1.setReference(0, tmo2.getID());
132: tmo2.setReference(0, tmo1.getID());
133:
134: root1.setReference(0, tmo1.getID());
135:
136: Set toDelete = collector.collect(filter, getRootIds(),
137: new HashSet(managed.keySet()));
138: // System.out.println(toDelete);
139: assertTrue(toDelete.size() == 0);
140: }
141:
142: public void testObjectCycleWithGarbage() {
143: TestManagedObject tmo1 = createObject(3);
144: TestManagedObject tmo2 = createObject(3);
145: createObject(3);
146:
147: tmo1.setReference(0, tmo2.getID());
148: tmo2.setReference(0, tmo1.getID());
149:
150: root1.setReference(0, tmo1.getID());
151:
152: Set toDelete = collector.collect(filter, getRootIds(),
153: new HashSet(managed.keySet()));
154: // System.out.println(toDelete);
155: assertTrue(toDelete.size() == 1);
156: }
157:
158: public void testFilter() {
159: final TestManagedObject tmo1 = createObject(3);
160: final TestManagedObject tmo2 = createObject(3);
161: final TestManagedObject tmo3 = createObject(3);
162:
163: tmo1.setReference(0, tmo2.getID());
164: tmo2.setReference(0, tmo1.getID());
165: tmo2.setReference(1, tmo3.getID());
166:
167: root1.setReference(0, tmo1.getID());
168:
169: Filter testFilter = new Filter() {
170: public boolean shouldVisit(ObjectID referencedObject) {
171: boolean rv = (!tmo2.getID().equals(referencedObject));
172: return rv;
173: }
174: };
175:
176: // make sure that the filter filters out the sub-graph starting at the reference to tmo2.
177: collector.collect(testFilter, getRootIds(), new HashSet(managed
178: .keySet()));
179: assertTrue(this .lookedUp.contains(tmo1.getID()));
180: assertFalse(this .lookedUp.contains(tmo2.getID()));
181: assertFalse(this .lookedUp.contains(tmo3.getID()));
182:
183: // try it with the regular filter to make sure the behavior is actually different.
184: collector.collect(filter, getRootIds(), new HashSet(managed
185: .keySet()));
186: assertTrue(this .lookedUp.contains(tmo1.getID()));
187: assertTrue(this .lookedUp.contains(tmo2.getID()));
188: assertTrue(this .lookedUp.contains(tmo3.getID()));
189: }
190:
191: public void testLookupAndReleaseBalanced() {
192: final TestManagedObject tmo1 = createObject(3);
193: final TestManagedObject tmo2 = createObject(3);
194: final TestManagedObject tmo3 = createObject(3);
195:
196: tmo1.setReference(0, tmo2.getID());
197: tmo2.setReference(0, tmo1.getID());
198: tmo2.setReference(1, tmo3.getID());
199:
200: root1.setReference(0, tmo1.getID());
201:
202: collector.collect(filter, getRootIds(), new HashSet(managed
203: .keySet()));
204: assertTrue(lookedUp.equals(released));
205: }
206:
207: public void testIsInGCPause() throws Exception {
208: assertFalse(collector.isPausingOrPaused());
209: collector.requestGCPause();
210: collector.notifyReadyToGC();
211: assertTrue(collector.isPausingOrPaused());
212: collector.notifyGCComplete();
213: assertFalse(collector.isPausingOrPaused());
214: }
215:
216: private ObjectID nextID() {
217: return new ObjectID(objectIDCounter++);
218: }
219:
220: private TestManagedObject createObject(int refCount) {
221: ObjectID[] ids = new ObjectID[refCount];
222:
223: Arrays.fill(ids, ObjectID.NULL_ID);
224:
225: TestManagedObject tmo = new TestManagedObject(nextID(), ids);
226: // System.out.println("Creating Object:" + tmo.getID());
227: managed.put(tmo.getID(), tmo.getReference());
228: return tmo;
229: }
230:
231: public ManagedObject getObjectByID(ObjectID id) {
232: this .lookedUp.add(id);
233: ManagedObjectReference ref = (ManagedObjectReference) managed
234: .get(id);
235: return (ref == null) ? null : ref.getObject();
236: }
237:
238: public void release(PersistenceTransaction tx, ManagedObject object) {
239: this .released.add(object.getID());
240: return;
241: }
242:
243: public void releaseAll(PersistenceTransaction tx, Collection c) {
244: return;
245: }
246:
247: public void stop() {
248: throw new ImplementMe();
249: }
250:
251: public boolean lookupObjectsAndSubObjectsFor(NodeID nodeID,
252: ObjectManagerResultsContext responseContext, int maxCount) {
253: throw new ImplementMe();
254: }
255:
256: public boolean lookupObjectsFor(NodeID nodeID,
257: ObjectManagerResultsContext context) {
258: throw new ImplementMe();
259: }
260:
261: public Iterator getRoots() {
262: throw new ImplementMe();
263: }
264:
265: public void createObject(ManagedObject object) {
266: throw new ImplementMe();
267: }
268:
269: public void createRoot(String name, ObjectID id) {
270: throw new ImplementMe();
271: }
272:
273: public ObjectID lookupRootID(String name) {
274: throw new ImplementMe();
275: }
276:
277: public GarbageCollector getGarbageCollector() {
278: throw new ImplementMe();
279: }
280:
281: public void setGarbageCollector(GarbageCollector gc) {
282: throw new ImplementMe();
283: }
284:
285: public void setStatsListener(ObjectManagerStatsListener listener) {
286: throw new ImplementMe();
287: }
288:
289: public void start() {
290: throw new ImplementMe();
291: }
292:
293: public PrettyPrinter prettyPrint(PrettyPrinter out) {
294: throw new ImplementMe();
295: }
296:
297: public void releaseReadOnly(ManagedObject object) {
298: this .released.add(object.getID());
299: return;
300: }
301:
302: public void dump() {
303: throw new ImplementMe();
304: }
305:
306: public void releaseAll(Collection objects) {
307: releaseAll(transactionProvider.nullTransaction(), objects);
308: }
309:
310: public int getCheckedOutCount() {
311: return 0;
312: }
313:
314: public Set getRootIDs() {
315: return roots;
316: }
317:
318: public ObjectIDSet2 getAllObjectIDs() {
319: return new ObjectIDSet2(managed.keySet());
320: }
321:
322: public void addFaultedObject(ObjectID oid, ManagedObject mo,
323: boolean removeOnRelease) {
324: throw new ImplementMe();
325: }
326:
327: public void waitUntilReadyToGC() {
328: throw new ImplementMe();
329: }
330:
331: public void notifyGCComplete(Set toDelete) {
332: throw new ImplementMe();
333: }
334:
335: public void flushAndEvict(List objects2Flush) {
336: throw new ImplementMe();
337: }
338:
339: public Map getRootNamesToIDsMap() {
340: throw new ImplementMe();
341: }
342:
343: }
|