cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject svn commit: r478018 - in /incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src: main/java/org/apache/cayenne/access/ObjectDiff.java main/java/org/apache/cayenne/access/ObjectStore.java test/java/org/apache/cayenne/access/ObjectStoreGCTst.java
Date Wed, 22 Nov 2006 03:22:17 GMT
Author: aadamchik
Date: Tue Nov 21 19:22:16 2006
New Revision: 478018

URL: http://svn.apache.org/viewvc?view=rev&rev=478018
Log:
CAY-709: Leak-free ObjectContext
(first cut - ObjectStore uses weak references to hollow and committed objects)

Added:
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/access/ObjectStoreGCTst.java
Modified:
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectDiff.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectStore.java

Modified: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectDiff.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectDiff.java?view=diff&rev=478018&r1=478017&r2=478018
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectDiff.java
(original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectDiff.java
Tue Nov 21 19:22:16 2006
@@ -62,10 +62,16 @@
     private Map currentArcSnapshot;
     private Map flatIds;
 
+    Persistent object;
+
     ObjectDiff(ObjectStore objectStore, final Persistent object) {
 
         super(object.getObjectId());
 
+        // retain the object, as ObjectStore may have weak references to registered
+        // objects and we can't allow it to deallocate dirty objects.
+        this.object = object;
+
         EntityResolver entityResolver = objectStore.getContext().getEntityResolver();
 
         this.entityName = object.getObjectId().getEntityName();
@@ -326,7 +332,7 @@
         getClassDescriptor().visitProperties(new PropertyVisitor() {
 
             public boolean visitAttributeProperty(AttributeProperty property) {
- 
+
                 Object newValue = property.readProperty(object);
 
                 // no baseline to compare

Modified: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectStore.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectStore.java?view=diff&rev=478018&r1=478017&r2=478018
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectStore.java
(original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/access/ObjectStore.java
Tue Nov 21 19:22:16 2006
@@ -56,6 +56,8 @@
 import org.apache.cayenne.query.PrefetchTreeNode;
 import org.apache.cayenne.query.QueryMetadata;
 import org.apache.cayenne.query.RefreshQuery;
+import org.apache.commons.collections.map.AbstractReferenceMap;
+import org.apache.commons.collections.map.ReferenceMap;
 
 /**
  * ObjectStore stores objects using their ObjectId as a key. It works as a dedicated
@@ -72,10 +74,20 @@
 // must be followed in any new related developments.
 public class ObjectStore implements Serializable, SnapshotEventListener, GraphManager {
 
+    /**
+     * Factory method to create default Map for storing registered objects.
+     * 
+     * @since 3.0
+     * @return a map with hard referenced keys and weak referenced values.
+     */
+    static Map createObjectMap() {
+        return new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.WEAK);
+    }
+
     protected transient Map newObjectsMap;
 
-    protected Map objectMap = new HashMap();
-    protected Map changes = new HashMap();
+    protected Map objectMap;
+    protected Map changes;
 
     // a sequential id used to tag GraphDiffs so that they can later be sorted in the
     // original creation order
@@ -100,10 +112,24 @@
     protected DataContext context;
 
     public ObjectStore() {
+        this(null);
     }
 
     public ObjectStore(DataRowStore dataRowCache) {
+        this(dataRowCache, null);
+    }
+
+    /**
+     * Creates an ObjectStore with {@link DataRowStore} and a map to use for storing
+     * registered objects. Passed map doesn't require any special synchronization
+     * behavior, as ObjectStore is synchronized itself.
+     * 
+     * @since 3.0
+     */
+    public ObjectStore(DataRowStore dataRowCache, Map objectMap) {
         setDataRowCache(dataRowCache);
+        this.objectMap = objectMap != null ? objectMap : ObjectStore.createObjectMap();
+        this.changes = new HashMap();
     }
 
     /**

Added: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/access/ObjectStoreGCTst.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/access/ObjectStoreGCTst.java?view=auto&rev=478018
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/access/ObjectStoreGCTst.java
(added)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/access/ObjectStoreGCTst.java
Tue Nov 21 19:22:16 2006
@@ -0,0 +1,115 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access;
+
+import org.apache.art.Artist;
+import org.apache.cayenne.DataObjectUtils;
+import org.apache.cayenne.query.SQLTemplate;
+import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.unit.CayenneTestCase;
+import org.apache.cayenne.unit.util.ThreadedTestHelper;
+
+public class ObjectStoreGCTst extends CayenneTestCase {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        deleteTestData();
+    }
+
+    public void testReleaseUnreferenced() throws Exception {
+        final DataContext context = createDataContext();
+        context.performGenericQuery(new SQLTemplate(
+                Artist.class,
+                "insert into ARTIST (ARTIST_ID, ARTIST_NAME) values (1, 'aa')"));
+
+        assertEquals(0, context.getObjectStore().registeredObjectsCount());
+        context.performQuery(new SelectQuery(Artist.class));
+        assertEquals(1, context.getObjectStore().registeredObjectsCount());
+
+        // allow for slow GC
+        new ThreadedTestHelper() {
+
+            protected void assertResult() throws Exception {
+                System.gc();
+                assertEquals(0, context.getObjectStore().registeredObjectsCount());
+            }
+        }.assertWithTimeout(2000);
+    }
+
+    public void testRetainUnreferencedNew() throws Exception {
+        final DataContext context = createDataContext();
+
+        assertEquals(0, context.getObjectStore().registeredObjectsCount());
+        Artist a = (Artist) context.newObject(Artist.class);
+        a.setArtistName("X");
+        a = null;
+        assertEquals(1, context.getObjectStore().registeredObjectsCount());
+
+        // allow for slow GC
+        new ThreadedTestHelper() {
+
+            protected void assertResult() throws Exception {
+                System.gc();
+                assertEquals(1, context.getObjectStore().registeredObjectsCount());
+            }
+        }.assertWithTimeout(2000);
+
+        assertEquals(1, context.getObjectStore().registeredObjectsCount());
+        context.commitChanges();
+        new ThreadedTestHelper() {
+
+            protected void assertResult() throws Exception {
+                System.gc();
+                assertEquals(0, context.getObjectStore().registeredObjectsCount());
+            }
+        }.assertWithTimeout(2000);
+
+    }
+
+    public void testRetainUnreferencedModified() throws Exception {
+        final DataContext context = createDataContext();
+        context.performGenericQuery(new SQLTemplate(
+                Artist.class,
+                "insert into ARTIST (ARTIST_ID, ARTIST_NAME) values (1, 'aa')"));
+
+        assertEquals(0, context.getObjectStore().registeredObjectsCount());
+        Artist a = (Artist) DataObjectUtils.objectForPK(context, Artist.class, 1);
+        a.setArtistName("Y");
+        a = null;
+        assertEquals(1, context.getObjectStore().registeredObjectsCount());
+
+        new ThreadedTestHelper() {
+
+            protected void assertResult() throws Exception {
+                System.gc();
+                assertEquals(1, context.getObjectStore().registeredObjectsCount());
+            }
+        }.assertWithTimeout(2000);
+
+        context.commitChanges();
+        new ThreadedTestHelper() {
+
+            protected void assertResult() throws Exception {
+                System.gc();
+                assertEquals(0, context.getObjectStore().registeredObjectsCount());
+            }
+        }.assertWithTimeout(2000);
+
+    }
+}



Mime
View raw message