From 791437a905bf5cb6ce61aecdc222dd4baaf78939 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Thu, 5 Dec 2019 07:57:47 +0100 Subject: [PATCH] Use copy on write in repository db --- .../scm/repository/xml/MetadataStore.java | 6 +++- .../scm/repository/xml/PathDatabase.java | 36 +++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/MetadataStore.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/MetadataStore.java index f22180ff9a..3a81f54fb2 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/MetadataStore.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/MetadataStore.java @@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory; import sonia.scm.ContextEntry; import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.Repository; +import sonia.scm.store.CopyOnWrite; import sonia.scm.store.StoreConstants; import sonia.scm.update.UpdateStepRepositoryMetadataAccess; @@ -43,7 +44,10 @@ public class MetadataStore implements UpdateStepRepositoryMetadataAccess { try { Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); - marshaller.marshal(repository, resolveDataPath(path).toFile()); + CopyOnWrite.withTemporaryFile( + temp -> marshaller.marshal(repository, temp.toFile()), + resolveDataPath(path) + ); } catch (JAXBException ex) { throw new InternalRepositoryException(repository, "failed write repository metadata", ex); } diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/PathDatabase.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/PathDatabase.java index 70698aed59..c895b69840 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/PathDatabase.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/PathDatabase.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.ContextEntry; import sonia.scm.repository.InternalRepositoryException; +import sonia.scm.store.CopyOnWrite; import sonia.scm.xml.IndentXMLStreamWriter; import sonia.scm.xml.XmlStreams; @@ -40,23 +41,28 @@ class PathDatabase { ensureParentDirectoryExists(); LOG.trace("write repository path database to {}", storePath); - try (IndentXMLStreamWriter writer = XmlStreams.createWriter(storePath)) { - writer.writeStartDocument(ENCODING, VERSION); + CopyOnWrite.withTemporaryFile( + temp -> { + try (IndentXMLStreamWriter writer = XmlStreams.createWriter(temp)) { + writer.writeStartDocument(ENCODING, VERSION); - writeRepositoriesStart(writer, creationTime, lastModified); - for (Map.Entry e : pathDatabase.entrySet()) { - writeRepository(writer, e.getKey(), e.getValue()); - } - writer.writeEndElement(); + writeRepositoriesStart(writer, creationTime, lastModified); + for (Map.Entry e : pathDatabase.entrySet()) { + writeRepository(writer, e.getKey(), e.getValue()); + } + writer.writeEndElement(); - writer.writeEndDocument(); - } catch (XMLStreamException | IOException ex) { - throw new InternalRepositoryException( - ContextEntry.ContextBuilder.entity(Path.class, storePath.toString()).build(), - "failed to write repository path database", - ex - ); - } + writer.writeEndDocument(); + } catch (XMLStreamException | IOException ex) { + throw new InternalRepositoryException( + ContextEntry.ContextBuilder.entity(Path.class, storePath.toString()).build(), + "failed to write repository path database", + ex + ); + } + }, + storePath + ); } private void ensureParentDirectoryExists() {