From 4aa181b91a11301e65ae068df426f077d0a7fce1 Mon Sep 17 00:00:00 2001 From: Graham Date: Sun, 21 Aug 2022 15:22:46 +0100 Subject: [PATCH] Add support for disabling fsync in atomicWrite Sometimes we want to ensure the write is atomic but don't care about durability. Signed-off-by: Graham --- .../org/openrs2/util/io/PathExtensions.kt | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/util/src/main/kotlin/org/openrs2/util/io/PathExtensions.kt b/util/src/main/kotlin/org/openrs2/util/io/PathExtensions.kt index 24645469..b157583d 100644 --- a/util/src/main/kotlin/org/openrs2/util/io/PathExtensions.kt +++ b/util/src/main/kotlin/org/openrs2/util/io/PathExtensions.kt @@ -107,25 +107,36 @@ public inline fun Path.useTempFile( } } -public inline fun Path.atomicWrite(f: (Path) -> T): T { +public inline fun Path.atomicWrite( + sync: Boolean = true, + f: (Path) -> T, +): T { parent.useTempFile(".$fileName", ".tmp") { tempFile -> val result = f(tempFile) - tempFile.fsync() + if (sync) { + tempFile.fsync() + } Files.move(tempFile, this, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING) - try { - parent.fsync() - } catch (ex: IOException) { - // can't fsync directories on (at least) Windows and jimfs + if (sync) { + try { + parent.fsync() + } catch (ex: IOException) { + // can't fsync directories on (at least) Windows and jimfs + } } return result } } -public inline fun Path.useAtomicBufferedWriter(vararg options: OpenOption, f: (BufferedWriter) -> T): T { - return atomicWrite { path -> +public inline fun Path.useAtomicBufferedWriter( + vararg options: OpenOption, + sync: Boolean = true, + f: (BufferedWriter) -> T, +): T { + return atomicWrite(sync) { path -> Files.newBufferedWriter(path, *options).use { writer -> f(writer) } @@ -135,17 +146,22 @@ public inline fun Path.useAtomicBufferedWriter(vararg options: OpenOption, f public inline fun Path.useAtomicBufferedWriter( cs: Charset, vararg options: OpenOption, - f: (BufferedWriter) -> T + sync: Boolean = true, + f: (BufferedWriter) -> T, ): T { - return atomicWrite { path -> + return atomicWrite(sync) { path -> Files.newBufferedWriter(path, cs, *options).use { writer -> f(writer) } } } -public inline fun Path.useAtomicOutputStream(vararg options: OpenOption, f: (OutputStream) -> T): T { - return atomicWrite { path -> +public inline fun Path.useAtomicOutputStream( + vararg options: OpenOption, + sync: Boolean = true, + f: (OutputStream) -> T, +): T { + return atomicWrite(sync) { path -> Files.newOutputStream(path, *options).use { output -> f(output) }