From a97a99d138cc36e433f00050c67b80e4aff259f9 Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Mon, 17 Apr 2023 17:28:34 +0300 Subject: [PATCH 01/15] SNRK-48: Add s3 implementation Use common s3 api and '/'-separated keys to simulate directories --- .../kscience/snark/storage/s3/Directory.kt | 41 +++++++++++++++++ .../space/kscience/snark/storage/s3/File.kt | 38 +++++++++++++++ .../space/kscience/snark/storage/s3/Root.kt | 46 +++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Directory.kt create mode 100644 snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/File.kt create mode 100644 snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Root.kt diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Directory.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Directory.kt new file mode 100644 index 0000000..27ece3b --- /dev/null +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Directory.kt @@ -0,0 +1,41 @@ +package space.kscience.snark.storage.s3 + +import aws.sdk.kotlin.services.s3.S3Client +import space.kscience.snark.storage.Directory as Dir +import space.kscience.snark.storage.FileReader +import space.kscience.snark.storage.FileWriter +import java.nio.file.Path + +public class Directory( + private val client: S3Client, + private val bucketName: String, + private val currentDir: String, +) : Dir { + override suspend fun get(filename: String): FileReader = run { + S3FileReader(client, bucketName, "$currentDir/$filename") + } + + override suspend fun create(filename: String, ignoreIfExists: Boolean) { + if (!ignoreIfExists) { + throw IllegalArgumentException("could not check if file exists") + } + } + + override suspend fun put(filename: String): FileWriter = run { + S3FileWriter(client, bucketName, "$currentDir/$filename") + } + + override suspend fun getSubdir(path: Path): Directory = run { + Directory(client, bucketName, "$currentDir/$path") + } + + override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory = run { + if (!ignoreIfExists) { + throw IllegalArgumentException("could not check if directory exists") + } + Directory(client, bucketName, "$currentDir/$dirname") + } + + override fun close() { + } +} \ No newline at end of file diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/File.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/File.kt new file mode 100644 index 0000000..43e872f --- /dev/null +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/File.kt @@ -0,0 +1,38 @@ +package space.kscience.snark.storage.s3 + +import aws.sdk.kotlin.services.s3.S3Client +import aws.sdk.kotlin.services.s3.model.GetObjectRequest +import aws.sdk.kotlin.services.s3.putObject +import aws.smithy.kotlin.runtime.content.ByteStream +import aws.smithy.kotlin.runtime.content.toByteArray +import space.kscience.snark.storage.FileReader +import space.kscience.snark.storage.FileWriter + +public class S3FileReader(private val client: S3Client, private val bucketName: String, private val fullQualifiedPath: String) : FileReader { + override suspend fun readAll(): ByteArray { + val result = client.getObject(GetObjectRequest{ + bucket = bucketName + key = fullQualifiedPath + }) { + it.body?.toByteArray() ?: ByteArray(0) + } + return result + } + + override fun close() { + } +} + +public class S3FileWriter(private val client: S3Client, private val bucketName: String, private val fullQualifiedPath: String) : FileWriter { + override suspend fun write(bytes: ByteArray) { + client.putObject { + bucket = bucketName + key = fullQualifiedPath + body = ByteStream.fromBytes(bytes) + } + } + + override fun close() { + } + +} \ No newline at end of file diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Root.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Root.kt new file mode 100644 index 0000000..de51731 --- /dev/null +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Root.kt @@ -0,0 +1,46 @@ +package space.kscience.snark.storage.s3 + +import aws.sdk.kotlin.services.s3.* +import space.kscience.snark.storage.Directory as Dir +import space.kscience.snark.storage.FileReader +import space.kscience.snark.storage.FileWriter +import java.io.File +import java.lang.Exception +import java.nio.file.Path + +public class Root(private val client: S3Client) : Dir { + override suspend fun get(filename: String): FileReader { + throw NoSuchFileException(File(filename)) + } + + override suspend fun create(filename: String, ignoreIfExists: Boolean) { + throw IllegalCallerException() + } + + override suspend fun put(filename: String): FileWriter { + throw NoSuchFileException(File(filename)) + } + + override suspend fun getSubdir(path: Path): Directory = try { + val bucketName = path.toString() + client.headBucket { + bucket = bucketName + } + Directory(client, bucketName, "") + } catch (ex: Exception) { + throw java.nio.file.AccessDeniedException(path.toString()).initCause(ex) + } + + override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory = try { + client.createBucket { + bucket = dirname + } + Directory(client, dirname, "") + } catch (ex: Exception) { + throw java.nio.file.AccessDeniedException(dirname).initCause(ex) + } + + override fun close() { + } + +} \ No newline at end of file From 9651ad1cd9a7052a0dc99fe5c05fd51b89911494 Mon Sep 17 00:00:00 2001 From: Anton Belyi Date: Mon, 24 Apr 2023 15:32:29 +0300 Subject: [PATCH 02/15] SNRK-60: slightly changed local driver and added unzip function --- .../snark/storage/local/localDriver.kt | 10 ++++---- .../kscience/snark/storage/unzip/Unzip.kt | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/unzip/Unzip.kt diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/localDriver.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/localDriver.kt index 554faf0..04c78f2 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/localDriver.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/localDriver.kt @@ -15,19 +15,19 @@ public class LocalFile(private val path: String) : FileReader, FileWriter { public class LocalDirectory(private val path: String) : Directory { override fun close() {} - override suspend fun get(filename: String): FileReader = LocalFile("${this.path}/$filename") + override suspend fun get(filename: String): FileReader = LocalFile("${this.path}${File.separator}$filename") override suspend fun create(filename: String, ignoreIfExists: Boolean) { - if (!File(filename).createNewFile() && !ignoreIfExists) { + if (!File("${this.path}${File.separator}$filename").createNewFile() && !ignoreIfExists) { throw UnsupportedOperationException("File already exists") } } - override suspend fun put(filename: String): FileWriter = LocalFile("${this.path}/$filename") + override suspend fun put(filename: String): FileWriter = LocalFile("${this.path}${File.separator}$filename") - override suspend fun getSubdir(dirpath: Path): Directory = LocalDirectory("${this.path}/$dirpath") + override suspend fun getSubdir(dirpath: Path): Directory = LocalDirectory("${this.path}${File.separator}$dirpath") override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory { - if (!File(dirname).mkdir() && !ignoreIfExists) { + if (!File("${this.path}${File.separator}$dirname").mkdir() && !ignoreIfExists) { throw UnsupportedOperationException("File already exists") } return this.getSubdir(File(dirname).toPath()) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/unzip/Unzip.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/unzip/Unzip.kt new file mode 100644 index 0000000..e7aff9c --- /dev/null +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/unzip/Unzip.kt @@ -0,0 +1,24 @@ +package space.kscience.snark.storage.unzip + +import space.kscience.snark.storage.Directory +import java.io.FileInputStream +import java.util.zip.ZipInputStream + +public suspend fun unzip(source_path: String, target: Directory) { + val zis = ZipInputStream(FileInputStream(source_path)) + var zipEntry = zis.nextEntry + while (zipEntry != null) { + if (!zipEntry.isDirectory) { + val filename = zipEntry.name + target.create(filename, true) + val fos = target.put(filename) + val buffer = ByteArray(zipEntry.size.toInt()) + zis.read(buffer) + fos.write(buffer) + fos.close() + } + zipEntry = zis.nextEntry + } + zis.closeEntry() + zis.close() +} \ No newline at end of file From 88510dbba80874e2dd13193220303415fadda715 Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Mon, 24 Apr 2023 00:27:24 +0300 Subject: [PATCH 03/15] SNRK-67: Fix pathes --- .../local/{localDriver.kt => LocalDriver.kt} | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) rename snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/{localDriver.kt => LocalDriver.kt} (64%) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/localDriver.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt similarity index 64% rename from snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/localDriver.kt rename to snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt index 04c78f2..bb76118 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/localDriver.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt @@ -13,23 +13,29 @@ public class LocalFile(private val path: String) : FileReader, FileWriter { override suspend fun write(bytes: ByteArray) = File(this.path).writeBytes(bytes) } -public class LocalDirectory(private val path: String) : Directory { +public class LocalDirectory(private val root: String, private val path: String) : Directory { + private val current = "$root/$path" + + private fun child(child: String): String = "$current/$child" + override fun close() {} - override suspend fun get(filename: String): FileReader = LocalFile("${this.path}${File.separator}$filename") + + override suspend fun get(filename: String): FileReader = LocalFile(child(filename)) override suspend fun create(filename: String, ignoreIfExists: Boolean) { - if (!File("${this.path}${File.separator}$filename").createNewFile() && !ignoreIfExists) { + if (!File(child(filename)).createNewFile() && !ignoreIfExists) { throw UnsupportedOperationException("File already exists") } } - override suspend fun put(filename: String): FileWriter = LocalFile("${this.path}${File.separator}$filename") + override suspend fun put(filename: String): FileWriter = LocalFile(child(filename)) - override suspend fun getSubdir(dirpath: Path): Directory = LocalDirectory("${this.path}${File.separator}$dirpath") + override suspend fun getSubdir(path: Path): Directory = LocalDirectory(root, child(path.toString())) override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory { - if (!File("${this.path}${File.separator}$dirname").mkdir() && !ignoreIfExists) { + val dir = child(dirname) + if (!File(dir).mkdir() && !ignoreIfExists) { throw UnsupportedOperationException("File already exists") } - return this.getSubdir(File(dirname).toPath()) + return this.getSubdir(File(dir).toPath()) } } From 8069ea2f0b441351f761b283a8dc7bc9fd734f61 Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Mon, 24 Apr 2023 00:36:33 +0300 Subject: [PATCH 04/15] SNRK-67: Add top-level function --- .../space/kscience/snark/storage/local/LocalDriver.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt index bb76118..d75db16 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt @@ -6,6 +6,10 @@ import space.kscience.snark.storage.FileWriter import java.io.File import java.nio.file.Path +public fun localStorage(rootPath: Path): Directory { + return LocalDirectory(rootPath, ".") +} + public class LocalFile(private val path: String) : FileReader, FileWriter { override fun close() {} override suspend fun readAll(): ByteArray = File(this.path).readBytes() @@ -13,7 +17,7 @@ public class LocalFile(private val path: String) : FileReader, FileWriter { override suspend fun write(bytes: ByteArray) = File(this.path).writeBytes(bytes) } -public class LocalDirectory(private val root: String, private val path: String) : Directory { +public class LocalDirectory(private val root: Path, path: String) : Directory { private val current = "$root/$path" private fun child(child: String): String = "$current/$child" From b543735628584d689705c26a3145e57cd5563066 Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Mon, 24 Apr 2023 00:37:14 +0300 Subject: [PATCH 05/15] SNRK-67: Make implementation private --- .../kotlin/space/kscience/snark/storage/local/LocalDriver.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt index d75db16..324267c 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt @@ -10,14 +10,14 @@ public fun localStorage(rootPath: Path): Directory { return LocalDirectory(rootPath, ".") } -public class LocalFile(private val path: String) : FileReader, FileWriter { +private class LocalFile(private val path: String) : FileReader, FileWriter { override fun close() {} override suspend fun readAll(): ByteArray = File(this.path).readBytes() override suspend fun write(bytes: ByteArray) = File(this.path).writeBytes(bytes) } -public class LocalDirectory(private val root: Path, path: String) : Directory { +private class LocalDirectory(private val root: Path, path: String) : Directory { private val current = "$root/$path" private fun child(child: String): String = "$current/$child" From 7c6157be96f2a5a3dd247defce596e58398cf0ad Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Mon, 24 Apr 2023 16:35:50 +0300 Subject: [PATCH 06/15] SNRK-67: Use system-specific path separator --- .../kotlin/space/kscience/snark/storage/local/LocalDriver.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt index 324267c..de6708b 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt @@ -18,9 +18,9 @@ private class LocalFile(private val path: String) : FileReader, FileWriter { } private class LocalDirectory(private val root: Path, path: String) : Directory { - private val current = "$root/$path" + private val current = "$root${File.separator}$path" - private fun child(child: String): String = "$current/$child" + private fun child(child: String): String = "$current${File.separator}$child" override fun close() {} From e9eaa0f8c27501432aa5b210e32e0152f2636dc9 Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Mon, 24 Apr 2023 16:53:48 +0300 Subject: [PATCH 07/15] SNRK-67: Use kotlin.io.Path --- .../snark/storage/local/LocalDriver.kt | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt index de6708b..28e9487 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/local/LocalDriver.kt @@ -3,43 +3,50 @@ package space.kscience.snark.storage.local import space.kscience.snark.storage.Directory import space.kscience.snark.storage.FileReader import space.kscience.snark.storage.FileWriter -import java.io.File import java.nio.file.Path +import kotlin.io.path.* public fun localStorage(rootPath: Path): Directory { - return LocalDirectory(rootPath, ".") + return LocalDirectory(rootPath) } -private class LocalFile(private val path: String) : FileReader, FileWriter { +private class LocalFile(private val path: Path) : FileReader, FileWriter { override fun close() {} - override suspend fun readAll(): ByteArray = File(this.path).readBytes() + override suspend fun readAll(): ByteArray = path.readBytes() - override suspend fun write(bytes: ByteArray) = File(this.path).writeBytes(bytes) + override suspend fun write(bytes: ByteArray) = path.writeBytes(bytes) } -private class LocalDirectory(private val root: Path, path: String) : Directory { - private val current = "$root${File.separator}$path" - - private fun child(child: String): String = "$current${File.separator}$child" +private class LocalDirectory(private val path: Path) : Directory { + private fun child(child: String): Path = path / child + private fun child(child: Path): Path = path / child override fun close() {} override suspend fun get(filename: String): FileReader = LocalFile(child(filename)) override suspend fun create(filename: String, ignoreIfExists: Boolean) { - if (!File(child(filename)).createNewFile() && !ignoreIfExists) { - throw UnsupportedOperationException("File already exists") + try { + child(filename).createFile() + } catch (ex: FileAlreadyExistsException) { + if (!ignoreIfExists) { + throw ex + } } } override suspend fun put(filename: String): FileWriter = LocalFile(child(filename)) - override suspend fun getSubdir(path: Path): Directory = LocalDirectory(root, child(path.toString())) + override suspend fun getSubdir(path: Path): Directory = LocalDirectory(child(path)) override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory { val dir = child(dirname) - if (!File(dir).mkdir() && !ignoreIfExists) { - throw UnsupportedOperationException("File already exists") + try { + dir.createDirectory() + } catch (ex: FileAlreadyExistsException) { + if (!ignoreIfExists) { + throw ex + } } - return this.getSubdir(File(dir).toPath()) + return LocalDirectory(dir) } } From d292abc816d0c2f3c803db3386cc9a05b2cfacbd Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Mon, 24 Apr 2023 21:12:21 +0300 Subject: [PATCH 08/15] SNRK-57: Fix internals --- .../s3/{Directory.kt => S3Directory.kt} | 25 ++++++++-------- .../snark/storage/s3/{File.kt => S3File.kt} | 10 ++++--- .../snark/storage/s3/{Root.kt => S3Root.kt} | 30 ++++++++++++++----- 3 files changed, 41 insertions(+), 24 deletions(-) rename snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/{Directory.kt => S3Directory.kt} (58%) rename snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/{File.kt => S3File.kt} (69%) rename snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/{Root.kt => S3Root.kt} (55%) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Directory.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt similarity index 58% rename from snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Directory.kt rename to snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt index 27ece3b..d972fed 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Directory.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt @@ -1,18 +1,19 @@ package space.kscience.snark.storage.s3 import aws.sdk.kotlin.services.s3.S3Client -import space.kscience.snark.storage.Directory as Dir +import space.kscience.snark.storage.Directory import space.kscience.snark.storage.FileReader import space.kscience.snark.storage.FileWriter import java.nio.file.Path +import kotlin.io.path.* -public class Directory( +internal class S3Directory( private val client: S3Client, private val bucketName: String, - private val currentDir: String, -) : Dir { + private val currentDir: Path, +) : Directory { override suspend fun get(filename: String): FileReader = run { - S3FileReader(client, bucketName, "$currentDir/$filename") + S3FileReader(client, bucketName, currentDir / filename) } override suspend fun create(filename: String, ignoreIfExists: Boolean) { @@ -21,19 +22,17 @@ public class Directory( } } - override suspend fun put(filename: String): FileWriter = run { - S3FileWriter(client, bucketName, "$currentDir/$filename") - } + override suspend fun put(filename: String): FileWriter = + S3FileWriter(client, bucketName, currentDir / filename) - override suspend fun getSubdir(path: Path): Directory = run { - Directory(client, bucketName, "$currentDir/$path") - } + override suspend fun getSubdir(path: Path): S3Directory = + S3Directory(client, bucketName, currentDir / path) - override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory = run { + override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): S3Directory = run { if (!ignoreIfExists) { throw IllegalArgumentException("could not check if directory exists") } - Directory(client, bucketName, "$currentDir/$dirname") + S3Directory(client, bucketName, currentDir / dirname) } override fun close() { diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/File.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3File.kt similarity index 69% rename from snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/File.kt rename to snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3File.kt index 43e872f..8255519 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/File.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3File.kt @@ -7,12 +7,14 @@ import aws.smithy.kotlin.runtime.content.ByteStream import aws.smithy.kotlin.runtime.content.toByteArray import space.kscience.snark.storage.FileReader import space.kscience.snark.storage.FileWriter +import java.nio.file.Path +import kotlin.io.path.* -public class S3FileReader(private val client: S3Client, private val bucketName: String, private val fullQualifiedPath: String) : FileReader { +internal class S3FileReader(private val client: S3Client, private val bucketName: String, private val path: Path) : FileReader { override suspend fun readAll(): ByteArray { val result = client.getObject(GetObjectRequest{ bucket = bucketName - key = fullQualifiedPath + key = path.toString() }) { it.body?.toByteArray() ?: ByteArray(0) } @@ -23,11 +25,11 @@ public class S3FileReader(private val client: S3Client, private val bucketName: } } -public class S3FileWriter(private val client: S3Client, private val bucketName: String, private val fullQualifiedPath: String) : FileWriter { +internal class S3FileWriter(private val client: S3Client, private val bucketName: String, private val path: Path) : FileWriter { override suspend fun write(bytes: ByteArray) { client.putObject { bucket = bucketName - key = fullQualifiedPath + key = path.toString() body = ByteStream.fromBytes(bytes) } } diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Root.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt similarity index 55% rename from snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Root.kt rename to snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt index de51731..4625a8c 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/Root.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt @@ -1,20 +1,35 @@ package space.kscience.snark.storage.s3 import aws.sdk.kotlin.services.s3.* -import space.kscience.snark.storage.Directory as Dir +import space.kscience.snark.storage.Directory import space.kscience.snark.storage.FileReader import space.kscience.snark.storage.FileWriter import java.io.File import java.lang.Exception import java.nio.file.Path +import kotlin.io.path.* -public class Root(private val client: S3Client) : Dir { +public fun s3Storage(client: S3Client): Directory { + return S3Root(client) +} + +public fun s3Bucket(client: S3Client, bucket: String): Directory { + return S3Directory(client, bucket, Path("")) +} + +internal fun splitPathIntoBucketAndPath(path: Path): Pair { + val bucket = path.getName(0) + val recent = path.relativize(bucket) + return Pair(bucket.toString(), recent) +} + +internal class S3Root(private val client: S3Client) : Directory { override suspend fun get(filename: String): FileReader { throw NoSuchFileException(File(filename)) } override suspend fun create(filename: String, ignoreIfExists: Boolean) { - throw IllegalCallerException() + throw NoSuchFileException(File(filename)) } override suspend fun put(filename: String): FileWriter { @@ -22,20 +37,21 @@ public class Root(private val client: S3Client) : Dir { } override suspend fun getSubdir(path: Path): Directory = try { - val bucketName = path.toString() + val (bucketName, recentPath) = splitPathIntoBucketAndPath(path) client.headBucket { bucket = bucketName } - Directory(client, bucketName, "") + S3Directory(client, bucketName, recentPath) } catch (ex: Exception) { throw java.nio.file.AccessDeniedException(path.toString()).initCause(ex) } override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory = try { + val (bucketName, recentPath) = splitPathIntoBucketAndPath(Path(dirname)) client.createBucket { - bucket = dirname + bucket = bucketName } - Directory(client, dirname, "") + S3Directory(client, bucketName, recentPath) } catch (ex: Exception) { throw java.nio.file.AccessDeniedException(dirname).initCause(ex) } From 256fb167483172b13eef2c694997bb9c26b3b014 Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Mon, 24 Apr 2023 21:45:42 +0300 Subject: [PATCH 09/15] SNRK-57: Pretty exceptions --- .../space/kscience/snark/storage/s3/S3Directory.kt | 8 ++++---- .../space/kscience/snark/storage/s3/S3Root.kt | 14 ++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt index d972fed..4ca0587 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt @@ -28,12 +28,12 @@ internal class S3Directory( override suspend fun getSubdir(path: Path): S3Directory = S3Directory(client, bucketName, currentDir / path) - override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): S3Directory = run { + override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): S3Directory = if (!ignoreIfExists) { - throw IllegalArgumentException("could not check if directory exists") + TODO("could not check if directory exists") + } else { + S3Directory(client, bucketName, currentDir / dirname) } - S3Directory(client, bucketName, currentDir / dirname) - } override fun close() { } diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt index 4625a8c..14f18bd 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt @@ -9,13 +9,11 @@ import java.lang.Exception import java.nio.file.Path import kotlin.io.path.* -public fun s3Storage(client: S3Client): Directory { - return S3Root(client) -} +public fun s3Storage(client: S3Client): Directory = + S3Root(client) -public fun s3Bucket(client: S3Client, bucket: String): Directory { - return S3Directory(client, bucket, Path("")) -} +public fun s3Bucket(client: S3Client, bucket: String): Directory = + S3Directory(client, bucket, Path("")) internal fun splitPathIntoBucketAndPath(path: Path): Pair { val bucket = path.getName(0) @@ -43,7 +41,7 @@ internal class S3Root(private val client: S3Client) : Directory { } S3Directory(client, bucketName, recentPath) } catch (ex: Exception) { - throw java.nio.file.AccessDeniedException(path.toString()).initCause(ex) + throw AccessDeniedException(path.toFile(), reason = ex.message) } override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory = try { @@ -53,7 +51,7 @@ internal class S3Root(private val client: S3Client) : Directory { } S3Directory(client, bucketName, recentPath) } catch (ex: Exception) { - throw java.nio.file.AccessDeniedException(dirname).initCause(ex) + throw AccessDeniedException(File(dirname), reason = ex.message) } override fun close() { From 52772cde7d3459857715aebbdbfe9b201d7043fe Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Fri, 28 Apr 2023 16:59:11 +0300 Subject: [PATCH 10/15] SNRK-57: Remove `run` --- .../main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt index 4ca0587..2cdc8fd 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt @@ -12,9 +12,8 @@ internal class S3Directory( private val bucketName: String, private val currentDir: Path, ) : Directory { - override suspend fun get(filename: String): FileReader = run { + override suspend fun get(filename: String): FileReader = S3FileReader(client, bucketName, currentDir / filename) - } override suspend fun create(filename: String, ignoreIfExists: Boolean) { if (!ignoreIfExists) { From f71e5a3f1ababf8b12c34c589f28b036daf2a29b Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Fri, 28 Apr 2023 17:07:54 +0300 Subject: [PATCH 11/15] SNRK-57: Format file --- .../space/kscience/snark/storage/s3/S3Directory.kt | 2 +- .../kotlin/space/kscience/snark/storage/s3/S3Root.kt | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt index 2cdc8fd..ed2c743 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Directory.kt @@ -17,7 +17,7 @@ internal class S3Directory( override suspend fun create(filename: String, ignoreIfExists: Boolean) { if (!ignoreIfExists) { - throw IllegalArgumentException("could not check if file exists") + TODO("could not check if file exists") } } diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt index 14f18bd..3ab1a68 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt @@ -17,8 +17,8 @@ public fun s3Bucket(client: S3Client, bucket: String): Directory = internal fun splitPathIntoBucketAndPath(path: Path): Pair { val bucket = path.getName(0) - val recent = path.relativize(bucket) - return Pair(bucket.toString(), recent) + val filePath = path.relativize(bucket) + return Pair(bucket.toString(), filePath) } internal class S3Root(private val client: S3Client) : Directory { @@ -35,21 +35,21 @@ internal class S3Root(private val client: S3Client) : Directory { } override suspend fun getSubdir(path: Path): Directory = try { - val (bucketName, recentPath) = splitPathIntoBucketAndPath(path) + val (bucketName, filePath) = splitPathIntoBucketAndPath(path) client.headBucket { bucket = bucketName } - S3Directory(client, bucketName, recentPath) + S3Directory(client, bucketName, filePath) } catch (ex: Exception) { throw AccessDeniedException(path.toFile(), reason = ex.message) } override suspend fun createSubdir(dirname: String, ignoreIfExists: Boolean): Directory = try { - val (bucketName, recentPath) = splitPathIntoBucketAndPath(Path(dirname)) + val (bucketName, filePath) = splitPathIntoBucketAndPath(Path(dirname)) client.createBucket { bucket = bucketName } - S3Directory(client, bucketName, recentPath) + S3Directory(client, bucketName, filePath) } catch (ex: Exception) { throw AccessDeniedException(File(dirname), reason = ex.message) } From a672db082f25814a9157c8e54aa2610d81fd545c Mon Sep 17 00:00:00 2001 From: Kirill Grachev Date: Fri, 28 Apr 2023 17:37:39 +0300 Subject: [PATCH 12/15] SNRK-57: Remove `File` from sources --- .../kotlin/space/kscience/snark/storage/s3/S3Root.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt index 3ab1a68..3f0037c 100644 --- a/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt +++ b/snark-storage-driver/src/main/kotlin/space/kscience/snark/storage/s3/S3Root.kt @@ -4,7 +4,6 @@ import aws.sdk.kotlin.services.s3.* import space.kscience.snark.storage.Directory import space.kscience.snark.storage.FileReader import space.kscience.snark.storage.FileWriter -import java.io.File import java.lang.Exception import java.nio.file.Path import kotlin.io.path.* @@ -23,15 +22,15 @@ internal fun splitPathIntoBucketAndPath(path: Path): Pair { internal class S3Root(private val client: S3Client) : Directory { override suspend fun get(filename: String): FileReader { - throw NoSuchFileException(File(filename)) + throw NoSuchFileException(Path(filename).toFile()) } override suspend fun create(filename: String, ignoreIfExists: Boolean) { - throw NoSuchFileException(File(filename)) + throw NoSuchFileException(Path(filename).toFile()) } override suspend fun put(filename: String): FileWriter { - throw NoSuchFileException(File(filename)) + throw NoSuchFileException(Path(filename).toFile()) } override suspend fun getSubdir(path: Path): Directory = try { @@ -51,7 +50,7 @@ internal class S3Root(private val client: S3Client) : Directory { } S3Directory(client, bucketName, filePath) } catch (ex: Exception) { - throw AccessDeniedException(File(dirname), reason = ex.message) + throw AccessDeniedException(Path(dirname).toFile(), reason = ex.message) } override fun close() { From 6c9a08a14a1acc031fd42c6220c3224597bcf72e Mon Sep 17 00:00:00 2001 From: "liubar.pa" Date: Thu, 4 May 2023 02:18:37 +0300 Subject: [PATCH 13/15] SNRK-70: better test naming --- snark-document-builder/src/test/kotlin/DocumentBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snark-document-builder/src/test/kotlin/DocumentBuilder.kt b/snark-document-builder/src/test/kotlin/DocumentBuilder.kt index bc019e3..6c16cc9 100644 --- a/snark-document-builder/src/test/kotlin/DocumentBuilder.kt +++ b/snark-document-builder/src/test/kotlin/DocumentBuilder.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.runBlocking class SomeTest { @Test - fun testEssential() = runBlocking { + fun justWorks() = runBlocking { buildDocument("../example") } } From 5458bd367740773e0a25f24d638fb679c88ddc23 Mon Sep 17 00:00:00 2001 From: "liubar.pa" Date: Thu, 4 May 2023 02:30:03 +0300 Subject: [PATCH 14/15] SNRK-70: better arguments in buildDocument --- snark-document-builder/src/main/kotlin/DocumentBuilder.kt | 4 +--- snark-document-builder/src/test/kotlin/DocumentBuilder.kt | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/snark-document-builder/src/main/kotlin/DocumentBuilder.kt b/snark-document-builder/src/main/kotlin/DocumentBuilder.kt index 551ba70..1b1ebe5 100644 --- a/snark-document-builder/src/main/kotlin/DocumentBuilder.kt +++ b/snark-document-builder/src/main/kotlin/DocumentBuilder.kt @@ -2,13 +2,11 @@ package documentBuilder import com.fasterxml.jackson.core.io.BigDecimalParser import space.kscience.snark.storage.* -import space.kscience.snark.storage.local.LocalDirectory import java.nio.file.Path val DEFAULT_DOCUMENT_ROOT = "main.md" -public suspend fun buildDocument(documentPath: String) { - val documentDirectory: Directory = LocalDirectory(documentPath) +public suspend fun buildDocument(documentDirectory: Directory) { val documentRoot = documentDirectory.get(DEFAULT_DOCUMENT_ROOT) TODO() diff --git a/snark-document-builder/src/test/kotlin/DocumentBuilder.kt b/snark-document-builder/src/test/kotlin/DocumentBuilder.kt index 6c16cc9..95c6002 100644 --- a/snark-document-builder/src/test/kotlin/DocumentBuilder.kt +++ b/snark-document-builder/src/test/kotlin/DocumentBuilder.kt @@ -6,6 +6,6 @@ import kotlinx.coroutines.runBlocking class SomeTest { @Test fun justWorks() = runBlocking { - buildDocument("../example") + // buildDocument(Directory("../example")) } } From dee40ecdcc699f33fa64e4bc7c92b0251845f264 Mon Sep 17 00:00:00 2001 From: "liubar.pa" Date: Thu, 4 May 2023 02:33:58 +0300 Subject: [PATCH 15/15] SNRK-70: visibility of DEFAULT_DICUMENT_ROOT is specified --- snark-document-builder/src/main/kotlin/DocumentBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snark-document-builder/src/main/kotlin/DocumentBuilder.kt b/snark-document-builder/src/main/kotlin/DocumentBuilder.kt index 1b1ebe5..fe96f5e 100644 --- a/snark-document-builder/src/main/kotlin/DocumentBuilder.kt +++ b/snark-document-builder/src/main/kotlin/DocumentBuilder.kt @@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.io.BigDecimalParser import space.kscience.snark.storage.* import java.nio.file.Path -val DEFAULT_DOCUMENT_ROOT = "main.md" +private val DEFAULT_DOCUMENT_ROOT = "main.md" public suspend fun buildDocument(documentDirectory: Directory) { val documentRoot = documentDirectory.get(DEFAULT_DOCUMENT_ROOT)