1 5 package com.tc.objectserver.api; 6 7 import EDU.oswego.cs.dl.util.concurrent.LinkedQueue; 8 9 import com.tc.exception.ImplementMe; 10 import com.tc.lang.TCThreadGroup; 11 import com.tc.lang.ThrowableHandler; 12 import com.tc.logging.TCLogger; 13 import com.tc.logging.TCLogging; 14 import com.tc.management.beans.object.MockObjectManagementMonitor; 15 import com.tc.net.protocol.tcm.ChannelID; 16 import com.tc.object.BaseDSOTestCase; 17 import com.tc.object.ObjectID; 18 import com.tc.object.SerializationUtil; 19 import com.tc.object.cache.EvictionPolicy; 20 import com.tc.object.cache.LRUEvictionPolicy; 21 import com.tc.object.cache.NullCache; 22 import com.tc.object.cache.TestCacheStats; 23 import com.tc.object.dna.api.DNA; 24 import com.tc.object.dna.api.DNACursor; 25 import com.tc.object.dna.api.DNAException; 26 import com.tc.object.dna.api.LiteralAction; 27 import com.tc.object.dna.api.LogicalAction; 28 import com.tc.object.dna.api.PhysicalAction; 29 import com.tc.object.dna.impl.DNAEncoding; 30 import com.tc.object.dna.impl.UTF8ByteDataHolder; 31 import com.tc.object.tx.TransactionID; 32 import com.tc.objectserver.context.ManagedObjectFaultingContext; 33 import com.tc.objectserver.context.ManagedObjectFlushingContext; 34 import com.tc.objectserver.context.ObjectManagerResultsContext; 35 import com.tc.objectserver.core.api.Filter; 36 import com.tc.objectserver.core.api.GarbageCollector; 37 import com.tc.objectserver.core.api.ManagedObject; 38 import com.tc.objectserver.core.api.TestDNA; 39 import com.tc.objectserver.core.impl.MarkAndSweepGarbageCollector; 40 import com.tc.objectserver.core.impl.TestManagedObject; 41 import com.tc.objectserver.impl.InMemoryManagedObjectStore; 42 import com.tc.objectserver.impl.ObjectInstanceMonitorImpl; 43 import com.tc.objectserver.impl.ObjectManagerConfig; 44 import com.tc.objectserver.impl.ObjectManagerImpl; 45 import com.tc.objectserver.impl.ObjectManagerStatsImpl; 46 import com.tc.objectserver.impl.PersistentManagedObjectStore; 47 import com.tc.objectserver.l1.api.ClientStateManager; 48 import com.tc.objectserver.l1.impl.ClientStateManagerImpl; 49 import com.tc.objectserver.managedobject.BackReferences; 50 import com.tc.objectserver.managedobject.ManagedObjectStateFactory; 51 import com.tc.objectserver.managedobject.NullManagedObjectChangeListenerProvider; 52 import com.tc.objectserver.mgmt.ManagedObjectFacade; 53 import com.tc.objectserver.mgmt.MapEntryFacade; 54 import com.tc.objectserver.persistence.api.ManagedObjectPersistor; 55 import com.tc.objectserver.persistence.api.ManagedObjectStore; 56 import com.tc.objectserver.persistence.api.PersistenceTransaction; 57 import com.tc.objectserver.persistence.api.PersistenceTransactionProvider; 58 import com.tc.objectserver.persistence.api.Persistor; 59 import com.tc.objectserver.persistence.impl.InMemoryPersistor; 60 import com.tc.objectserver.persistence.impl.TestPersistenceTransaction; 61 import com.tc.objectserver.persistence.impl.TestPersistenceTransactionProvider; 62 import com.tc.objectserver.persistence.sleepycat.CustomSerializationAdapterFactory; 63 import com.tc.objectserver.persistence.sleepycat.DBEnvironment; 64 import com.tc.objectserver.persistence.sleepycat.SerializationAdapterFactory; 65 import com.tc.objectserver.persistence.sleepycat.SleepycatPersistor; 66 import com.tc.objectserver.persistence.sleepycat.SleepycatSerializationAdapterFactory; 67 import com.tc.stats.counter.sampled.SampledCounter; 68 import com.tc.stats.counter.sampled.SampledCounterConfig; 69 import com.tc.stats.counter.sampled.SampledCounterImpl; 70 import com.tc.text.PrettyPrinter; 71 import com.tc.util.concurrent.LifeCycleState; 72 import com.tc.util.concurrent.StoppableThread; 73 import com.tc.util.concurrent.ThreadUtil; 74 75 import java.io.File ; 76 import java.util.ArrayList ; 77 import java.util.Arrays ; 78 import java.util.Collection ; 79 import java.util.Collections ; 80 import java.util.Date ; 81 import java.util.HashMap ; 82 import java.util.HashSet ; 83 import java.util.Iterator ; 84 import java.util.List ; 85 import java.util.Map ; 86 import java.util.Set ; 87 88 import javax.management.NotCompliantMBeanException ; 89 90 93 public class ObjectManagerTest extends BaseDSOTestCase { 94 95 private Map managed; 96 private ObjectManagerImpl objectManager; 97 private TestObjectManagerConfig config; 98 private ClientStateManager clientStateManager; 99 private ManagedObjectStore objectStore; 100 private TCLogger logger; 101 private ObjectManagerStatsImpl stats; 102 private SampledCounter newObjectCounter; 103 private SampledCounterImpl objectfaultCounter; 104 private TestPersistenceTransactionProvider persistenceTransactionProvider; 105 private TestPersistenceTransaction NULL_TRANSACTION; 106 107 112 public ObjectManagerTest(String arg0) { 113 super(arg0); 114 } 115 116 protected void setUp() throws Exception { 117 super.setUp(); 118 this.logger = TCLogging.getLogger(getClass()); 119 this.managed = new HashMap (); 120 config = new TestObjectManagerConfig(); 121 clientStateManager = new ClientStateManagerImpl(TCLogging.getLogger(ClientStateManager.class)); 122 ManagedObjectStateFactory.disableSingleton(true); 123 ManagedObjectStateFactory.createInstance(new NullManagedObjectChangeListenerProvider(), new InMemoryPersistor()); 124 this.newObjectCounter = new SampledCounterImpl(new SampledCounterConfig(1, 1, true, 0L)); 125 this.objectfaultCounter = new SampledCounterImpl(new SampledCounterConfig(1, 1, true, 0L)); 126 stats = new ObjectManagerStatsImpl(newObjectCounter, objectfaultCounter); 127 persistenceTransactionProvider = new TestPersistenceTransactionProvider(); 128 NULL_TRANSACTION = TestPersistenceTransaction.NULL_TRANSACTION; 129 } 130 131 private void initObjectManager() { 132 initObjectManager(createThreadGroup()); 133 } 134 135 private TCThreadGroup createThreadGroup() { 136 return new TCThreadGroup(new ThrowableHandler(TCLogging.getLogger(ObjectManagerImpl.class))); 137 } 138 139 private void initObjectManager(ThreadGroup threadGroup) { 140 initObjectManager(threadGroup, new NullCache()); 141 } 142 143 private void initObjectManager(ThreadGroup threadGroup, EvictionPolicy cache) { 144 this.objectStore = new InMemoryManagedObjectStore(this.managed); 145 initObjectManager(threadGroup, cache, this.objectStore); 146 } 147 148 private void initObjectManager(ThreadGroup threadGroup, EvictionPolicy cache, ManagedObjectStore store) { 149 TestSink faultSink = new TestSink(); 150 TestSink flushSink = new TestSink(); 151 try { 152 this.objectManager = new ObjectManagerImpl(config, threadGroup, clientStateManager, store, cache, 153 persistenceTransactionProvider, faultSink, flushSink, 154 new MockObjectManagementMonitor()); 155 } catch (NotCompliantMBeanException e) { 156 throw new RuntimeException (e); 157 } 158 new TestMOFaulter(this.objectManager, store, faultSink).start(); 159 new TestMOFlusher(this.objectManager, flushSink).start(); 160 } 161 162 public void testShutdownAndSetGarbageCollector() throws Exception { 163 initObjectManager(); 164 objectManager.stop(); 165 try { 166 objectManager.setGarbageCollector(null); 167 fail("Should have thrown a ShutdownError."); 168 } catch (ShutdownError e) { 169 } 171 } 172 173 public void testShutdownAndLookup() throws Exception { 174 initObjectManager(); 175 objectManager.stop(); 176 try { 177 objectManager.getObjectByID(null); 178 fail("Should have thrown a ShutdownError."); 179 } catch (ShutdownError e) { 180 } 182 } 183 184 public void testShutdownAndLookupRootID() throws Exception { 185 initObjectManager(); 186 objectManager.stop(); 187 try { 188 objectManager.lookupRootID(null); 189 fail("Should have thrown a ShutdownError."); 190 } catch (ShutdownError e) { 191 } 193 } 194 195 public void testShutdownAndCreateRoot() throws Exception { 196 initObjectManager(); 197 objectManager.stop(); 198 try { 199 objectManager.createRoot(null, null); 200 fail("Should have thrown a ShutdownError."); 201 } catch (ShutdownError e) { 202 } 204 } 205 206 public void testShutdownAndCreateObject() throws Exception { 207 initObjectManager(); 208 objectManager.stop(); 209 try { 210 objectManager.createObject(null); 211 fail("Should have thrown a ShutdownError."); 212 } catch (ShutdownError e) { 213 } 215 } 216 217 public void testShutdownAndGetRoots() throws Exception { 218 initObjectManager(); 219 objectManager.stop(); 220 try { 221 objectManager.getRoots(); 222 fail("Should have thrown a ShutdownError"); 223 } catch (ShutdownError e) { 224 } 226 227 } 228 229 public void testShutdownAndLookupObjectsForCreateIfNecessary() throws Exception { 230 initObjectManager(); 231 232 objectManager.stop(); 233 234 try { 235 objectManager.lookupObjectsForCreateIfNecessary(null, null); 236 fail("Should have thrown a ShutdownError."); 237 } catch (ShutdownError e) { 238 } 240 } 241 242 public void testShutdownAndLookupObjectsFor() throws Exception { 243 initObjectManager(); 244 245 objectManager.stop(); 246 247 try { 248 objectManager.lookupObjectsAndSubObjectsFor(null, null, -1); 249 fail("Should have thrown a ShutdownError."); 250 } catch (ShutdownError e) { 251 } 253 } 254 255 public void testNewObjectIDs() { 256 initObjectManager(); 259 260 Set ids = new HashSet (); 262 ObjectID id1; 263 ids.add((id1 = new ObjectID(1))); 264 ObjectID id2; 265 ids.add((id2 = new ObjectID(2))); 266 ChannelID key = new ChannelID(0); 267 268 TestResultsContext results = new TestResultsContext(ids, ids); 269 this.objectManager.lookupObjectsForCreateIfNecessary(key, results); 270 assertEquals(2, results.objects.size()); 271 272 ObjectInstanceMonitor imo = new ObjectInstanceMonitorImpl(); 273 274 ManagedObject mo = (ManagedObject) results.objects.get(id1); 275 TestArrayDNA ta; 276 mo.apply((ta = new TestArrayDNA(id1)), new TransactionID(1), new BackReferences(), imo); 277 mo = (ManagedObject) results.objects.get(id2); 278 mo.apply(new TestArrayDNA(id2), new TransactionID(2), new BackReferences(), imo); 279 280 Map ic = imo.getInstanceCounts(); 281 assertEquals(1, ic.size()); 282 assertEquals(new Integer (2), ic.get(ta.getTypeName())); 283 284 this.objectManager.releaseAll(NULL_TRANSACTION, results.objects.values()); 285 286 ids.add(new ObjectID(3)); 287 ids.add(new ObjectID(4)); 288 Set newIDs = new HashSet (); 289 newIDs.add(new ObjectID(3)); 290 newIDs.add(new ObjectID(4)); 291 292 results = new TestResultsContext(ids, newIDs); 293 294 this.objectManager.lookupObjectsForCreateIfNecessary(key, results); 295 assertEquals(4, results.objects.size()); 296 297 int count = 100; 298 for (Iterator i = ids.iterator(); i.hasNext();) { 299 ObjectID id = (ObjectID) i.next(); 300 mo = (ManagedObject) results.objects.get(id); 301 mo.apply(new TestArrayDNA(id), new TransactionID(count++), new BackReferences(), imo); 302 } 303 ic = imo.getInstanceCounts(); 304 assertEquals(1, ic.size()); 305 assertEquals(new Integer (4), ic.get(ta.getTypeName())); 306 307 this.objectManager.releaseAll(NULL_TRANSACTION, results.objects.values()); 308 } 309 310 public void testArrayFacade() throws Exception { 311 initObjectManager(); 312 313 ObjectID id = new ObjectID(1); 314 HashSet ids = new HashSet (); 315 ids.add(id); 316 317 TestResultsContext responseContext = new TestResultsContext(ids, ids); 318 final Map lookedUpObjects = responseContext.objects; 319 320 this.objectManager.lookupObjectsForCreateIfNecessary(null, responseContext); 321 assertEquals(ids.size(), lookedUpObjects.size()); 322 323 ObjectInstanceMonitor imo = new ObjectInstanceMonitorImpl(); 324 ManagedObject mo = (ManagedObject) lookedUpObjects.get(id); 325 mo.apply(new TestArrayDNA(id), new TransactionID(1), new BackReferences(), imo); 326 objectManager.releaseAll(NULL_TRANSACTION, lookedUpObjects.values()); 327 328 ManagedObjectFacade facade; 329 330 facade = objectManager.lookupFacade(id, -1); 331 assertTrue(facade.isArray()); 332 assertFalse(facade.isInnerClass()); 333 assertFalse(facade.isMap()); 334 assertFalse(facade.isList()); 335 assertFalse(facade.isSet()); 336 assertEquals(3, facade.getArrayLength()); 337 assertTrue(Arrays.equals(new String [] { "0", "1", "2" }, facade.getFields())); 338 assertEquals("[Ljava/lang/String;", facade.getClassName()); 339 340 for (int i = 0; i < 3; i++) { 341 assertEquals("String", facade.getFieldType("" + i)); 342 } 343 344 assertEquals("tim", facade.getFieldValue("0")); 345 assertEquals("is", facade.getFieldValue("1")); 346 assertEquals("here", facade.getFieldValue("2")); 347 348 facade = objectManager.lookupFacade(id, 1); 350 assertEquals(1, facade.getArrayLength()); 351 assertEquals("tim", facade.getFieldValue("0")); 352 353 facade = objectManager.lookupFacade(id, 19212); 354 assertEquals(3, facade.getArrayLength()); 355 assertEquals("tim", facade.getFieldValue("0")); 356 assertEquals("is", facade.getFieldValue("1")); 357 assertEquals("here", facade.getFieldValue("2")); 358 } 359 360 public void testDateFacades() throws NoSuchObjectException { 361 initObjectManager(); 362 363 ObjectID dateID = new ObjectID(1); 364 365 Set ids = new HashSet (); 366 ids.add(dateID); 367 368 TestResultsContext responseContext = new TestResultsContext(ids, ids); 369 final Map lookedUpObjects = responseContext.objects; 370 371 this.objectManager.lookupObjectsForCreateIfNecessary(null, responseContext); 372 assertEquals(ids.size(), lookedUpObjects.size()); 373 374 ManagedObject dateManagedObject = (ManagedObject) lookedUpObjects.get(dateID); 375 376 ObjectInstanceMonitor imo = new ObjectInstanceMonitorImpl(); 377 dateManagedObject.apply(new TestDateDNA("java.util.Date", dateID), new TransactionID(1), new BackReferences(), imo); 378 379 objectManager.releaseAll(NULL_TRANSACTION, lookedUpObjects.values()); 380 381 ManagedObjectFacade facade; 382 383 facade = objectManager.lookupFacade(dateID, 1); 384 validateDateFacade(facade); 385 386 } 387 388 public void testLiteralFacades() throws NoSuchObjectException { 389 initObjectManager(); 390 391 ObjectID literalID = new ObjectID(1); 392 393 Set ids = new HashSet (); 394 ids.add(literalID); 395 396 TestResultsContext responseContext = new TestResultsContext(ids, ids); 397 final Map lookedUpObjects = responseContext.objects; 398 399 this.objectManager.lookupObjectsForCreateIfNecessary(null, responseContext); 400 assertEquals(ids.size(), lookedUpObjects.size()); 401 402 ManagedObject managedObject = (ManagedObject) lookedUpObjects.get(literalID); 403 404 ObjectInstanceMonitor imo = new ObjectInstanceMonitorImpl(); 405 managedObject.apply(new TestLiteralValuesDNA(literalID), new TransactionID(1), new BackReferences(), imo); 406 407 objectManager.releaseAll(NULL_TRANSACTION, lookedUpObjects.values()); 408 409 ManagedObjectFacade facade; 410 411 facade = objectManager.lookupFacade(literalID, 1); 412 validateLiteralFacade(facade); 413 414 } 415 416 private void validateLiteralFacade(ManagedObjectFacade literalFacade) { 417 assertFalse(literalFacade.isArray()); 418 assertFalse(literalFacade.isMap()); 419 assertFalse(literalFacade.isSet()); 420 assertFalse(literalFacade.isList()); 421 assertEquals("java.lang.Integer", literalFacade.getClassName()); 422 423 Object value = literalFacade.getFieldValue("java.lang.Integer"); 424 425 assertTrue(value instanceof Integer ); 426 } 427 428 public void testLogicalFacades() throws NoSuchObjectException { 429 initObjectManager(); 430 431 ObjectID mapID = new ObjectID(1); 432 ObjectID listID = new ObjectID(2); 433 ObjectID setID = new ObjectID(3); 434 435 Set ids = new HashSet (); 436 ids.add(mapID); 437 ids.add(listID); 438 ids.add(setID); 439 440 TestResultsContext responseContext = new TestResultsContext(ids, ids); 441 final Map lookedUpObjects = responseContext.objects; 442 443 this.objectManager.lookupObjectsForCreateIfNecessary(null, responseContext); 444 assertEquals(ids.size(), lookedUpObjects.size()); 445 446 ManagedObject list = (ManagedObject) lookedUpObjects.get(listID); 447 ManagedObject set = (ManagedObject) lookedUpObjects.get(setID); 448 ManagedObject map = (ManagedObject) lookedUpObjects.get(mapID); 449 450 ObjectInstanceMonitor imo = new ObjectInstanceMonitorImpl(); 451 map.apply(new TestMapDNA(mapID), new TransactionID(1), new BackReferences(), imo); 452 set.apply(new TestListSetDNA("java.util.HashSet", setID), new TransactionID(1), new BackReferences(), imo); 453 list.apply(new TestListSetDNA("java.util.LinkedList", listID), new TransactionID(1), new BackReferences(), imo); 454 455 objectManager.releaseAll(NULL_TRANSACTION, lookedUpObjects.values()); 456 457 ManagedObjectFacade facade; 458 459 facade = objectManager.lookupFacade(mapID, -1); 460 validateMapFacade(facade, 3, 3); 461 facade = objectManager.lookupFacade(mapID, 5); 462 validateMapFacade(facade, 3, 3); 463 facade = objectManager.lookupFacade(mapID, 1); 464 validateMapFacade(facade, 1, 3); 465 facade = objectManager.lookupFacade(mapID, 0); 466 validateMapFacade(facade, 0, 3); 467 468 facade = objectManager.lookupFacade(setID, -1); 469 validateSetFacade(facade, 3, 3); 470 facade = objectManager.lookupFacade(setID, 5); 471 validateSetFacade(facade, 3, 3); 472 facade = objectManager.lookupFacade(setID, 1); 473 validateSetFacade(facade, 1, 3); 474 facade = objectManager.lookupFacade(setID, 0); 475 validateSetFacade(facade, 0, 3); 476 477 facade = objectManager.lookupFacade(listID, -1); 478 validateListFacade(facade, 3, 3); 479 facade = objectManager.lookupFacade(listID, 5); 480 validateListFacade(facade, 3, 3); 481 facade = objectManager.lookupFacade(listID, 1); 482 validateListFacade(facade, 1, 3); 483 facade = objectManager.lookupFacade(listID, 0); 484 validateListFacade(facade, 0, 3); 485 486 } 487 488 private void validateListFacade(ManagedObjectFacade listFacade, int facadeSize, int totalSize) { 489 assertFalse(listFacade.isArray()); 490 assertFalse(listFacade.isMap()); 491 assertFalse(listFacade.isSet()); 492 assertTrue(listFacade.isList()); 493 assertEquals("java.util.LinkedList", listFacade.getClassName()); 494 assertEquals(facadeSize, listFacade.getFacadeSize()); 495 assertEquals(totalSize, listFacade.getTrueObjectSize()); 496 497 for (int i = 0; i < facadeSize; i++) { 498 String fName = String.valueOf(i); 499 Object value = listFacade.getFieldValue(fName); 500 assertTrue(value instanceof String ); 501 assertEquals("item" + (i + 1), value); 502 } 503 } 504 505 private void validateSetFacade(ManagedObjectFacade setFacade, int facadeSize, int totalSize) { 506 assertFalse(setFacade.isArray()); 507 assertFalse(setFacade.isMap()); 508 assertTrue(setFacade.isSet()); 509 assertFalse(setFacade.isList()); 510 assertEquals("java.util.HashSet", setFacade.getClassName()); 511 assertEquals(facadeSize, setFacade.getFacadeSize()); 512 assertEquals(totalSize, setFacade.getTrueObjectSize()); 513 514 Set expect = new HashSet (); 515 expect.add("item1"); 516 expect.add("item2"); 517 expect.add("item3"); 518 519 Set actual = new HashSet (); 520 for (int i = 0; i < facadeSize; i++) { 521 String fName = String.valueOf(i); 522 Object value = setFacade.getFieldValue(fName); 523 assertTrue(value instanceof String ); 524 actual.add(value); 525 } 526 527 assertTrue(expect.containsAll(actual)); 528 } 529 530 private void validateMapFacade(ManagedObjectFacade mapFacade, int facadeSize, int totalSize) { 531 assertFalse(mapFacade.isArray()); 532 assertTrue(mapFacade.isMap()); 533 assertFalse(mapFacade.isSet()); 534 assertFalse(mapFacade.isList()); 535 assertEquals("java.util.HashMap", mapFacade.getClassName()); 536 assertEquals(facadeSize, mapFacade.getFacadeSize()); 537 assertEquals(totalSize, mapFacade.getTrueObjectSize()); 538 539 Map expect = new HashMap (); 540 expect.put("key1", "val1"); 541 expect.put("key2", "val2"); 542 expect.put("key3", "val3"); 543 544 Map actual = new HashMap (); 545 546 for (int i = 0; i < facadeSize; i++) { 547 String fName = String.valueOf(i); 548 Object value = mapFacade.getFieldValue(fName); 549 assertTrue(value instanceof MapEntryFacade); 550 MapEntryFacade entry = (MapEntryFacade) value; 551 actual.put(entry.getKey(), entry.getValue()); 552 } 553 554 for (Iterator iter = actual.keySet().iterator(); iter.hasNext();) { 555 Object key = iter.next(); 556 assertEquals(expect.get(key), actual.get(key)); 557 } 558 } 559 560 private void validateDateFacade(ManagedObjectFacade dateFacade) { 561 assertFalse(dateFacade.isArray()); 562 assertFalse(dateFacade.isMap()); 563 assertFalse(dateFacade.isSet()); 564 assertFalse(dateFacade.isList()); 565 assertEquals("java.util.Date", dateFacade.getClassName()); 566 567 Object value = dateFacade.getFieldValue("date"); 568 569 assertTrue(value instanceof Date ); 570 } 571 572 private DBEnvironment newDBEnvironment(boolean paranoid) throws Exception { 573 File dbHome; 574 int count = 0; 575 do { 576 dbHome = new File (this.getTempDirectory(), getClass().getName() + "db" + (++count)); 577 } while (dbHome.exists()); 578 dbHome.mkdir(); 579 assertTrue(dbHome.exists()); 580 assertTrue(dbHome.isDirectory()); 581 System.out.println("DB Home: " + dbHome); 582 DBEnvironment env = new DBEnvironment(paranoid, dbHome); 583 return env; 584 } 585 586 private Persistor newPersistor(boolean paranoid, DBEnvironment dbEnv, 587 SerializationAdapterFactory serializationAdapterFactory) throws Exception { 588 Persistor persistor = new SleepycatPersistor(logger, dbEnv, serializationAdapterFactory); 589 return persistor; 590 } 591 592 private SerializationAdapterFactory newSleepycatSerializationAdapterFactory(DBEnvironment dbEnv) { 593 return new SleepycatSerializationAdapterFactory(); 594 } 595 596 private SerializationAdapterFactory newCustomSerializationAdapterFactory() { 597 return new CustomSerializationAdapterFactory(); 598 } 599 600 public void testLookupInPersistentContext() throws Exception { 601 boolean paranoid = false; 602 DBEnvironment dbEnv = newDBEnvironment(paranoid); 604 SerializationAdapterFactory saf = newSleepycatSerializationAdapterFactory(dbEnv); 605 Persistor persistor = newPersistor(paranoid, dbEnv, saf); 606 607 testLookupInPersistentContext(persistor, paranoid); 608 609 dbEnv = newDBEnvironment(paranoid); 611 saf = newCustomSerializationAdapterFactory(); 612 persistor = newPersistor(paranoid, dbEnv, saf); 613 testLookupInPersistentContext(persistor, paranoid); 614 615 paranoid = true; 617 dbEnv = newDBEnvironment(paranoid); 618 saf = newSleepycatSerializationAdapterFactory(dbEnv); 619 persistor = newPersistor(paranoid, dbEnv, saf); 620 testLookupInPersistentContext(persistor, paranoid); 621 622 dbEnv = newDBEnvironment(paranoid); 624 saf = newCustomSerializationAdapterFactory(); 625 persistor = newPersistor(paranoid, dbEnv, saf); 626 testLookupInPersistentContext(persistor, paranoid); 627 } 628 629 private void testLookupInPersistentContext(Persistor persistor, boolean paranoid) throws Exception { 630 ManagedObjectPersistor mop = persistor.getManagedObjectPersistor(); 631 PersistenceTransactionProvider ptp = persistor.getPersistenceTransactionProvider(); 632 PersistentManagedObjectStore store = new PersistentManagedObjectStore(mop); 633 TestSink faultSink = new TestSink(); 634 TestSink flushSink = new TestSink(); 635 config.paranoid = paranoid; 636 objectManager = new ObjectManagerImpl(config, createThreadGroup(), clientStateManager, store, 637 new LRUEvictionPolicy(100), persistenceTransactionProvider, faultSink, 638 flushSink, new MockObjectManagementMonitor()); 639 new TestMOFaulter(this.objectManager, store, faultSink).start(); 640 new TestMOFlusher(this.objectManager, flushSink).start(); 641 642 ObjectID id = new ObjectID(1); 643 Set ids = new HashSet (); 644 ids.add(id); 645 ChannelID key = new ChannelID(0); 646 647 TestResultsContext responseContext = new TestResultsContext(ids, ids); 648 Map lookedUpObjects = responseContext.objects; 649 650 objectManager.lookupObjectsForCreateIfNecessary(key, responseContext); 651 652 ManagedObject lookedUpViaLookupObjectsForCreateIfNecessary = (ManagedObject) lookedUpObjects.get(id); 653 654 final String fieldName = "myField"; 655 final List countSlot = new ArrayList (1); 656 countSlot.add(new Integer (1)); 657 final List fieldValueSlot = new ArrayList (1); 658 fieldValueSlot.add(new ObjectID(100)); 659 660 DNACursor cursor = new DNACursor() { 661 public LogicalAction getLogicalAction() { 662 return null; 663 } 664 665 public PhysicalAction getPhysicalAction() { 666 return new PhysicalAction(fieldName, fieldValueSlot.get(0), true); 667 } 668 669 public boolean next() { 670 int count = ((Integer ) countSlot.get(0)).intValue(); 671 count--; 672 countSlot.set(0, new Integer (count)); 673 return count >= 0; 674 } 675 676 public boolean next(DNAEncoding encoding) { 677 throw new ImplementMe(); 678 } 679 680 public Object getAction() { 681 throw new ImplementMe(); 682 } 683 684 public int getActionCount() { 685 return 1; 686 } 687 688 public void reset() throws UnsupportedOperationException { 689 countSlot.set(0, new Integer (1)); 690 } 691 }; 692 693 DNA dna = new TestDNA(cursor); 694 695 ObjectInstanceMonitor imo = new ObjectInstanceMonitorImpl(); 696 lookedUpViaLookupObjectsForCreateIfNecessary.apply(dna, new TransactionID(1), new BackReferences(), imo); 697 698 PersistenceTransaction tx = ptp.newTransaction(); 699 objectManager.release(tx, lookedUpViaLookupObjectsForCreateIfNecessary); 700 tx.commit(); 701 702 ManagedObject lookedUpViaLookup = objectManager.getObjectByID(id); 703 assertEquals(1, lookedUpViaLookupObjectsForCreateIfNecessary.getObjectReferences().size()); 704 assertEquals(lookedUpViaLookup.getObjectReferences(), lookedUpViaLookupObjectsForCreateIfNecessary 705 .getObjectReferences()); 706 707 tx = ptp.newTransaction(); 708 objectManager.release(tx, lookedUpViaLookup); 709 tx.commit(); 710 711 responseContext = new TestResultsContext(ids, Collections.EMPTY_SET); 713 lookedUpObjects = responseContext.objects; 714 715 objectManager.lookupObjectsForCreateIfNecessary(key, responseContext); 716 lookedUpViaLookupObjectsForCreateIfNecessary = (ManagedObject) lookedUpObjects.get(id); 717 countSlot.set(0, new Integer (1)); 718 ObjectID newReferenceID = new ObjectID(9324); 719 fieldValueSlot.set(0, newReferenceID); 720 dna = new TestDNA(cursor); 721 lookedUpViaLookupObjectsForCreateIfNecessary.apply(dna, new TransactionID(2), new BackReferences(), imo); 722 tx = ptp.newTransaction(); 724 objectManager.release(tx, lookedUpViaLookupObjectsForCreateIfNecessary); 725 tx.commit(); 726 727 lookedUpViaLookup = objectManager.getObjectByID(id); 728 assertEquals(1, lookedUpViaLookupObjectsForCreateIfNecessary.getObjectReferences().size()); 729 assertTrue(lookedUpViaLookupObjectsForCreateIfNecessary.getObjectReferences().contains(newReferenceID)); 730 731 assertEquals(lookedUpViaLookup.getObjectReferences(), lookedUpViaLookupObjectsForCreateIfNecessary 732 .getObjectReferences()); 733 734 persistor.getManagedObjectPersistor().getAllObjectIDs().size(); 738 store.shutdown(); 739 persistor.close(); 740 } 741 742 public void testExplodingGarbageCollector() throws Exception { 743 LinkedQueue exceptionQueue = new LinkedQueue(); 744 TestThreadGroup tg = new TestThreadGroup(exceptionQueue); 745 initObjectManager(tg); 746 RuntimeException toThrow = new RuntimeException (); 747 this.objectManager.setGarbageCollector(new ExplodingGarbageCollector(toThrow)); 748 this.objectManager.start(); 749 Object o = exceptionQueue.poll(30 * 1000); 750 assertEquals(toThrow, o); 751 } 752 753 public void testObjectManagerBasics() { 754 initObjectManager(); 755 final ObjectID id = new ObjectID(0); 756 ManagedObject mo = new TestManagedObject(id, new ObjectID[0]); 757 objectManager.createObject(mo); 758 assertFalse(objectManager.isReferenced(id)); 759 ManagedObject mo2 = objectManager.getObjectByID(id); 760 assertTrue(mo == mo2); 761 assertTrue(objectManager.isReferenced(id)); 762 objectManager.release(NULL_TRANSACTION, mo); 763 assertFalse(objectManager.isReferenced(id)); 764 765 objectManager.getObjectByID(id); 766 767 final boolean[] gotIt = new boolean[1]; 768 gotIt[0] = false; 769 770 Thread t = new Thread () { 771 public void run() { 772 objectManager.getObjectByID(id); 773 gotIt[0] = true; 774 } 775 }; 776 777 t.start(); 778 ThreadUtil.reallySleep(1000); 779 assertFalse(gotIt[0]); 780 objectManager.release(NULL_TRANSACTION, mo); 781 ThreadUtil.reallySleep(1000); 782 assertTrue(gotIt[0]); 783 } 784 785 public void testPhysicalObjectFacade() throws Exception { 786 testPhysicalObjectFacade(false); 787 testPhysicalObjectFacade(true); 788 } 789 790 private void testPhysicalObjectFacade(boolean paranoid) throws Exception { 791 DBEnvironment dbEnv = newDBEnvironment(paranoid); 792 SerializationAdapterFactory saf = newCustomSerializationAdapterFactory(); 793 Persistor persistor = newPersistor(paranoid, dbEnv, saf); 794 PersistenceTransactionProvider ptp = persistor.getPersistenceTransactionProvider(); 795 this.objectStore = new PersistentManagedObjectStore(persistor.getManagedObjectPersistor()); 796 this.config.paranoid = paranoid; 797 initObjectManager(new TCThreadGroup(new ThrowableHandler(TCLogging.getTestingLogger(getClass()))), new NullCache(), 798 this.objectStore); 799 800 HashSet oids = new HashSet (); 801 oids.add(new ObjectID(1)); 802 803 final TestResultsContext context = new TestResultsContext(oids, oids); 804 this.objectManager.lookupObjectsForCreateIfNecessary(null, context); 805 context.waitTillComplete(); 806 ManagedObject mo = (ManagedObject) (context.objects).get(new ObjectID(1)); 807 assertTrue(mo.isNew()); 808 ObjectInstanceMonitor imo = new ObjectInstanceMonitorImpl(); 809 mo.apply(new TestPhysicalDNA(new ObjectID(1)), new TransactionID(1), new BackReferences(), imo); 810 811 PersistenceTransaction tx = ptp.newTransaction(); 812 this.objectManager.release(tx, mo); 813 tx.commit(); 814 815 ManagedObjectFacade facade; 816 try { 817 facade = this.objectManager.lookupFacade(new ObjectID(1), -1); 818 } catch (NoSuchObjectException e1) { 819 fail(e1.getMessage()); 820 return; 821 } 822 823 String [] fieldNames = facade.getFields(); 824 assertEquals(6, fieldNames.length); 825 assertTrue(Arrays.asList(fieldNames).toString(), Arrays.equals(fieldNames, new String [] { "access$0", "this$0", 827 "intField", "objField", "stringField", "zzzField" })); 828 assertEquals("TestPhysicalDNA.class.name", facade.getClassName()); 829 assertEquals("Integer", facade.getFieldType("intField")); 830 assertEquals("ObjectID", facade.getFieldType("objField")); 831 assertEquals("Byte", facade.getFieldType("zzzField")); 832 assertEquals("String", facade.getFieldType("stringField")); 833 assertEquals(new Integer (42), facade.getFieldValue("intField")); 834 assertEquals(new Byte ((byte) 1), facade.getFieldValue("zzzField")); 835 assertEquals(new ObjectID(696969), facade.getFieldValue("objField")); 836 assertEquals("yo yo yo", facade.getFieldValue("stringField")); 837 assertEquals(new ObjectID(1), facade.getObjectId()); 838 assertTrue(facade.isPrimitive("intField")); 839 assertTrue(facade.isPrimitive("zzzField")); 840 assertTrue(facade.isPrimitive("stringField")); 841 assertFalse(facade.isPrimitive("objField")); 842 843 try { 844 facade.getFieldType("does not exist"); 845 fail(); 846 } catch (IllegalArgumentException iae) { 847 } 849 850 try { 851 facade.getFieldValue("does not exist"); 852 fail(); 853 } catch (IllegalArgumentException iae) { 854 } 856 857 try { 858 facade.isPrimitive("does not exist"); 859 fail(); 860 } catch (IllegalArgumentException iae) { 861 } 863 864 this.objectStore.shutdown(); 865 866 } 869 870 public void testObjectManagerAsync() { 871 initObjectManager(); 872 final ObjectID id = new ObjectID(0); 873 final ObjectID id1 = new ObjectID(1); 874 875 Set objectIDs = new HashSet (); 876 877 ManagedObject mo = new TestManagedObject(id, new ObjectID[0]); 878 ManagedObject mo1 = new TestManagedObject(id1, new ObjectID[0]); 879 objectManager.createObject(mo); 880 objectManager.createObject(mo1); 881 882 assertFalse(objectManager.isReferenced(id)); 883 884 objectIDs.add(id); 885 886 TestObjectManagerResultsContext context; 887 assertTrue(objectManager 888 .lookupObjectsAndSubObjectsFor(null, context = new TestObjectManagerResultsContext(new HashMap (), objectIDs), 889 -1)); 890 891 ManagedObject retrievedMo = (ManagedObject) context.getResults().values().iterator().next(); 892 assertTrue(mo == retrievedMo); 893 assertTrue(objectManager.isReferenced(id)); 894 objectManager.release(NULL_TRANSACTION, mo); 895 assertFalse(objectManager.isReferenced(id)); 896 897 objectManager.getObjectByID(id); 898 899 objectIDs.add(id1); 900 901 boolean notPending = objectManager 902 .lookupObjectsAndSubObjectsFor(null, context = new TestObjectManagerResultsContext(new HashMap (), objectIDs), 903 -1); 904 assertFalse(notPending); 905 assertEquals(0, context.getResults().size()); 906 objectManager.release(NULL_TRANSACTION, mo); 907 assertEquals(objectIDs.size(), context.getResults().size()); 908 909 Collection objs = context.getResults().values(); 910 assertTrue(objs.contains(mo)); 911 assertTrue(objs.contains(mo1)); 912 assertTrue(objs.size() == 2); 913 } 914 915 public void testNewObjectCounter() { 916 initObjectManager(); 917 objectManager.setStatsListener(stats); 918 createObjects(666); 919 assertEquals(666, stats.getTotalObjectsCreated()); 920 assertEquals(666, newObjectCounter.getValue()); 921 922 objectManager.createRoot("root", new ObjectID(4444)); 924 assertEquals(667, stats.getTotalObjectsCreated()); 925 assertEquals(667, newObjectCounter.getValue()); 926 } 927 928 public void testCacheStats() throws Exception { 929 config.paranoid = true; 930 initObjectManager(new TCThreadGroup(new ThrowableHandler(TCLogging.getTestingLogger(getClass()))), 931 new LRUEvictionPolicy(-1)); 932 objectManager.setStatsListener(this.stats); 933 934 assertEquals(0, stats.getTotalRequests()); 935 assertEquals(0, stats.getTotalCacheHits()); 936 assertEquals(0, stats.getTotalCacheMisses()); 937 938 createObjects(50, 10); 939 Set ids = makeObjectIDSet(0, 10); 940 TestResultsContext results = new TestResultsContext(ids, Collections.EMPTY_SET); 942 943 objectManager.lookupObjectsAndSubObjectsFor(null, results, -1); 944 results.waitTillComplete(); 945 objectManager.releaseAll(NULL_TRANSACTION, results.objects.values()); 946 947 assertEquals(10, stats.getTotalRequests()); 948 assertEquals(0, stats.getTotalCacheHits()); 949 assertEquals(10, stats.getTotalCacheMisses()); 950 951 results = new TestResultsContext(ids, Collections.EMPTY_SET); 952 objectManager.lookupObjectsAndSubObjectsFor(null, results, -1); 953 results.waitTillComplete(); 954 objectManager.releaseAll(NULL_TRANSACTION, results.objects.values()); 955 assertEquals(20, stats.getTotalRequests()); 956 assertEquals(10, stats.getTotalCacheHits()); 957 assertEquals(10, stats.getTotalCacheMisses()); 958 959 ids = makeObjectIDSet(10, 20); 960 results = new TestResultsContext(ids, Collections.EMPTY_SET); 961 objectManager.lookupObjectsAndSubObjectsFor(null, results, -1); 962 results.waitTillComplete(); 963 objectManager.releaseAll(NULL_TRANSACTION, results.objects.values()); 964 assertEquals(30, stats.getTotalRequests()); 965 assertEquals(10, stats.getTotalCacheHits()); 966 assertEquals(20, stats.getTotalCacheMisses()); 967 968 evictCache(10); 969 970 ids = makeObjectIDSet(14, 4); 971 results = new TestResultsContext(ids, Collections.EMPTY_SET); 972 objectManager.lookupObjectsAndSubObjectsFor(null, results, -1); 973 results.waitTillComplete(); 974 objectManager.releaseAll(NULL_TRANSACTION, results.objects.values()); 975 assertEquals(40, stats.getTotalRequests()); 976 assertEquals(15, stats.getTotalCacheHits()); 977 assertEquals(25, stats.getTotalCacheMisses()); 978 979 double hitRate = ((double) 15) / ((double) 40); 980 assertEquals(hitRate, stats.getCacheHitRatio(), 0D); 981 } 982 983 private void evictCache(int inCache) { 984 TestCacheStats tc = new TestCacheStats(); 985 tc.toKeep = inCache; 986 objectManager.evictCache(tc); 987 tc.validate(); 988 } 989 990 private void createObjects(int num, int inCache) { 991 createObjects(num); 992 evictCache(inCache); 993 } 994 995 private Set makeObjectIDSet(int begin, int end) { 996 Set rv = new HashSet (); 997 998 if (begin > end) { 999 for (int i = begin; i > end; i--) { 1000 rv.add(new ObjectID(i)); 1001 } 1002 } else { 1003 for (int i = begin; i < end; i++) { 1004 rv.add(new ObjectID(i)); 1005 } 1006 } 1007 return rv; 1008 } 1009 1010 private void createObjects(int num) { 1011 for (int i = 0; i < num; i++) { 1012 TestManagedObject mo = new TestManagedObject(new ObjectID(i), new ObjectID[] {}); 1013 objectManager.createObject(mo); 1014 } 1015 } 1016 1017 public void testGCStats() { 1018 initObjectManager(); 1019 1020 this.config.myGCThreadSleepTime = -1; 1023 1024 GarbageCollector gc = new MarkAndSweepGarbageCollector(objectManager, clientStateManager, true); 1025 objectManager.setGarbageCollector(gc); 1026 1027 Listener listener = new Listener(); 1028 this.objectManager.addListener(listener); 1029 1030 objectManager.createRoot("root-me", new ObjectID(0)); 1031 ManagedObject root = new TestManagedObject(new ObjectID(0), new ObjectID[] { new ObjectID(1) }); 1032 objectManager.createObject(root); 1033 1034 TestManagedObject mo1 = new TestManagedObject(new ObjectID(1), new ObjectID[] { new ObjectID(2) }); 1035 TestManagedObject mo2 = new TestManagedObject(new ObjectID(2), new ObjectID[] { new ObjectID(3) }); 1036 TestManagedObject mo3 = new TestManagedObject(new ObjectID(3), new ObjectID[] {}); 1037 objectManager.createObject(mo1); 1038 objectManager.createObject(mo2); 1039 objectManager.createObject(mo3); 1040 1041 ChannelID cid1 = new ChannelID(1); 1042 clientStateManager.addReference(cid1, root.getID()); 1043 clientStateManager.addReference(cid1, mo1.getID()); 1044 clientStateManager.addReference(cid1, mo2.getID()); 1045 clientStateManager.addReference(cid1, mo3.getID()); 1046 1047 assertEquals(0, objectManager.getGarbageCollectorStats().length); 1048 assertEquals(0, listener.gcEvents.size()); 1049 1050 long start = System.currentTimeMillis(); 1051 1052 objectManager.gc(); 1053 1054 assertEquals(1, objectManager.getGarbageCollectorStats().length); 1055 assertEquals(1, listener.gcEvents.size()); 1056 1057 GCStats stats1 = (GCStats) listener.gcEvents.get(0); 1058 final int firstIterationNumber = stats1.getIteration(); 1059 assertSame(stats1, objectManager.getGarbageCollectorStats()[0]); 1060 assertTrue("external: " + start + ", reported: " + stats1.getStartTime(), stats1.getStartTime() >= start); 1061 assertTrue(String.valueOf(stats1.getElapsedTime()), stats1.getElapsedTime() >= 0); 1062 assertEquals(4, stats1.getBeginObjectCount()); 1063 assertEquals(0, stats1.getCandidateGarbageCount()); 1064 assertEquals(0, stats1.getActualGarbageCount()); 1065 1066 listener.gcEvents.clear(); 1067 objectManager.gc(); 1068 assertEquals(2, objectManager.getGarbageCollectorStats().length); 1069 assertEquals(1, listener.gcEvents.size()); 1070 assertEquals(firstIterationNumber + 1, objectManager.getGarbageCollectorStats()[0].getIteration()); 1071 1072 listener.gcEvents.clear(); 1073 Set removed = new HashSet (); 1074 removed.add(mo3.getID()); 1075 clientStateManager.removeReferences(cid1, removed); 1076 mo2.setReferences(new ObjectID[] {}); 1077 objectManager.gc(); 1078 assertEquals(3, objectManager.getGarbageCollectorStats().length); 1079 assertEquals(1, listener.gcEvents.size()); 1080 GCStats stats3 = (GCStats) listener.gcEvents.get(0); 1081 assertEquals(4, stats3.getBeginObjectCount()); 1082 assertEquals(1, stats3.getActualGarbageCount()); 1083 assertEquals(1, stats3.getCandidateGarbageCount()); 1084 } 1085 1086 public void testLookupFacadeForMissingObject() { 1087 initObjectManager(); 1088 1089 try { 1090 this.objectManager.lookupFacade(new ObjectID(1), -1); 1091 fail("lookup didn't throw exception"); 1092 } catch (NoSuchObjectException e) { 1093 } 1095 } 1096 1097 public void testObjectManagerGC() throws Exception { 1098 initObjectManager(); 1099 this.config.myGCThreadSleepTime = -1; 1101 TestGarbageCollector gc = new TestGarbageCollector(objectManager); 1102 objectManager.setGarbageCollector(gc); 1103 final ObjectID id = new ObjectID(0); 1104 ManagedObject mo = new TestManagedObject(id, new ObjectID[3]); 1105 objectManager.createObject(mo); 1106 1107 assertFalse(gc.isCollected()); 1108 1109 gc.allow_blockUntilReadyToGC_ToProceed(); 1110 1111 objectManager.gc(); 1112 assertTrue(gc.isCollected()); 1113 1114 gc.reset(); 1115 1116 objectManager.getObjectByID(id); 1118 1119 assertFalse(gc.collectWasCalled()); 1121 assertFalse(gc.blockUntilReadyToGC_WasCalled()); 1122 1123 Thread gcCaller = new Thread (new GCCaller(), "GCCaller"); 1124 gcCaller.start(); 1125 1126 assertTrue(gc.waitForCollectToBeCalled(5000)); 1128 1129 assertTrue(gc.waitFor_blockUntilReadyToGC_ToBeCalled(5000)); 1131 1132 1135 assertFalse(gc.notifyReadyToGC_WasCalled()); 1136 objectManager.release(NULL_TRANSACTION, mo); 1137 1138 assertTrue(gc.waitFor_notifyReadyToGC_ToBeCalled(5000)); 1140 1141 gc.allow_blockUntilReadyToGC_ToProceed(); 1143 1144 assertTrue(gc.waitFor_notifyGCComplete_ToBeCalled(5000)); 1146 gcCaller.join(); 1147 } 1148 1149 private static class TestArrayDNA implements DNA { 1150 1151 private final ObjectID id; 1152 1153 public TestArrayDNA(ObjectID id) { 1154 this.id = id; 1155 } 1156 1157 public long getVersion() { 1158 return 0; 1159 } 1160 1161 public boolean hasLength() { 1162 return true; 1163 } 1164 1165 public int getArraySize() { 1166 return 3; 1167 } 1168 1169 public String getDefiningLoaderDescription() { 1170 return ""; 1171 } 1172 1173 public String getTypeName() { 1174 return "[Ljava/lang/String;"; 1175 } 1176 1177 public ObjectID getObjectID() throws DNAException { 1178 return id; 1179 } 1180 1181 public ObjectID getParentObjectID() throws DNAException { 1182 return ObjectID.NULL_ID; 1183 } 1184 1185 public DNACursor getCursor() { 1186 return new DNACursor() { 1187 int count = 0; 1188 1189 public boolean next() { 1190 count++; 1191 return count <= 2; 1192 } 1193 1194 public LogicalAction getLogicalAction() { 1195 throw new ImplementMe(); 1196 } 1197 1198 public Object getAction() { 1199 throw new ImplementMe(); 1200 } 1201 1202 public PhysicalAction getPhysicalAction() { 1203 switch (count) { 1204 case 1: 1205 return new PhysicalAction(new String [] { "tim", "was", "here" }); 1206 case 2: 1207 return new PhysicalAction(1, "is", false); 1208 default: 1209 throw new RuntimeException ("bad count: " + count); 1210 } 1211 } 1212 1213 public boolean next(DNAEncoding encoding) { 1214 throw new ImplementMe(); 1215 } 1216 1217 public int getActionCount() { 1218 return 2; 1219 } 1220 1221 public void reset() throws UnsupportedOperationException { 1222 throw new ImplementMe(); 1223 } 1224 }; 1225 } 1226 1227 public boolean isDelta() { 1228 return false; 1229 } 1230 } 1231 1232 private static class TestListSetDNA implements DNA { 1233 1234 final ObjectID setID; 1235 final String className; 1236 1237 public TestListSetDNA(String className, ObjectID setID) { 1238 this.className = className; 1239 this.setID = setID; 1240 } 1241 1242 public long getVersion() { 1243 return 0; 1244 } 1245 1246 public boolean hasLength() { 1247 return false; 1248 } 1249 1250 public int getArraySize() { 1251 return -1; 1252 } 1253 1254 public String getDefiningLoaderDescription() { 1255 return ""; 1256 } 1257 1258 public String getTypeName() { 1259 return this.className; 1260 } 1261 1262 public ObjectID getObjectID() throws DNAException { 1263 return this.setID; 1264 } 1265 1266 public ObjectID getParentObjectID() throws DNAException { 1267 return ObjectID.NULL_ID; 1268 } 1269 1270 public DNACursor getCursor() { 1271 return new DNACursor() { 1272 int count; 1273 1274 public boolean next() { 1275 count++; 1276 return count <= 3; 1277 } 1278 1279 public LogicalAction getLogicalAction() { 1280 switch (count) { 1281 case 1: 1282 case 2: 1283 case 3: 1284 Object item = new UTF8ByteDataHolder("item" + count); 1285 return new LogicalAction(SerializationUtil.ADD, new Object [] { item }); 1286 default: 1287 throw new RuntimeException ("bad count: " + count); 1288 } 1289 } 1290 1291 public PhysicalAction getPhysicalAction() { 1292 throw new ImplementMe(); 1293 } 1294 1295 public boolean next(DNAEncoding encoding) { 1296 throw new ImplementMe(); 1297 } 1298 1299 public Object getAction() { 1300 throw new ImplementMe(); 1301 } 1302 1303 public int getActionCount() { 1304 return 3; 1305 } 1306 1307 public void reset() throws UnsupportedOperationException { 1308 throw new ImplementMe(); 1309 } 1310 }; 1311 } 1312 1313 public boolean isDelta() { 1314 return false; 1315 } 1316 1317 } 1318 1319 private static class TestMapDNA implements DNA { 1320 1321 final ObjectID objectID; 1322 1323 TestMapDNA(ObjectID id) { 1324 this.objectID = id; 1325 } 1326 1327 public long getVersion() { 1328 return 0; 1329 } 1330 1331 public boolean hasLength() { 1332 return false; 1333 } 1334 1335 public int getArraySize() { 1336 return -1; 1337 } 1338 1339 public String getDefiningLoaderDescription() { 1340 return ""; 1341 } 1342 1343 public String getTypeName() { 1344 return "java.util.HashMap"; 1345 } 1346 1347 public ObjectID getObjectID() throws DNAException { 1348 return this.objectID; 1349 } 1350 1351 public ObjectID getParentObjectID() throws DNAException { 1352 return ObjectID.NULL_ID; 1353 } 1354 1355 public DNACursor getCursor() { 1356 return new DNACursor() { 1357 1358 int count = 0; 1359 1360 public boolean next() { 1361 count++; 1362 return count <= 3; 1363 } 1364 1365 public LogicalAction getLogicalAction() { 1366 switch (count) { 1367 case 1: 1368 case 2: 1369 case 3: 1370 Object key = new UTF8ByteDataHolder("key" + count); 1371 Object val = new UTF8ByteDataHolder("val" + count); 1372 return new LogicalAction(SerializationUtil.PUT, new Object [] { key, val }); 1373 default: 1374 throw new RuntimeException ("bad count: " + count); 1375 } 1376 } 1377 1378 public PhysicalAction getPhysicalAction() { 1379 throw new ImplementMe(); 1380 } 1381 1382 public boolean next(DNAEncoding encoding) { 1383 throw new ImplementMe(); 1384 } 1385 1386 public Object getAction() { 1387 throw new ImplementMe(); 1388 } 1389 1390 public int getActionCount() { 1391 return 3; 1392 } 1393 1394 public void reset() throws UnsupportedOperationException { 1395 throw new ImplementMe(); 1396 } 1397 }; 1398 } 1399 1400 public boolean isDelta() { 1401 return false; 1402 } 1403 1404 } 1405 1406 private static class TestDateDNA implements DNA { 1407 1408 final ObjectID setID; 1409 final String className; 1410 1411 public TestDateDNA(String className, ObjectID setID) { 1412 this.className = className; 1413 this.setID = setID; 1414 } 1415 1416 public long getVersion() { 1417 return 0; 1418 } 1419 1420 public boolean hasLength() { 1421 return false; 1422 } 1423 1424 public int getArraySize() { 1425 return -1; 1426 } 1427 1428 public String getDefiningLoaderDescription() { 1429 return ""; 1430 } 1431 1432 public String getTypeName() { 1433 return this.className; 1434 } 1435 1436 public ObjectID getObjectID() throws DNAException { 1437 return this.setID; 1438 } 1439 1440 public ObjectID getParentObjectID() throws DNAException { 1441 return ObjectID.NULL_ID; 1442 } 1443 1444 public DNACursor getCursor() { 1445 return new DNACursor() { 1446 int count; 1447 1448 public boolean next() { 1449 count++; 1450 return count <= 1; 1451 } 1452 1453 public LogicalAction getLogicalAction() { 1454 switch (count) { 1455 case 1: 1456 return new LogicalAction(SerializationUtil.SET_TIME, 1457 new Object [] { new Long (System.currentTimeMillis()) }); 1458 default: 1459 throw new RuntimeException ("bad count: " + count); 1460 } 1461 } 1462 1463 public PhysicalAction getPhysicalAction() { 1464 throw new ImplementMe(); 1465 } 1466 1467 public boolean next(DNAEncoding encoding) { 1468 throw new ImplementMe(); 1469 } 1470 1471 public Object getAction() { 1472 throw new ImplementMe(); 1473 } 1474 1475 public int getActionCount() { 1476 return 1; 1477 } 1478 1479 public void reset() throws UnsupportedOperationException { 1480 throw new ImplementMe(); 1481 } 1482 }; 1483 } 1484 1485 public boolean isDelta() { 1486 return false; 1487 } 1488 1489 } 1490 1491 private static class TestResultsContext implements ObjectManagerResultsContext { 1492 public Map objects = new HashMap (); 1493 boolean complete = false; 1494 private final Set ids; 1495 private final Set newIDS; 1496 1497 public TestResultsContext(Set ids, Set newIDS) { 1498 this.ids = ids; 1499 this.newIDS = newIDS; 1500 } 1501 1502 public synchronized void waitTillComplete() { 1503 while (!complete) { 1504 try { 1505 wait(); 1506 } catch (InterruptedException e) { 1507 throw new AssertionError (e); 1508 } 1509 } 1510 } 1511 1512 public synchronized void setResults(ObjectManagerLookupResults results) { 1513 complete = true; 1514 this.objects.putAll(results.getObjects()); 1515 notifyAll(); 1516 } 1517 1518 public Set getLookupIDs() { 1519 return ids; 1520 } 1521 1522 public Set getNewObjectIDs() { 1523 return newIDS; 1524 } 1525 1526 } 1527 1528 private static class TestPhysicalDNA implements DNA { 1529 private final ObjectID id; 1530 1531 TestPhysicalDNA(ObjectID id) { 1532 this.id = id; 1533 } 1534 1535 public long getVersion() { 1536 return 0; 1537 } 1538 1539 public boolean hasLength() { 1540 return false; 1541 } 1542 1543 public String getDefiningLoaderDescription() { 1544 return "System"; 1545 } 1546 1547 public int getArraySize() { 1548 return -1; 1549 } 1550 1551 public String getTypeName() { 1552 return "TestPhysicalDNA.class.name"; 1553 } 1554 1555 public ObjectID getObjectID() throws DNAException { 1556 return this.id; 1557 } 1558 1559 public ObjectID getParentObjectID() throws DNAException { 1560 return new ObjectID(25); 1561 } 1562 1563 public void setHeaderInformation(ObjectID id, ObjectID parentID, String typeName, int length, long version) { 1564 } 1566 1567 public void addLogicalAction(int method, Object [] parameters) { 1568 } 1570 1571 public void addPhysicalAction(String field, Object value) throws DNAException { 1572 } 1574 1575 public DNACursor getCursor() { 1576 return new DNACursor() { 1577 1578 int count = 0; 1579 1580 public boolean next() { 1581 count++; 1582 return count < 7; 1583 } 1584 1585 public LogicalAction getLogicalAction() { 1586 return null; 1587 } 1588 1589 public Object getAction() { 1590 throw new ImplementMe(); 1591 } 1592 1593 public PhysicalAction getPhysicalAction() { 1594 switch (count) { 1595 case 1: { 1596 return new PhysicalAction("intField", new Integer (42), false); 1597 } 1598 case 2: { 1599 return new PhysicalAction("zzzField", new Byte ((byte) 1), false); 1600 } 1601 case 3: { 1602 return new PhysicalAction("objField", new ObjectID(696969), true); 1603 } 1604 case 4: { 1605 return new PhysicalAction("this$0", new ObjectID(25), true); 1606 } 1607 case 5: { 1608 return new PhysicalAction("access$0", new Float (2.4), false); 1609 } 1610 case 6: { 1611 return new PhysicalAction("stringField", new UTF8ByteDataHolder("yo yo yo"), false); 1612 } 1613 default: { 1614 throw new RuntimeException (); 1615 } 1616 } 1617 1618 } 1619 1620 public boolean next(DNAEncoding encoding) { 1621 throw new ImplementMe(); 1622 } 1623 1624 public int getActionCount() { 1625 return 6; 1626 } 1627 1628 public void reset() throws UnsupportedOperationException { 1629 count = 0; 1630 } 1631 1632 }; 1633 } 1634 1635 public boolean isDelta() { 1636 return false; 1637 } 1638 } 1639 1640 private static class TestLiteralValuesDNA implements DNA { 1641 private final ObjectID id; 1642 1643 TestLiteralValuesDNA(ObjectID id) { 1644 this.id = id; 1645 } 1646 1647 public long getVersion() { 1648 return 0; 1649 } 1650 1651 public boolean hasLength() { 1652 return false; 1653 } 1654 1655 public String getDefiningLoaderDescription() { 1656 return ""; 1657 } 1658 1659 public int getArraySize() { 1660 return -1; 1661 } 1662 1663 public String getTypeName() { 1664 return "java.lang.Integer"; 1665 } 1666 1667 public ObjectID getObjectID() throws DNAException { 1668 return this.id; 1669 } 1670 1671 public ObjectID getParentObjectID() throws DNAException { 1672 return new ObjectID(25); 1673 } 1674 1675 public void setHeaderInformation(ObjectID id, ObjectID parentID, String typeName, int length, long version) { 1676 } 1678 1679 public void addLogicalAction(int method, Object [] parameters) { 1680 } 1682 1683 public void addPhysicalAction(String field, Object value) throws DNAException { 1684 } 1686 1687 public DNACursor getCursor() { 1688 return new DNACursor() { 1689 1690 int count = 0; 1691 1692 public boolean next() { 1693 count++; 1694 return count < 2; 1695 } 1696 1697 public LogicalAction getLogicalAction() { 1698 return null; 1699 } 1700 1701 public Object getAction() { 1702 switch (count) { 1703 case 1: { 1704 return new LiteralAction(new Integer (42)); 1705 } 1706 default: { 1707 throw new RuntimeException (); 1708 } 1709 } 1710 } 1711 1712 public PhysicalAction getPhysicalAction() { 1713 throw new ImplementMe(); 1714 } 1715 1716 public boolean next(DNAEncoding encoding) { 1717 throw new ImplementMe(); 1718 } 1719 1720 public int getActionCount() { 1721 return 1; 1722 } 1723 1724 public void reset() throws UnsupportedOperationException { 1725 throw new ImplementMe(); 1726 } 1727 }; 1728 } 1729 1730 public boolean isDelta() { 1731 return false; 1732 } 1733 1734 } 1735 1736 private static class Listener implements ObjectManagerEventListener { 1737 final List gcEvents = new ArrayList (); 1738 1739 public void garbageCollectionComplete(GCStats stats) { 1740 gcEvents.add(stats); 1741 } 1742 } 1743 1744 private class ExplodingGarbageCollector implements GarbageCollector { 1745 1746 private final RuntimeException toThrow; 1747 private LifeCycleState gcState; 1748 1749 public ExplodingGarbageCollector(RuntimeException toThrow) { 1750 this.toThrow = toThrow; 1751 } 1752 1753 public boolean isPausingOrPaused() { 1754 return false; 1755 } 1756 1757 public boolean isPaused() { 1758 return false; 1759 } 1760 1761 public void notifyReadyToGC() { 1762 return; 1763 } 1764 1765 public void requestGCPause() { 1766 return; 1767 } 1768 1769 public void notifyGCComplete() { 1770 return; 1771 } 1772 1773 public void blockUntilReadyToGC() { 1774 return; 1775 } 1776 1777 public Set collect(Filter traverser, Collection roots, Set managedObjectIds) { 1778 throw toThrow; 1779 } 1780 1781 public PrettyPrinter prettyPrint(PrettyPrinter out) { 1782 return out.print(getClass().getName()); 1783 } 1784 1785 public Set collect(Filter traverser, Collection roots, Set managedObjectIds, LifeCycleState state) { 1786 return collect(traverser, roots, managedObjectIds); 1787 } 1788 1789 public void changed(ObjectID changedObject, ObjectID oldReference, ObjectID newReference) { 1790 1792 } 1793 1794 public void gc() { 1795 throw toThrow; 1796 } 1797 1798 public void addNewReferencesTo(Set rescueIds) { 1799 1801 } 1802 1803 public void start() { 1804 gcState.start(); 1805 } 1806 1807 public void stop() { 1808 } 1810 1811 public void setState(StoppableThread st) { 1812 this.gcState = st; 1813 } 1814 1815 public void addListener(ObjectManagerEventListener listener) { 1816 1818 } 1819 1820 public GCStats[] getGarbageCollectorStats() { 1821 return null; 1822 } 1823 1824 } 1825 1826 private class TestThreadGroup extends ThreadGroup { 1827 1828 private final LinkedQueue exceptionQueue; 1829 1830 public TestThreadGroup(LinkedQueue exceptionQueue) { 1831 super("test thread group"); 1832 this.exceptionQueue = exceptionQueue; 1833 } 1834 1835 public void uncaughtException(Thread t, Throwable e) { 1836 try { 1837 exceptionQueue.put(e); 1838 } catch (InterruptedException ie) { 1839 fail(ie); 1840 } 1841 } 1842 1843 } 1844 1845 private class GCCaller implements Runnable { 1846 1847 public void run() { 1848 objectManager.gc(); 1849 } 1850 } 1851 1852 1855 protected void tearDown() throws Exception { 1856 super.tearDown(); 1857 } 1858 1859 private static class TestObjectManagerConfig extends ObjectManagerConfig { 1860 1861 public long myGCThreadSleepTime = 100; 1862 public boolean paranoid; 1863 1864 public TestObjectManagerConfig() { 1865 super(10000, true, true, true, 1000); 1866 } 1867 1868 TestObjectManagerConfig(long gcThreadSleepTime, boolean doGC) { 1869 super(gcThreadSleepTime, doGC, true, true, 1000); 1870 throw new RuntimeException ("Don't use me."); 1871 } 1872 1873 public long gcThreadSleepTime() { 1874 return myGCThreadSleepTime; 1875 } 1876 1877 public boolean paranoid() { 1878 return paranoid; 1879 } 1880 } 1881 1882 private static class TestMOFaulter extends Thread { 1883 1884 private final ObjectManagerImpl objectManager; 1885 private final ManagedObjectStore store; 1886 private final TestSink faultSink; 1887 1888 public TestMOFaulter(ObjectManagerImpl objectManager, ManagedObjectStore store, TestSink faultSink) { 1889 this.store = store; 1890 this.faultSink = faultSink; 1891 this.objectManager = objectManager; 1892 setName("TestMOFaulter"); 1893 setDaemon(true); 1894 } 1895 1896 public void run() { 1897 while (true) { 1898 try { 1899 ManagedObjectFaultingContext ec = (ManagedObjectFaultingContext) faultSink.take(); 1900 objectManager.addFaultedObject(ec.getId(), store.getObjectByID(ec.getId()), ec.isRemoveOnRelease()); 1901 } catch (InterruptedException e) { 1902 throw new AssertionError (e); 1903 } 1904 } 1905 } 1906 } 1907 1908 private static class TestMOFlusher extends Thread { 1909 1910 private final ObjectManagerImpl objectManager; 1911 private final TestSink flushSink; 1912 1913 public TestMOFlusher(ObjectManagerImpl objectManager, TestSink flushSink) { 1914 this.objectManager = objectManager; 1915 this.flushSink = flushSink; 1916 setName("TestMOFlusher"); 1917 setDaemon(true); 1918 } 1919 1920 public void run() { 1921 while (true) { 1922 try { 1923 ManagedObjectFlushingContext ec = (ManagedObjectFlushingContext) flushSink.take(); 1924 objectManager.flushAndEvict(ec.getObjectToFlush()); 1925 } catch (InterruptedException e) { 1926 throw new AssertionError (e); 1927 } 1928 } 1929 } 1930 } 1931} 1932 | Popular Tags |