sboag 00/10/12 13:53:03
Modified: src makexpath4j
src/org/apache/xalan/xpath XPathEnvSupport.java
XPathSupportDefault.java
src/org/apache/xalan/xpath/dtm DTM.java DTMLiaison.java
DTMProxy.java DTMProxyMap.java
src/org/apache/xalan/xpath/xdom XercesLiaison.java
src/org/apache/xalan/xpath/xml XMLParserLiaisonDefault.java
src/org/apache/xalan/xslt ElemForEach.java FuncDocument.java
StylesheetHandler.java XSLTEngineImpl.java
Added: src/org/apache/xalan/xpath/xml ObjectPool.java
Log:
Use object pool for parsers. Call reset() on parsers when done to release
memory. Provide special PI (<?xalan-doc-cache-off?>) to turn the doc cache off
in some circumstances.
Revision Changes Path
1.21 +1 -0 xml-xalan/src/makexpath4j
Index: makexpath4j
===================================================================
RCS file: /home/cvs/xml-xalan/src/makexpath4j,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- makexpath4j 2000/08/23 13:39:10 1.20
+++ makexpath4j 2000/10/12 20:52:19 1.21
@@ -134,6 +134,7 @@
$(XMLLIAISONDIR)$(PATHSEP)StringToStringTable.java \
$(XMLLIAISONDIR)$(PATHSEP)StringToStringTableVector.java \
$(XMLLIAISONDIR)$(PATHSEP)StringKey.java \
+ $(XMLLIAISONDIR)$(PATHSEP)ObjectPool.java \
$(XMLLIAISONDIR)$(PATHSEP)BoolStack.java \
$(XMLLIAISONDIR)$(PATHSEP)IntStack.java \
$(XMLLIAISONDIR)$(PATHSEP)IntVector.java \
1.9 +6 -0 xml-xalan/src/org/apache/xalan/xpath/XPathEnvSupport.java
Index: XPathEnvSupport.java
===================================================================
RCS file:
/home/cvs/xml-xalan/src/org/apache/xalan/xpath/XPathEnvSupport.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- XPathEnvSupport.java 2000/03/02 10:22:11 1.8
+++ XPathEnvSupport.java 2000/10/12 20:52:25 1.9
@@ -140,6 +140,12 @@
void associateXLocatorToNode(Node node, XLocator xlocator);
/**
+ * Deassociate an XLocator provider to a node based on the root of the
tree that the
+ * node is parented by.
+ */
+ public void deassociateXLocatorToNode(Node node);
+
+ /**
* Determine whether extra whitespace should be stripped from the node.
The determination is based
* on the combination of the default-space attribute on xsl:stylesheet,
xsl:strip-space, xsl:preserve-space,
* and the xml:space attribute.
1.23 +8 -0
xml-xalan/src/org/apache/xalan/xpath/XPathSupportDefault.java
Index: XPathSupportDefault.java
===================================================================
RCS file:
/home/cvs/xml-xalan/src/org/apache/xalan/xpath/XPathSupportDefault.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- XPathSupportDefault.java 2000/09/25 19:40:28 1.22
+++ XPathSupportDefault.java 2000/10/12 20:52:26 1.23
@@ -666,6 +666,14 @@
public void associateXLocatorToNode(Node node, XLocator xlocator)
{
}
+
+ /**
+ * Deassociate an XLocator provider to a node based on the root of the
tree that the
+ * node is parented by.
+ */
+ public void deassociateXLocatorToNode(Node node)
+ {
+ }
/**
* Get an XLocator provider keyed by node. This get's
1.25 +41 -15 xml-xalan/src/org/apache/xalan/xpath/dtm/DTM.java
Index: DTM.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/dtm/DTM.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- DTM.java 2000/08/17 21:32:53 1.24
+++ DTM.java 2000/10/12 20:52:31 1.25
@@ -81,10 +81,9 @@
import org.apache.xalan.xpath.res.XPATHErrorResources;
import org.apache.xerces.utils.QName;
import org.apache.xerces.framework.XMLAttrList;
+import org.apache.xalan.xpath.xml.ObjectPool;
-
-
/**
* <meta name="usage" content="internal"/>
* <code>DTM</code> is an XML document model expressed as a table rather than
@@ -213,7 +212,8 @@
initHandlers(false, this, this);
fScanner.setDTDHandler(this);
m_problemListener = new
org.apache.xalan.xpath.xml.ProblemListenerDefault();
-
+ // Runtime.getRuntime().gc();
+ // Runtime.getRuntime().runFinalization();
// setSendCharDataAsCharArray(false);
}
@@ -229,6 +229,8 @@
fScanner.setDTDHandler(this);
m_problemListener = listener;
+ // Runtime.getRuntime().gc();
+ // Runtime.getRuntime().runFinalization();
// setSendCharDataAsCharArray(false);
}
@@ -242,9 +244,29 @@
}
*/
+ /**
+ * Override reset so it doesn't release the string pool. DTM
+ * parsers are not reuseable (because the DTM is the same object
+ * as the parser).
+ */
+ public void reset()
+ throws Exception
+ {
+ fGrammarResolver.clearGrammarResolver();
+ // fStringPool.reset();
+ fEntityHandler.reset(fStringPool);
+ fScanner.reset(fStringPool, null);
+ fValidator.reset(fStringPool);
+ // fNeedReset = false;
+ }
+
boolean m_throwNewError = true;
-
+ protected void finalize() throws Throwable
+ {
+ // System.out.println("finalize called!");
+ }
+
/**
* Run the parse thread.
*/
@@ -275,6 +297,10 @@
// Should I throw again?? In general, how should
// the error be handled from here.
}
+ finally
+ {
+ // reset()?
+ }
}
@@ -367,8 +393,8 @@
// Make sure nobody is still waiting
synchronized (this)
{
- if(DEBUG_WAITS)
- System.out.println("startDocument(1): "+document);
+ // if(DEBUG_WAITS)
+ // System.out.println("startDocument(1): "+document);
notify();
}
}
@@ -390,8 +416,8 @@
// Make sure nobody is still waiting
synchronized (this)
{
- if(DEBUG_WAITS)
- System.out.println("startDocument(1): "+document);
+ // if(DEBUG_WAITS)
+ // System.out.println("startDocument(1): "+document);
notify();
}
}
@@ -1361,8 +1387,8 @@
if(DEBUG_WAITS)
System.out.println("Waiting... getDocument");
wait();
- if(DEBUG_WAITS)
- System.out.println("Out of waiting... getDocument: "+document);
+ // if(DEBUG_WAITS)
+ // System.out.println("Out of waiting... getDocument: "+document);
}
catch (InterruptedException e)
{
@@ -1370,8 +1396,8 @@
}
}
}
- if(DEBUG_WAITS)
- System.out.println("getDocument returning: "+document);
+ // if(DEBUG_WAITS)
+ // System.out.println("getDocument returning: "+document);
return document;
}
@@ -1741,8 +1767,8 @@
return position+1;
else
{
- if(DEBUG_WAITS)
- System.out.println("Not descendent...");
+ // if(DEBUG_WAITS)
+ // System.out.println("Not descendent...");
return -1; // Not descendent.
}
}
@@ -2224,7 +2250,7 @@
* @return String String represented by that number.
*/
private final String intToString(int i)
- {
+ {
if(fStringPool==null)
return (String)symbolList.elementAt(i);
else
1.22 +19 -5 xml-xalan/src/org/apache/xalan/xpath/dtm/DTMLiaison.java
Index: DTMLiaison.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/dtm/DTMLiaison.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- DTMLiaison.java 2000/09/25 19:40:30 1.21
+++ DTMLiaison.java 2000/10/12 20:52:35 1.22
@@ -71,7 +71,7 @@
import org.apache.xalan.xpath.XLocator;
import org.apache.xalan.xpath.res.XPATHErrorResources;
import org.apache.xalan.xpath.xml.XSLMessages;
-
+
/**
* <meta name="usage" content="internal"/>
* Liaison to Document Table Model (DTM) XML parser -- the default liaison
and parser that XSLTProcessor
@@ -161,7 +161,7 @@
throw new
SAXException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_DTM_CANNOT_HANDLE_NODES,
new Object[]{((Object)node).getClass()})); //"DTMLiaison can not handle nodes
of type"
//+((Object)node).getClass());
}
-
+
/**
* Parse an XML document.
*
@@ -194,6 +194,7 @@
{
if(null == m_docHandler)
{
+ // System.out.println(source.getSystemId());
DTM parser = new DTM(this.getProblemListener());
Thread parseThread = null;
{
@@ -243,10 +244,23 @@
// by default. It incorrectly decides to validate documents that
declare
// internal entities. -<[EMAIL PROTECTED]>
- if(m_doThreading)
+ // if(m_doThreading)
+ if(true)
{
// System.out.println("id: "+source.getSystemId());
+ // System.out.println("Calling direct...");
parser.parse(source);
+ try{ parser.reset(); } catch(Exception e){}
+
+ m_parseCountSinceGC++;
+ if( m_parseCountSinceGC > 10 )
+ {
+ m_parseCountSinceGC = 0;;
+ // System.out.print( "[gc]" );
+ System.gc();
+ }
+ // System.gc();
+ // System.runFinalization();
}
else
{
@@ -265,8 +279,8 @@
m_document = parser.getDocument();
if(null != source.getSystemId())
{
- if(null != getSourceDocsTable())
- getSourceDocsTable().put(source.getSystemId(), m_document);
+ // if(null != getSourceDocsTable())
+ // getSourceDocsTable().put(source.getSystemId(), m_document);
}
}
}
1.14 +5 -0 xml-xalan/src/org/apache/xalan/xpath/dtm/DTMProxy.java
Index: DTMProxy.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/dtm/DTMProxy.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- DTMProxy.java 2000/08/04 03:22:33 1.13
+++ DTMProxy.java 2000/10/12 20:52:35 1.14
@@ -285,10 +285,15 @@
int newnode=dtm.getNextSibling(node);
return (newnode==-1) ? null : dtm.getNode(newnode);
}
+
+ // DTMProxyMap m_attrs;
/** @see org.w3c.dom.Node */
public final NamedNodeMap getAttributes()
{
+ // if(null == m_attrs)
+ // m_attrs = new DTMProxyMap(dtm,node);
+ // return m_attrs;
return new DTMProxyMap(dtm,node);
}
1.5 +8 -3 xml-xalan/src/org/apache/xalan/xpath/dtm/DTMProxyMap.java
Index: DTMProxyMap.java
===================================================================
RCS file:
/home/cvs/xml-xalan/src/org/apache/xalan/xpath/dtm/DTMProxyMap.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- DTMProxyMap.java 2000/03/06 20:13:41 1.4
+++ DTMProxyMap.java 2000/10/12 20:52:36 1.5
@@ -78,6 +78,7 @@
{
DTM dtm;
int element;
+ short m_count = -1;
/** Create a getAttributes NamedNodeMap for a given DTM element node */
DTMProxyMap(DTM dtm,int element)
@@ -89,14 +90,18 @@
/** Return the number of Attributes on this Element */
public int getLength()
{
- int count=0;
+ if(m_count == -1)
+ {
+ short count=0;
for(int n=dtm.getNextAttribute(element);
n!=-1;
n=dtm.getNextAttribute(n))
{
- ++count;
+ ++count;
}
- return count;
+ m_count = count;
+ }
+ return (int)m_count;
}
/** Return the Attr node having a specific name */
1.24 +51 -7
xml-xalan/src/org/apache/xalan/xpath/xdom/XercesLiaison.java
Index: XercesLiaison.java
===================================================================
RCS file:
/home/cvs/xml-xalan/src/org/apache/xalan/xpath/xdom/XercesLiaison.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- XercesLiaison.java 2000/09/12 01:12:46 1.23
+++ XercesLiaison.java 2000/10/12 20:52:43 1.24
@@ -177,6 +177,23 @@
}
return versionNum;
}
+
+ /**
+ * Pool the DOM parsers for reuse.
+ */
+ private ObjectPool m_domParserPool = new ObjectPool(DOMParser.class);
+
+ /**
+ * Pool the SAX parsers for reuse.
+ */
+ private ObjectPool m_saxParserPool = new ObjectPool(SAXParser.class);
+
+ /**
+ * Count the parses since the last garbage collection. GC every
+ * 10 parses or so. (This might be a bad idea, but it seems to
+ * help...)
+ */
+ protected int m_parseCountSinceGC = 0;
/**
* <meta name="usage" content="internal"/>
@@ -214,7 +231,7 @@
if(null == m_docHandler)
{
isDomParser = true;
- DOMParser domParser = new MyParser();
+ DOMParser domParser = (DOMParser)m_domParserPool.getInstance();
domParser.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes",
getShouldExpandEntityRefs()? false : true);
if(m_useDOM2getNamespaceURI)
{
@@ -232,7 +249,7 @@
else
{
isDomParser = false;
- SAXParser saxparser = new SAXParser();
+ SAXParser saxparser = (SAXParser)m_saxParserPool.getInstance();
saxparser.setDocumentHandler(m_docHandler);
m_docHandler = null;
parser = saxparser;
@@ -293,6 +310,38 @@
*/
throw new
SAXException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_XERCES_PARSE_ERROR,
null), e); //"XercesLiaison.parse error", e);
}
+ finally
+ {
+ if(null != parser)
+ {
+ try
+ {
+ if(isDomParser)
+ {
+ parser.reset();
+ m_domParserPool.freeInstance(parser);
+ m_parseCountSinceGC++;
+
+ /* GC every 10 parses or so. (This might be a bad
+ idea, but it seems to help...) */
+ if( m_parseCountSinceGC > 10 )
+ {
+ m_parseCountSinceGC = 0;;
+ System.gc();
+ }
+ }
+ else
+ {
+ parser.reset();
+ m_saxParserPool.freeInstance(parser);
+ }
+ }
+ catch(Exception e)
+ {
+ }
+ }
+ }
+
}
public void copyFromOtherLiaison(XMLParserLiaisonDefault from)
@@ -406,11 +455,6 @@
{
return (Node.ATTRIBUTE_NODE == node.getNodeType())
? ((Attr)node).getOwnerElement() : node.getParentNode();
- }
-
- class MyParser extends DOMParser
- {
-
}
}
1.39 +28 -1
xml-xalan/src/org/apache/xalan/xpath/xml/XMLParserLiaisonDefault.java
Index: XMLParserLiaisonDefault.java
===================================================================
RCS file:
/home/cvs/xml-xalan/src/org/apache/xalan/xpath/xml/XMLParserLiaisonDefault.java,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- XMLParserLiaisonDefault.java 2000/09/07 22:21:08 1.38
+++ XMLParserLiaisonDefault.java 2000/10/12 20:52:47 1.39
@@ -1938,7 +1938,7 @@
}
return result;
}
-
+
public Hashtable getSourceDocsTable()
{
return m_sourceDocs;
@@ -1989,6 +1989,33 @@
if(null == found)
{
m_dataProviders.addElement(new DataProviderAssociation(root,
xlocator));
+ // System.out.println("Added: "+m_dataProviders.size());
+ }
+ }
+
+ /**
+ * <meta name="usage" content="advanced"/>
+ * Associate an XLocator provider to a node. This makes
+ * the association based on the root of the tree that the
+ * node is parented by.
+ */
+ public void deassociateXLocatorToNode(Node node)
+ {
+ Node root = getRoot(node);
+ int n = m_dataProviders.size();
+ // System.out.println("Trying to deassociate... "+n+"
"+root.getNodeType()+" "+root);
+ for(int i = 0; i < n; i++)
+ {
+ DataProviderAssociation ass
+ = (DataProviderAssociation)m_dataProviders.elementAt(i);
+ // System.out.println("testing: "+((Node)ass.m_key).getNodeType()+"
"+((Node)ass.m_key));
+ if((null != ass) && (root == ass.m_key))
+ {
+ // System.out.println("Deassociating...");
+ ass.m_key = null;
+ m_dataProviders.setElementAt(null, i);
+ break;
+ }
}
}
1.1 xml-xalan/src/org/apache/xalan/xpath/xml/ObjectPool.java
Index: ObjectPool.java
===================================================================
package org.apache.xalan.xpath.xml;
import java.util.*;
public class ObjectPool
{
private final Class objectType;
private final Vector freeStack;
public ObjectPool(Class type) {
objectType = type;
freeStack = new Vector();
}
public ObjectPool(Class type, int size) {
objectType = type;
freeStack = new Vector(size);
}
public ObjectPool()
{
objectType = null;
freeStack = new Vector();
}
public synchronized Object getInstanceIfFree()
{
// Check if the pool is empty.
if (!freeStack.isEmpty())
{
// Remove object from end of free pool.
Object result = freeStack.lastElement();
freeStack.setSize(freeStack.size() - 1);
return result;
}
return null;
}
public synchronized Object getInstance()
{
// Check if the pool is empty.
if (freeStack.isEmpty()) {
// Create a new object if so.
try {
return objectType.newInstance();
} catch (InstantiationException ex) {}
catch (IllegalAccessException ex) {}
// Throw unchecked exception for error in pool configuration.
throw new RuntimeException("exception creating new instance for pool");
} else {
// Remove object from end of free pool.
Object result = freeStack.lastElement();
freeStack.setSize(freeStack.size() - 1);
return result;
}
}
public synchronized void freeInstance(Object obj)
{
// Make sure the object is of the correct type.
if (objectType.isInstance(obj)) {
freeStack.addElement(obj);
} else {
throw new IllegalArgumentException("argument type invalid for pool");
}
}
}
1.8 +7 -0 xml-xalan/src/org/apache/xalan/xslt/ElemForEach.java
Index: ElemForEach.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/ElemForEach.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ElemForEach.java 2000/03/02 10:23:02 1.7
+++ ElemForEach.java 2000/10/12 20:52:52 1.8
@@ -72,6 +72,13 @@
public XPath m_selectPattern = null;
public Vector m_sortElems = null;
+ /**
+ * This is set by a "doc-cache-off" pi. It tells the engine
+ * that documents created in the location paths executed by
+ * this element will not be reparsed.
+ */
+ public boolean m_doc_cache_off;
+
public int getXSLToken()
{
return Constants.ELEMNAME_FOREACH;
1.18 +22 -1 xml-xalan/src/org/apache/xalan/xslt/FuncDocument.java
Index: FuncDocument.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/FuncDocument.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- FuncDocument.java 2000/08/24 16:10:09 1.17
+++ FuncDocument.java 2000/10/12 20:52:53 1.18
@@ -242,7 +242,28 @@
}
else
{
- execContext.getSourceDocsTable().put(uri, newDoc);
+ ElemTemplateElement templElem =
(ElemTemplateElement)execContext.getNamespaceContext();
+ boolean doc_cache_off = false;
+ // System.out.println("Doc func at line# "
+ //
+((ElemTemplateElement)templElem).m_lineNumber);
+
+ // A xsl:for-each or xsl:apply-templates may have a special
+ // attribute that tells us not to cache the document.
+ if(templElem instanceof ElemForEach)
+ {
+ doc_cache_off = ((ElemForEach)templElem).m_doc_cache_off;
+ }
+
+ if(!doc_cache_off)
+ {
+ execContext.getSourceDocsTable().put(uri, newDoc);
+ }
+ else
+ {
+ execContext.deassociateXLocatorToNode(newDoc);
+ // Runtime.getRuntime().gc();
+ // Runtime.getRuntime().runFinalization();
+ }
}
}
}
1.30 +21 -1
xml-xalan/src/org/apache/xalan/xslt/StylesheetHandler.java
Index: StylesheetHandler.java
===================================================================
RCS file:
/home/cvs/xml-xalan/src/org/apache/xalan/xslt/StylesheetHandler.java,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- StylesheetHandler.java 2000/08/11 05:36:15 1.29
+++ StylesheetHandler.java 2000/10/12 20:52:54 1.30
@@ -1800,8 +1800,28 @@
public void processingInstruction (String target, String data)
throws SAXException
{
+ String ns = m_stylesheet.getNamespaceFromStack(target);
+ String localName = getLocalName(target);
+ try
+ {
+ // A xsl:for-each or xsl:apply-templates may have a special
+ // PI that tells us not to cache the document. This PI
+ // should really be namespaced.
+ if( localName.equals("doc-cache-off") &&
+ ns.equals("http://xml.apache.org/xslt"))
+ {
+ ElemForEach elem = (ElemForEach)m_elems.peek();
+ if(!(elem instanceof ElemForEach))
+ throw new SAXParseException("xalan:doc-cache-off not allowed
here!",
+ (Locator)m_processor.m_stylesheetLocatorStack.peek());
+ System.out.println("Found it!");
+ elem.m_doc_cache_off = true;
+ }
+ }
+ catch(Exception e) {}
+ // System.out.println(target);
// No action for the moment.
-// m_lastPopped = null; // Reset this so that it does not affect
future elements
+ // m_lastPopped = null; // Reset this so that it does not affect
future elements
}
1.73 +11 -0 xml-xalan/src/org/apache/xalan/xslt/XSLTEngineImpl.java
Index: XSLTEngineImpl.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/XSLTEngineImpl.java,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- XSLTEngineImpl.java 2000/09/27 19:49:32 1.72
+++ XSLTEngineImpl.java 2000/10/12 20:52:55 1.73
@@ -3014,6 +3014,17 @@
{
m_parserLiaison.associateXLocatorToNode(node, xlocator);
}
+
+ /**
+ * Deassociate an XLocator provider to a node. This makes
+ * the association based on the root of the tree that the
+ * node is parented by.
+ */
+ public void deassociateXLocatorToNode(Node node)
+ {
+ m_parserLiaison.deassociateXLocatorToNode(node);
+ }
+
/**
* Create a document fragment. This function may return null.