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/04/03 10:20:26 UTC
[jena] branch main updated: GH-1225: Safe write of spatial index
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 36f985b GH-1225: Safe write of spatial index
new 186a071 Merge pull request #1238 from afs/safe-write
36f985b is described below
commit 36f985b13d4965da158403e9bbafc8e76e287b66
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Sat Mar 26 14:34:26 2022 +0000
GH-1225: Safe write of spatial index
---
.../main/java/org/apache/jena/atlas/io/IOX.java | 24 +++++++++++
.../jena/geosparql/spatial/SpatialIndex.java | 49 ++++++++++------------
2 files changed, 45 insertions(+), 28 deletions(-)
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java
index 181e8e4..75f0731 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java
@@ -104,6 +104,20 @@ public class IOX {
} catch(IOException ex) { throw IOX.exception(ex); }
}
+ /** Write a file safely, but allow system to use copy-delete if the chnage can not be done atomically.
+ * Prefer {@link #safeWrite} which requires an atomic move.
+ */
+ public static boolean safeWriteOrCopy(Path file, Path tmpFile, IOConsumer<OutputStream> writerAction) {
+ try {
+ try(OutputStream out = new BufferedOutputStream(Files.newOutputStream(tmpFile)) ) {
+ writerAction.actionEx(out);
+ }
+ moveAllowCopy(tmpFile, file);
+ return true;
+ } catch(IOException ex) { throw IOX.exception(ex); }
+ }
+
+
/** Delete a file. */
public static void delete(Path path) {
try { Files.delete(path); }
@@ -122,6 +136,16 @@ public class IOX {
}
}
+ /** Move a file, allowing the system to copy-delete it if it can not be moved atomically. */
+ public static void moveAllowCopy(Path src, Path dst) {
+ try { Files.move(src, dst); }
+ catch (IOException ex) {
+ FmtLog.error(IOX.class, ex, "IOException moving %s to %s", src, dst);
+ throw IOX.exception(ex);
+ }
+ }
+
+
public static void deleteAll(String start) {
deleteAll(Paths.get(start));
}
diff --git a/jena-geosparql/src/main/java/org/apache/jena/geosparql/spatial/SpatialIndex.java b/jena-geosparql/src/main/java/org/apache/jena/geosparql/spatial/SpatialIndex.java
index 952ca1f..63f48f2 100644
--- a/jena-geosparql/src/main/java/org/apache/jena/geosparql/spatial/SpatialIndex.java
+++ b/jena-geosparql/src/main/java/org/apache/jena/geosparql/spatial/SpatialIndex.java
@@ -17,19 +17,14 @@
*/
package org.apache.jena.geosparql.spatial;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
+import java.io.*;
import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import org.apache.commons.io.FileUtils;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+
+import org.apache.jena.atlas.RuntimeIOException;
+import org.apache.jena.atlas.io.IOX;
import org.apache.jena.geosparql.configuration.GeoSPARQLOperations;
import org.apache.jena.geosparql.implementation.GeometryWrapper;
import org.apache.jena.geosparql.implementation.SRSInfo;
@@ -40,14 +35,7 @@ import org.apache.jena.geosparql.implementation.vocabulary.SpatialExtension;
import org.apache.jena.query.Dataset;
import org.apache.jena.query.DatasetFactory;
import org.apache.jena.query.ReadWrite;
-import org.apache.jena.rdf.model.Literal;
-import org.apache.jena.rdf.model.Model;
-import org.apache.jena.rdf.model.NodeIterator;
-import org.apache.jena.rdf.model.RDFNode;
-import org.apache.jena.rdf.model.ResIterator;
-import org.apache.jena.rdf.model.Resource;
-import org.apache.jena.rdf.model.Statement;
-import org.apache.jena.rdf.model.StmtIterator;
+import org.apache.jena.rdf.model.*;
import org.apache.jena.sparql.engine.ExecutionContext;
import org.apache.jena.sparql.util.Context;
import org.apache.jena.sparql.util.Symbol;
@@ -534,20 +522,25 @@ public class SpatialIndex {
if (spatialIndexFile != null) {
LOGGER.info("Saving Spatial Index - Started: {}", spatialIndexFile.getAbsolutePath());
SpatialIndexStorage storage = new SpatialIndexStorage(spatialIndexItems, srsURI);
- File file;
+ String filename = spatialIndexFile.getAbsolutePath();
+ Path file = Path.of(filename);
+ Path tmpFile = IOX.uniqueDerivedPath(file, null);
try {
- file = File.createTempFile("spatial_index", null);
- file.deleteOnExit();
- try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file))) {
- out.writeObject(storage);
- FileUtils.copyFile(file, spatialIndexFile);
- }
+ Files.deleteIfExists(file);
} catch (IOException ex) {
+ throw new SpatialIndexException("Failed to delete file: " + ex.getMessage());
+ }
+ try {
+ IOX.safeWriteOrCopy(file, tmpFile,
+ out->{
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(storage);
+ });
+ } catch (RuntimeIOException ex) {
throw new SpatialIndexException("Save Exception: " + ex.getMessage());
} finally {
LOGGER.info("Saving Spatial Index - Completed: {}", spatialIndexFile.getAbsolutePath());
}
}
}
-
}