Improve code for merging an old and new master index together

Signed-off-by: Graham <gpe@openrs2.org>
Graham 4 years ago
parent b410b69771
commit 4fa67c37fc
  1. 117
      archive/src/main/kotlin/org/openrs2/archive/cache/CacheImporter.kt

@ -76,7 +76,7 @@ public class CacheImporter @Inject constructor(
// import master index // import master index
val masterIndex = createMasterIndex(store) val masterIndex = createMasterIndex(store)
try { try {
addMasterIndex(connection, masterIndex, gameId, build, timestamp, name, description) addMasterIndex(connection, masterIndex, gameId, build, timestamp, name, description, false)
} finally { } finally {
masterIndex.release() masterIndex.release()
} }
@ -140,7 +140,7 @@ public class CacheImporter @Inject constructor(
prepare(connection) prepare(connection)
val gameId = getGameId(connection, game) val gameId = getGameId(connection, game)
addMasterIndex(connection, masterIndex, gameId, build, timestamp, name, description) addMasterIndex(connection, masterIndex, gameId, build, timestamp, name, description, false)
} }
} }
} }
@ -169,7 +169,7 @@ public class CacheImporter @Inject constructor(
stmt.execute() stmt.execute()
} }
addMasterIndex(connection, MasterIndex(masterIndex, buf), gameId, build, timestamp, name, null) addMasterIndex(connection, MasterIndex(masterIndex, buf), gameId, build, timestamp, name, null, true)
connection.prepareStatement( connection.prepareStatement(
""" """
@ -320,49 +320,126 @@ public class CacheImporter @Inject constructor(
build: Int?, build: Int?,
timestamp: Instant?, timestamp: Instant?,
name: String?, name: String?,
description: String? description: String?,
overwrite: Boolean
) { ) {
val containerId = addContainer(connection, masterIndex) val containerId = addContainer(connection, masterIndex)
var exists: Boolean
var newBuild: Int?
var newTimestamp: Instant?
var newName: String?
var newDescription: String?
connection.prepareStatement(
"""
SELECT game_id, build, timestamp, name, description
FROM master_indexes
WHERE container_id = ?
FOR UPDATE
""".trimIndent()
).use { stmt ->
stmt.setLong(1, containerId)
stmt.executeQuery().use { rows ->
exists = rows.next()
if (exists && !overwrite) {
val oldGameId = rows.getInt(1)
var oldBuild: Int? = rows.getInt(2)
if (rows.wasNull()) {
oldBuild = null
}
val oldTimestamp: Instant? = rows.getTimestamp(3)?.toInstant()
val oldName: String? = rows.getString(4)
val oldDescription: String? = rows.getString(5)
check(oldGameId == gameId)
if (oldBuild != null && build != null) {
check(oldBuild == build)
newBuild = oldBuild
} else if (oldBuild != null) {
newBuild = oldBuild
} else {
newBuild = build
}
if (oldTimestamp != null && timestamp != null) {
newTimestamp = if (oldTimestamp.isBefore(timestamp)) {
oldTimestamp
} else {
timestamp
}
} else if (oldTimestamp != null) {
newTimestamp = oldTimestamp
} else {
newTimestamp = timestamp
}
if (oldName != null && name != null) {
newName = "$oldName/$name"
} else if (oldName != null) {
newName = oldName
} else {
newName = name
}
if (oldDescription != null && description != null) {
newDescription = "$oldDescription\n\n$description"
} else if (oldDescription != null) {
newDescription = oldDescription
} else {
newDescription = description
}
} else {
newBuild = build
newTimestamp = timestamp
newName = name
newDescription = description
}
}
}
// TODO(gpe): combine name/description instead of overwriting one with the other?
// or a mechanism to control priority?
connection.prepareStatement( connection.prepareStatement(
""" """
INSERT INTO master_indexes (container_id, game_id, build, timestamp, name, description) INSERT INTO master_indexes (container_id, game_id, build, timestamp, name, description)
VALUES (?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT (container_id) DO UPDATE SET ON CONFLICT (container_id) DO UPDATE SET
build = COALESCE(EXCLUDED.build, master_indexes.build), game_id = EXCLUDED.game_id,
timestamp = COALESCE( build = EXCLUDED.build,
LEAST(EXCLUDED.timestamp, master_indexes.timestamp), timestamp = EXCLUDED.timestamp,
EXCLUDED.timestamp, name = EXCLUDED.name,
master_indexes.timestamp description = EXCLUDED.description
),
name = COALESCE(EXCLUDED.name, master_indexes.name),
description = COALESCE(EXCLUDED.description, master_indexes.description)
""".trimIndent() """.trimIndent()
).use { stmt -> ).use { stmt ->
stmt.setLong(1, containerId) stmt.setLong(1, containerId)
stmt.setInt(2, gameId) stmt.setInt(2, gameId)
stmt.setObject(3, build, Types.INTEGER) stmt.setObject(3, newBuild, Types.INTEGER)
if (timestamp != null) { if (newTimestamp != null) {
val offsetDateTime = OffsetDateTime.ofInstant(timestamp, ZoneOffset.UTC) val offsetDateTime = OffsetDateTime.ofInstant(newTimestamp, ZoneOffset.UTC)
stmt.setObject(4, offsetDateTime, Types.TIMESTAMP_WITH_TIMEZONE) stmt.setObject(4, offsetDateTime, Types.TIMESTAMP_WITH_TIMEZONE)
} else { } else {
stmt.setNull(4, Types.TIMESTAMP_WITH_TIMEZONE) stmt.setNull(4, Types.TIMESTAMP_WITH_TIMEZONE)
} }
stmt.setString(5, name) stmt.setString(5, newName)
stmt.setString(6, description) stmt.setString(6, newDescription)
stmt.execute() stmt.execute()
} }
if (exists) {
return
}
connection.prepareStatement( connection.prepareStatement(
""" """
INSERT INTO master_index_archives (container_id, archive_id, crc32, version) INSERT INTO master_index_archives (container_id, archive_id, crc32, version)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)
ON CONFLICT DO NOTHING
""".trimIndent() """.trimIndent()
).use { stmt -> ).use { stmt ->
for ((i, entry) in masterIndex.index.entries.withIndex()) { for ((i, entry) in masterIndex.index.entries.withIndex()) {

Loading…
Cancel
Save