Hi all, I was playing with the profiler when I noticed the way the ProfilingXMLPipe works. Every component is given the opportunity to stream its sax events, they are buffered in a DOM, the DOM is then used (to display the intermediate XML and) to stream SAX events to the next component. This behavior is different from how a pipeline normally works, and can cause strange errors (or mask errors that will appear when the profiler is removed).
So I implemented another class, the ProfilingSAXPipe, that does all the ProfilingXMLPipe does, but stream the sax events directly, without storing them in a DOM and doing it step by step. Time calculation is obviously more complicated, and I'm not yet sure it's precise enough, but seems to be consistent with the default implementation. To activate it pass a sax-stream="true" on the pipeline definition, or use the profile-caching-sax and profile-noncaching-sax pipeline types. Can someone point me to the right documentation branch where I should update documentation? Simone [EMAIL PROTECTED] wrote: > Author: simoneg > Date: Mon Feb 5 18:46:03 2007 > New Revision: 503964 > > URL: http://svn.apache.org/viewvc?view=rev&rev=503964 > Log: > Added another implemetation of profiling pipe respecting the sax streaming > contract > > Added: > > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingSAXPipe.java > Modified: > > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingCachingProcessingPipeline.java > > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingNonCachingProcessingPipeline.java > > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/resources/META-INF/cocoon/avalon/cocoon-profiler-sitemap.xconf > > Modified: > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingCachingProcessingPipeline.java > URL: > http://svn.apache.org/viewvc/cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingCachingProcessingPipeline.java?view=diff&rev=503964&r1=503963&r2=503964 > ============================================================================== > --- > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingCachingProcessingPipeline.java > (original) > +++ > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingCachingProcessingPipeline.java > Mon Feb 5 18:46:03 2007 > @@ -18,6 +18,9 @@ > > import java.util.Iterator; > > +import org.apache.avalon.framework.configuration.Configurable; > +import org.apache.avalon.framework.configuration.Configuration; > +import org.apache.avalon.framework.configuration.ConfigurationException; > import org.apache.avalon.framework.parameters.Parameters; > import org.apache.avalon.framework.service.ServiceException; > import org.apache.avalon.framework.service.ServiceManager; > @@ -27,13 +30,14 @@ > import org.apache.cocoon.sitemap.SitemapModelComponent; > import org.apache.cocoon.transformation.Transformer; > import org.apache.cocoon.xml.XMLConsumer; > +import org.apache.cocoon.xml.XMLPipe; > import org.apache.cocoon.xml.XMLProducer; > > /** > * @version $Id$ > */ > public class ProfilingCachingProcessingPipeline > - extends CachingProcessingPipeline { > + extends CachingProcessingPipeline implements Configurable { > > private Profiler profiler; > > @@ -41,6 +45,8 @@ > > private int index; > > + private boolean saxstream = false; > + > /** > * @see > org.apache.cocoon.components.pipeline.AbstractProcessingPipeline#service(org.apache.avalon.framework.service.ServiceManager) > */ > @@ -48,6 +54,11 @@ > super.service(aManager); > this.profiler = (Profiler) manager.lookup(Profiler.ROLE); > } > + > + public void configure(Configuration conf) throws ConfigurationException > { > + this.saxstream = conf.getAttributeAsBoolean("sax-stream", > false); > + } > + > > /** > * @see > org.apache.cocoon.components.pipeline.impl.BaseCachingProcessingPipeline#dispose() > @@ -298,10 +309,18 @@ > protected void connect(Environment environment, XMLProducer producer, > XMLConsumer consumer) > throws ProcessingException { > - ProfilingXMLPipe connector = new ProfilingXMLPipe(); > - connector.setup(this.index, this.data); > + XMLPipe pipe = null; > + if (saxstream) { > + ProfilingSAXPipe connector = new ProfilingSAXPipe(); > + connector.setup(this.index, this.data); > + pipe = connector; > + } else { > + ProfilingXMLPipe connector = new ProfilingXMLPipe(); > + connector.setup(this.index, this.data); > + pipe = connector; > + } > this.index++; > - super.connect(environment, producer, connector); > - super.connect(environment, connector, consumer); > + super.connect(environment, producer, pipe); > + super.connect(environment, pipe, consumer); > } > } > > Modified: > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingNonCachingProcessingPipeline.java > URL: > http://svn.apache.org/viewvc/cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingNonCachingProcessingPipeline.java?view=diff&rev=503964&r1=503963&r2=503964 > ============================================================================== > --- > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingNonCachingProcessingPipeline.java > (original) > +++ > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingNonCachingProcessingPipeline.java > Mon Feb 5 18:46:03 2007 > @@ -19,6 +19,9 @@ > import java.util.Iterator; > > import org.apache.avalon.framework.activity.Disposable; > +import org.apache.avalon.framework.configuration.Configurable; > +import org.apache.avalon.framework.configuration.Configuration; > +import org.apache.avalon.framework.configuration.ConfigurationException; > import org.apache.avalon.framework.parameters.Parameters; > import org.apache.avalon.framework.service.ServiceException; > import org.apache.avalon.framework.service.ServiceManager; > @@ -28,6 +31,7 @@ > import org.apache.cocoon.sitemap.SitemapModelComponent; > import org.apache.cocoon.transformation.Transformer; > import org.apache.cocoon.xml.XMLConsumer; > +import org.apache.cocoon.xml.XMLPipe; > import org.apache.cocoon.xml.XMLProducer; > > /** > @@ -38,13 +42,15 @@ > * @version $Id$ > */ > public class ProfilingNonCachingProcessingPipeline extends > NonCachingProcessingPipeline > - implements Disposable { > + implements Disposable, > Configurable { > > private Profiler profiler; > > private ProfilerData data; > > private int index; > + > + private boolean saxstream = false; > > /** > * @see > org.apache.cocoon.components.pipeline.AbstractProcessingPipeline#service(org.apache.avalon.framework.service.ServiceManager) > @@ -54,6 +60,10 @@ > this.profiler = (Profiler) manager.lookup(Profiler.ROLE); > } > > + public void configure(Configuration conf) throws ConfigurationException > { > + this.saxstream = conf.getAttributeAsBoolean("sax-stream", > false); > + } > + > /** > * @see org.apache.avalon.framework.activity.Disposable#dispose() > */ > @@ -295,12 +305,19 @@ > */ > protected void connect(Environment environment, XMLProducer producer, > XMLConsumer consumer) throws ProcessingException { > - ProfilingXMLPipe connector = new ProfilingXMLPipe(); > - > - connector.setup(this.index, this.data); > + XMLPipe pipe = null; > + if (saxstream) { > + ProfilingSAXPipe connector = new ProfilingSAXPipe(); > + connector.setup(this.index, this.data); > + pipe = connector; > + } else { > + ProfilingXMLPipe connector = new ProfilingXMLPipe(); > + connector.setup(this.index, this.data); > + pipe = connector; > + } > this.index++; > - super.connect(environment, producer, connector); > - super.connect(environment, connector, consumer); > + super.connect(environment, producer, pipe); > + super.connect(environment, pipe, consumer); > } > > } > > Added: > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingSAXPipe.java > URL: > http://svn.apache.org/viewvc/cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingSAXPipe.java?view=auto&rev=503964 > ============================================================================== > --- > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingSAXPipe.java > (added) > +++ > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/java/org/apache/cocoon/components/profiler/ProfilingSAXPipe.java > Mon Feb 5 18:46:03 2007 > @@ -0,0 +1,219 @@ > +package org.apache.cocoon.components.profiler; > + > +import java.util.Map; > +import java.util.WeakHashMap; > + > +import org.apache.cocoon.components.sax.XMLByteStreamCompiler; > +import org.apache.cocoon.xml.XMLConsumer; > +import org.apache.cocoon.xml.XMLPipe; > +import org.xml.sax.Attributes; > +import org.xml.sax.Locator; > +import org.xml.sax.SAXException; > + > +public class ProfilingSAXPipe implements XMLPipe { > + > + private static Map pipes = new WeakHashMap(); > + > + private XMLConsumer consumer; > + > + // Data of the profile > + private ProfilerData data; > + > + // Index of the component > + private int index; > + > + // Start time > + private long time; > + private boolean inside = false; > + > + // Time difference > + private long total; > + > + private XMLByteStreamCompiler serializer; > + > + /** > + * Setup this XMLPipe. > + * > + * @param index Index of the component. > + * @param data Data of the profile. > + */ > + public void setup(int index, ProfilerData data) { > + this.index = index; > + this.data = data; > + this.serializer = new XMLByteStreamCompiler(); > + } > + > + /** > + * Set the <code>XMLConsumer</code> that will receive XML data. > + */ > + public void setConsumer(XMLConsumer consumer) { > + this.consumer = consumer; > + } > + > + private void entered() { > + assert(!this.inside); > + ProfilingSAXPipe other = (ProfilingSAXPipe) pipes.get(this.data); > + assert(other != null); > + if (other != this) other.exited(); > + this.inside = true; > + this.time = System.currentTimeMillis(); > + } > + > + private void exited() { > + long current = System.currentTimeMillis(); > + if (!this.inside) { > + ProfilingSAXPipe other = (ProfilingSAXPipe) > pipes.get(this.data); > + if (other != null) { > + this.time = other.getTime(); > + } else { > + this.time = current; > + } > + } > + this.total += current - this.time; > + this.time = current; > + pipes.put(this.data, this); > + } > + > + public void startDocument() throws SAXException { > + exited(); > + this.serializer.startDocument(); > + this.consumer.startDocument(); > + entered(); > + } > + > + public void endDocument() throws SAXException { > + exited(); > + this.serializer.endDocument(); > + this.consumer.endDocument(); > + > + if (this.index != -1) > + this.data.setProcessingTime(this.index, this.total); > + > + // push the content of the buffer through the next component > + Object fragment = this.serializer.getSAXFragment(); > + > + if (this.index != -1) > + this.data.setSAXFragment(this.index, fragment); > + } > + > + public void setDocumentLocator(Locator locator) { > + exited(); > + this.serializer.setDocumentLocator(locator); > + this.consumer.setDocumentLocator(locator); > + entered(); > + } > + > + public void startPrefixMapping(String prefix, String uri) throws > SAXException { > + exited(); > + this.serializer.startPrefixMapping(prefix, uri); > + this.consumer.startPrefixMapping(prefix, uri); > + entered(); > + } > + > + public void endPrefixMapping(String prefix) throws SAXException { > + exited(); > + this.serializer.endPrefixMapping(prefix); > + this.consumer.endPrefixMapping(prefix); > + entered(); > + } > + > + public void startElement(String uri, String loc, String raw, Attributes > a) throws SAXException { > + exited(); > + this.serializer.startElement(uri, loc, raw, a); > + this.consumer.startElement(uri, loc, raw, a); > + entered(); > + } > + > + public void endElement(String uri, String loc, String raw) throws > SAXException { > + exited(); > + this.serializer.endElement(uri, loc, raw); > + this.consumer.endElement(uri, loc, raw); > + entered(); > + } > + > + public void characters(char c[], int start, int len) throws SAXException > { > + exited(); > + this.serializer.characters(c, start, len); > + this.consumer.characters(c, start, len); > + entered(); > + } > + > + public void ignorableWhitespace(char c[], int start, int len) throws > SAXException { > + exited(); > + this.serializer.ignorableWhitespace(c, start, len); > + this.consumer.ignorableWhitespace(c, start, len); > + entered(); > + } > + > + public void processingInstruction(String target, String data) throws > SAXException { > + exited(); > + this.serializer.processingInstruction(target, data); > + this.consumer.processingInstruction(target, data); > + entered(); > + } > + > + public void skippedEntity(String name) throws SAXException { > + exited(); > + this.serializer.skippedEntity(name); > + this.consumer.skippedEntity(name); > + entered(); > + } > + > + public void startDTD(String name, String publicId, String systemId) > throws SAXException { > + exited(); > + this.serializer.startDTD(name, publicId, systemId); > + this.consumer.startDTD(name, publicId, systemId); > + entered(); > + } > + > + public void endDTD() throws SAXException { > + exited(); > + this.serializer.endDTD(); > + this.consumer.endDTD(); > + entered(); > + } > + > + public void startEntity(String name) throws SAXException { > + exited(); > + this.serializer.startEntity(name); > + this.consumer.startEntity(name); > + entered(); > + } > + > + public void endEntity(String name) throws SAXException { > + exited(); > + this.serializer.endEntity(name); > + this.consumer.endEntity(name); > + entered(); > + } > + > + public void startCDATA() throws SAXException { > + exited(); > + this.serializer.startCDATA(); > + this.consumer.startCDATA(); > + entered(); > + } > + > + public void endCDATA() throws SAXException { > + exited(); > + this.serializer.endCDATA(); > + this.consumer.endCDATA(); > + entered(); > + } > + > + public void comment(char ch[], int start, int len) throws SAXException { > + exited(); > + this.serializer.comment(ch, start, len); > + this.consumer.comment(ch, start, len); > + entered(); > + } > + > + public boolean isInside() { > + return inside; > + } > + > + public long getTime() { > + return time; > + } > + > +} > > Modified: > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/resources/META-INF/cocoon/avalon/cocoon-profiler-sitemap.xconf > URL: > http://svn.apache.org/viewvc/cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/resources/META-INF/cocoon/avalon/cocoon-profiler-sitemap.xconf?view=diff&rev=503964&r1=503963&r2=503964 > ============================================================================== > --- > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/resources/META-INF/cocoon/avalon/cocoon-profiler-sitemap.xconf > (original) > +++ > cocoon/trunk/blocks/cocoon-profiler/cocoon-profiler-impl/src/main/resources/META-INF/cocoon/avalon/cocoon-profiler-sitemap.xconf > Mon Feb 5 18:46:03 2007 > @@ -32,5 +32,9 @@ > > src="org.apache.cocoon.components.profiler.ProfilingCachingProcessingPipeline"/> > <map:pipe name="profile-noncaching" > > src="org.apache.cocoon.components.profiler.ProfilingNonCachingProcessingPipeline"/> > + <map:pipe name="profile-caching-sax" > + > src="org.apache.cocoon.components.profiler.ProfilingCachingProcessingPipeline" > sax-stream="true"/> > + <map:pipe name="profile-noncaching-sax" > + > src="org.apache.cocoon.components.profiler.ProfilingNonCachingProcessingPipeline" > sax-stream="true"/> > </map:pipes> > </map:components> > > >
