Split out cache updater into own project

This commit is contained in:
Adam
2018-02-03 18:45:34 -05:00
parent 8c678f69eb
commit cda04b7acd
21 changed files with 557 additions and 598 deletions

View File

@@ -24,7 +24,6 @@
*/
package net.runelite.http.service.cache;
import java.time.Instant;
import java.util.List;
import net.runelite.cache.IndexType;
import net.runelite.http.service.cache.beans.ArchiveEntry;
@@ -37,12 +36,6 @@ import org.sql2o.ResultSetIterable;
class CacheDAO
{
// cache prepared statements for high volume queries
private Query associateArchive;
private Query findArchive, insertArchive;
private Query associateFile;
private Query findFilesForArchive;
public List<CacheEntry> listCaches(Connection con)
{
return con.createQuery("select id, revision, date from cache")
@@ -94,22 +87,6 @@ class CacheDAO
.executeAndFetchFirst(ArchiveEntry.class);
}
public ArchiveEntry findArchiveById(Connection con, CacheEntry cache, IndexType index, int archiveId)
{
return con.createQuery("select archive.id, archive.archiveId, archive.nameHash,"
+ " archive.crc, archive.revision, archive.hash from archive "
+ "join index_archive on index_archive.archive = archive.id "
+ "join `index` on index.id = index_archive.index "
+ "where index.cache = :cacheId "
+ "and index.indexId = :indexId "
+ "and archive.archiveId = :archiveId "
+ "limit 1")
.addParameter("cacheId", cache.getId())
.addParameter("indexId", index.getNumber())
.addParameter("archiveId", archiveId)
.executeAndFetchFirst(ArchiveEntry.class);
}
public ArchiveEntry findArchiveByName(Connection con, CacheEntry cache, IndexType index, int nameHash)
{
return con.createQuery("select archive.id, archive.archiveId, archive.nameHash,"
@@ -128,32 +105,14 @@ class CacheDAO
public ResultSetIterable<FileEntry> findFilesForArchive(Connection con, ArchiveEntry archiveEntry)
{
if (findFilesForArchive == null)
{
findFilesForArchive = con.createQuery("select id, fileId, nameHash from file "
+ "where archive = :archive");
}
Query findFilesForArchive = con.createQuery("select id, fileId, nameHash from file "
+ "where archive = :archive");
return findFilesForArchive
.addParameter("archive", archiveEntry.getId())
.executeAndFetchLazy(FileEntry.class);
}
public CacheEntry createCache(Connection con, int revision, Instant date)
{
int cacheId = con.createQuery("insert into cache (revision, date) values (:revision, :date)")
.addParameter("revision", revision)
.addParameter("date", date)
.executeUpdate()
.getKey(int.class);
CacheEntry entry = new CacheEntry();
entry.setId(cacheId);
entry.setRevision(revision);
entry.setDate(date);
return entry;
}
public CacheEntry findCache(Connection con, int cacheId)
{
return con.createQuery("select id, revision, date from cache "
@@ -161,101 +120,4 @@ class CacheDAO
.addParameter("cacheId", cacheId)
.executeAndFetchFirst(CacheEntry.class);
}
public IndexEntry createIndex(Connection con, CacheEntry cache, int indexId, int crc, int revision)
{
int id = con.createQuery("insert into `index` (cache, indexId, crc, revision) values (:cache, :indexId, :crc, :revision)")
.addParameter("cache", cache.getId())
.addParameter("indexId", indexId)
.addParameter("crc", crc)
.addParameter("revision", revision)
.executeUpdate()
.getKey(int.class);
IndexEntry entry = new IndexEntry();
entry.setId(id);
entry.setIndexId(indexId);
entry.setCrc(crc);
entry.setRevision(revision);
return entry;
}
public void associateArchiveToIndex(Connection con, ArchiveEntry archive, IndexEntry index)
{
if (associateArchive == null)
{
associateArchive = con.createQuery("insert into index_archive (`index`, archive) values (:index, :archive)");
}
associateArchive
.addParameter("index", index.getId())
.addParameter("archive", archive.getId())
.executeUpdate();
}
public ArchiveEntry findArchive(Connection con, IndexEntry index,
int archiveId, int nameHash, int crc, int revision)
{
if (findArchive == null)
{
findArchive = con.createQuery("select distinct archive.id, archive.archiveId, archive.nameHash,"
+ " archive.crc, archive.revision, archive.hash from archive "
+ " join index_archive on index_archive.archive = archive.id"
+ " join `index` on index.id = index_archive.index"
+ " where archive.archiveId = :archiveId"
+ " and archive.nameHash = :nameHash"
+ " and archive.crc = :crc"
+ " and archive.revision = :revision"
+ " and index.indexId = :indexId");
}
ArchiveEntry entry = findArchive
.addParameter("archiveId", archiveId)
.addParameter("nameHash", nameHash)
.addParameter("crc", crc)
.addParameter("revision", revision)
.addParameter("indexId", index.getIndexId())
.executeAndFetchFirst(ArchiveEntry.class);
return entry;
}
public ArchiveEntry createArchive(Connection con, IndexEntry index,
int archiveId, int nameHash, int crc, int revision, byte[] hash)
{
if (insertArchive == null)
{
insertArchive = con.createQuery("insert into archive (archiveId, nameHash, crc, revision, hash) values "
+ "(:archiveId, :nameHash, :crc, :revision, :hash)");
}
int id = insertArchive
.addParameter("archiveId", archiveId)
.addParameter("nameHash", nameHash)
.addParameter("crc", crc)
.addParameter("revision", revision)
.addParameter("hash", hash)
.executeUpdate()
.getKey(int.class);
ArchiveEntry entry = new ArchiveEntry();
entry.setId(id);
entry.setArchiveId(archiveId);
entry.setNameHash(nameHash);
entry.setCrc(crc);
entry.setRevision(revision);
entry.setHash(hash);
return entry;
}
public void associateFileToArchive(Connection con, ArchiveEntry archive, int fileId, int nameHash)
{
if (associateFile == null)
{
associateFile = con.createQuery("insert into file (archive, fileId, nameHash) values (:archive, :fileId, :nameHash)");
}
associateFile
.addParameter("archive", archive.getId())
.addParameter("fileId", fileId)
.addParameter("nameHash", nameHash)
.executeUpdate();
}
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright (c) 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.http.service.cache;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@Order(200)
public class CacheSecurity extends WebSecurityConfigurerAdapter
{
@Value("${auth.password}")
private String password;
@Override
protected void configure(HttpSecurity http) throws Exception
{
// By default spring security adds headers to not cache anything
http.headers().cacheControl().disable();
http.csrf().disable();
http.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/cache/admin/**")
.hasRole("ADMIN");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication()
.withUser("admin")
.password(password)
.roles("ADMIN");
}
}

View File

@@ -1,146 +0,0 @@
/*
* Copyright (c) 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.http.service.cache;
import java.io.IOException;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import net.runelite.cache.fs.Archive;
import net.runelite.cache.fs.Index;
import net.runelite.cache.fs.Storage;
import net.runelite.cache.fs.Store;
import net.runelite.cache.index.FileData;
import net.runelite.http.service.cache.beans.ArchiveEntry;
import net.runelite.http.service.cache.beans.CacheEntry;
import net.runelite.http.service.cache.beans.IndexEntry;
import org.sql2o.Connection;
import org.sql2o.ResultSetIterable;
@Slf4j
public class CacheStorage implements Storage
{
private CacheEntry cacheEntry;
private final CacheDAO cacheDao;
private final Connection con;
public CacheStorage(CacheEntry cacheEntry, CacheDAO cacheDao, Connection con)
{
this.cacheEntry = cacheEntry;
this.cacheDao = cacheDao;
this.con = con;
}
public CacheEntry getCacheEntry()
{
return cacheEntry;
}
public void setCacheEntry(CacheEntry cacheEntry)
{
this.cacheEntry = cacheEntry;
}
@Override
public void init(Store store) throws IOException
{
}
@Override
public void close() throws IOException
{
}
@Override
public void load(Store store) throws IOException
{
List<IndexEntry> indexes = cacheDao.findIndexesForCache(con, cacheEntry);
for (IndexEntry indexEntry : indexes)
{
Index index = store.addIndex(indexEntry.getIndexId());
index.setCrc(indexEntry.getCrc());
index.setRevision(indexEntry.getRevision());
try (ResultSetIterable<ArchiveEntry> archives = cacheDao.findArchivesForIndex(con, indexEntry))
{
for (ArchiveEntry archiveEntry : archives)
{
if (index.getArchive(archiveEntry.getArchiveId()) != null)
{
throw new IOException("Duplicate archive " + archiveEntry + " on " + indexEntry);
}
Archive archive = index.addArchive(archiveEntry.getArchiveId());
archive.setNameHash(archiveEntry.getNameHash());
archive.setCrc(archiveEntry.getCrc());
archive.setRevision(archiveEntry.getRevision());
archive.setHash(archiveEntry.getHash());
// File data is not necessary for cache updating
}
}
}
}
@Override
public void save(Store store) throws IOException
{
for (Index index : store.getIndexes())
{
IndexEntry entry = cacheDao.createIndex(con, cacheEntry, index.getId(), index.getCrc(), index.getRevision());
for (Archive archive : index.getArchives())
{
ArchiveEntry archiveEntry = cacheDao.findArchive(con, entry, archive.getArchiveId(),
archive.getNameHash(), archive.getCrc(), archive.getRevision());
if (archiveEntry == null)
{
byte[] hash = archive.getHash();
archiveEntry = cacheDao.createArchive(con, entry, archive.getArchiveId(),
archive.getNameHash(), archive.getCrc(), archive.getRevision(), hash);
for (FileData file : archive.getFileData())
{
cacheDao.associateFileToArchive(con, archiveEntry, file.getId(), file.getNameHash());
}
}
cacheDao.associateArchiveToIndex(con, archiveEntry, entry);
}
}
}
@Override
public byte[] loadArchive(Archive archive) throws IOException
{
throw new UnsupportedOperationException();
}
@Override
public void saveArchive(Archive archive, byte[] data) throws IOException
{
throw new UnsupportedOperationException();
}
}

View File

@@ -1,161 +0,0 @@
/*
* Copyright (c) 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.http.service.cache;
import io.minio.MinioClient;
import io.minio.errors.InvalidEndpointException;
import io.minio.errors.InvalidPortException;
import java.io.IOException;
import java.time.Instant;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import net.runelite.cache.client.CacheClient;
import net.runelite.cache.client.IndexInfo;
import net.runelite.cache.fs.Archive;
import net.runelite.cache.fs.Store;
import net.runelite.http.api.RuneLiteAPI;
import net.runelite.http.service.cache.beans.CacheEntry;
import net.runelite.http.service.cache.beans.IndexEntry;
import net.runelite.protocol.api.login.HandshakeResponseType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.sql2o.Connection;
import org.sql2o.Sql2o;
@RestController
@RequestMapping("/cache/admin")
public class CacheUpdater
{
private static final Logger logger = LoggerFactory.getLogger(CacheUpdater.class);
private final Sql2o sql2o;
private final MinioClient minioClient;
@Value("${minio.bucket}")
private String minioBucket;
@Autowired
public CacheUpdater(
@Qualifier("Runelite Cache SQL2O") Sql2o sql2o,
MinioClient minioClient
)
{
this.sql2o = sql2o;
this.minioClient = minioClient;
}
@RequestMapping("/update")
public void check() throws IOException, InvalidEndpointException, InvalidPortException, InterruptedException
{
int rsVersion = RuneLiteAPI.getRsVersion();
try (Connection con = sql2o.beginTransaction())
{
CacheDAO cacheDao = new CacheDAO();
CacheEntry cache = cacheDao.findMostRecent(con);
boolean created = false;
if (cache == null)
{
created = true;
cache = cacheDao.createCache(con, rsVersion, Instant.now());
}
CacheStorage storage = new CacheStorage(cache, cacheDao, con);
Store store = new Store(storage);
store.load();
ExecutorService executor = Executors.newSingleThreadExecutor();
CacheClient client = new CacheClient(store, rsVersion,
(Archive archive, byte[] data) -> executor.submit(new CacheUploader(minioClient, minioBucket, archive, data)));
client.connect();
HandshakeResponseType result = client.handshake().join();
if (result != HandshakeResponseType.RESPONSE_OK)
{
throw new OutOfDateException();
}
List<IndexInfo> indexes = client.requestIndexes();
List<IndexEntry> entries = cacheDao.findIndexesForCache(con, cache);
if (!checkOutOfDate(indexes, entries))
{
logger.info("All up to date.");
return;
}
client.download();
CacheEntry newCache = created ? cache : cacheDao.createCache(con, rsVersion, Instant.now());
storage.setCacheEntry(newCache);
store.save();
// ensure objects are added to the store before they become
// visible in the database
executor.shutdown();
while (!executor.awaitTermination(1, TimeUnit.SECONDS))
{
logger.debug("Waiting for termination of executor...");
}
// commit database
con.commit();
}
}
private boolean checkOutOfDate(List<IndexInfo> indexes, List<IndexEntry> dbIndexes)
{
if (indexes.size() != dbIndexes.size())
{
return true;
}
for (int i = 0; i < indexes.size(); ++i)
{
IndexInfo ii = indexes.get(i);
IndexEntry ie = dbIndexes.get(i);
if (ii.getId() != ie.getIndexId()
|| ii.getRevision() != ie.getRevision()
|| ii.getCrc() != ie.getCrc())
{
return true;
}
}
return false;
}
}

View File

@@ -1,96 +0,0 @@
/*
* Copyright (c) 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.http.service.cache;
import com.google.common.hash.Hashing;
import com.google.common.io.BaseEncoding;
import io.minio.MinioClient;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidArgumentException;
import io.minio.errors.InvalidBucketNameException;
import io.minio.errors.NoResponseException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import net.runelite.cache.fs.Archive;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmlpull.v1.XmlPullParserException;
public class CacheUploader implements Runnable
{
private static final Logger logger = LoggerFactory.getLogger(CacheUploader.class);
private final MinioClient minioClient;
private final String minioBucket;
private final Archive archive;
private final byte[] data;
public CacheUploader(MinioClient minioClient, String minioBucket, Archive archive, byte[] data)
{
this.minioClient = minioClient;
this.minioBucket = minioBucket;
this.archive = archive;
this.data = data;
}
@Override
public void run()
{
byte[] hash = Hashing.sha256().hashBytes(data).asBytes();
String hashStr = BaseEncoding.base16().encode(hash);
archive.setHash(hash);
String path = new StringBuilder()
.append(hashStr.substring(0, 2))
.append('/')
.append(hashStr.substring(2))
.toString();
try
{
try (InputStream in = minioClient.getObject(minioBucket, path))
{
return; // already exists
}
catch (ErrorResponseException ex)
{
// doesn't exist
}
minioClient.putObject(minioBucket, path, new ByteArrayInputStream(data), data.length, "binary/octet-stream");
}
catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidArgumentException | InvalidBucketNameException | NoResponseException | IOException | InvalidKeyException | NoSuchAlgorithmException | XmlPullParserException ex)
{
logger.warn("unable to upload data to store", ex);
}
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright (c) 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.http.service.cache;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(reason = "Out of date")
public class OutOfDateException extends RuntimeException
{
}

View File

@@ -24,8 +24,9 @@
*/
package net.runelite.http.service.cache.beans;
import java.util.Arrays;
import lombok.Data;
@Data
public class ArchiveEntry
{
private int id;
@@ -34,127 +35,4 @@ public class ArchiveEntry
private int crc;
private int revision;
private byte[] hash;
@Override
public String toString()
{
return "ArchiveEntry{" + "id=" + id + ", archiveId=" + archiveId + ", nameHash=" + nameHash + ", crc=" + crc + ", revision=" + revision + '}';
}
@Override
public int hashCode()
{
int hash = 3;
hash = 53 * hash + this.id;
hash = 53 * hash + this.archiveId;
hash = 53 * hash + this.nameHash;
hash = 53 * hash + this.crc;
hash = 53 * hash + this.revision;
hash = 53 * hash + Arrays.hashCode(this.hash);
return hash;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final ArchiveEntry other = (ArchiveEntry) obj;
if (this.id != other.id)
{
return false;
}
if (this.archiveId != other.archiveId)
{
return false;
}
if (this.nameHash != other.nameHash)
{
return false;
}
if (this.crc != other.crc)
{
return false;
}
if (this.revision != other.revision)
{
return false;
}
if (!Arrays.equals(this.hash, other.hash))
{
return false;
}
return true;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getArchiveId()
{
return archiveId;
}
public void setArchiveId(int archiveId)
{
this.archiveId = archiveId;
}
public int getNameHash()
{
return nameHash;
}
public void setNameHash(int nameHash)
{
this.nameHash = nameHash;
}
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 byte[] getHash()
{
return hash;
}
public void setHash(byte[] hash)
{
this.hash = hash;
}
}

View File

@@ -25,88 +25,12 @@
package net.runelite.http.service.cache.beans;
import java.time.Instant;
import java.util.Objects;
import lombok.Data;
@Data
public class CacheEntry
{
private int id;
private int revision;
private Instant date;
@Override
public String toString()
{
return "CacheEntry{" + "id=" + id + ", revision=" + revision + ", date=" + date + '}';
}
@Override
public int hashCode()
{
int hash = 7;
hash = 23 * hash + this.id;
hash = 23 * hash + this.revision;
hash = 23 * hash + Objects.hashCode(this.date);
return hash;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final CacheEntry other = (CacheEntry) obj;
if (this.id != other.id)
{
return false;
}
if (this.revision != other.revision)
{
return false;
}
if (!Objects.equals(this.date, other.date))
{
return false;
}
return true;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getRevision()
{
return revision;
}
public void setRevision(int revision)
{
this.revision = revision;
}
public Instant getDate()
{
return date;
}
public void setDate(Instant date)
{
this.date = date;
}
}

View File

@@ -24,103 +24,13 @@
*/
package net.runelite.http.service.cache.beans;
import lombok.Data;
@Data
public class FileEntry
{
private int id;
private int archiveId;
private int fileId;
private int nameHash;
@Override
public String toString()
{
return "FileEntry{" + "id=" + id + ", archiveId=" + archiveId + ", fileId=" + fileId + ", nameHash=" + nameHash + '}';
}
@Override
public int hashCode()
{
int hash = 5;
hash = 67 * hash + this.id;
hash = 67 * hash + this.archiveId;
hash = 67 * hash + this.fileId;
hash = 67 * hash + this.nameHash;
return hash;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final FileEntry other = (FileEntry) obj;
if (this.id != other.id)
{
return false;
}
if (this.archiveId != other.archiveId)
{
return false;
}
if (this.fileId != other.fileId)
{
return false;
}
if (this.nameHash != other.nameHash)
{
return false;
}
return true;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getArchiveId()
{
return archiveId;
}
public void setArchiveId(int archiveId)
{
this.archiveId = archiveId;
}
public int getFileId()
{
return fileId;
}
public void setFileId(int fileId)
{
this.fileId = fileId;
}
public int getNameHash()
{
return nameHash;
}
public void setNameHash(int nameHash)
{
this.nameHash = nameHash;
}
}

View File

@@ -24,102 +24,13 @@
*/
package net.runelite.http.service.cache.beans;
import lombok.Data;
@Data
public class IndexEntry
{
private int id;
private int indexId;
private int crc;
private int revision;
@Override
public String toString()
{
return "IndexEntry{" + "id=" + id + ", indexId=" + indexId + ", crc=" + crc + ", revision=" + revision + '}';
}
@Override
public int hashCode()
{
int hash = 5;
hash = 17 * hash + this.id;
hash = 17 * hash + this.indexId;
hash = 17 * hash + this.crc;
hash = 17 * hash + this.revision;
return hash;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final IndexEntry other = (IndexEntry) obj;
if (this.id != other.id)
{
return false;
}
if (this.indexId != other.indexId)
{
return false;
}
if (this.crc != other.crc)
{
return false;
}
if (this.revision != other.revision)
{
return false;
}
return true;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getIndexId()
{
return indexId;
}
public void setIndexId(int indexId)
{
this.indexId = indexId;
}
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;
}
}