Add name and description to the master_indexes table

Signed-off-by: Graham <gpe@openrs2.org>
Graham 4 years ago
parent dc9852e77c
commit a19a69b21e
  1. 8
      archive/src/main/kotlin/org/openrs2/archive/cache/CacheExporter.kt
  2. 66
      archive/src/main/kotlin/org/openrs2/archive/cache/CacheImporter.kt
  3. 4
      archive/src/main/kotlin/org/openrs2/archive/cache/ImportCommand.kt
  4. 4
      archive/src/main/kotlin/org/openrs2/archive/cache/ImportMasterIndexCommand.kt
  5. 3
      archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt
  6. 4
      archive/src/main/resources/org/openrs2/archive/V1__init.sql
  7. 2
      archive/src/main/resources/org/openrs2/archive/templates/caches/index.html

@ -20,14 +20,15 @@ public class CacheExporter @Inject constructor(
val whirlpool: ByteArray,
val game: String,
val build: Int?,
val timestamp: Instant?
val timestamp: Instant?,
val name: String?
)
public suspend fun list(): List<Cache> {
return database.execute { connection ->
connection.prepareStatement(
"""
SELECT c.id, c.whirlpool, g.name, m.build, m.timestamp
SELECT c.id, c.whirlpool, g.name, m.build, m.timestamp, m.name
FROM master_indexes m
JOIN games g ON g.id = m.game_id
JOIN containers c ON c.id = m.container_id
@ -48,8 +49,9 @@ public class CacheExporter @Inject constructor(
}
val timestamp = rows.getTimestamp(5)?.toInstant()
val name = rows.getString(6)
caches += Cache(id, whirlpool, game, build, timestamp)
caches += Cache(id, whirlpool, game, build, timestamp, name)
}
caches

@ -60,7 +60,14 @@ public class CacheImporter @Inject constructor(
encrypted: Boolean
) : Container(data, encrypted)
public suspend fun import(store: Store, game: String, build: Int?, timestamp: Instant?) {
public suspend fun import(
store: Store,
game: String,
build: Int?,
timestamp: Instant?,
name: String?,
description: String?
) {
database.execute { connection ->
prepare(connection)
@ -69,7 +76,7 @@ public class CacheImporter @Inject constructor(
// import master index
val masterIndex = createMasterIndex(store)
try {
addMasterIndex(connection, masterIndex, gameId, build, timestamp)
addMasterIndex(connection, masterIndex, gameId, build, timestamp, name, description)
} finally {
masterIndex.release()
}
@ -118,7 +125,14 @@ public class CacheImporter @Inject constructor(
}
}
public suspend fun importMasterIndex(buf: ByteBuf, game: String, build: Int?, timestamp: Instant?) {
public suspend fun importMasterIndex(
buf: ByteBuf,
game: String,
build: Int?,
timestamp: Instant?,
name: String?,
description: String?
) {
Js5Compression.uncompress(buf.slice()).use { uncompressed ->
val masterIndex = MasterIndex(Js5MasterIndex.read(uncompressed.slice()), buf)
@ -126,7 +140,7 @@ public class CacheImporter @Inject constructor(
prepare(connection)
val gameId = getGameId(connection, game)
addMasterIndex(connection, masterIndex, gameId, build, timestamp)
addMasterIndex(connection, masterIndex, gameId, build, timestamp, name, description)
}
}
}
@ -136,7 +150,8 @@ public class CacheImporter @Inject constructor(
buf: ByteBuf,
gameId: Int,
build: Int,
timestamp: Instant
timestamp: Instant,
name: String,
): List<ByteBuf?> {
return database.execute { connection ->
prepare(connection)
@ -154,7 +169,7 @@ public class CacheImporter @Inject constructor(
stmt.execute()
}
addMasterIndex(connection, MasterIndex(masterIndex, buf), gameId, build, timestamp)
addMasterIndex(connection, MasterIndex(masterIndex, buf), gameId, build, timestamp, name, null)
connection.prepareStatement(
"""
@ -302,21 +317,32 @@ public class CacheImporter @Inject constructor(
connection: Connection,
masterIndex: MasterIndex,
gameId: Int,
build: Int? = null,
timestamp: Instant? = null
build: Int?,
timestamp: Instant?,
name: String?,
description: String?
) {
val containerId = addContainer(connection, masterIndex)
val savepoint = connection.setSavepoint()
// TODO(gpe): override game_id/build/timestamp if they're null?
// TODO(gpe): combine name/description instead of overwriting one with the other?
// or a mechanism to control priority?
connection.prepareStatement(
"""
INSERT INTO master_indexes (container_id, game_id, build, timestamp)
VALUES (?, ?, ?, ?)
INSERT INTO master_indexes (container_id, game_id, build, timestamp, name, description)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT (container_id) DO UPDATE SET
build = COALESCE(EXCLUDED.build, master_indexes.build),
timestamp = COALESCE(
LEAST(EXCLUDED.timestamp, master_indexes.timestamp),
EXCLUDED.timestamp,
master_indexes.timestamp
),
name = COALESCE(EXCLUDED.name, master_indexes.name),
description = COALESCE(EXCLUDED.description, master_indexes.description)
""".trimIndent()
).use { stmt ->
stmt.setLong(1, containerId)
stmt.setObject(2, gameId, Types.INTEGER)
stmt.setInt(2, gameId)
stmt.setObject(3, build, Types.INTEGER)
if (timestamp != null) {
@ -326,21 +352,17 @@ public class CacheImporter @Inject constructor(
stmt.setNull(4, Types.TIMESTAMP_WITH_TIMEZONE)
}
try {
stmt.execute()
} catch (ex: SQLException) {
if (ex.sqlState == PSQLState.UNIQUE_VIOLATION.state) {
connection.rollback(savepoint)
return@addMasterIndex
}
throw ex
}
stmt.setString(5, name)
stmt.setString(6, description)
stmt.execute()
}
connection.prepareStatement(
"""
INSERT INTO master_index_archives (container_id, archive_id, crc32, version)
VALUES (?, ?, ?, ?)
ON CONFLICT DO NOTHING
""".trimIndent()
).use { stmt ->
for ((i, entry) in masterIndex.index.entries.withIndex()) {

@ -14,6 +14,8 @@ import org.openrs2.cli.instant
public class ImportCommand : CliktCommand(name = "import") {
private val build by option().int()
private val timestamp by option().instant()
private val name by option()
private val description by option()
private val game by argument()
private val input by argument().path(
@ -27,7 +29,7 @@ public class ImportCommand : CliktCommand(name = "import") {
val importer = injector.getInstance(CacheImporter::class.java)
Store.open(input).use { store ->
importer.import(store, game, build, timestamp)
importer.import(store, game, build, timestamp, name, description)
}
}
}

@ -16,6 +16,8 @@ import java.nio.file.Files
public class ImportMasterIndexCommand : CliktCommand(name = "import-master-index") {
private val build by option().int()
private val timestamp by option().instant()
private val name by option()
private val description by option()
private val game by argument()
private val input by argument().path(
@ -29,7 +31,7 @@ public class ImportMasterIndexCommand : CliktCommand(name = "import-master-index
val importer = injector.getInstance(CacheImporter::class.java)
Unpooled.wrappedBuffer(Files.readAllBytes(input)).use { buf ->
importer.importMasterIndex(buf, game, build, timestamp)
importer.importMasterIndex(buf, game, build, timestamp, name, description)
}
}
}

@ -158,7 +158,8 @@ public class Js5ChannelHandler(
}
val rawIndexes = runBlocking {
importer.importMasterIndexAndGetIndexes(masterIndex!!, buf, gameId, build, Instant.now())
val name = "Downloaded from $hostname:$port"
importer.importMasterIndexAndGetIndexes(masterIndex!!, buf, gameId, build, Instant.now(), name)
}
try {
indexes = arrayOfNulls(rawIndexes.size)

@ -86,7 +86,9 @@ CREATE TABLE master_indexes (
container_id BIGINT PRIMARY KEY NOT NULL REFERENCES containers (id),
game_id INTEGER NOT NULL REFERENCES games (id),
build INTEGER NULL,
timestamp TIMESTAMPTZ NULL
timestamp TIMESTAMPTZ NULL,
name TEXT NULL,
description TEXT NULL
);
CREATE TABLE master_index_archives (

@ -8,6 +8,7 @@
<th>Game</th>
<th>Build</th>
<th>Timestamp</th>
<th>Name</th>
<th></th>
</tr>
</thead>
@ -18,6 +19,7 @@
<td th:text="${cache.game}">runescape</td>
<td th:text="${cache.build}">550</td>
<td th:text="${#temporals.formatISO(cache.timestamp)}"></td>
<td th:text="${cache.name}"></td>
<td>
<a th:href="${'/caches/' + cache.id + '.zip'}">Download</a>
</td>

Loading…
Cancel
Save