Combine master_index_{archive,group}_stats

Signed-off-by: Graham <gpe@openrs2.org>
pull/132/head
Graham 3 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 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 validIndexesFraction: Double = if (indexes == 0L) {
1.0
} else {
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 validGroupsFraction: Double = if (groups == 0L) {
1.0
@ -49,8 +54,7 @@ public class CacheExporter @Inject constructor(
val timestamp: Instant?,
val name: String?,
val description: String?,
val archiveStats: ArchiveStats?,
val groupStats: GroupStats?
val stats: Stats?
)
public data class Key(
@ -68,12 +72,11 @@ public class CacheExporter @Inject constructor(
"""
SELECT
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
JOIN games g ON g.id = m.game_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_group_stats gs ON gs.master_index_id = m.id
LEFT JOIN master_index_stats s ON s.master_index_id = m.id
ORDER BY g.name ASC, m.build ASC, m.timestamp ASC
""".trimIndent()
).use { stmt ->
@ -92,25 +95,19 @@ public class CacheExporter @Inject constructor(
val timestamp = rows.getTimestamp(4)?.toInstant()
val name = rows.getString(5)
val indexes = rows.getLong(6)
val archiveStats = if (!rows.wasNull()) {
val validIndexes = rows.getLong(7)
ArchiveStats(indexes, validIndexes)
} else {
null
}
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)
val validIndexes = rows.getLong(6)
val stats = if (!rows.wasNull()) {
val indexes = rows.getLong(7)
val validGroups = rows.getLong(8)
val groups = rows.getLong(9)
val validKeys = rows.getLong(10)
val keys = rows.getLong(11)
Stats(validIndexes, indexes, validGroups, groups, validKeys, keys)
} else {
null
}
caches += Cache(id, game, build, timestamp, name, description = null, archiveStats, groupStats)
caches += Cache(id, game, build, timestamp, name, description = null, stats)
}
caches
@ -125,12 +122,11 @@ public class CacheExporter @Inject constructor(
"""
SELECT
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
JOIN games g ON g.id = m.game_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_group_stats gs ON gs.master_index_id = m.id
LEFT JOIN master_index_stats s ON s.master_index_id = m.id
WHERE m.id = ?
""".trimIndent()
).use { stmt ->
@ -152,25 +148,19 @@ public class CacheExporter @Inject constructor(
val name = rows.getString(4)
val description = rows.getString(5)
val indexes = rows.getLong(6)
val archiveStats = if (!rows.wasNull()) {
val validIndexes = rows.getLong(7)
ArchiveStats(indexes, validIndexes)
} else {
null
}
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)
val validIndexes = rows.getLong(6)
val stats = if (!rows.wasNull()) {
val indexes = rows.getLong(7)
val validGroups = rows.getLong(8)
val groups = rows.getLong(9)
val validKeys = rows.getLong(10)
val keys = rows.getLong(11)
Stats(validIndexes, indexes, validGroups, groups, validKeys, keys)
} else {
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;
CREATE MATERIALIZED VIEW master_index_archive_stats (master_index_id, indexes, valid_indexes) AS
SELECT a.master_index_id, COUNT(*), COUNT(i.container_id)
FROM master_index_archives a
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
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;
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
CREATE MATERIALIZED VIEW master_index_stats (
master_index_id,
valid_indexes,
indexes,
valid_groups,
groups,
valid_keys,
keys,
size
) AS
SELECT
i.master_index_id,
COUNT(*),
COUNT(g.container_id),
COUNT(*) FILTER (WHERE c.encrypted),
COUNT(*) FILTER (WHERE c.key_id IS NOT NULL),
SUM(length(c.data))
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;
CREATE UNIQUE INDEX ON master_index_group_stats (master_index_id);
a.master_index_id,
a.valid_indexes,
a.indexes,
COALESCE(g.valid_groups, 0),
COALESCE(g.groups, 0),
COALESCE(g.valid_keys, 0),
COALESCE(g.keys, 0),
COALESCE(g.size, 0)
FROM (
SELECT
a.master_index_id,
COUNT(i.container_id) AS valid_indexes,
COUNT(*) AS indexes
FROM master_index_archives a
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
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
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>
</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">
<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 />
<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 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">
<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 />
<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 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">
<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 />
<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>
<div class="btn-group">

@ -33,22 +33,22 @@
</tr>
<tr class="thead-dark">
<th>Indexes</th>
<td th:class="${cache.archiveStats}? (${cache.archiveStats.allIndexesValid}? 'table-success' : 'table-danger')"
th:text="${cache.archiveStats}? ${cache.archiveStats.validIndexes} + ' / ' + ${cache.archiveStats.indexes} + ' (' + ${#numbers.formatPercent(cache.archiveStats.validIndexesFraction, 1, 2)} + ')' : 'Calculating...'">
<td th:class="${cache.stats}? (${cache.stats.allIndexesValid}? 'table-success' : 'table-danger')"
th:text="${cache.stats}? ${cache.stats.validIndexes} + ' / ' + ${cache.stats.indexes} + ' (' + ${#numbers.formatPercent(cache.stats.validIndexesFraction, 1, 2)} + ')' : 'Calculating...'">
Calculating...
</td>
</tr>
<tr class="thead-dark">
<th>Groups</th>
<td th:class="${cache.groupStats}? (${cache.groupStats.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...'">
<td th:class="${cache.stats}? (${cache.stats.allGroupsValid}? 'table-success' : 'table-warning')"
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...
</td>
</tr>
<tr class="thead-dark">
<th>Keys</th>
<td th:class="${cache.groupStats}? (${cache.groupStats.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...'">
<td th:class="${cache.stats}? (${cache.stats.allKeysValid}? 'table-success' : 'table-warning')"
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...
</td>
</tr>

Loading…
Cancel
Save