forked from openrs2/openrs2
parent
e0a2df889b
commit
6aea0cfc8e
@ -0,0 +1,91 @@ |
|||||||
|
package org.openrs2.cache |
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf |
||||||
|
import java.nio.file.attribute.FileTime |
||||||
|
import java.time.Instant |
||||||
|
import java.util.zip.Deflater |
||||||
|
import java.util.zip.ZipEntry |
||||||
|
import java.util.zip.ZipOutputStream |
||||||
|
|
||||||
|
/** |
||||||
|
* A specialised [Store] implementation that writes a cache in the |
||||||
|
* [FlatFileStore] format to a [ZipOutputStream]. |
||||||
|
* |
||||||
|
* The cache is not buffered to disk. |
||||||
|
* |
||||||
|
* This implementation only supports the [create] and [write] methods. All |
||||||
|
* other methods throw [UnsupportedOperationException]. |
||||||
|
* |
||||||
|
* It is only intended for use by the cache archiving service's web interface. |
||||||
|
*/ |
||||||
|
public class FlatFileStoreZipWriter( |
||||||
|
private val out: ZipOutputStream, |
||||||
|
private val prefix: String = "cache/", |
||||||
|
level: Int = Deflater.BEST_COMPRESSION, |
||||||
|
timestamp: Instant = Instant.EPOCH |
||||||
|
) : Store { |
||||||
|
private val timestamp = FileTime.from(timestamp) |
||||||
|
|
||||||
|
init { |
||||||
|
out.setLevel(level) |
||||||
|
} |
||||||
|
|
||||||
|
private fun createZipEntry(name: String): ZipEntry { |
||||||
|
val entry = ZipEntry(prefix + name) |
||||||
|
entry.creationTime = timestamp |
||||||
|
entry.lastAccessTime = timestamp |
||||||
|
entry.lastModifiedTime = timestamp |
||||||
|
return entry |
||||||
|
} |
||||||
|
|
||||||
|
override fun exists(archive: Int): Boolean { |
||||||
|
throw UnsupportedOperationException() |
||||||
|
} |
||||||
|
|
||||||
|
override fun exists(archive: Int, group: Int): Boolean { |
||||||
|
throw UnsupportedOperationException() |
||||||
|
} |
||||||
|
|
||||||
|
override fun list(): List<Int> { |
||||||
|
throw UnsupportedOperationException() |
||||||
|
} |
||||||
|
|
||||||
|
override fun list(archive: Int): List<Int> { |
||||||
|
throw UnsupportedOperationException() |
||||||
|
} |
||||||
|
|
||||||
|
override fun create(archive: Int) { |
||||||
|
require(archive in 0..Store.MAX_ARCHIVE) |
||||||
|
|
||||||
|
out.putNextEntry(createZipEntry("$archive/")) |
||||||
|
} |
||||||
|
|
||||||
|
override fun read(archive: Int, group: Int): ByteBuf { |
||||||
|
throw UnsupportedOperationException() |
||||||
|
} |
||||||
|
|
||||||
|
override fun write(archive: Int, group: Int, buf: ByteBuf) { |
||||||
|
require(archive in 0..Store.MAX_ARCHIVE) |
||||||
|
require(group >= 0) |
||||||
|
require(buf.readableBytes() <= Store.MAX_GROUP_SIZE) |
||||||
|
|
||||||
|
out.putNextEntry(createZipEntry("$archive/$group.dat")) |
||||||
|
buf.readBytes(out, buf.readableBytes()) |
||||||
|
} |
||||||
|
|
||||||
|
override fun remove(archive: Int) { |
||||||
|
throw UnsupportedOperationException() |
||||||
|
} |
||||||
|
|
||||||
|
override fun remove(archive: Int, group: Int) { |
||||||
|
throw UnsupportedOperationException() |
||||||
|
} |
||||||
|
|
||||||
|
override fun flush() { |
||||||
|
out.flush() |
||||||
|
} |
||||||
|
|
||||||
|
override fun close() { |
||||||
|
out.close() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,125 @@ |
|||||||
|
package org.openrs2.cache |
||||||
|
|
||||||
|
import com.google.common.jimfs.Configuration |
||||||
|
import com.google.common.jimfs.Jimfs |
||||||
|
import io.netty.buffer.Unpooled |
||||||
|
import org.openrs2.buffer.copiedBuffer |
||||||
|
import org.openrs2.buffer.use |
||||||
|
import org.openrs2.util.io.recursiveEquals |
||||||
|
import java.io.OutputStream |
||||||
|
import java.nio.file.Files |
||||||
|
import java.nio.file.Path |
||||||
|
import java.util.zip.ZipOutputStream |
||||||
|
import kotlin.test.Test |
||||||
|
import kotlin.test.assertFailsWith |
||||||
|
import kotlin.test.assertTrue |
||||||
|
|
||||||
|
public class FlatFileStoreZipWriterTest { |
||||||
|
@Test |
||||||
|
fun testBounds() { |
||||||
|
FlatFileStoreZipWriter(ZipOutputStream(OutputStream.nullOutputStream())).use { store -> |
||||||
|
// create |
||||||
|
assertFailsWith<IllegalArgumentException> { |
||||||
|
store.create(-1) |
||||||
|
} |
||||||
|
|
||||||
|
store.create(0) |
||||||
|
store.create(1) |
||||||
|
store.create(254) |
||||||
|
store.create(255) |
||||||
|
|
||||||
|
assertFailsWith<IllegalArgumentException> { |
||||||
|
store.create(256) |
||||||
|
} |
||||||
|
|
||||||
|
// write archive |
||||||
|
assertFailsWith<IllegalArgumentException> { |
||||||
|
store.write(-1, 0, Unpooled.EMPTY_BUFFER) |
||||||
|
} |
||||||
|
|
||||||
|
store.write(0, 0, Unpooled.EMPTY_BUFFER) |
||||||
|
store.write(1, 0, Unpooled.EMPTY_BUFFER) |
||||||
|
store.write(254, 0, Unpooled.EMPTY_BUFFER) |
||||||
|
store.write(255, 0, Unpooled.EMPTY_BUFFER) |
||||||
|
|
||||||
|
assertFailsWith<IllegalArgumentException> { |
||||||
|
store.write(256, 0, Unpooled.EMPTY_BUFFER) |
||||||
|
} |
||||||
|
|
||||||
|
// write group |
||||||
|
assertFailsWith<IllegalArgumentException> { |
||||||
|
store.write(0, -1, Unpooled.EMPTY_BUFFER) |
||||||
|
} |
||||||
|
|
||||||
|
store.write(2, 0, Unpooled.EMPTY_BUFFER) |
||||||
|
store.write(2, 1, Unpooled.EMPTY_BUFFER) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun testUnsupported() { |
||||||
|
FlatFileStoreZipWriter(ZipOutputStream(OutputStream.nullOutputStream())).use { store -> |
||||||
|
assertFailsWith<UnsupportedOperationException> { |
||||||
|
store.exists(0) |
||||||
|
} |
||||||
|
|
||||||
|
assertFailsWith<UnsupportedOperationException> { |
||||||
|
store.exists(0, 0) |
||||||
|
} |
||||||
|
|
||||||
|
assertFailsWith<UnsupportedOperationException> { |
||||||
|
store.list() |
||||||
|
} |
||||||
|
|
||||||
|
assertFailsWith<UnsupportedOperationException> { |
||||||
|
store.list(0) |
||||||
|
} |
||||||
|
|
||||||
|
assertFailsWith<UnsupportedOperationException> { |
||||||
|
store.read(0, 0) |
||||||
|
} |
||||||
|
|
||||||
|
assertFailsWith<UnsupportedOperationException> { |
||||||
|
store.remove(0) |
||||||
|
} |
||||||
|
|
||||||
|
assertFailsWith<UnsupportedOperationException> { |
||||||
|
store.remove(0, 0) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun testWrite() { |
||||||
|
Jimfs.newFileSystem(Configuration.forCurrentPlatform()).use { fs -> |
||||||
|
val actual = fs.rootDirectories.first().resolve("zip") |
||||||
|
Files.createDirectories(actual) |
||||||
|
|
||||||
|
Files.newOutputStream(actual.resolve("cache.zip")).use { out -> |
||||||
|
FlatFileStoreZipWriter(ZipOutputStream(out)).use { store -> |
||||||
|
store.create(0) |
||||||
|
|
||||||
|
copiedBuffer("OpenRS2").use { buf -> |
||||||
|
store.write(2, 0, buf) |
||||||
|
} |
||||||
|
|
||||||
|
copiedBuffer("OpenRS2".repeat(100)).use { buf -> |
||||||
|
store.write(2, 65535, buf) |
||||||
|
} |
||||||
|
|
||||||
|
copiedBuffer("OpenRS2".repeat(100)).use { buf -> |
||||||
|
store.write(2, 65536, buf) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
assertTrue(ROOT.recursiveEquals(actual)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private companion object { |
||||||
|
private val ROOT = Path.of( |
||||||
|
FlatFileStoreZipWriterTest::class.java.getResource("flat-file-store-zip").toURI() |
||||||
|
) |
||||||
|
} |
||||||
|
} |
Binary file not shown.
Loading…
Reference in new issue