[Fix] first write files to a temporary path, then rename to actual path

this solves issues where files are not written properly on power failure.
This commit is contained in:
Robert von Burg 2019-05-12 20:18:01 +02:00
parent 3a009a6857
commit ed2526ec95
1 changed files with 24 additions and 10 deletions

View File

@ -50,16 +50,18 @@ public class FileIo {
private static final Logger logger = LoggerFactory.getLogger(FileIo.class);
private final File path;
private final File tmpPath;
public FileIo(File path) {
this.path = path;
this.tmpPath = new File(this.path.getParentFile(), ".tmp_" + this.path.getName());
}
public <T> void writeSax(PersistenceContext<T> ctx) {
XMLStreamWriter writer = null;
XMLStreamWriter writer;
try {
try (FileWriter fileWriter = new FileWriter(this.path);) {
try (FileWriter fileWriter = new FileWriter(this.tmpPath)) {
XMLOutputFactory factory = XMLOutputFactory.newInstance();
writer = factory.createXMLStreamWriter(fileWriter);
@ -78,9 +80,16 @@ public class FileIo {
writer.flush();
}
if (!this.tmpPath.renameTo(this.path)) {
throw new IllegalStateException(
"Failed to rename temp file " + this.tmpPath.getName() + " to " + this.path.getAbsolutePath());
}
} catch (FactoryConfigurationError | XMLStreamException | IOException e) {
if (this.path.exists())
this.path.delete();
if (this.tmpPath.exists()) {
if (!this.tmpPath.delete())
logger.error("Failed to delete existing temp file " + this.tmpPath.getAbsolutePath());
}
String msg = "Writing to file failed due to internal error: {0}"; //$NON-NLS-1$
msg = MessageFormat.format(msg, e.getMessage());
throw new XmlException(msg, e);
@ -149,20 +158,25 @@ public class FileIo {
// transformer.setOutputProperty("{http://xml.apache.org/xalan}line-separator", "\t");
// Transform to file
StreamResult result = new StreamResult(this.path);
StreamResult result = new StreamResult(this.tmpPath);
Source xmlSource = new DOMSource(document);
transformer.transform(xmlSource, result);
if (logger.isDebugEnabled()) {
String msg = MessageFormat.format("Wrote DOM to {0}", this.path.getAbsolutePath()); //$NON-NLS-1$
String msg = MessageFormat.format("Wrote DOM to {0}", this.tmpPath.getAbsolutePath()); //$NON-NLS-1$
logger.info(msg);
}
if (!this.tmpPath.renameTo(this.path)) {
throw new IllegalStateException(
"Failed to rename temp file " + this.tmpPath.getName() + " to " + this.path.getAbsolutePath());
}
} catch (TransformerFactoryConfigurationError | TransformerException e) {
if (this.path.exists())
this.path.delete();
if (this.tmpPath.exists()) {
if (!this.tmpPath.delete())
logger.error("Failed to delete existing temp file " + this.tmpPath.getAbsolutePath());
}
String msg = "Writing to file failed due to internal error: {0}"; //$NON-NLS-1$
msg = MessageFormat.format(msg, e.getMessage());
throw new XmlException(msg, e);