[hibernate-commits] Hibernate SVN: r11652 - in trunk/Hibernate3/code/core/src/main/java/org/hibernate: engine/loading and 1 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Thu Jun 7 14:26:42 EDT 2007
Author: steve.ebersole at jboss.com
Date: 2007-06-07 14:26:42 -0400 (Thu, 07 Jun 2007)
New Revision: 11652
Modified:
trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java
trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/CollectionLoadContext.java
trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/EntityLoadContext.java
trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/LoadContexts.java
trunk/Hibernate3/code/core/src/main/java/org/hibernate/impl/AbstractScrollableResults.java
trunk/Hibernate3/code/core/src/main/java/org/hibernate/impl/IteratorImpl.java
Log:
HHH-2631 : LoadContext cleanup
Modified: trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java
===================================================================
--- trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java 2007-06-07 18:22:50 UTC (rev 11651)
+++ trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java 2007-06-07 18:26:42 UTC (rev 11652)
@@ -203,6 +203,9 @@
batchFetchQueue.clear();
}
hasNonReadOnlyEntities = false;
+ if ( loadContexts != null ) {
+ loadContexts.cleanup();
+ }
}
public boolean hasNonReadOnlyEntities() {
Modified: trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/CollectionLoadContext.java
===================================================================
--- trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/CollectionLoadContext.java 2007-06-07 18:22:50 UTC (rev 11651)
+++ trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/CollectionLoadContext.java 2007-06-07 18:26:42 UTC (rev 11652)
@@ -2,7 +2,6 @@
import java.sql.ResultSet;
import java.io.Serializable;
-import java.util.Map;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@@ -126,7 +125,7 @@
collection.beforeInitialize( persister, -1 );
collection.beginRead();
localLoadingCollectionKeys.add( collectionKey );
- loadContexts.registerLoadingCollectionEntry( collectionKey, new LoadingCollectionEntry( resultSet, persister, key, collection ) );
+ loadContexts.registerLoadingCollectionXRef( collectionKey, new LoadingCollectionEntry( resultSet, persister, key, collection ) );
return collection;
}
else {
@@ -152,8 +151,7 @@
*/
public void endLoadingCollections(CollectionPersister persister) {
SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
- if ( loadContexts.getLoadingCollectionEntryMap() == null
- || loadContexts.getLoadingCollectionEntryMap().isEmpty()
+ if ( !loadContexts.hasLoadingCollectionEntries()
|| localLoadingCollectionKeys.isEmpty() ) {
return;
}
@@ -165,12 +163,14 @@
// in a temp collection. the temp collection is then used to "drive"
// the #endRead processing.
List matches = null;
- Iterator iter = loadContexts.getLoadingCollectionEntryMap().entrySet().iterator();
+ Iterator iter = localLoadingCollectionKeys.iterator();
while ( iter.hasNext() ) {
- final Map.Entry mapEntry = ( Map.Entry ) iter.next();
- final CollectionKey collectionKey = ( CollectionKey ) mapEntry.getKey();
- final LoadingCollectionEntry lce = ( LoadingCollectionEntry ) mapEntry.getValue();
- if ( localLoadingCollectionKeys.contains( collectionKey ) && lce.getResultSet() == resultSet && lce.getPersister() == persister) {
+ final CollectionKey collectionKey = (CollectionKey) iter.next();
+ final LoadingCollectionEntry lce = loadContexts.locateLoadingCollectionEntry( collectionKey );
+ if ( lce == null) {
+ log.warn( "In CollectionLoadContext#endLoadingCollections, localLoadingCollectionKeys contained [" + collectionKey + "], but no LoadingCollectionEntry was found in loadContexts" );
+ }
+ else if ( lce.getResultSet() == resultSet && lce.getPersister() == persister ) {
if ( matches == null ) {
matches = new ArrayList();
}
@@ -184,11 +184,23 @@
if ( log.isTraceEnabled() ) {
log.trace( "removing collection load entry [" + lce + "]" );
}
+
+ // todo : i'd much rather have this done from #endLoadingCollection(CollectionPersister,LoadingCollectionEntry)...
+ loadContexts.unregisterLoadingCollectionXRef( collectionKey );
iter.remove();
}
}
endLoadingCollections( persister, matches );
+ if ( localLoadingCollectionKeys.isEmpty() ) {
+ // todo : hack!!!
+ // NOTE : here we cleanup the load context when we have no more local
+ // LCE entries. This "works" for the time being because really
+ // only the collection load contexts are implemented. Long term,
+ // this cleanup should become part of the "close result set"
+ // processing from the (sandbox/jdbc) jdbc-container code.
+ loadContexts.cleanup( resultSet );
+ }
}
private void endLoadingCollections(CollectionPersister persister, List matchedCollectionEntries) {
@@ -309,9 +321,9 @@
void cleanup() {
if ( !localLoadingCollectionKeys.isEmpty() ) {
- log.warn( "On CollectionLoadContext#clear, loadingCollections contained [" + localLoadingCollectionKeys.size() + "] entries" );
+ log.warn( "On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [" + localLoadingCollectionKeys.size() + "] entries" );
}
- loadContexts.cleanupCollectionEntries( localLoadingCollectionKeys );
+ loadContexts.cleanupCollectionXRefs( localLoadingCollectionKeys );
localLoadingCollectionKeys.clear();
}
Modified: trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/EntityLoadContext.java
===================================================================
--- trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/EntityLoadContext.java 2007-06-07 18:22:50 UTC (rev 11651)
+++ trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/EntityLoadContext.java 2007-06-07 18:26:42 UTC (rev 11652)
@@ -30,4 +30,10 @@
}
hydratingEntities.clear();
}
+
+
+ public String toString() {
+ return super.toString() + "<rs=" + resultSet + ">";
+ }
+
}
Modified: trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/LoadContexts.java
===================================================================
--- trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/LoadContexts.java 2007-06-07 18:22:50 UTC (rev 11651)
+++ trunk/Hibernate3/code/core/src/main/java/org/hibernate/engine/loading/LoadContexts.java 2007-06-07 18:26:42 UTC (rev 11652)
@@ -63,7 +63,80 @@
return persistenceContext;
}
+ private SessionImplementor getSession() {
+ return getPersistenceContext().getSession();
+ }
+
+ private EntityMode getEntityMode() {
+ return getSession().getEntityMode();
+ }
+
+
+ // cleanup code ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * Release internal state associated with the given result set.
+ * <p/>
+ * This should be called when we are done with processing said result set,
+ * ideally as the result set is being closed.
+ *
+ * @param resultSet The result set for which it is ok to release
+ * associated resources.
+ */
+ public void cleanup(ResultSet resultSet) {
+ if ( collectionLoadContexts != null ) {
+ CollectionLoadContext collectionLoadContext = ( CollectionLoadContext ) collectionLoadContexts.remove( resultSet );
+ collectionLoadContext.cleanup();
+ }
+ if ( entityLoadContexts != null ) {
+ EntityLoadContext entityLoadContext = ( EntityLoadContext ) entityLoadContexts.remove( resultSet );
+ entityLoadContext.cleanup();
+ }
+ }
+
/**
+ * Release internal state associated with *all* result sets.
+ * <p/>
+ * This is intended as a "failsafe" process to make sure we get everything
+ * cleaned up and released.
+ */
+ public void cleanup() {
+ if ( collectionLoadContexts != null ) {
+ Iterator itr = collectionLoadContexts.values().iterator();
+ while ( itr.hasNext() ) {
+ CollectionLoadContext collectionLoadContext = ( CollectionLoadContext ) itr.next();
+ log.warn( "fail-safe cleanup (collections) : " + collectionLoadContext );
+ collectionLoadContext.cleanup();
+ }
+ collectionLoadContexts.clear();
+ }
+ if ( entityLoadContexts != null ) {
+ Iterator itr = entityLoadContexts.values().iterator();
+ while ( itr.hasNext() ) {
+ EntityLoadContext entityLoadContext = ( EntityLoadContext ) itr.next();
+ log.warn( "fail-safe cleanup (entities) : " + entityLoadContext );
+ entityLoadContext.cleanup();
+ }
+ entityLoadContexts.clear();
+ }
+ }
+
+
+ // Collection load contexts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * Do we currently have any internal entries corresponding to loading
+ * collections?
+ *
+ * @return True if we currently hold state pertaining to loading collections;
+ * false otherwise.
+ */
+ public boolean hasLoadingCollectionEntries() {
+ return ( xrefLoadingCollectionEntries != null && !xrefLoadingCollectionEntries.isEmpty() );
+ }
+
+
+ /**
* Get the {@link CollectionLoadContext} associated with the given
* {@link ResultSet}, creating one if needed.
*
@@ -113,7 +186,60 @@
}
}
+
+
+
+ // loading collection xrefs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
/**
+ * Register a loading collection xref.
+ * <p/>
+ * This xref map is used because sometimes a collection is in process of
+ * being loaded from one result set, but needs to be accessed from the
+ * context of another "nested" result set processing.
+ * <p/>
+ * Implementation note: package protected, as this is meant solely for use
+ * by {@link CollectionLoadContext} to be able to locate collections
+ * being loaded by other {@link CollectionLoadContext}s/{@link ResultSet}s.
+ *
+ * @param entryKey The xref collection key
+ * @param entry The corresponding loading collection entry
+ */
+ void registerLoadingCollectionXRef(CollectionKey entryKey, LoadingCollectionEntry entry) {
+ if ( xrefLoadingCollectionEntries == null ) {
+ xrefLoadingCollectionEntries = new HashMap();
+ }
+ xrefLoadingCollectionEntries.put( entryKey, entry );
+ }
+
+ /**
+ * The inverse of {@link #registerLoadingCollectionXRef}. Here, we are done
+ * processing the said collection entry, so we remove it from the
+ * load context.
+ * <p/>
+ * The idea here is that other loading collections can now reference said
+ * collection directly from the {@link PersistenceContext} because it
+ * has completed its load cycle.
+ * <p/>
+ * Implementation note: package protected, as this is meant solely for use
+ * by {@link CollectionLoadContext} to be able to locate collections
+ * being loaded by other {@link CollectionLoadContext}s/{@link ResultSet}s.
+ *
+ * @param key The key of the collection we are done processing.
+ */
+ void unregisterLoadingCollectionXRef(CollectionKey key) {
+ if ( !hasLoadingCollectionEntries() ) {
+ return;
+ }
+ xrefLoadingCollectionEntries.remove(key);
+ }
+
+ /*package*/Map getLoadingCollectionXRefs() {
+ return xrefLoadingCollectionEntries;
+ }
+
+
+ /**
* Locate the LoadingCollectionEntry within *any* of the tracked
* {@link CollectionLoadContext}s.
* <p/>
@@ -143,18 +269,7 @@
return rtn;
}
- /*package*/void registerLoadingCollectionEntry(CollectionKey entryKey, LoadingCollectionEntry entry) {
- if ( xrefLoadingCollectionEntries == null ) {
- xrefLoadingCollectionEntries = new HashMap();
- }
- xrefLoadingCollectionEntries.put( entryKey, entry );
- }
-
- /*package*/Map getLoadingCollectionEntryMap() {
- return xrefLoadingCollectionEntries;
- }
-
- /*package*/void cleanupCollectionEntries(Set entryKeys) {
+ /*package*/void cleanupCollectionXRefs(Set entryKeys) {
Iterator itr = entryKeys.iterator();
while ( itr.hasNext() ) {
final CollectionKey entryKey = ( CollectionKey ) itr.next();
@@ -162,6 +277,10 @@
}
}
+
+ // Entity load contexts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // * currently, not yet used...
+
public EntityLoadContext getEntityLoadContext(ResultSet resultSet) {
EntityLoadContext context = null;
if ( entityLoadContexts == null ) {
@@ -177,23 +296,4 @@
return context;
}
- public void cleanup(ResultSet resultSet) {
- if ( collectionLoadContexts != null ) {
- CollectionLoadContext collectionLoadContext = ( CollectionLoadContext ) collectionLoadContexts.remove( resultSet );
- collectionLoadContext.cleanup();
- }
- if ( entityLoadContexts != null ) {
- EntityLoadContext entityLoadContext = ( EntityLoadContext ) entityLoadContexts.remove( resultSet );
- entityLoadContext.cleanup();
- }
- }
-
- private SessionImplementor getSession() {
- return getPersistenceContext().getSession();
- }
-
- private EntityMode getEntityMode() {
- return getSession().getEntityMode();
- }
-
}
Modified: trunk/Hibernate3/code/core/src/main/java/org/hibernate/impl/AbstractScrollableResults.java
===================================================================
--- trunk/Hibernate3/code/core/src/main/java/org/hibernate/impl/AbstractScrollableResults.java 2007-06-07 18:22:50 UTC (rev 11651)
+++ trunk/Hibernate3/code/core/src/main/java/org/hibernate/impl/AbstractScrollableResults.java 2007-06-07 18:26:42 UTC (rev 11652)
@@ -13,6 +13,9 @@
import java.util.Locale;
import java.util.TimeZone;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
@@ -31,6 +34,8 @@
*/
public abstract class AbstractScrollableResults implements ScrollableResults {
+ private static final Log log = LogFactory.getLog( AbstractScrollableResults.class );
+
private final ResultSet resultSet;
private final PreparedStatement ps;
private final SessionImplementor session;
@@ -91,7 +96,7 @@
public final void close() throws HibernateException {
try {
// not absolutely necessary, but does help with aggressive release
- session.getBatcher().closeQueryStatement(ps, resultSet);
+ session.getBatcher().closeQueryStatement( ps, resultSet );
}
catch (SQLException sqle) {
throw JDBCExceptionHelper.convert(
@@ -100,6 +105,15 @@
"could not close results"
);
}
+ finally {
+ try {
+ session.getPersistenceContext().getLoadContexts().cleanup( resultSet );
+ }
+ catch( Throwable ignore ) {
+ // ignore this error for now
+ log.trace( "exception trying to cleanup load context : " + ignore.getMessage() );
+ }
+ }
}
public final Object[] get() throws HibernateException {
Modified: trunk/Hibernate3/code/core/src/main/java/org/hibernate/impl/IteratorImpl.java
===================================================================
--- trunk/Hibernate3/code/core/src/main/java/org/hibernate/impl/IteratorImpl.java 2007-06-07 18:22:50 UTC (rev 11651)
+++ trunk/Hibernate3/code/core/src/main/java/org/hibernate/impl/IteratorImpl.java 2007-06-07 18:26:42 UTC (rev 11652)
@@ -76,6 +76,15 @@
"Unable to close iterator"
);
}
+ finally {
+ try {
+ session.getPersistenceContext().getLoadContexts().cleanup( rs );
+ }
+ catch( Throwable ignore ) {
+ // ignore this error for now
+ log.trace( "exception trying to cleanup load context : " + ignore.getMessage() );
+ }
+ }
}
}
More information about the hibernate-commits
mailing list