http-service: add cache service
This commit is contained in:
@@ -51,6 +51,11 @@
|
||||
<version>${spring.boot.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
@@ -63,6 +68,11 @@
|
||||
<artifactId>http-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.runelite</groupId>
|
||||
<artifactId>cache</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.sql2o</groupId>
|
||||
@@ -89,6 +99,11 @@
|
||||
<artifactId>scribejava-apis</artifactId>
|
||||
<version>4.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>3.0.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -56,7 +56,15 @@ public class SpringBootWebApplication extends SpringBootServletInitializer
|
||||
Map<Class, Converter> converters = new HashMap<>();
|
||||
converters.put(Instant.class, new InstantConverter());
|
||||
return new Sql2o(dataSource, new NoQuirks(converters));
|
||||
}
|
||||
|
||||
@Bean("Runelite Cache SQL2O")
|
||||
Sql2o cacheSql2o() throws NamingException
|
||||
{
|
||||
DataSource dataSource = (DataSource) getContext().lookup("jdbc/runelite-cache");
|
||||
Map<Class, Converter> converters = new HashMap<>();
|
||||
converters.put(Instant.class, new InstantConverter());
|
||||
return new Sql2o(dataSource, new NoQuirks(converters));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
260
http-service/src/main/java/net/runelite/http/service/cache/CacheDAO.java
vendored
Normal file
260
http-service/src/main/java/net/runelite/http/service/cache/CacheDAO.java
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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.time.Instant;
|
||||
import java.util.List;
|
||||
import net.runelite.http.service.cache.beans.ArchiveEntry;
|
||||
import net.runelite.http.service.cache.beans.CacheEntry;
|
||||
import net.runelite.http.service.cache.beans.FileEntry;
|
||||
import net.runelite.http.service.cache.beans.IndexEntry;
|
||||
import org.sql2o.Connection;
|
||||
import org.sql2o.Query;
|
||||
|
||||
public class CacheDAO
|
||||
{
|
||||
// cache prepared statements for high volume queries
|
||||
private Query associateArchive;
|
||||
private Query findArchive, insertArchive;
|
||||
private Query associateFile;
|
||||
|
||||
public List<CacheEntry> listCaches(Connection con)
|
||||
{
|
||||
return con.createQuery("select id, revision, date from cache")
|
||||
.executeAndFetch(CacheEntry.class);
|
||||
}
|
||||
|
||||
public CacheEntry findMostRecent(Connection con)
|
||||
{
|
||||
return con.createQuery("select id from cache order by revision,date desc limit 1")
|
||||
.executeAndFetchFirst(CacheEntry.class);
|
||||
}
|
||||
|
||||
public List<IndexEntry> findIndexesForCache(Connection con, CacheEntry cache)
|
||||
{
|
||||
return con.createQuery("select index.id, index.indexId, index.revision from cache "
|
||||
+ "join cache_index on cache_index.cache = cache.id "
|
||||
+ "join `index` on cache_index.index = index.id "
|
||||
+ "where cache.id = :id "
|
||||
+ "order by index.indexId asc")
|
||||
.addParameter("id", cache.getId())
|
||||
.executeAndFetch(IndexEntry.class);
|
||||
}
|
||||
|
||||
public IndexEntry findIndexForCache(Connection con, CacheEntry cache, int indexId)
|
||||
{
|
||||
return con.createQuery("select index.id, index.indexId, index.revision from cache "
|
||||
+ "join cache_index on cache_index.cache = cache.id "
|
||||
+ "join `index` on cache_index.index = index.id "
|
||||
+ "where cache.id = :id "
|
||||
+ "and index.indexId = :indexId")
|
||||
.addParameter("id", cache.getId())
|
||||
.addParameter("indexId", indexId)
|
||||
.executeAndFetchFirst(IndexEntry.class);
|
||||
}
|
||||
|
||||
public List<ArchiveEntry> findArchivesForIndex(Connection con, IndexEntry indexEntry)
|
||||
{
|
||||
return con.createQuery("select archive.id, archive.archiveId, archive.nameHash, archive.revision from index_archive "
|
||||
+ "join archive on index_archive.archive = archive.id "
|
||||
+ "where index_archive.index = :id")
|
||||
.addParameter("id", indexEntry.getId())
|
||||
.executeAndFetch(ArchiveEntry.class);
|
||||
}
|
||||
|
||||
public ArchiveEntry findArchiveForIndex(Connection con, IndexEntry indexEntry, int archiveId)
|
||||
{
|
||||
return con.createQuery("select archive.id, archive.archiveId, archive.nameHash, archive.revision from index_archive "
|
||||
+ "join archive on index_archive.archive = archive.id "
|
||||
+ "where index_archive.index = :id "
|
||||
+ "and archive.archiveId = :archiveId")
|
||||
.addParameter("id", indexEntry.getId())
|
||||
.addParameter("archiveId", archiveId)
|
||||
.executeAndFetchFirst(ArchiveEntry.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the most recent archive for the given indexId/archiveId
|
||||
* @param con
|
||||
* @param indexId
|
||||
* @param archiveId
|
||||
* @return
|
||||
*/
|
||||
public ArchiveEntry findMostRecentArchive(Connection con, int indexId, int archiveId)
|
||||
{
|
||||
return con.createQuery("select archive.id, archive.archiveId, archive.nameHash, archive.revision from archive "
|
||||
+ "join index_archive on index_archive.archive = archive.id "
|
||||
+ "join `index` on index.id = index_archive.index "
|
||||
+ "where index.indexId = :indexId and archive.archiveId = :archiveId "
|
||||
+ "group by archive.id "
|
||||
+ "order by archive.revision desc "
|
||||
+ "limit 1")
|
||||
.addParameter("indexId", indexId)
|
||||
.addParameter("archiveId", archiveId)
|
||||
.executeAndFetchFirst(ArchiveEntry.class);
|
||||
}
|
||||
|
||||
public List<FileEntry> findFilesForArchive(Connection con, ArchiveEntry archiveEntry)
|
||||
{
|
||||
return con.createQuery("select id, fileId, nameHash from file "
|
||||
+ "where archive = :archive")
|
||||
.addParameter("archive", archiveEntry.getId())
|
||||
.executeAndFetch(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 "
|
||||
+ "where id = :cacheId")
|
||||
.addParameter("cacheId", cacheId)
|
||||
.executeAndFetchFirst(CacheEntry.class);
|
||||
}
|
||||
|
||||
public IndexEntry findIndex(Connection con, int indexId, int revision)
|
||||
{
|
||||
return con.createQuery("select id, indexId, revision from `index` "
|
||||
+ "where indexId = :indexId "
|
||||
+ "and revision = :revision")
|
||||
.addParameter("indexId", indexId)
|
||||
.addParameter("revision", revision)
|
||||
.executeAndFetchFirst(IndexEntry.class);
|
||||
}
|
||||
|
||||
public void associateIndexToCache(Connection con, CacheEntry cache, IndexEntry index)
|
||||
{
|
||||
con.createQuery("insert into cache_index (cache, `index`) values (:cache, :index)")
|
||||
.addParameter("cache", cache.getId())
|
||||
.addParameter("index", index.getId())
|
||||
.executeUpdate();
|
||||
}
|
||||
|
||||
public IndexEntry findOrCreateIndex(Connection con, CacheEntry cache, int indexId, int revision)
|
||||
{
|
||||
IndexEntry entry = con.createQuery("select id, indexId, revision from `index` where indexId = :indexId and revision = :revision")
|
||||
.addParameter("indexId", indexId)
|
||||
.addParameter("revision", revision)
|
||||
.executeAndFetchFirst(IndexEntry.class);
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
|
||||
int id = con.createQuery("insert into `index` (indexId, revision) values (:indexId, :revision)")
|
||||
.addParameter("indexId", indexId)
|
||||
.addParameter("revision", revision)
|
||||
.executeUpdate()
|
||||
.getKey(int.class);
|
||||
|
||||
entry = new IndexEntry();
|
||||
entry.setId(id);
|
||||
entry.setIndexId(indexId);
|
||||
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 revision)
|
||||
{
|
||||
if (findArchive == null)
|
||||
{
|
||||
findArchive = con.createQuery("select archive.id, archive.archiveId, archive.nameHash, archive.revision 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.revision = :revision and index.indexId = :indexId");
|
||||
}
|
||||
|
||||
ArchiveEntry entry = findArchive
|
||||
.addParameter("archiveId", archiveId)
|
||||
.addParameter("revision", revision)
|
||||
.addParameter("indexId", index.getIndexId())
|
||||
.executeAndFetchFirst(ArchiveEntry.class);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public ArchiveEntry createArchive(Connection con, IndexEntry index,
|
||||
int archiveId, int nameHash, int revision)
|
||||
{
|
||||
if (insertArchive == null)
|
||||
{
|
||||
insertArchive = con.createQuery("insert into archive (archiveId, nameHash, revision) values "
|
||||
+ "(:archiveId, :nameHash, :revision)");
|
||||
}
|
||||
|
||||
int id = insertArchive
|
||||
.addParameter("archiveId", archiveId)
|
||||
.addParameter("nameHash", nameHash)
|
||||
.addParameter("revision", revision)
|
||||
.executeUpdate()
|
||||
.getKey(int.class);
|
||||
|
||||
ArchiveEntry entry = new ArchiveEntry();
|
||||
entry.setId(id);
|
||||
entry.setArchiveId(archiveId);
|
||||
entry.setNameHash(nameHash);
|
||||
entry.setRevision(revision);
|
||||
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();
|
||||
}
|
||||
}
|
||||
59
http-service/src/main/java/net/runelite/http/service/cache/CacheSecurity.java
vendored
Normal file
59
http-service/src/main/java/net/runelite/http/service/cache/CacheSecurity.java
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.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
|
||||
public class CacheSecurity extends WebSecurityConfigurerAdapter
|
||||
{
|
||||
@Value("${auth.password}")
|
||||
private String password;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
387
http-service/src/main/java/net/runelite/http/service/cache/CacheService.java
vendored
Normal file
387
http-service/src/main/java/net/runelite/http/service/cache/CacheService.java
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* 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.io.ByteStreams;
|
||||
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.InvalidEndpointException;
|
||||
import io.minio.errors.InvalidPortException;
|
||||
import io.minio.errors.NoResponseException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import net.runelite.cache.ConfigType;
|
||||
import net.runelite.cache.IndexType;
|
||||
import net.runelite.cache.definitions.ItemDefinition;
|
||||
import net.runelite.cache.definitions.NpcDefinition;
|
||||
import net.runelite.cache.definitions.ObjectDefinition;
|
||||
import net.runelite.cache.definitions.loaders.ItemLoader;
|
||||
import net.runelite.cache.definitions.loaders.NpcLoader;
|
||||
import net.runelite.cache.definitions.loaders.ObjectLoader;
|
||||
import net.runelite.cache.fs.ArchiveFiles;
|
||||
import net.runelite.cache.fs.FSFile;
|
||||
import net.runelite.cache.fs.jagex.DataFile;
|
||||
import net.runelite.cache.fs.jagex.DataFileReadResult;
|
||||
import net.runelite.http.api.cache.Cache;
|
||||
import net.runelite.http.api.cache.CacheArchive;
|
||||
import net.runelite.http.api.cache.CacheIndex;
|
||||
import net.runelite.http.service.cache.beans.ArchiveEntry;
|
||||
import net.runelite.http.service.cache.beans.CacheEntry;
|
||||
import net.runelite.http.service.cache.beans.FileEntry;
|
||||
import net.runelite.http.service.cache.beans.IndexEntry;
|
||||
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.context.annotation.Bean;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.sql2o.Connection;
|
||||
import org.sql2o.Sql2o;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/cache")
|
||||
public class CacheService
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(CacheService.class);
|
||||
|
||||
@Autowired
|
||||
@Qualifier("Runelite Cache SQL2O")
|
||||
private Sql2o sql2o;
|
||||
|
||||
@Value("${minio.bucket}")
|
||||
private String minioBucket;
|
||||
|
||||
private final MinioClient minioClient;
|
||||
|
||||
@Autowired
|
||||
public CacheService(
|
||||
@Value("${minio.endpoint}") String minioEndpoint,
|
||||
@Value("${minio.accesskey}") String accessKey,
|
||||
@Value("${minio.secretkey}") String secretKey
|
||||
) throws InvalidEndpointException, InvalidPortException
|
||||
{
|
||||
this.minioClient = new MinioClient(minioEndpoint, accessKey, secretKey);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MinioClient minioClient()
|
||||
{
|
||||
return minioClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve archive from storage
|
||||
*
|
||||
* @param indexId
|
||||
* @param archiveId
|
||||
* @param revision
|
||||
* @return
|
||||
*/
|
||||
private byte[] getArchive(int indexId, int archiveId, int revision)
|
||||
{
|
||||
String path = new StringBuilder()
|
||||
.append(indexId)
|
||||
.append('/')
|
||||
.append(archiveId)
|
||||
.append('/')
|
||||
.append(revision)
|
||||
.toString();
|
||||
|
||||
try (InputStream in = minioClient.getObject(minioBucket, path))
|
||||
{
|
||||
return ByteStreams.toByteArray(in);
|
||||
}
|
||||
catch (InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException | InvalidKeyException | NoResponseException | XmlPullParserException | ErrorResponseException | InternalException | InvalidArgumentException ex)
|
||||
{
|
||||
logger.warn(null, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ArchiveFiles getArchiveFiles(IndexType index, ConfigType config,
|
||||
ArchiveEntry archiveEntry) throws IOException
|
||||
{
|
||||
List<FileEntry> files;
|
||||
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
files = cacheDao.findFilesForArchive(con, archiveEntry);
|
||||
}
|
||||
|
||||
byte[] archiveData = getArchive(index.getNumber(), config.getId(), archiveEntry.getRevision());
|
||||
|
||||
if (archiveData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
DataFileReadResult result = DataFile.decompress(archiveData, null);
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] decompressedData = result.data;
|
||||
|
||||
ArchiveFiles archiveFiles = new ArchiveFiles();
|
||||
for (FileEntry fileEntry : files)
|
||||
{
|
||||
FSFile file = new FSFile(fileEntry.getFileId());
|
||||
archiveFiles.addFile(file);
|
||||
file.setNameHash(fileEntry.getNameHash());
|
||||
}
|
||||
archiveFiles.loadContents(decompressedData);
|
||||
return archiveFiles;
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public List<Cache> listCaches()
|
||||
{
|
||||
List<CacheEntry> caches;
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
caches = cacheDao.listCaches(con);
|
||||
}
|
||||
return caches.stream()
|
||||
.map(entry -> new Cache(entry.getId(), entry.getRevision(), entry.getDate()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@RequestMapping("{cacheId}")
|
||||
public List<CacheIndex> listIndexes(@PathVariable int cacheId)
|
||||
{
|
||||
List<IndexEntry> indexes;
|
||||
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
CacheEntry cacheEntry = cacheDao.findCache(con, cacheId);
|
||||
if (cacheEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
indexes = cacheDao.findIndexesForCache(con, cacheEntry);
|
||||
}
|
||||
|
||||
return indexes.stream()
|
||||
.map(entry -> new CacheIndex(entry.getIndexId(), entry.getRevision()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@RequestMapping("{cacheId}/{indexId}")
|
||||
public List<CacheArchive> listArchives(@PathVariable int cacheId,
|
||||
@PathVariable int indexId)
|
||||
{
|
||||
List<ArchiveEntry> archives;
|
||||
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
CacheEntry cacheEntry = cacheDao.findCache(con, cacheId);
|
||||
if (cacheEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
IndexEntry indexEntry = cacheDao.findIndexForCache(con, cacheEntry, indexId);
|
||||
if (indexEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
archives = cacheDao.findArchivesForIndex(con, indexEntry);
|
||||
}
|
||||
|
||||
return archives.stream()
|
||||
.map(archive -> new CacheArchive(archive.getArchiveId(), archive.getNameHash(), archive.getRevision()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@RequestMapping("{cacheId}/{indexId}/{archiveId}")
|
||||
public CacheArchive getCacheArchive(@PathVariable int cacheId,
|
||||
@PathVariable int indexId,
|
||||
@PathVariable int archiveId)
|
||||
{
|
||||
ArchiveEntry archiveEntry;
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
CacheEntry cacheEntry = cacheDao.findCache(con, cacheId);
|
||||
if (cacheEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
IndexEntry indexEntry = cacheDao.findIndexForCache(con, cacheEntry, indexId);
|
||||
if (indexEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
archiveEntry = cacheDao.findArchiveForIndex(con, indexEntry, archiveId);
|
||||
}
|
||||
|
||||
return new CacheArchive(archiveEntry.getArchiveId(),
|
||||
archiveEntry.getNameHash(), archiveEntry.getRevision());
|
||||
}
|
||||
|
||||
@RequestMapping("{cacheId}/{indexId}/{archiveId}/data")
|
||||
public byte[] getArchiveData(
|
||||
@PathVariable int cacheId,
|
||||
@PathVariable int indexId,
|
||||
@PathVariable int archiveId
|
||||
)
|
||||
{
|
||||
ArchiveEntry archiveEntry;
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
CacheEntry cacheEntry = cacheDao.findCache(con, cacheId);
|
||||
if (cacheEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
IndexEntry indexEntry = cacheDao.findIndexForCache(con, cacheEntry, indexId);
|
||||
if (indexEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
archiveEntry = cacheDao.findArchiveForIndex(con, indexEntry, archiveId);
|
||||
}
|
||||
|
||||
return getArchive(indexId, archiveId, archiveEntry.getRevision());
|
||||
}
|
||||
|
||||
@RequestMapping("item/{itemId}")
|
||||
public ItemDefinition getItem(@PathVariable int itemId) throws IOException
|
||||
{
|
||||
ArchiveEntry archiveEntry;
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
archiveEntry = cacheDao.findMostRecentArchive(con, IndexType.CONFIGS.getNumber(), ConfigType.ITEM.getId());
|
||||
if (archiveEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveFiles archiveFiles = getArchiveFiles(IndexType.CONFIGS, ConfigType.ITEM, archiveEntry);
|
||||
if (archiveFiles == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
FSFile file = archiveFiles.findFile(itemId);
|
||||
if (file == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
ItemDefinition itemdef = new ItemLoader().load(itemId, file.getContents());
|
||||
return itemdef;
|
||||
}
|
||||
|
||||
@RequestMapping("object/{objectId}")
|
||||
public ObjectDefinition getObject(
|
||||
@PathVariable int objectId
|
||||
) throws IOException
|
||||
{
|
||||
ArchiveEntry archiveEntry;
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
archiveEntry = cacheDao.findMostRecentArchive(con, IndexType.CONFIGS.getNumber(), ConfigType.OBJECT.getId());
|
||||
if (archiveEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveFiles archiveFiles = getArchiveFiles(IndexType.CONFIGS, ConfigType.OBJECT, archiveEntry);
|
||||
if (archiveFiles == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
FSFile file = archiveFiles.findFile(objectId);
|
||||
if (file == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
ObjectDefinition objectdef = new ObjectLoader().load(objectId, file.getContents());
|
||||
return objectdef;
|
||||
}
|
||||
|
||||
@RequestMapping("npc/{npcId}")
|
||||
public NpcDefinition getNpc(
|
||||
@PathVariable int npcId
|
||||
) throws IOException
|
||||
{
|
||||
ArchiveEntry archiveEntry;
|
||||
try (Connection con = sql2o.open())
|
||||
{
|
||||
CacheDAO cacheDao = new CacheDAO();
|
||||
archiveEntry = cacheDao.findMostRecentArchive(con, IndexType.CONFIGS.getNumber(), ConfigType.NPC.getId());
|
||||
if (archiveEntry == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveFiles archiveFiles = getArchiveFiles(IndexType.CONFIGS, ConfigType.NPC, archiveEntry);
|
||||
if (archiveFiles == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
FSFile file = archiveFiles.findFile(npcId);
|
||||
if (file == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
NpcDefinition npcdef = new NpcLoader().load(npcId, file.getContents());
|
||||
return npcdef;
|
||||
}
|
||||
}
|
||||
126
http-service/src/main/java/net/runelite/http/service/cache/CacheStorage.java
vendored
Normal file
126
http-service/src/main/java/net/runelite/http/service/cache/CacheStorage.java
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 net.runelite.cache.fs.Archive;
|
||||
import net.runelite.cache.fs.FSFile;
|
||||
import net.runelite.cache.fs.Index;
|
||||
import net.runelite.cache.fs.Storage;
|
||||
import net.runelite.cache.fs.Store;
|
||||
import net.runelite.http.service.cache.beans.ArchiveEntry;
|
||||
import net.runelite.http.service.cache.beans.CacheEntry;
|
||||
import net.runelite.http.service.cache.beans.FileEntry;
|
||||
import net.runelite.http.service.cache.beans.IndexEntry;
|
||||
import org.sql2o.Connection;
|
||||
|
||||
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.setRevision(indexEntry.getRevision());
|
||||
|
||||
List<ArchiveEntry> archives = cacheDao.findArchivesForIndex(con, indexEntry);
|
||||
for (ArchiveEntry archiveEntry : archives)
|
||||
{
|
||||
Archive archive = index.addArchive(archiveEntry.getArchiveId());
|
||||
archive.setRevision(archiveEntry.getRevision());
|
||||
archive.setNameHash(archiveEntry.getNameHash());
|
||||
|
||||
List<FileEntry> files = cacheDao.findFilesForArchive(con, archiveEntry);
|
||||
for (FileEntry fileEntry : files)
|
||||
{
|
||||
FSFile file = archive.addFile(fileEntry.getFileId());
|
||||
file.setNameHash(fileEntry.getNameHash());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Store store) throws IOException
|
||||
{
|
||||
for (Index index : store.getIndexes())
|
||||
{
|
||||
IndexEntry entry = cacheDao.findOrCreateIndex(con, cacheEntry, index.getId(), index.getRevision());
|
||||
// this assumes nothing is associated to the cache yet
|
||||
cacheDao.associateIndexToCache(con, cacheEntry, entry);
|
||||
|
||||
for (Archive archive : index.getArchives())
|
||||
{
|
||||
ArchiveEntry archiveEntry = cacheDao.findArchive(con, entry, archive.getArchiveId(),
|
||||
archive.getNameHash(), archive.getRevision());
|
||||
if (archiveEntry == null)
|
||||
{
|
||||
archiveEntry = cacheDao.createArchive(con, entry, archive.getArchiveId(), archive.getNameHash(), archive.getRevision());
|
||||
|
||||
for (FSFile file : archive.getFiles())
|
||||
{
|
||||
cacheDao.associateFileToArchive(con, archiveEntry, file.getFileId(), file.getNameHash());
|
||||
}
|
||||
}
|
||||
cacheDao.associateArchiveToIndex(con, archiveEntry, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
159
http-service/src/main/java/net/runelite/http/service/cache/CacheUpdater.java
vendored
Normal file
159
http-service/src/main/java/net/runelite/http/service/cache/CacheUpdater.java
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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 static net.runelite.cache.client.requests.HelloHandshake.RESPONSE_OK;
|
||||
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 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) -> executor.submit(new CacheUploader(minioClient, minioBucket, archive)));
|
||||
|
||||
client.connect();
|
||||
int result = client.handshake().join();
|
||||
|
||||
if (result != RESPONSE_OK)
|
||||
{
|
||||
throw new OutOfDateException();
|
||||
}
|
||||
|
||||
List<IndexInfo> indexes = client.requestIndexes();
|
||||
List<IndexEntry> entries = cacheDao.findIndexesForCache(con, cache);
|
||||
|
||||
if (!checkOutOfDate(indexes, entries))
|
||||
{
|
||||
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())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
90
http-service/src/main/java/net/runelite/http/service/cache/CacheUploader.java
vendored
Normal file
90
http-service/src/main/java/net/runelite/http/service/cache/CacheUploader.java
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.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;
|
||||
|
||||
public CacheUploader(MinioClient minioClient, String minioBucket, Archive archive)
|
||||
{
|
||||
this.minioClient = minioClient;
|
||||
this.minioBucket = minioBucket;
|
||||
this.archive = archive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
byte[] data = archive.getData();
|
||||
String path = new StringBuilder()
|
||||
.append(archive.getIndex().getId())
|
||||
.append('/')
|
||||
.append(archive.getArchiveId())
|
||||
.append('/')
|
||||
.append(archive.getRevision())
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
34
http-service/src/main/java/net/runelite/http/service/cache/NotFoundException.java
vendored
Normal file
34
http-service/src/main/java/net/runelite/http/service/cache/NotFoundException.java
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Not found")
|
||||
public class NotFoundException extends RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
33
http-service/src/main/java/net/runelite/http/service/cache/OutOfDateException.java
vendored
Normal file
33
http-service/src/main/java/net/runelite/http/service/cache/OutOfDateException.java
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
|
||||
}
|
||||
126
http-service/src/main/java/net/runelite/http/service/cache/beans/ArchiveEntry.java
vendored
Normal file
126
http-service/src/main/java/net/runelite/http/service/cache/beans/ArchiveEntry.java
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.beans;
|
||||
|
||||
public class ArchiveEntry
|
||||
{
|
||||
private int id;
|
||||
private int archiveId;
|
||||
private int nameHash;
|
||||
private int revision;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "ArchiveEntry{" + "id=" + id + ", archiveId=" + archiveId + ", nameHash=" + nameHash + ", revision=" + revision + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 7;
|
||||
hash = 89 * hash + this.id;
|
||||
hash = 89 * hash + this.archiveId;
|
||||
hash = 89 * hash + this.nameHash;
|
||||
hash = 89 * 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 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.revision != other.revision)
|
||||
{
|
||||
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 getRevision()
|
||||
{
|
||||
return revision;
|
||||
}
|
||||
|
||||
public void setRevision(int revision)
|
||||
{
|
||||
this.revision = revision;
|
||||
}
|
||||
|
||||
}
|
||||
112
http-service/src/main/java/net/runelite/http/service/cache/beans/CacheEntry.java
vendored
Normal file
112
http-service/src/main/java/net/runelite/http/service/cache/beans/CacheEntry.java
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.beans;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
126
http-service/src/main/java/net/runelite/http/service/cache/beans/FileEntry.java
vendored
Normal file
126
http-service/src/main/java/net/runelite/http/service/cache/beans/FileEntry.java
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.beans;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
109
http-service/src/main/java/net/runelite/http/service/cache/beans/IndexEntry.java
vendored
Normal file
109
http-service/src/main/java/net/runelite/http/service/cache/beans/IndexEntry.java
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.beans;
|
||||
|
||||
public class IndexEntry
|
||||
{
|
||||
private int id;
|
||||
private int indexId;
|
||||
private int revision;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "IndexEntry{" + "id=" + id + ", indexId=" + indexId + ", revision=" + revision + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 5;
|
||||
hash = 83 * hash + this.id;
|
||||
hash = 83 * hash + this.indexId;
|
||||
hash = 83 * 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.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 getRevision()
|
||||
{
|
||||
return revision;
|
||||
}
|
||||
|
||||
public void setRevision(int revision)
|
||||
{
|
||||
this.revision = revision;
|
||||
}
|
||||
}
|
||||
132
http-service/src/main/java/net/runelite/http/service/cache/schema.sql
vendored
Normal file
132
http-service/src/main/java/net/runelite/http/service/cache/schema.sql
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
-- MySQL dump 10.16 Distrib 10.2.8-MariaDB, for osx10.12 (x86_64)
|
||||
--
|
||||
-- Host: localhost Database: cache
|
||||
-- ------------------------------------------------------
|
||||
-- Server version 10.2.8-MariaDB
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
--
|
||||
-- Table structure for table `archive`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `archive`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `archive` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`archiveId` int(11) NOT NULL,
|
||||
`nameHash` int(11) NOT NULL,
|
||||
`revision` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `archive_revision` (`archiveId`,`revision`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `cache`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `cache`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `cache` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`revision` int(11) NOT NULL,
|
||||
`date` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `revision_date` (`revision`,`date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `cache_index`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `cache_index`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `cache_index` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`cache` int(11) NOT NULL,
|
||||
`index` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `cacheId` (`cache`),
|
||||
KEY `indexId` (`index`),
|
||||
CONSTRAINT `cache_index_ibfk_1` FOREIGN KEY (`cache`) REFERENCES `cache` (`id`),
|
||||
CONSTRAINT `cache_index_ibfk_2` FOREIGN KEY (`index`) REFERENCES `index` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `file`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `file`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `file` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`archive` int(11) NOT NULL,
|
||||
`fileId` int(11) NOT NULL,
|
||||
`nameHash` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `archive_file` (`archive`,`fileId`),
|
||||
CONSTRAINT `file_ibfk_1` FOREIGN KEY (`archive`) REFERENCES `archive` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `index`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `index`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `index` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`indexId` int(11) NOT NULL,
|
||||
`revision` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `indexId` (`indexId`,`revision`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `index_archive`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `index_archive`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `index_archive` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`index` int(11) NOT NULL,
|
||||
`archive` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `index` (`index`) USING BTREE,
|
||||
KEY `archive` (`archive`) USING BTREE,
|
||||
CONSTRAINT `index_archive_ibfk_1` FOREIGN KEY (`index`) REFERENCES `index` (`id`),
|
||||
CONSTRAINT `index_archive_ibfk_2` FOREIGN KEY (`archive`) REFERENCES `archive` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2017-09-10 13:11:23
|
||||
@@ -27,6 +27,7 @@ package net.runelite.http.service;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.naming.NamingException;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@@ -44,8 +45,15 @@ public class SpringBootWebApplicationTest
|
||||
{
|
||||
Map<Class, Converter> converters = new HashMap<>();
|
||||
converters.put(Instant.class, new InstantConverter());
|
||||
return new Sql2o("jdbc:mysql://192.168.1.2/runelite", "adam", "", new NoQuirks(converters));
|
||||
return new Sql2o("jdbc:mysql://localhost/runelite", "root", "", new NoQuirks(converters));
|
||||
}
|
||||
|
||||
@Bean("Runelite Cache SQL2O")
|
||||
Sql2o cacheSql2o() throws NamingException
|
||||
{
|
||||
Map<Class, Converter> converters = new HashMap<>();
|
||||
converters.put(Instant.class, new InstantConverter());
|
||||
return new Sql2o("jdbc:mysql://localhost/cache", "root", "", new NoQuirks(converters));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
oauth.client-id=moo
|
||||
oauth.client-secret=cow
|
||||
oauth.client-secret=cow
|
||||
minio.endpoint=http://10.96.22.171:9000
|
||||
minio.accesskey=AM54M27O4WZK65N6F8IP
|
||||
minio.secretkey=/PZCxzmsJzwCHYlogcymuprniGCaaLUOET2n6yMP
|
||||
minio.bucket=runelite
|
||||
auth.password=password
|
||||
|
||||
Reference in New Issue
Block a user