You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2022/09/02 08:57:29 UTC

[jena] branch main updated: GH-1500: Write backup file atomically in backup

This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new 9d0837c607 GH-1500: Write backup file atomically in backup
     new db8b12b740 Merge pull request #1513 from afs/gh-1501-backup
9d0837c607 is described below

commit 9d0837c60775ec041a62b0ddc79964fdcc5d943a
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Wed Aug 31 22:43:14 2022 +0100

    GH-1500: Write backup file atomically in backup
---
 .../java/org/apache/jena/fuseki/mgt/Backup.java    | 56 ++++++++++------------
 1 file changed, 26 insertions(+), 30 deletions(-)

diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/Backup.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
index 5a49653278..b032d0dda2 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
@@ -18,13 +18,15 @@
 
 package org.apache.jena.fuseki.mgt;
 
-import java.io.*;
+import java.io.BufferedOutputStream;
+import java.io.OutputStream;
+import java.nio.file.Path;
 import java.util.Collections;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.zip.GZIPOutputStream;
 
-import org.apache.jena.atlas.io.IO;
+import org.apache.jena.atlas.io.IOX;
 import org.apache.jena.atlas.lib.DateTimeUtils;
 import org.apache.jena.atlas.logging.FmtLog;
 import org.apache.jena.fuseki.Fuseki;
@@ -72,18 +74,22 @@ public class Backup
         Txn.executeRead(transactional, ()->backup(dsg, backupfile));
     }
 
-    /** Perform a backup.
+    // This seems to achieve about the same as "gzip -6"
+    // It's not too expensive in elapsed time but it's not
+    // zero cost. GZip, large buffer.
+    private static final boolean USE_GZIP = true;
+
+    /**
+     * Perform a backup.
      *
      * @see #backup(Transactional, DatasetGraph, String)
      */
+
     private static void backup(DatasetGraph dsg, String backupfile) {
         if (dsg == null) {
             throw new FusekiException("No dataset provided to backup");
         }
 
-        if ( !backupfile.endsWith(".nq") )
-            backupfile = backupfile + ".nq";
-
         // Per backup source lock.
         synchronized(activeBackups) {
             // Atomically check-and-set
@@ -92,32 +98,22 @@ public class Backup
             activeBackups.add(dsg);
         }
 
-        OutputStream out = null;
+        if ( !backupfile.endsWith(".nq") )
+            backupfile = backupfile + ".nq";
+
+        if ( USE_GZIP )
+            backupfile = backupfile + ".gz";
+
         try {
-            if ( true ) {
-                // This seems to achieve about the same as "gzip -6"
-                // It's not too expensive in elapsed time but it's not
-                // zero cost. GZip, large buffer.
-                out = new FileOutputStream(backupfile + ".gz");
-                out = new GZIPOutputStream(out, 8 * 1024);
-                out = new BufferedOutputStream(out);
-            } else {
-                out = new FileOutputStream(backupfile);
-                out = new BufferedOutputStream(out);
-            }
-            RDFDataMgr.write(out, dsg, Lang.NQUADS);
-            out.close();
-            out = null;
-        } catch (FileNotFoundException e) {
-            FmtLog.warn(Fuseki.serverLog, "File not found: %s", backupfile);
-            throw new FusekiException("File not found: " + backupfile);
-        } catch (IOException e) {
-            IO.exception(e);
+            IOX.safeWrite(Path.of(backupfile), outfile -> {
+                OutputStream out = outfile;
+                if ( USE_GZIP )
+                    out = new GZIPOutputStream(outfile, 8 * 1024);
+                try (OutputStream out2 = new BufferedOutputStream(out)) {
+                    RDFDataMgr.write(out2, dsg, Lang.NQUADS);
+                }
+            });
         } finally {
-            try {
-                if ( out != null )
-                    out.close();
-            } catch (IOException e) { /* ignore */}
             // Remove lock.
             synchronized(activeBackups) {
                 activeBackups.remove(dsg);