Add per-archive stats to the cache pages

These replace the whirlpool, group count and total uncompressed length
columns, which were kind of useless - in particular:

* The group count is also represented with the new stats columns.
* The total uncompressed length overflows, as some indexes are now
  larger than 2 gigabytes. One of the new stats columns contains the
  compressed size of each archive, which isn't too different.

Signed-off-by: Graham <gpe@openrs2.org>
master
Graham 3 years ago
parent ce9604a28d
commit f5b9f269f6
  1. 69
      archive/src/main/kotlin/org/openrs2/archive/cache/CacheExporter.kt
  2. 44
      archive/src/main/resources/org/openrs2/archive/templates/caches/show.html

@ -77,6 +77,36 @@ public class CacheExporter @Inject constructor(
public val diskStoreValid: Boolean = blocks <= DiskStore.MAX_BLOCK
}
public data class Index(
val resolved: Boolean,
val stats: IndexStats?
)
public data class IndexStats(
val validGroups: Long,
val groups: Long,
val validKeys: Long,
val keys: Long,
val size: Long,
val blocks: Long
) {
public val allGroupsValid: Boolean = groups == validGroups
public val validGroupsFraction: Double = if (groups == 0L) {
1.0
} else {
validGroups.toDouble() / groups
}
public val allKeysValid: Boolean = keys == validKeys
public val validKeysFraction: Double = if (keys == 0L) {
1.0
} else {
validKeys.toDouble() / keys
}
}
public data class Build(val major: Int, val minor: Int?) : Comparable<Build> {
override fun compareTo(other: Build): Int {
return compareValuesBy(this, other, Build::major, Build::minor)
@ -128,6 +158,7 @@ public class CacheExporter @Inject constructor(
val sources: List<Source>,
val updates: List<String>,
val stats: Stats?,
val indexes: List<Index>,
val masterIndex: Js5MasterIndex?,
val checksumTable: ChecksumTable?
)
@ -379,7 +410,43 @@ public class CacheExporter @Inject constructor(
}
}
Cache(id, sources, updates, stats, masterIndex, checksumTable)
val indexes = mutableListOf<Index>()
connection.prepareStatement(
"""
SELECT c.id IS NOT NULL, s.valid_groups, s.groups, s.valid_keys, s.keys, s.size, s.blocks
FROM master_index_archives a
LEFT JOIN resolve_index((SELECT id FROM scopes WHERE name = ?), a.archive_id, a.crc32, a.version) c ON TRUE
LEFT JOIN index_stats s ON s.container_id = c.id
WHERE a.master_index_id = ?
ORDER BY a.archive_id ASC
""".trimIndent()
).use { stmt ->
stmt.setString(1, scope)
stmt.setInt(2, id)
stmt.executeQuery().use { rows ->
while (rows.next()) {
val resolved = rows.getBoolean(1)
val validGroups = rows.getLong(2)
val indexStats = if (!rows.wasNull()) {
val groups = rows.getLong(3)
val validKeys = rows.getLong(4)
val keys = rows.getLong(5)
val size = rows.getLong(6)
val blocks = rows.getLong(7)
IndexStats(validGroups, groups, validKeys, keys, size, blocks)
} else {
null
}
indexes += Index(resolved, indexStats)
}
}
}
Cache(id, sources, updates, stats, indexes, masterIndex, checksumTable)
}
}

@ -124,37 +124,43 @@
<th>Archive</th>
<th>Version</th>
<th>Checksum</th>
<th>Digest</th>
<th>Groups</th>
<th>Total uncompressed length</th>
<th>Keys<sup><a href="/caches#empty-locs">1</a></sup></th>
<th>Size<sup><a href="/caches#size">2</a></sup></th>
</tr>
</thead>
<tbody>
<tr th:each="entry, it : ${cache.masterIndex.entries}">
<tr th:each="entry, it : ${cache.masterIndex.entries}" th:with="index=${cache.indexes[it.index]}">
<td th:text="${it.index}" class="text-right">0</td>
<td th:text="${#numbers.formatInteger(entry.version, 1, 'COMMA')}" class="text-right">0</td>
<td class="text-right">
<code th:text="${entry.checksum}">0</code>
</td>
<td>
<code
th:if="${cache.masterIndex.format >= @org.openrs2.cache.MasterIndexFormat@DIGESTS}"><span
th:remove="tag"
th:text="${@io.netty.buffer.ByteBufUtil@hexDump(entry.digest).substring(0, 64)}"></span>&ZeroWidthSpace;<span
th:remove="tag"
th:text="${@io.netty.buffer.ByteBufUtil@hexDump(entry.digest).substring(64)}"></span></code>
<div th:switch="true" th:remove="tag">
<div th:case="${entry.checksum == 0 && entry.version == 0}" th:remove="tag">
<td class="text-center text-muted" colspan="3">N/A</td>
</div>
<div th:case="${!index.resolved}" th:remove="tag">
<td class="text-center table-danger" colspan="3">Index missing</td>
</div>
<div th:case="${index.stats != null}" th:remove="tag">
<td th:classappend="${index.stats.allGroupsValid}? 'table-success' : 'table-warning'" class="text-right">
<span th:text="${#numbers.formatInteger(index.stats.validGroups, 1, 'COMMA')} + '&nbsp;/&nbsp;' + ${#numbers.formatInteger(index.stats.groups, 1, 'COMMA')}"></span>
<br />
<span th:text="'(' + ${#numbers.formatPercent(index.stats.validGroupsFraction, 1, 2)} + ')'"></span>
</td>
<td class="text-right">
<span
th:if="${cache.masterIndex.format >= @org.openrs2.cache.MasterIndexFormat@LENGTHS}"
th:text="${#numbers.formatInteger(entry.groups, 1, 'COMMA')}"></span>
<td th:classappend="${index.stats.allKeysValid}? 'table-success' : 'table-warning'" class="text-right">
<span th:text="${#numbers.formatInteger(index.stats.validKeys, 1, 'COMMA')} + '&nbsp;/&nbsp;' + ${#numbers.formatInteger(index.stats.keys, 1, 'COMMA')}"></span>
<br />
<span th:text="'(' + ${#numbers.formatPercent(index.stats.validKeysFraction, 1, 2)} + ')'"></span>
</td>
<td class="text-right">
<!--/*@thymesVar id="#byteunits" type="org.openrs2.archive.web.ByteUnits"*/-->
<span
th:if="${cache.masterIndex.format >= @org.openrs2.cache.MasterIndexFormat@LENGTHS}"
th:text="${#byteunits.format(@java.lang.Integer@toUnsignedLong(entry.totalUncompressedLength))}"></span>
</td>
<td th:text="${#byteunits.format(index.stats.size)}" class="text-right">0 B</td>
</div>
<div th:case="true" th:remove="tag">
<td class="text-center" colspan="3">Calculating...</td>
</div>
</div>
</tr>
</tbody>
</table>

Loading…
Cancel
Save