Combine master_index_{archive,group}_stats

Signed-off-by: Graham <gpe@openrs2.org>
Graham 4 years ago
parent 20988a70cc
commit 70644b5e06
  1. 72
      archive/src/main/kotlin/org/openrs2/archive/cache/CacheExporter.kt
  2. 81
      archive/src/main/resources/org/openrs2/archive/migrations/V1__init.sql
  3. 18
      archive/src/main/resources/org/openrs2/archive/templates/caches/index.html
  4. 12
      archive/src/main/resources/org/openrs2/archive/templates/caches/show.html

@ -17,16 +17,21 @@ public class CacheExporter @Inject constructor(
private val database: Database, private val database: Database,
private val alloc: ByteBufAllocator private val alloc: ByteBufAllocator
) { ) {
public data class ArchiveStats(val indexes: Long, val validIndexes: Long) { public data class Stats(
val validIndexes: Long,
val indexes: Long,
val validGroups: Long,
val groups: Long,
val validKeys: Long,
val keys: Long
) {
public val allIndexesValid: Boolean = indexes == validIndexes public val allIndexesValid: Boolean = indexes == validIndexes
public val validIndexesFraction: Double = if (indexes == 0L) { public val validIndexesFraction: Double = if (indexes == 0L) {
1.0 1.0
} else { } else {
validIndexes.toDouble() / indexes validIndexes.toDouble() / indexes
} }
}
public data class GroupStats(val groups: Long, val validGroups: Long, val keys: Long, val validKeys: Long) {
public val allGroupsValid: Boolean = groups == validGroups public val allGroupsValid: Boolean = groups == validGroups
public val validGroupsFraction: Double = if (groups == 0L) { public val validGroupsFraction: Double = if (groups == 0L) {
1.0 1.0
@ -49,8 +54,7 @@ public class CacheExporter @Inject constructor(
val timestamp: Instant?, val timestamp: Instant?,
val name: String?, val name: String?,
val description: String?, val description: String?,
val archiveStats: ArchiveStats?, val stats: Stats?
val groupStats: GroupStats?
) )
public data class Key( public data class Key(
@ -68,12 +72,11 @@ public class CacheExporter @Inject constructor(
""" """
SELECT SELECT
m.id, g.name, m.build, m.timestamp, m.name, m.id, g.name, m.build, m.timestamp, m.name,
a.indexes, a.valid_indexes, gs.groups, gs.valid_groups, gs.keys, gs.valid_keys s.valid_indexes, s.indexes, s.valid_groups, s.groups, s.valid_keys, s.keys
FROM master_indexes m FROM master_indexes m
JOIN games g ON g.id = m.game_id JOIN games g ON g.id = m.game_id
JOIN containers c ON c.id = m.container_id JOIN containers c ON c.id = m.container_id
LEFT JOIN master_index_archive_stats a ON a.master_index_id = m.id LEFT JOIN master_index_stats s ON s.master_index_id = m.id
LEFT JOIN master_index_group_stats gs ON gs.master_index_id = m.id
ORDER BY g.name ASC, m.build ASC, m.timestamp ASC ORDER BY g.name ASC, m.build ASC, m.timestamp ASC
""".trimIndent() """.trimIndent()
).use { stmt -> ).use { stmt ->
@ -92,25 +95,19 @@ public class CacheExporter @Inject constructor(
val timestamp = rows.getTimestamp(4)?.toInstant() val timestamp = rows.getTimestamp(4)?.toInstant()
val name = rows.getString(5) val name = rows.getString(5)
val indexes = rows.getLong(6) val validIndexes = rows.getLong(6)
val archiveStats = if (!rows.wasNull()) { val stats = if (!rows.wasNull()) {
val validIndexes = rows.getLong(7) val indexes = rows.getLong(7)
ArchiveStats(indexes, validIndexes) val validGroups = rows.getLong(8)
} else { val groups = rows.getLong(9)
null val validKeys = rows.getLong(10)
} val keys = rows.getLong(11)
Stats(validIndexes, indexes, validGroups, groups, validKeys, keys)
val groups = rows.getLong(8)
val groupStats = if (!rows.wasNull()) {
val validGroups = rows.getLong(9)
val keys = rows.getLong(10)
val validKeys = rows.getLong(11)
GroupStats(groups, validGroups, keys, validKeys)
} else { } else {
null null
} }
caches += Cache(id, game, build, timestamp, name, description = null, archiveStats, groupStats) caches += Cache(id, game, build, timestamp, name, description = null, stats)
} }
caches caches
@ -125,12 +122,11 @@ public class CacheExporter @Inject constructor(
""" """
SELECT SELECT
g.name, m.build, m.timestamp, m.name, m.description, g.name, m.build, m.timestamp, m.name, m.description,
a.indexes, a.valid_indexes, gs.groups, gs.valid_groups, gs.keys, gs.valid_keys s.valid_indexes, s.indexes, s.valid_groups, s.groups, s.valid_keys, s.keys
FROM master_indexes m FROM master_indexes m
JOIN games g ON g.id = m.game_id JOIN games g ON g.id = m.game_id
JOIN containers c ON c.id = m.container_id JOIN containers c ON c.id = m.container_id
LEFT JOIN master_index_archive_stats a ON a.master_index_id = m.id LEFT JOIN master_index_stats s ON s.master_index_id = m.id
LEFT JOIN master_index_group_stats gs ON gs.master_index_id = m.id
WHERE m.id = ? WHERE m.id = ?
""".trimIndent() """.trimIndent()
).use { stmt -> ).use { stmt ->
@ -152,25 +148,19 @@ public class CacheExporter @Inject constructor(
val name = rows.getString(4) val name = rows.getString(4)
val description = rows.getString(5) val description = rows.getString(5)
val indexes = rows.getLong(6) val validIndexes = rows.getLong(6)
val archiveStats = if (!rows.wasNull()) { val stats = if (!rows.wasNull()) {
val validIndexes = rows.getLong(7) val indexes = rows.getLong(7)
ArchiveStats(indexes, validIndexes) val validGroups = rows.getLong(8)
} else { val groups = rows.getLong(9)
null val validKeys = rows.getLong(10)
} val keys = rows.getLong(11)
Stats(validIndexes, indexes, validGroups, groups, validKeys, keys)
val groups = rows.getLong(8)
val groupStats = if (!rows.wasNull()) {
val validGroups = rows.getLong(9)
val keys = rows.getLong(10)
val validKeys = rows.getLong(11)
GroupStats(groups, validGroups, keys, validKeys)
} else { } else {
null null
} }
return@execute Cache(id, game, build, timestamp, name, description, archiveStats, groupStats) return@execute Cache(id, game, build, timestamp, name, description, stats)
} }
} }
} }

@ -160,37 +160,58 @@ JOIN groups g ON g.archive_id = i.archive_id AND g.group_id = ig.group_id AND (
) )
JOIN containers c ON c.id = g.container_id AND c.crc32 = ig.crc32; JOIN containers c ON c.id = g.container_id AND c.crc32 = ig.crc32;
CREATE MATERIALIZED VIEW master_index_archive_stats (master_index_id, indexes, valid_indexes) AS CREATE MATERIALIZED VIEW master_index_stats (
SELECT a.master_index_id, COUNT(*), COUNT(i.container_id) master_index_id,
FROM master_index_archives a valid_indexes,
LEFT JOIN groups g ON g.archive_id = 255 AND g.group_id = a.archive_id::INTEGER AND indexes,
g.version = a.version AND NOT g.version_truncated AND valid_groups,
g.container_id IN (SELECT id FROM containers WHERE crc32 = a.crc32) groups,
LEFT JOIN containers c ON c.id = g.container_id valid_keys,
LEFT JOIN indexes i ON i.container_id = g.container_id AND i.version = a.version keys,
GROUP BY a.master_index_id; size
) AS
CREATE UNIQUE INDEX ON master_index_archive_stats (master_index_id);
CREATE MATERIALIZED VIEW master_index_group_stats (master_index_id, groups, valid_groups, keys, valid_keys, size) AS
SELECT SELECT
i.master_index_id, a.master_index_id,
COUNT(*), a.valid_indexes,
COUNT(g.container_id), a.indexes,
COUNT(*) FILTER (WHERE c.encrypted), COALESCE(g.valid_groups, 0),
COUNT(*) FILTER (WHERE c.key_id IS NOT NULL), COALESCE(g.groups, 0),
SUM(length(c.data)) COALESCE(g.valid_keys, 0),
FROM resolved_indexes i COALESCE(g.keys, 0),
JOIN index_groups ig ON ig.container_id = i.container_id COALESCE(g.size, 0)
LEFT JOIN groups g ON g.archive_id = i.archive_id AND g.group_id = ig.group_id AND ( FROM (
(g.version = ig.version AND NOT g.version_truncated) OR SELECT
(g.version = ig.version & 65535 AND g.version_truncated) a.master_index_id,
) AND g.container_id IN (SELECT id FROM containers WHERE crc32 = ig.crc32) COUNT(i.container_id) AS valid_indexes,
LEFT JOIN containers c ON c.id = g.container_id COUNT(*) AS indexes
LEFT JOIN keys k ON k.id = c.key_id FROM master_index_archives a
GROUP BY i.master_index_id; LEFT JOIN groups g ON g.archive_id = 255 AND g.group_id = a.archive_id::INTEGER AND
g.version = a.version AND NOT g.version_truncated AND
CREATE UNIQUE INDEX ON master_index_group_stats (master_index_id); g.container_id IN (SELECT id FROM containers WHERE crc32 = a.crc32)
LEFT JOIN containers c ON c.id = g.container_id
LEFT JOIN indexes i ON i.container_id = g.container_id AND i.version = a.version
GROUP BY a.master_index_id
) a
LEFT JOIN (
SELECT
i.master_index_id,
COUNT(g.container_id) AS valid_groups,
COUNT(*) AS groups,
COUNT(*) FILTER (WHERE c.key_id IS NOT NULL) AS valid_keys,
COUNT(*) FILTER (WHERE c.encrypted) AS keys,
SUM(length(c.data)) AS size
FROM resolved_indexes i
JOIN index_groups ig ON ig.container_id = i.container_id
LEFT JOIN groups g ON g.archive_id = i.archive_id AND g.group_id = ig.group_id AND (
(g.version = ig.version AND NOT g.version_truncated) OR
(g.version = ig.version & 65535 AND g.version_truncated)
) AND g.container_id IN (SELECT id FROM containers WHERE crc32 = ig.crc32)
LEFT JOIN containers c ON c.id = g.container_id
LEFT JOIN keys k ON k.id = c.key_id
GROUP BY i.master_index_id
) g ON g.master_index_id = a.master_index_id;
CREATE UNIQUE INDEX ON master_index_stats (master_index_id);
CREATE VIEW collisions (archive_id, group_id, crc32, truncated_version, containers) AS CREATE VIEW collisions (archive_id, group_id, crc32, truncated_version, containers) AS
SELECT g.archive_id, g.group_id, c.crc32, g.version & 65535 AS truncated_version, COUNT(DISTINCT c.id) SELECT g.archive_id, g.group_id, c.crc32, g.version & 65535 AS truncated_version, COUNT(DISTINCT c.id)

@ -33,29 +33,29 @@
<span th:text="${#temporals.format(cache.timestamp, 'HH:mm:ss')}"></span> <span th:text="${#temporals.format(cache.timestamp, 'HH:mm:ss')}"></span>
</td> </td>
<td th:text="${cache.name}"></td> <td th:text="${cache.name}"></td>
<td th:classappend="${cache.archiveStats}? (${cache.archiveStats.allIndexesValid}? 'table-success' : 'table-danger')" <td th:classappend="${cache.stats}? (${cache.stats.allIndexesValid}? 'table-success' : 'table-danger')"
class="text-right"> class="text-right">
<span <span
th:text="${cache.archiveStats}? ${cache.archiveStats.validIndexes} + '&nbsp;/&nbsp;' + ${cache.archiveStats.indexes}"></span> th:text="${cache.stats}? ${cache.stats.validIndexes} + '&nbsp;/&nbsp;' + ${cache.stats.indexes}"></span>
<br /> <br />
<span <span
th:text="${cache.archiveStats}? '(' + ${#numbers.formatPercent(cache.archiveStats.validIndexesFraction, 1, 2)} + ')' : 'Calculating...'"></span> th:text="${cache.stats}? '(' + ${#numbers.formatPercent(cache.stats.validIndexesFraction, 1, 2)} + ')' : 'Calculating...'"></span>
</td> </td>
<td th:classappend="${cache.groupStats}? (${cache.groupStats.allGroupsValid}? 'table-success' : 'table-warning')" <td th:classappend="${cache.stats}? (${cache.stats.allGroupsValid}? 'table-success' : 'table-warning')"
class="text-right"> class="text-right">
<span <span
th:text="${cache.groupStats}? ${#numbers.formatInteger(cache.groupStats.validGroups, 1, 'COMMA')} + '&nbsp;/&nbsp;' + ${#numbers.formatInteger(cache.groupStats.groups, 1, 'COMMA')}"></span> th:text="${cache.stats}? ${#numbers.formatInteger(cache.stats.validGroups, 1, 'COMMA')} + '&nbsp;/&nbsp;' + ${#numbers.formatInteger(cache.stats.groups, 1, 'COMMA')}"></span>
<br /> <br />
<span <span
th:text="${cache.groupStats}? '(' + ${#numbers.formatPercent(cache.groupStats.validGroupsFraction, 1, 2)} + ')' : 'Calculating...'"></span> th:text="${cache.stats}? '(' + ${#numbers.formatPercent(cache.stats.validGroupsFraction, 1, 2)} + ')' : 'Calculating...'"></span>
</td> </td>
<td th:classappend="${cache.groupStats}? (${cache.groupStats.allKeysValid}? 'table-success' : 'table-warning')" <td th:classappend="${cache.stats}? (${cache.stats.allKeysValid}? 'table-success' : 'table-warning')"
class="text-right"> class="text-right">
<span <span
th:text="${cache.groupStats}? ${#numbers.formatInteger(cache.groupStats.validKeys, 1, 'COMMA')} + '&nbsp;/&nbsp;' + ${#numbers.formatInteger(cache.groupStats.keys, 1, 'COMMA')}"></span> th:text="${cache.stats}? ${#numbers.formatInteger(cache.stats.validKeys, 1, 'COMMA')} + '&nbsp;/&nbsp;' + ${#numbers.formatInteger(cache.stats.keys, 1, 'COMMA')}"></span>
<br /> <br />
<span <span
th:text="${cache.groupStats}? '(' + ${#numbers.formatPercent(cache.groupStats.validKeysFraction, 1, 2)} + ')' : 'Calculating...'"></span> th:text="${cache.stats}? '(' + ${#numbers.formatPercent(cache.stats.validKeysFraction, 1, 2)} + ')' : 'Calculating...'"></span>
</td> </td>
<td> <td>
<div class="btn-group"> <div class="btn-group">

@ -33,22 +33,22 @@
</tr> </tr>
<tr class="thead-dark"> <tr class="thead-dark">
<th>Indexes</th> <th>Indexes</th>
<td th:class="${cache.archiveStats}? (${cache.archiveStats.allIndexesValid}? 'table-success' : 'table-danger')" <td th:class="${cache.stats}? (${cache.stats.allIndexesValid}? 'table-success' : 'table-danger')"
th:text="${cache.archiveStats}? ${cache.archiveStats.validIndexes} + ' / ' + ${cache.archiveStats.indexes} + ' (' + ${#numbers.formatPercent(cache.archiveStats.validIndexesFraction, 1, 2)} + ')' : 'Calculating...'"> th:text="${cache.stats}? ${cache.stats.validIndexes} + ' / ' + ${cache.stats.indexes} + ' (' + ${#numbers.formatPercent(cache.stats.validIndexesFraction, 1, 2)} + ')' : 'Calculating...'">
Calculating... Calculating...
</td> </td>
</tr> </tr>
<tr class="thead-dark"> <tr class="thead-dark">
<th>Groups</th> <th>Groups</th>
<td th:class="${cache.groupStats}? (${cache.groupStats.allGroupsValid}? 'table-success' : 'table-warning')" <td th:class="${cache.stats}? (${cache.stats.allGroupsValid}? 'table-success' : 'table-warning')"
th:text="${cache.groupStats}? ${#numbers.formatInteger(cache.groupStats.validGroups, 1, 'COMMA')} + ' / ' + ${#numbers.formatInteger(cache.groupStats.groups, 1, 'COMMA')} + ' (' + ${#numbers.formatPercent(cache.groupStats.validGroupsFraction, 1, 2)} + ')' : 'Calculating...'"> th:text="${cache.stats}? ${#numbers.formatInteger(cache.stats.validGroups, 1, 'COMMA')} + ' / ' + ${#numbers.formatInteger(cache.stats.groups, 1, 'COMMA')} + ' (' + ${#numbers.formatPercent(cache.stats.validGroupsFraction, 1, 2)} + ')' : 'Calculating...'">
Calculating... Calculating...
</td> </td>
</tr> </tr>
<tr class="thead-dark"> <tr class="thead-dark">
<th>Keys</th> <th>Keys</th>
<td th:class="${cache.groupStats}? (${cache.groupStats.allKeysValid}? 'table-success' : 'table-warning')" <td th:class="${cache.stats}? (${cache.stats.allKeysValid}? 'table-success' : 'table-warning')"
th:text="${cache.groupStats}? ${#numbers.formatInteger(cache.groupStats.validKeys, 1, 'COMMA')} + ' / ' + ${#numbers.formatInteger(cache.groupStats.keys, 1, 'COMMA')} + ' (' + ${#numbers.formatPercent(cache.groupStats.validKeysFraction, 1, 2)} + ')' : 'Calculating...'"> th:text="${cache.stats}? ${#numbers.formatInteger(cache.stats.validKeys, 1, 'COMMA')} + ' / ' + ${#numbers.formatInteger(cache.stats.keys, 1, 'COMMA')} + ' (' + ${#numbers.formatPercent(cache.stats.validKeysFraction, 1, 2)} + ')' : 'Calculating...'">
Calculating... Calculating...
</td> </td>
</tr> </tr>

Loading…
Cancel
Save