-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor to use store for all temp IO #3548
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,14 +12,14 @@ | |
import org.apache.tools.ant.Task; | ||
import org.dita.dost.log.DITAOTAntLogger; | ||
import org.dita.dost.store.Store; | ||
import org.dita.dost.store.StreamStore; | ||
import org.dita.dost.store.StoreBuilder; | ||
import org.dita.dost.util.CatalogUtils; | ||
import org.dita.dost.util.XMLUtils; | ||
|
||
import java.io.File; | ||
import java.util.ServiceLoader; | ||
|
||
import static org.dita.dost.util.Constants.ANT_REFERENCE_STORE; | ||
import static org.dita.dost.util.Constants.ANT_REFERENCE_XML_UTILS; | ||
import static org.dita.dost.util.Constants.*; | ||
import static org.dita.dost.util.URLUtils.toFile; | ||
|
||
/** | ||
|
@@ -28,6 +28,11 @@ | |
* @since 3.5 | ||
*/ | ||
public final class InitializeProjectTask extends Task { | ||
|
||
private static ServiceLoader<StoreBuilder> storeBuilderLoader = ServiceLoader.load(StoreBuilder.class); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use service loader to load |
||
|
||
private String storeType = "file"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Default |
||
|
||
@Override | ||
public void execute() throws BuildException { | ||
log("Initializing project", Project.MSG_INFO); | ||
|
@@ -42,10 +47,28 @@ public void execute() throws BuildException { | |
xmlUtils.setLogger(new DITAOTAntLogger(getProject())); | ||
getProject().addReference(ANT_REFERENCE_XML_UTILS, xmlUtils); | ||
} | ||
final Store store = getStore(xmlUtils); | ||
getProject().addReference(ANT_REFERENCE_STORE, store); | ||
} | ||
|
||
private Store getStore(XMLUtils xmlUtils) { | ||
Store store = getProject().getReference(ANT_REFERENCE_STORE); | ||
if (store == null) { | ||
store = new StreamStore(xmlUtils); | ||
getProject().addReference(ANT_REFERENCE_STORE, store); | ||
if (store != null) { | ||
return store; | ||
} | ||
File tempDir = toFile(getProject().getUserProperty(ANT_TEMP_DIR)); | ||
if (tempDir == null) { | ||
tempDir = toFile(getProject().getProperty(ANT_TEMP_DIR)); | ||
} | ||
for (StoreBuilder storeBuilder : storeBuilderLoader) { | ||
if (storeBuilder.getType().equals(storeType)) { | ||
return storeBuilder.setTempDir(tempDir).setXmlUtils(xmlUtils).build(); | ||
} | ||
} | ||
throw new BuildException(String.format("Unsupported store type %s", storeType)); | ||
} | ||
|
||
public void setStoreType(final String storeType) { | ||
this.storeType = storeType; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
import org.apache.tools.ant.types.resources.FileResource; | ||
import org.apache.tools.ant.types.resources.URLResource; | ||
import org.dita.dost.ant.ExtensibleAntInvoker; | ||
import org.dita.dost.store.ant.types.StoreResource; | ||
import org.dita.dost.util.Constants; | ||
import org.dita.dost.util.FileUtils; | ||
import org.dita.dost.util.Job; | ||
|
@@ -58,9 +59,9 @@ private Collection<Resource> getResults() { | |
for (final FileInfo f : job.getFileInfo(this::filter)) { | ||
log("Scanning for " + f.file.getPath(), Project.MSG_VERBOSE); | ||
final File tempFile = new File(job.tempDir, f.file.getPath()); | ||
if (tempFile.exists()) { | ||
if (job.getStore().exists(tempFile.toURI())) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All cases where we used to test file existance with |
||
log("Found temporary directory file " + tempFile, Project.MSG_VERBOSE); | ||
res.add(new FileResource(job.tempDir, f.file.toString())); | ||
res.add(new StoreResource(job, job.tempDirURI.relativize(f.uri))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Custom Ant resource that can read from any |
||
} else if (f.src.getScheme().equals("file")) { | ||
final File srcFile = new File(f.src); | ||
if (srcFile.exists()) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -145,6 +145,7 @@ protected void processMap(final URI map) { | |
logger.debug("Writing " + currentFile); | ||
|
||
try { | ||
doc.setDocumentURI(currentFile.toString()); | ||
job.getStore().writeDocument(doc, currentFile); | ||
} catch (final IOException e) { | ||
logger.error("Failed to serialize " + map.toString() + ": " + e.getMessage(), e); | ||
|
@@ -374,10 +375,6 @@ private void generateCopies(final Element topicref, final List<FilterUtils> filt | |
writer.setCurrentFile(dstAbsUri); | ||
final List<XMLFilter> pipe = singletonList(writer); | ||
|
||
final File dstDirUri = new File(dstAbsUri.resolve(".")); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to create directories into temporary directory in disk, the |
||
if (!dstDirUri.exists() && !dstDirUri.mkdirs()) { | ||
logger.error("Failed to create directory " + dstDirUri); | ||
} | ||
try { | ||
job.getStore().transform(srcAbsUri, dstAbsUri, pipe); | ||
} catch (final DITAOTException e) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,6 @@ | |
*/ | ||
package org.dita.dost.module; | ||
|
||
import net.sf.saxon.s9api.Serializer; | ||
import org.dita.dost.exception.DITAOTException; | ||
import org.dita.dost.exception.DITAOTXMLErrorHandler; | ||
import org.dita.dost.module.reader.TempFileNameScheme; | ||
|
@@ -121,11 +120,6 @@ private void processFile(final FileInfo f) { | |
return; | ||
} | ||
outputFile = new File(job.tempDir, f.file.getPath()); | ||
final File outputDir = outputFile.getParentFile(); | ||
if (!outputDir.exists() && !outputDir.mkdirs()) { | ||
logger.error("Failed to create output directory " + outputDir.getAbsolutePath()); | ||
return; | ||
} | ||
logger.info("Processing " + f.src + " to " + outputFile.toURI()); | ||
|
||
final Set<URI> schemaSet = dic.get(f.uri); | ||
|
@@ -167,9 +161,9 @@ private void processFile(final FileInfo f) { | |
|
||
in = new InputSource(f.src.toString()); | ||
|
||
final Serializer result = processor.newSerializer(outputFile); | ||
final ContentHandler result = job.getStore().getContentHandler(outputFile.toURI()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of manually creating a S9api |
||
|
||
xmlSource.setContentHandler(result.getContentHandler()); | ||
xmlSource.setContentHandler(result); | ||
xmlSource.parse(in); | ||
} catch (final RuntimeException e) { | ||
throw e; | ||
|
@@ -476,10 +470,6 @@ private Element searchForKey(final Element root, final String key) { | |
* @throws DITAOTException if generation fails | ||
*/ | ||
private void generateScheme(final File filename, final Document root) throws DITAOTException { | ||
final File p = filename.getParentFile(); | ||
if (!p.exists() && !p.mkdirs()) { | ||
throw new DITAOTException("Failed to make directory " + p.getAbsolutePath()); | ||
} | ||
try { | ||
job.getStore().writeDocument(root, filename.toURI()); | ||
} catch (final IOException e) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ | |
import org.dita.dost.exception.DITAOTException; | ||
import org.dita.dost.pipeline.AbstractPipelineInput; | ||
import org.dita.dost.pipeline.AbstractPipelineOutput; | ||
import org.dita.dost.util.CatalogUtils; | ||
import org.dita.dost.util.DelegatingURIResolver; | ||
import org.dita.dost.util.Job.FileInfo; | ||
import org.dita.dost.util.XMLUtils; | ||
import org.dita.dost.writer.DitaLinksWriter; | ||
|
@@ -60,6 +62,8 @@ public AbstractPipelineOutput execute(final AbstractPipelineInput input) throws | |
|
||
final XsltTransformer transformer = xsltCompiler.compile(new StreamSource(styleFile)).load(); | ||
transformer.setErrorListener(toErrorListener(logger)); | ||
transformer.setURIResolver(new DelegatingURIResolver(CatalogUtils.getCatalogResolver(), job.getStore())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
if (input.getAttribute("include.rellinks") != null) { | ||
transformer.setParameter(new QName("include.rellinks"), | ||
XdmItem.makeValue(input.getAttribute("include.rellinks"))); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Store
XMLUtils
into Ant project reference, because we want to reuse the same SaxonProcessor
everywhere. This allows reusing the same name pool etc. that's needed for in-memoryStore
implementation.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious -- in the past we had memory crashes in steps where Saxon ended up reading 5,000 or 10,000 topics (like the
mappull
step). Is reusing the same SaxonProcessor
going to have any impact on that sort of case, either better or worse, or is there no change?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the
Processor
class is what maintains the name pool etc. TheXsltExecutable
is the one that would be a problem and we don't reuse it by default.