Fix legacy DiskStore support

The archive IDs are offset by one in a legacy main_file_cache.dat cache.

Signed-off-by: Graham <gpe@openrs2.org>
Graham 3 years ago
parent b1c3cbc7e3
commit 02f35fd014
  1. 30
      cache/src/main/kotlin/org/openrs2/cache/DiskStore.kt
  2. 56
      cache/src/test/kotlin/org/openrs2/cache/DiskStoreTest.kt
  3. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-legacy/main_file_cache.dat
  4. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-legacy/main_file_cache.idx0
  5. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-overwritten-legacy/main_file_cache.dat
  6. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-overwritten-legacy/main_file_cache.idx0
  7. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-legacy/main_file_cache.dat
  8. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-legacy/main_file_cache.idx0
  9. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-overwritten-legacy/main_file_cache.dat
  10. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-overwritten-legacy/main_file_cache.idx0
  11. BIN
      cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/main_file_cache.dat
  12. 0
      cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/main_file_cache.idx0

@ -30,10 +30,13 @@ public class DiskStore private constructor(
private val data: BufferedFileChannel,
private val musicData: BufferedFileChannel?,
private val indexes: Array<BufferedFileChannel?>,
private val alloc: ByteBufAllocator
private val alloc: ByteBufAllocator,
legacyData: Boolean
) : Store {
private data class IndexEntry(val size: Int, val block: Int)
private val archiveOffset = if (legacyData) 1 else 0
init {
require(indexes.size == Store.MAX_ARCHIVE + 1)
}
@ -194,7 +197,7 @@ public class DiskStore private constructor(
}
val actualNum = tempBuf.readUnsignedShort()
val nextBlock = tempBuf.readUnsignedMedium()
val actualArchive = tempBuf.readUnsignedByte().toInt()
val actualArchive = (tempBuf.readUnsignedByte().toInt() - archiveOffset) and 0xFF
// verify header
when {
@ -317,7 +320,7 @@ public class DiskStore private constructor(
}
val actualNum = tempBuf.readUnsignedShort()
nextBlock = tempBuf.readUnsignedMedium()
val actualArchive = tempBuf.readUnsignedByte().toInt()
val actualArchive = (tempBuf.readUnsignedByte().toInt() - archiveOffset) and 0xFF
if (actualGroup != group || actualNum != num || actualArchive != archive) {
block = 0
@ -371,7 +374,7 @@ public class DiskStore private constructor(
}
val actualNum = tempBuf.readUnsignedShort()
nextNextBlock = tempBuf.readUnsignedMedium()
val actualArchive = tempBuf.readUnsignedByte().toInt()
val actualArchive = (tempBuf.readUnsignedByte().toInt() - archiveOffset) and 0xFF
if (actualGroup != group || actualNum != nextNum || actualArchive != archive) {
nextBlock = 0
@ -403,7 +406,7 @@ public class DiskStore private constructor(
}
tempBuf.writeShort(num)
tempBuf.writeMedium(nextBlock)
tempBuf.writeByte(archive)
tempBuf.writeByte(archive + archiveOffset)
data.write(blockPos, tempBuf, headerSize)
@ -501,10 +504,13 @@ public class DiskStore private constructor(
val js5DataPath = dataPath(root)
val legacyDataPath = legacyDataPath(root)
val dataPath = if (Files.exists(js5DataPath)) {
js5DataPath
} else {
// We check for js5DataPath first as it takes precedence.
val legacyDataFile = !Files.exists(js5DataPath)
val dataPath = if (legacyDataFile) {
legacyDataPath
} else {
js5DataPath
}
val data = BufferedFileChannel(
FileChannel.open(dataPath, READ, WRITE),
@ -539,17 +545,17 @@ public class DiskStore private constructor(
}
}
return DiskStore(root, data, musicData, archives, alloc)
return DiskStore(root, data, musicData, archives, alloc, legacyDataFile)
}
public fun create(
root: Path,
alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT,
legacyDataPath: Boolean = false
legacyDataFile: Boolean = false
): Store {
Files.createDirectories(root)
val dataPath = if (legacyDataPath) {
val dataPath = if (legacyDataFile) {
legacyDataPath(root)
} else {
dataPath(root)
@ -563,7 +569,7 @@ public class DiskStore private constructor(
val archives = Array<BufferedFileChannel?>(Store.MAX_ARCHIVE + 1) { null }
return DiskStore(root, data, null, archives, alloc)
return DiskStore(root, data, null, archives, alloc, legacyDataFile)
}
}
}

@ -507,6 +507,12 @@ class DiskStoreTest {
}
}
readTest("corrupt-first-invalid-archive-legacy") { store ->
assertFailsWith<StoreCorruptException> {
store.read(0, 1).release()
}
}
readTest("corrupt-first-invalid-block-number") { store ->
assertFailsWith<StoreCorruptException> {
store.read(255, 1).release()
@ -537,6 +543,12 @@ class DiskStoreTest {
}
}
readTest("corrupt-second-invalid-archive-legacy") { store ->
assertFailsWith<StoreCorruptException> {
store.read(0, 1).release()
}
}
readTest("corrupt-second-invalid-block-number") { store ->
assertFailsWith<StoreCorruptException> {
store.read(255, 1).release()
@ -587,6 +599,15 @@ class DiskStoreTest {
}
}
overwriteTest(
"corrupt-first-invalid-archive-legacy",
"corrupt-first-invalid-archive-overwritten-legacy"
) { store ->
copiedBuffer("Hello".repeat(300)).use { buf ->
store.write(0, 1, buf)
}
}
overwriteTest("corrupt-first-invalid-block-number", "corrupt-first-invalid-block-number-overwritten") { store ->
copiedBuffer("Hello".repeat(300)).use { buf ->
store.write(255, 1, buf)
@ -617,6 +638,15 @@ class DiskStoreTest {
}
}
overwriteTest(
"corrupt-second-invalid-archive-legacy",
"corrupt-second-invalid-archive-overwritten-legacy"
) { store ->
copiedBuffer("Hello".repeat(300)).use { buf ->
store.write(0, 1, buf)
}
}
overwriteTest(
"corrupt-second-invalid-block-number",
"corrupt-second-invalid-block-number-overwritten"
@ -665,6 +695,14 @@ class DiskStoreTest {
}
}
readTest("corrupt-first-invalid-archive-overwritten-legacy") { store ->
store.read(0, 1).use { actual ->
copiedBuffer("Hello".repeat(300)).use { expected ->
assertEquals(expected, actual)
}
}
}
readTest("corrupt-first-invalid-block-number-overwritten") { store ->
store.read(255, 1).use { actual ->
copiedBuffer("Hello".repeat(300)).use { expected ->
@ -705,6 +743,14 @@ class DiskStoreTest {
}
}
readTest("corrupt-second-invalid-archive-overwritten-legacy") { store ->
store.read(0, 1).use { actual ->
copiedBuffer("Hello".repeat(300)).use { expected ->
assertEquals(expected, actual)
}
}
}
readTest("corrupt-second-invalid-block-number-overwritten") { store ->
store.read(255, 1).use { actual ->
copiedBuffer("Hello".repeat(300)).use { expected ->
@ -762,9 +808,9 @@ class DiskStoreTest {
@Test
fun testCreateLegacyDataFile() {
writeTest("single-block-legacy", legacyDataPath = true) { store ->
writeTest("single-block-legacy", legacyDataFile = true) { store ->
copiedBuffer("OpenRS2").use { buf ->
store.write(255, 1, buf)
store.write(0, 1, buf)
}
}
}
@ -773,7 +819,7 @@ class DiskStoreTest {
fun testOpenLegacyDataFile() {
readTest("single-block-legacy") { store ->
copiedBuffer("OpenRS2").use { expected ->
store.read(255, 1).use { actual ->
store.read(0, 1).use { actual ->
assertEquals(expected, actual)
}
}
@ -786,10 +832,10 @@ class DiskStoreTest {
}
}
private fun writeTest(name: String, legacyDataPath: Boolean = false, f: (Store) -> Unit) {
private fun writeTest(name: String, legacyDataFile: Boolean = false, f: (Store) -> Unit) {
Jimfs.newFileSystem(Configuration.forCurrentPlatform()).use { fs ->
val actual = fs.rootDirectories.first().resolve("cache")
DiskStore.create(actual, legacyDataPath = legacyDataPath).use { store ->
DiskStore.create(actual, legacyDataFile = legacyDataFile).use { store ->
f(store)
}

Loading…
Cancel
Save