cache: split index data reading off. It is shared with the cache client too.

This commit is contained in:
Adam
2017-09-03 20:49:58 -04:00
parent bee7bcec37
commit bf4436178d
5 changed files with 365 additions and 106 deletions

View File

@@ -120,19 +120,6 @@ public class Archive
return file;
}
public void loadFiles(InputStream stream, int numberOfFiles, int protocol)
{
int archive = 0;
for (int i = 0; i < numberOfFiles; ++i)
{
int fileId = archive += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
FSFile file = new FSFile(this, fileId);
this.files.add(file);
}
}
public void decompressAndLoad(int[] keys) throws IOException
{
byte[] encryptedData = this.getData();
@@ -428,16 +415,6 @@ public class Archive
Collections.sort(files, (f1, f2) -> Integer.compare(f1.getFileId(), f2.getFileId()));
}
public void loadNames(InputStream stream, int numberOfFiles)
{
for (int i = 0; i < numberOfFiles; ++i)
{
FSFile file = this.files.get(i);
int name = stream.readInt();
file.setNameHash(name);
}
}
public int getArchiveId()
{
return archiveId;

View File

@@ -35,8 +35,10 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import net.runelite.cache.index.ArchiveData;
import net.runelite.cache.index.FileData;
import net.runelite.cache.index.IndexData;
import net.runelite.cache.util.Djb2;
import net.runelite.cache.io.InputStream;
import net.runelite.cache.io.OutputStream;
import net.runelite.cache.util.Crc32;
import net.runelite.cache.util.Whirlpool;
@@ -347,92 +349,29 @@ public class Index implements Closeable
public void readIndexData(byte[] data)
{
InputStream stream = new InputStream(data);
protocol = stream.readUnsignedByte();
if (protocol >= 5 && protocol <= 7)
IndexData indexData = new IndexData();
indexData.load(data);
protocol = indexData.getProtocol();
revision = indexData.getRevision();
named = indexData.isNamed();
usesWhirpool = indexData.isUsesWhirpool();
for (ArchiveData ad : indexData.getArchives())
{
if (protocol >= 6)
Archive archive = new Archive(this, ad.getId());
archive.setNameHash(ad.getNameHash());
archive.setWhirlpool(ad.getWhirlpool());
archive.setCrc(ad.getCrc());
archive.setRevision(ad.getRevision());
for (FileData fd : ad.getFiles())
{
this.revision = stream.readInt();
FSFile file = archive.addFile(fd.getId());
file.setNameHash(fd.getNameHash());
}
int hash = stream.readUnsignedByte();
named = (1 & hash) != 0;
usesWhirpool = (2 & hash) != 0;
assert (hash & ~3) == 0;
int validArchivesCount = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
int lastArchiveId = 0;
int index;
int archive;
for (index = 0; index < validArchivesCount; ++index)
{
archive = lastArchiveId += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
Archive a = new Archive(this, archive);
this.archives.add(a);
}
if (named)
{
for (index = 0; index < validArchivesCount; ++index)
{
int nameHash = stream.readInt();
Archive a = this.archives.get(index);
a.setNameHash(nameHash);
}
}
if (usesWhirpool)
{
for (index = 0; index < validArchivesCount; ++index)
{
byte[] var13 = new byte[64];
stream.readBytes(var13);
Archive a = this.archives.get(index);
a.setWhirlpool(var13);
}
}
for (index = 0; index < validArchivesCount; ++index)
{
int crc = stream.readInt();
Archive a = this.archives.get(index);
a.setCrc(crc);
}
for (index = 0; index < validArchivesCount; ++index)
{
int revision = stream.readInt();
Archive a = this.archives.get(index);
a.setRevision(revision);
}
int[] numberOfFiles = new int[validArchivesCount];
for (index = 0; index < validArchivesCount; ++index)
{
int num = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
numberOfFiles[index] = num;
}
for (index = 0; index < validArchivesCount; ++index)
{
archive = 0;
Archive a = this.archives.get(index);
a.loadFiles(stream, numberOfFiles[index], protocol);
}
if (named)
{
for (index = 0; index < validArchivesCount; ++index)
{
Archive a = this.archives.get(index);
a.loadNames(stream, numberOfFiles[index]);
}
}
archives.add(archive);
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.cache.index;
public class ArchiveData
{
int id;
int nameHash;
byte[] whirlpool;
int crc;
int revision;
FileData[] files;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getNameHash()
{
return nameHash;
}
public void setNameHash(int nameHash)
{
this.nameHash = nameHash;
}
public byte[] getWhirlpool()
{
return whirlpool;
}
public void setWhirlpool(byte[] whirlpool)
{
this.whirlpool = whirlpool;
}
public int getCrc()
{
return crc;
}
public void setCrc(int crc)
{
this.crc = crc;
}
public int getRevision()
{
return revision;
}
public void setRevision(int revision)
{
this.revision = revision;
}
public FileData[] getFiles()
{
return files;
}
public void setFiles(FileData[] files)
{
this.files = files;
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.cache.index;
public class FileData
{
int id;
int nameHash;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getNameHash()
{
return nameHash;
}
public void setNameHash(int nameHash)
{
this.nameHash = nameHash;
}
}

View File

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.cache.index;
import net.runelite.cache.io.InputStream;
public class IndexData
{
private int protocol;
private int revision;
private boolean named;
private boolean usesWhirpool;
private ArchiveData[] archives;
public void load(byte[] data)
{
InputStream stream = new InputStream(data);
protocol = stream.readUnsignedByte();
if (protocol < 5 || protocol > 7)
{
throw new IllegalArgumentException("Unsupported protocol");
}
if (protocol >= 6)
{
this.revision = stream.readInt();
}
int hash = stream.readUnsignedByte();
named = (1 & hash) != 0;
usesWhirpool = (2 & hash) != 0;
assert (hash & ~3) == 0;
int validArchivesCount = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
int lastArchiveId = 0;
archives = new ArchiveData[validArchivesCount];
for (int index = 0; index < validArchivesCount; ++index)
{
int archive = lastArchiveId += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
ArchiveData ad = new ArchiveData();
ad.id = archive;
archives[index] = ad;
}
if (named)
{
for (int index = 0; index < validArchivesCount; ++index)
{
int nameHash = stream.readInt();
ArchiveData ad = archives[index];
ad.nameHash = nameHash;
}
}
if (usesWhirpool)
{
for (int index = 0; index < validArchivesCount; ++index)
{
byte[] w = new byte[64];
stream.readBytes(w);
ArchiveData ad = archives[index];
ad.whirlpool = w;
}
}
for (int index = 0; index < validArchivesCount; ++index)
{
int crc = stream.readInt();
ArchiveData ad = archives[index];
ad.crc = crc;
}
for (int index = 0; index < validArchivesCount; ++index)
{
int revision = stream.readInt();
ArchiveData ad = archives[index];
ad.revision = revision;
}
int[] numberOfFiles = new int[validArchivesCount];
for (int index = 0; index < validArchivesCount; ++index)
{
int num = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
numberOfFiles[index] = num;
}
for (int index = 0; index < validArchivesCount; ++index)
{
ArchiveData ad = archives[index];
int num = numberOfFiles[index];
ad.files = new FileData[num];
int last = 0;
for (int i = 0; i < num; ++i)
{
int fileId = last += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
FileData fd = ad.files[i] = new FileData();
fd.id = fileId;
}
}
if (named)
{
for (int index = 0; index < validArchivesCount; ++index)
{
ArchiveData ad = archives[index];
int num = numberOfFiles[index];
for (int i = 0; i < num; ++i)
{
FileData fd = ad.files[i];
int name = stream.readInt();
fd.nameHash = name;
}
}
}
}
public int getProtocol()
{
return protocol;
}
public void setProtocol(int protocol)
{
this.protocol = protocol;
}
public int getRevision()
{
return revision;
}
public void setRevision(int revision)
{
this.revision = revision;
}
public boolean isNamed()
{
return named;
}
public void setNamed(boolean named)
{
this.named = named;
}
public boolean isUsesWhirpool()
{
return usesWhirpool;
}
public void setUsesWhirpool(boolean usesWhirpool)
{
this.usesWhirpool = usesWhirpool;
}
public ArchiveData[] getArchives()
{
return archives;
}
public void setArchives(ArchiveData[] archives)
{
this.archives = archives;
}
}