package org.apache.fop.threading;
import java.io.File;
-import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.CountingOutputStream;
+import org.apache.commons.io.output.NullOutputStream;
/**
* Testbed for multi-threading tests. The class can run a configurable set of task a number of
private File outputDir;
private Configuration fopCfg;
private FOProcessor foprocessor;
+ private boolean writeToDevNull;
private int counter = 0;
+ private List results = Collections.synchronizedList(new java.util.LinkedList());
+
/** {@inheritDoc} */
public void configure(Configuration configuration) throws ConfigurationException {
this.threads = configuration.getChild("threads").getValueAsInteger(10);
this.outputDir = new File(configuration.getChild("output-dir").getValue());
+ this.writeToDevNull = configuration.getChild("devnull").getValueAsBoolean(false);
Configuration tasks = configuration.getChild("tasks");
this.repeat = tasks.getAttributeAsInteger("repeat", 1);
Configuration[] entries = tasks.getChildren("task");
this.counter = 0;
//Initialize threads
+ ThreadGroup workerGroup = new ThreadGroup("FOP workers");
List threadList = new java.util.LinkedList();
for (int ti = 0; ti < this.threads; ti++) {
TaskRunner runner = new TaskRunner();
ContainerUtil.enableLogging(runner, getLogger());
- Thread thread = new Thread(runner);
+ Thread thread = new Thread(workerGroup, runner, "Worker- " + ti);
threadList.add(thread);
}
//ignore
}
}
- getLogger().info("Stress test duration: " + (System.currentTimeMillis() - start) + "ms");
+ long duration = System.currentTimeMillis() - start;
+
+ report(duration);
+ }
+
+ private void report(long duration) {
+ int count = this.results.size();
+ int failures = 0;
+ long bytesWritten = 0;
+ System.out.println("Report on " + count + " tasks:");
+ Iterator iter = this.results.iterator();
+ while (iter.hasNext()) {
+ Result res = (Result)iter.next();
+ if (res.failure != null) {
+ System.out.println("FAIL: " + (res.end - res.start) + " " + res.task);
+ System.out.println(" -> " + res.failure.getMessage());
+ failures++;
+ } else {
+ System.out.println("good: " + (res.end - res.start) + " " + res.filesize
+ + " " + res.task);
+ bytesWritten += res.filesize;
+ }
+ }
+ System.out.println("Stress test duration: " + duration + "ms");
+ if (failures > 0) {
+ System.out.println(failures + " failures of " + count + " documents!!!");
+ } else {
+ float mb = 1024f * 1024f;
+ System.out.println("Bytes written: " + (bytesWritten / mb) + " MB, "
+ + (bytesWritten * 1000 / duration) + " bytes / sec");
+ System.out.println("NO failures with " + count + " documents.");
+ }
}
private class TaskRunner extends AbstractLogEnabled implements Runnable {
public void execute() throws Exception {
getLogger().info("Processing: " + def);
- DecimalFormat df = new DecimalFormat("00000");
- File outfile = new File(outputDir, df.format(num) + fop.getTargetFileExtension());
- OutputStream out = new java.io.FileOutputStream(outfile);
+ long start = System.currentTimeMillis();
try {
- InputStream in;
- Templates templates;
-
- if (def.getFO() != null) {
- in = new java.io.FileInputStream(new File(def.getFO()));
- templates = null;
+ DecimalFormat df = new DecimalFormat("00000");
+ File outfile = new File(outputDir, df.format(num) + fop.getTargetFileExtension());
+ OutputStream out;
+ if (writeToDevNull) {
+ out = new NullOutputStream();
} else {
- in = new java.io.FileInputStream(new File(def.getXML()));
- templates = def.getTemplates();
+ out = new java.io.FileOutputStream(outfile);
+ out = new java.io.BufferedOutputStream(out);
}
+ CountingOutputStream cout = new CountingOutputStream(out);
try {
- fop.process(in, templates, out);
+ Source src;
+ Templates templates;
+
+ if (def.getFO() != null) {
+ src = new StreamSource(new File(def.getFO()));
+ templates = null;
+ } else {
+ src = new StreamSource(new File(def.getXML()));
+ templates = def.getTemplates();
+ }
+ fop.process(src, templates, cout);
} finally {
- IOUtils.closeQuietly(in);
+ IOUtils.closeQuietly(cout);
}
- } finally {
- IOUtils.closeQuietly(out);
+ results.add(new Result(def, start, System.currentTimeMillis(),
+ cout.getByteCount()));
+ } catch (Exception e) {
+ results.add(new Result(def, start, System.currentTimeMillis(), e));
+ throw e;
}
}
}
+ private static class Result {
+
+ private TaskDef task;
+ private long start;
+ private long end;
+ private long filesize;
+ private Throwable failure;
+
+ public Result(TaskDef task, long start, long end, long filesize) {
+ this(task, start, end, null);
+ this.filesize = filesize;
+ }
+
+ public Result(TaskDef task, long start, long end, Throwable failure) {
+ this.task = task;
+ this.start = start;
+ this.end = end;
+ this.failure = failure;
+ }
+ }
+
}
\ No newline at end of file
package org.apache.fop.threading;
-import java.io.InputStream;
import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.stream.StreamSource;
import org.apache.avalon.framework.activity.Initializable;
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.logger.AbstractLogEnabled;
+import org.apache.commons.io.FilenameUtils;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.events.Event;
+import org.apache.fop.events.EventFormatter;
+import org.apache.fop.events.EventListener;
+import org.apache.fop.events.model.EventSeverity;
/**
* Default implementation of the FOProcessor interface using FOP.
}
/** {@inheritDoc} */
- public void process(InputStream in, Templates templates, OutputStream out)
+ public void process(Source src, Templates templates, OutputStream out)
throws org.apache.fop.apps.FOPException, java.io.IOException {
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
+ foUserAgent.setBaseURL(src.getSystemId());
+ try {
+ URL url = new URL(src.getSystemId());
+ String filename = FilenameUtils.getName(url.getPath());
+ foUserAgent.getEventBroadcaster().addEventListener(new AvalonAdapter(filename));
+ } catch (MalformedURLException mfue) {
+ throw new RuntimeException(mfue);
+ }
Fop fop = fopFactory.newFop(this.mime, foUserAgent, out);
try {
} else {
transformer = templates.newTransformer();
}
- Source src = new StreamSource(in);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
} catch (TransformerException e) {
return this.fileExtension;
}
+ private class AvalonAdapter implements EventListener {
+
+ private String filename;
+
+ public AvalonAdapter(String filename) {
+ this.filename = filename;
+ }
+
+ public void processEvent(Event event) {
+ String msg = EventFormatter.format(event);
+ EventSeverity severity = event.getSeverity();
+ if (severity == EventSeverity.INFO) {
+ //getLogger().info(filename + ": " + msg);
+ } else if (severity == EventSeverity.WARN) {
+ //getLogger().warn(filename + ": " + msg);
+ } else if (severity == EventSeverity.ERROR) {
+ getLogger().error(filename + ": " + msg);
+ } else if (severity == EventSeverity.FATAL) {
+ getLogger().fatalError(filename + ": " + msg);
+ } else {
+ assert false;
+ }
+ }
+
+ }
}
\ No newline at end of file