User: starksm
Date: 02/04/14 12:43:07
Modified: src/main/org/jboss/ejb/plugins/jaws/jdbc
JDBCCommandFactory.java
Log:
Make the PreloadRefQueueHandlerTask inner class a static as its reference
to the container was preventing the container from being GCd.
Revision Changes Path
1.19 +143 -93
jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommandFactory.java
Index: JDBCCommandFactory.java
===================================================================
RCS file:
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommandFactory.java,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- JDBCCommandFactory.java 8 Mar 2002 20:37:06 -0000 1.18
+++ JDBCCommandFactory.java 14 Apr 2002 19:43:07 -0000 1.19
@@ -46,13 +46,13 @@
/**
* Command factory for the JAWS JDBC layer. This class is primarily responsible
- * for creating instances of the JDBC implementations for the various JPM
+ * for creating instances of the JDBC implementations for the various JPM
* commands so that the JAWSPersistenceManager (actually an persistence store)
* can delegate to them in a decoupled manner.
- * <p>This class also acts as the manager for the read-ahead buffer added in
+ * <p>This class also acts as the manager for the read-ahead buffer added in
* version 2.3/2.4. In order to manage this buffer, it must register itself
- * with any transaction that is active when a finder is called so that the
- * data that was read ahead can be discarded before completion of the
+ * with any transaction that is active when a finder is called so that the
+ * data that was read ahead can be discarded before completion of the
* transaction. The read ahead buffer is managed using Soft references, with
* a ReferenceQueue being used to tell when the VM has garbage collected an
* object so that we can keep the hashtables clean.
@@ -60,11 +60,11 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Justin Forder</a>
* @author <a href="[EMAIL PROTECTED]">danch (Dan Christopherson)</a>
* @author <a href="[EMAIL PROTECTED]">Bill Burke</a>
- * @version $Revision: 1.18 $
+ * @version $Revision: 1.19 $
*
* <p><b>Revisions:</b>
*
- * <p><b>20010621 Bill Burke:</b>
+ * <p><b>20010621 Bill Burke:</b>
* <ul>
* <li>createDefinedFinderCommand creates different objects
* based on the read-head flag of the FinderMetaData.
@@ -72,7 +72,7 @@
*
* <p><b>20010621 danch:</b>
* <ul>
- * <li>extended Bill's change to work on other finder types;
+ * <li>extended Bill's change to work on other finder types;
* removed stale todos.
* </ul>
*
@@ -89,15 +89,15 @@
private EntityContainer container;
private JawsEntityMetaData metadata;
private final Logger log = Logger.getLogger(this.getClass());
-
+
/** Timer queue used to time polls on the preloadRefQueue on all JAWS
* handled entities
*/
private static TimerQueue softRefHandler;
-
+
/** Timer queue used to get references to preload data who've been GC'ed */
private ReferenceQueue preloadRefQueue = new ReferenceQueue();
-
+
/** a map of data preloaded within some transaction for some entity. This map
* is keyed by Transaction and the data are hashmaps with key = entityKey and
* data = Object[] containing the entity data. */
@@ -106,55 +106,60 @@
* data = Object[] containing entity data
*/
private Map nonTransactionalPreloadData = new HashMap();
-
+
/** a Transaction manager so that we can link preloaded data to a transaction */
private TransactionManager tm;
-
+
// These support singletons (within the scope of this factory)
private JDBCBeanExistsCommand beanExistsCommand;
private JPMFindEntitiesCommand findEntitiesCommand;
-
+
//static initializer to kick off our softRefhandler
- static {
+ static
+ {
softRefHandler = new TimerQueue("JAWS Preload reference handler");
softRefHandler.start();
}
-
+
// Constructors --------------------------------------------------
-
+
public JDBCCommandFactory(EntityContainer container)
- throws Exception
+ throws Exception
{
this.container = container;
-
+
String ejbName = container.getBeanMetaData().getEjbName();
ApplicationMetaData amd =
container.getBeanMetaData().getApplicationMetaData();
JawsApplicationMetaData jamd =
(JawsApplicationMetaData)amd.getPluginData("JAWS");
-
- if (jamd == null) {
+
+ if (jamd == null)
+ {
// we are the first cmp entity to need jaws. Load jaws.xml for the whole
application
JawsXmlFileLoader jfl = new JawsXmlFileLoader(amd,
container.getClassLoader(), container.getLocalClassLoader());
jamd = jfl.load();
amd.addPluginData("JAWS", jamd);
}
-
+
metadata = jamd.getBeanByEjbName(ejbName);
- if (metadata == null) {
+ if (metadata == null)
+ {
throw new DeploymentException("No metadata found for bean " + ejbName);
}
-
+
tm = (TransactionManager) container.getTransactionManager();
- softRefHandler.schedule(new PreloadRefQueueHandlerTask());
+ PreloadRefQueueHandlerTask reqQue = new
PreloadRefQueueHandlerTask(preloadRefQueue,
+ preloadedData, nonTransactionalPreloadData);
+ softRefHandler.schedule(reqQue);
}
-
+
// Public --------------------------------------------------------
-
+
public EntityContainer getContainer()
{
return container;
}
-
+
public JawsEntityMetaData getMetaData()
{
return metadata;
@@ -163,7 +168,7 @@
// Additional Command creation
/**
- * Singleton: multiple callers get references to the
+ * Singleton: multiple callers get references to the
* same command instance.
*/
public JDBCBeanExistsCommand createBeanExistsCommand()
@@ -182,7 +187,7 @@
{
return new JDBCPreloadFinderCommand(this, new JDBCFindAllCommand(this, f));
}
- else
+ else
{
return new JDBCFindAllCommand(this, f);
}
@@ -201,13 +206,13 @@
}
public JPMFindEntitiesCommand createFindByCommand(Method finderMethod,
FinderMetaData f)
- throws IllegalArgumentException
+ throws IllegalArgumentException
{
if (f.hasReadAhead())
{
return new JDBCPreloadFinderCommand(this, new JDBCFindByCommand(this,
finderMethod, f));
}
- else
+ else
{
return new JDBCFindByCommand(this, finderMethod, f);
}
@@ -245,7 +250,7 @@
}
/**
- * Singleton: multiple callers get references to the
+ * Singleton: multiple callers get references to the
* same command instance.
*/
public JPMFindEntitiesCommand createFindEntitiesCommand()
@@ -297,27 +302,35 @@
/** Add preloaded data for an entity within the scope of a transaction */
- /*package*/ void addPreloadData(Object entityKey, Object[] entityData)
+ /*package*/ void addPreloadData(Object entityKey, Object[] entityData)
{
Transaction trans = null;
- try {
+ try
+ {
trans = tm.getTransaction();
- } catch (javax.transaction.SystemException sysE) {
+ } catch (javax.transaction.SystemException sysE)
+ {
log.warn("System exception getting transaction for preload - can't preload
data for "+entityKey, sysE);
return;
}
-//log.debug("PRELOAD: adding preload for "+entityKey+" in transaction "+(trans !=
null ? trans.toString() : "NONE")+" entityData="+entityData);
+ //log.debug("PRELOAD: adding preload for "+entityKey+" in transaction
"+(trans != null ? trans.toString() : "NONE")+" entityData="+entityData);
- if (trans != null) {
- synchronized (preloadedData) {
+ if (trans != null)
+ {
+ synchronized (preloadedData)
+ {
Map entitiesInTransaction = (Map)preloadedData.get(trans);
- if (entitiesInTransaction == null) {
- try {
+ if (entitiesInTransaction == null)
+ {
+ try
+ {
trans.registerSynchronization(new PreloadClearSynch(trans));
- } catch (javax.transaction.SystemException se) {
+ } catch (javax.transaction.SystemException se)
+ {
log.warn("System exception getting transaction for preload -
can't get preloaded data for "+entityKey, se);
return;
- } catch (javax.transaction.RollbackException re) {
+ } catch (javax.transaction.RollbackException re)
+ {
log.warn("Rollback exception getting transaction for preload -
can't get preloaded data for "+entityKey, re);
return;
}
@@ -327,66 +340,77 @@
PreloadData preloadData = new PreloadData(trans, entityKey, entityData,
preloadRefQueue);
entitiesInTransaction.put(entityKey, preloadData);
}
- } else {
- synchronized (nonTransactionalPreloadData) {
+ } else
+ {
+ synchronized (nonTransactionalPreloadData)
+ {
PreloadData preloadData = new PreloadData(null, entityKey, entityData,
preloadRefQueue);
nonTransactionalPreloadData.put(entityKey, preloadData);
}
}
}
- /** get data that we might have preloaded for an entity in a transaction -
+ /** get data that we might have preloaded for an entity in a transaction -
* may return null!
*/
- /*package*/ Object[] getPreloadData(Object entityKey)
+ /*package*/ Object[] getPreloadData(Object entityKey)
{
Transaction trans = null;
- try {
+ try
+ {
trans = tm.getTransaction();
- } catch (javax.transaction.SystemException sysE) {
+ } catch (javax.transaction.SystemException sysE)
+ {
log.warn("System exception getting transaction for preload - not
preloading "+entityKey, sysE);
return null;
}
Object[] result = null;
PreloadData preloadData = null;
- if (trans != null) {
+ if (trans != null)
+ {
Map entitiesInTransaction = null;
- // Do we really need this to be syncrhonized? What is the effect of
+ // Do we really need this to be syncrhonized? What is the effect of
// another thread trying to modify this map? It won't be to remove
- // our transaction (we're in it here!, trying to call a business
+ // our transaction (we're in it here!, trying to call a business
// method), and who cares if another is added/removed?
-// synchronized (preloadedData) {
- entitiesInTransaction = (Map)preloadedData.get(trans);
-// }
- if (entitiesInTransaction != null) {
- synchronized (entitiesInTransaction) {
+ // synchronized (preloadedData) {
+ entitiesInTransaction = (Map)preloadedData.get(trans);
+ // }
+ if (entitiesInTransaction != null)
+ {
+ synchronized (entitiesInTransaction)
+ {
preloadData = (PreloadData)entitiesInTransaction.get(entityKey);
entitiesInTransaction.remove(entityKey);
}
}
- } else {
- synchronized (nonTransactionalPreloadData) {
+ } else
+ {
+ synchronized (nonTransactionalPreloadData)
+ {
preloadData = (PreloadData)nonTransactionalPreloadData.get(entityKey);
nonTransactionalPreloadData.remove(entityKey);
}
}
- if (preloadData != null) {
+ if (preloadData != null)
+ {
result = preloadData.getData();
} /*else {
log.debug("PRELOAD: preloadData == null for "+entityKey);
}
if (result == null)
log.debug("PRELOAD: returning null as preload for "+entityKey);
- */
+ */
return result;
}
/** clear out any data we have preloaded for any entity in this transaction */
- /*package*/ void clearPreloadForTrans(Transaction trans)
+ /*package*/ void clearPreloadForTrans(Transaction trans)
{
-//log.debug("PRELOAD: clearing preload for transaction "+trans.toString());
- synchronized (preloadedData) {
+ //log.debug("PRELOAD: clearing preload for transaction "+trans.toString());
+ synchronized (preloadedData)
+ {
preloadedData.remove(trans);
}
}
@@ -394,35 +418,51 @@
// Private -------------------------------------------------------
- /** Inner class that handles our reference queue. I didn't think this would
- * be neccessary, but for some reason the VM won't call an override of
- * Reference.clear()
- */
- private class PreloadRefQueueHandlerTask extends TimerTask {
- PreloadRefQueueHandlerTask() {
+ /** Static class that handles our reference queue. It is a static class
+ to avoid a strong reference to the container instance variable as this
+ prevents GC of the container.
+ */
+ private static class PreloadRefQueueHandlerTask extends TimerTask
+ {
+ ReferenceQueue preloadRefQueue;
+ Map preloadedData;
+ Map nonTransactionalPreloadData;
+ PreloadRefQueueHandlerTask(ReferenceQueue preloadRefQueue,
+ Map preloadedData, Map nonTransactionalPreloadData)
+ {
super(50);
+ this.preloadRefQueue = preloadRefQueue;
+ this.preloadedData = preloadedData;
+ this.nonTransactionalPreloadData = nonTransactionalPreloadData;
}
-
- public void execute() throws Exception {
+
+ public void execute() throws Exception
+ {
PreloadData preloadData = (PreloadData)preloadRefQueue.poll();
int handled = 0;
- while (preloadData != null && handled < 10) {
- if (preloadData.getTransaction() != null) {
+ while (preloadData != null && handled < 10)
+ {
+ if (preloadData.getTransaction() != null)
+ {
Map entitiesInTransaction = null;
- // Do we really need this to be syncrhonized? What is the effect of
+ // Do we really need this to be syncrhonized? What is the effect of
// another thread trying to modify this map? It won't be to remove
- // our transaction (we're in it here!, trying to call a business
+ // our transaction (we're in it here!, trying to call a business
// method), and who cares if another is added/removed?
- // synchronized (preloadedData) {
- entitiesInTransaction =
(Map)preloadedData.get(preloadData.getTransaction());
- // }
- if (entitiesInTransaction != null) {
- synchronized (entitiesInTransaction) {
+ // synchronized (preloadedData) {
+ entitiesInTransaction =
(Map)preloadedData.get(preloadData.getTransaction());
+ // }
+ if (entitiesInTransaction != null)
+ {
+ synchronized (entitiesInTransaction)
+ {
entitiesInTransaction.remove(preloadData.getKey());
}
}
- } else {
- synchronized (nonTransactionalPreloadData) {
+ } else
+ {
+ synchronized (nonTransactionalPreloadData)
+ {
nonTransactionalPreloadData.remove(preloadData.getKey());
}
}
@@ -434,46 +474,56 @@
}
}
- /** Inner class used in the preload Data hashmaps so that we can wrap a
+ /** Inner class used in the preload Data hashmaps so that we can wrap a
* SoftReference around the data and still have enough information to remove
* the reference from the appropriate hashMap.
*/
- private class PreloadData extends SoftReference {
+ private class PreloadData extends SoftReference
+ {
private Object key;
private Transaction trans;
- PreloadData(Transaction trans, Object key, Object[] data, ReferenceQueue
queue) {
+ PreloadData(Transaction trans, Object key, Object[] data, ReferenceQueue
queue)
+ {
super(data, queue);
this.trans = trans;
this.key = key;
}
- Transaction getTransaction() {
+ Transaction getTransaction()
+ {
return trans;
}
- Object getKey() {
+ Object getKey()
+ {
return key;
}
- Object[] getData() {
+ Object[] getData()
+ {
return (Object[])get();
}
/** Named empty to not collide with superclass clear */
- public void empty() {
+ public void empty()
+ {
key = null;
trans = null;
}
}
- private class PreloadClearSynch implements javax.transaction.Synchronization{
+ private class PreloadClearSynch implements javax.transaction.Synchronization
+ {
private Transaction forTrans;
- public PreloadClearSynch(Transaction forTrans) {
+ public PreloadClearSynch(Transaction forTrans)
+ {
this.forTrans = forTrans;
}
- public void afterCompletion(int p0) {
+ public void afterCompletion(int p0)
+ {
clearPreloadForTrans(forTrans);
}
- public void beforeCompletion() {
+ public void beforeCompletion()
+ {
//no-op
}
}
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development