From db5bdc2087317df4b6a060bf82f64f5f73a178cf Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 6 Nov 2024 10:52:11 -0500 Subject: [PATCH] cache: fix archive ids being written out of order --- .../java/net/runelite/cache/fs/Index.java | 47 ++++++++++++++++--- .../runelite/cache/fs/flat/FlatStorage.java | 1 - .../net/runelite/cache/index/IndexData.java | 2 + .../java/net/runelite/cache/fs/StoreTest.java | 3 ++ 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/cache/src/main/java/net/runelite/cache/fs/Index.java b/cache/src/main/java/net/runelite/cache/fs/Index.java index 321aec77959..73b5f6c1006 100644 --- a/cache/src/main/java/net/runelite/cache/fs/Index.java +++ b/cache/src/main/java/net/runelite/cache/fs/Index.java @@ -25,6 +25,7 @@ package net.runelite.cache.fs; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import net.runelite.cache.index.ArchiveData; @@ -147,26 +148,60 @@ public void setCompression(int compression) public List getArchives() { - return archives; + return Collections.unmodifiableList(archives); } public Archive addArchive(int id) { + int idx = findArchiveIndex(id); + if (idx >= 0) + { + throw new IllegalArgumentException("archive " + id + " already exists"); + } + + idx = -idx - 1; Archive archive = new Archive(this, id); - this.archives.add(archive); + this.archives.add(idx, archive); return archive; } public Archive getArchive(int id) { - for (Archive a : archives) + int idx = findArchiveIndex(id); + if (idx < 0) { - if (a.getArchiveId() == id) + return null; + } + + return archives.get(idx); + } + + private int findArchiveIndex(int id) + { + int low = 0; + int high = archives.size() - 1; + + while (low <= high) + { + int mid = (low + high) >>> 1; + + Archive a = archives.get(mid); + int cmp = Integer.compare(a.getArchiveId(), id); + if (cmp < 0) { - return a; + low = mid + 1; + } + else if (cmp > 0) + { + high = mid - 1; + } + else + { + return mid; } } - return null; + + return -(low + 1); } public boolean removeArchive(Archive archive) diff --git a/cache/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java b/cache/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java index 0d2d6084641..3ac0d5161b3 100644 --- a/cache/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java +++ b/cache/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java @@ -219,7 +219,6 @@ public void save(Store store) throws IOException br.printf("crc=%d\n", idx.getCrc()); br.printf("named=%b\n", idx.isNamed()); - idx.getArchives().sort(Comparator.comparingInt(Archive::getArchiveId)); for (Archive archive : idx.getArchives()) { br.printf("id=%d\n", archive.getArchiveId()); diff --git a/cache/src/main/java/net/runelite/cache/index/IndexData.java b/cache/src/main/java/net/runelite/cache/index/IndexData.java index d644eaae296..3c7bab3065f 100644 --- a/cache/src/main/java/net/runelite/cache/index/IndexData.java +++ b/cache/src/main/java/net/runelite/cache/index/IndexData.java @@ -162,6 +162,7 @@ public byte[] writeIndexData() if (i != 0) { ArchiveData prev = this.archives[i - 1]; + assert a.id > prev.id : "archive ids out of order"; archive -= prev.getId(); } @@ -224,6 +225,7 @@ public byte[] writeIndexData() if (j != 0) { FileData prev = a.getFiles()[j - 1]; + assert file.id > prev.id : "file ids out of order"; offset -= prev.getId(); } diff --git a/cache/src/test/java/net/runelite/cache/fs/StoreTest.java b/cache/src/test/java/net/runelite/cache/fs/StoreTest.java index 8953d481cf1..67d2f76e9d8 100644 --- a/cache/src/test/java/net/runelite/cache/fs/StoreTest.java +++ b/cache/src/test/java/net/runelite/cache/fs/StoreTest.java @@ -121,6 +121,7 @@ public void testMultipleArchives() throws IOException { FileData[] fileData = archive.getFileData(); FileData file = fileData[i] = new FileData(); + file.setId(i); file.setNameHash(random.nextInt(Integer.MAX_VALUE)); } @@ -128,6 +129,7 @@ public void testMultipleArchives() throws IOException { FileData[] fileData = archive2.getFileData(); FileData file = fileData[i] = new FileData(); + file.setId(i); file.setNameHash(random.nextInt(Integer.MAX_VALUE)); } @@ -135,6 +137,7 @@ public void testMultipleArchives() throws IOException { FileData[] fileData = archive3.getFileData(); FileData file = fileData[i] = new FileData(); + file.setId(i); file.setNameHash(random.nextInt(Integer.MAX_VALUE)); }