mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[MG_Backend, tools] (P7): every WireDeclines.def row has a site and every site a warning-or-error line, and a tree-only audit fails the job when one does not
The B3 review (ID-P7-34) counted 12 of the 52 rows with no site at all - TexViewFormat, TexNoApplierRecord, TexRecordDeadOrStale and the nine Shape* rows were declared and never counted - and ten sites that counted with no (MGLOG_D included) line, so "a name, a tally and a decline line" did not describe the tree. - SyncWireTextureShape: all nine Shape* exits now count; the ViewOf exit and the preserve-flush exit were bare `return false` and are now MGL_WIRE_DECLINE_AT; the image-flags exit logged only MGLOG_D, which a Release build compiles away, and is promoted likewise. - The preserve-copy exit was the one Shape exit with no row: appended as ShapePreserveCopyFailed (rows are append-only), 53 rows. - SyncTextureResourceByHandle / UploadPendingWireLevels: the count-only sites without a log of their own are promoted to MGL_WIRE_DECLINE_AT; the ones already under a W/E _ONCE line keep that line and gain the count. - scripts/ci/wire_declines_audit.py: fails on a row with no site, a site naming no row, or a bare Count() with no MGLOG_W/E within 8 lines above it. WireDeclineTally.h (the macro's definition) is not a site. Wired into the job that runs the fatal census. Audit before: 52 rows, 40 with sites, 10 unlogged under the W/E rule (rc 1). After: 53 rows, 53 with sites, 0 unlogged (rc 0). Forced red (ShapeNoVkFormat made true for 1x1 textures, reverted): Split.Fm.F1WireScenario.VertexIdSampler... fails on pixels with ShapeNoVkFormat=2 / TexShapeSync=2 in the shutdown tally.
This commit is contained in:
@@ -2146,6 +2146,11 @@ jobs:
|
||||
- name: Fatal census (S7)
|
||||
run: python3 scripts/ci/fatal_census.py
|
||||
|
||||
# The decline half of rule I (P7 B3): every WireDeclines.def row has a site, every site a
|
||||
# warning-or-error line. Same shape as the census - tree-only, no build.
|
||||
- name: Wire declines audit (B3)
|
||||
run: python3 scripts/ci/wire_declines_audit.py
|
||||
|
||||
- name: Load trace cases
|
||||
id: trace-cases
|
||||
run: |
|
||||
|
||||
@@ -2071,13 +2071,21 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (desc.StorageKind != static_cast<Uint8>(TextureStorageType::Mipmap)) {
|
||||
MGLOG_W_ONCE("Magma wire texture {slot=%u, gen=%u}: buffer-backed textures are not migrated; declined",
|
||||
desc.Resource.Slot, desc.Resource.Gen);
|
||||
WireDeclineTally::Count(WireDeclineSite::ShapeBufferBacked);
|
||||
return false;
|
||||
}
|
||||
// ResolveWireTextureStorage has already followed ViewOf. Views share the storage
|
||||
// owner's image and layout; allocating a second image would break aliasing.
|
||||
if (!MG_Pipe::MGPipeHandleIsNull(desc.ViewOf)) return false;
|
||||
if (!MG_Pipe::MGPipeHandleIsNull(desc.ViewOf)) {
|
||||
MGL_WIRE_DECLINE_AT(ShapeViewOfStorage,
|
||||
"texture {slot=%u, gen=%u} is a view whose storage owner did not resolve",
|
||||
desc.Resource.Slot, desc.Resource.Gen);
|
||||
return false;
|
||||
}
|
||||
if (desc.Levels == 0) {
|
||||
// A create before the first respecify: no storage, nothing to back.
|
||||
MGL_WIRE_DECLINE_AT(ShapeNoLevels, "texture {slot=%u, gen=%u} has no defined level yet",
|
||||
desc.Resource.Slot, desc.Resource.Gen);
|
||||
return false;
|
||||
}
|
||||
TextureShapeInfo shapeInfo{};
|
||||
@@ -2086,6 +2094,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
"(%ux%ux%u, %u layers); declined",
|
||||
desc.Resource.Slot, desc.Resource.Gen, static_cast<Uint32>(desc.Target), desc.Width,
|
||||
desc.Height, desc.Depth, static_cast<Uint32>(desc.ArrayLayers));
|
||||
WireDeclineTally::Count(WireDeclineSite::ShapeNoVulkanShape);
|
||||
return false;
|
||||
}
|
||||
const TextureInternalFormat internalFormat = static_cast<TextureInternalFormat>(desc.InternalFormat);
|
||||
@@ -2094,6 +2103,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (format == VK_FORMAT_UNDEFINED) {
|
||||
MGLOG_W_ONCE("Magma wire texture {slot=%u, gen=%u}: no backing VkFormat for internal format 0x%x",
|
||||
desc.Resource.Slot, desc.Resource.Gen, desc.InternalFormat);
|
||||
WireDeclineTally::Count(WireDeclineSite::ShapeNoVkFormat);
|
||||
return false;
|
||||
}
|
||||
// X8_D24 lacks optimal-tiling support on several drivers (lavapipe included); the same
|
||||
@@ -2116,6 +2126,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (!TryResolveSampleCountFlagBits(static_cast<Int>(desc.Samples), resolvedSampleCount)) {
|
||||
MGLOG_W_ONCE("Magma wire texture {slot=%u, gen=%u}: unsupported sample count %u",
|
||||
desc.Resource.Slot, desc.Resource.Gen, static_cast<Uint32>(desc.Samples));
|
||||
WireDeclineTally::Count(WireDeclineSite::ShapeSampleCount);
|
||||
return false;
|
||||
}
|
||||
// glTexStorage*Multisample(samples = 1) is legal GL, but a one-sample image cannot
|
||||
@@ -2251,7 +2262,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// old image must reach the queue first; waiting only for the preservation
|
||||
// fence cannot order work that is still in the renderer's open recording.
|
||||
// The descriptor caller preflights this before capturing its command buffer.
|
||||
if (preserve && pVulkanRenderer && !pVulkanRenderer->FlushWirePendingCommandsForTextureUpdate()) return false;
|
||||
if (preserve && pVulkanRenderer && !pVulkanRenderer->FlushWirePendingCommandsForTextureUpdate()) {
|
||||
MGL_WIRE_DECLINE_AT(ShapePreserveFlushFailed,
|
||||
"texture {slot=%u, gen=%u}: earlier work could not be submitted before "
|
||||
"preserving its texels across a reallocation",
|
||||
desc.Resource.Slot, desc.Resource.Gen);
|
||||
return false;
|
||||
}
|
||||
TextureResource replacement;
|
||||
|
||||
VkImageCreateInfo imageInfo{};
|
||||
@@ -2298,9 +2315,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
if (imageFormatResult != VK_SUCCESS ||
|
||||
(isMultisample && (imageFormatProperties.sampleCounts & resolvedSampleCount) == 0)) {
|
||||
MGLOG_D("%s: image flags=0x%x sampleCount=%d are unsupported for texture {slot=%u, gen=%u}",
|
||||
__func__, static_cast<Uint32>(imageInfo.flags),
|
||||
static_cast<Int>(imageInfo.samples), desc.Resource.Slot, desc.Resource.Gen);
|
||||
// Was an MGLOG_D, which a Release build compiles away: the one Shape* exit that
|
||||
// left no line on the builds that ship.
|
||||
MGL_WIRE_DECLINE_AT(ShapeImageFlagsUnsupported,
|
||||
"texture {slot=%u, gen=%u}: image flags=0x%x sampleCount=%d are unsupported "
|
||||
"by the device",
|
||||
desc.Resource.Slot, desc.Resource.Gen, static_cast<Uint32>(imageInfo.flags),
|
||||
static_cast<Int>(imageInfo.samples));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2319,6 +2340,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
imageInfo.extent.height, imageInfo.extent.depth, imageInfo.arrayLayers,
|
||||
imageInfo.mipLevels, static_cast<Int>(imageInfo.samples),
|
||||
static_cast<Int>(imageInfo.format));
|
||||
WireDeclineTally::Count(WireDeclineSite::ShapeCreateImageFailed);
|
||||
return false;
|
||||
}
|
||||
++m_textureImageEpoch; // a new attachment image invalidates cached render passes
|
||||
@@ -2340,7 +2362,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (preserve) {
|
||||
FlushPendingUploads();
|
||||
if (!PreserveTextureContentsOnRecreate(m_device, m_commandPool, m_graphicsQueue,
|
||||
resource, replacement, true)) return false;
|
||||
resource, replacement, true)) {
|
||||
MGL_WIRE_DECLINE_AT(ShapePreserveCopyFailed,
|
||||
"texture {slot=%u, gen=%u}: its texels could not be copied into the "
|
||||
"reallocated image",
|
||||
desc.Resource.Slot, desc.Resource.Gen);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DeferResourceRelease(Move(resource));
|
||||
std::destroy_at(&resource);
|
||||
@@ -2412,11 +2440,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// NOT `incomplete`: this arm reports SUCCESS while leaving the entry pending,
|
||||
// so the draw proceeds against texels that were never uploaded. Counted
|
||||
// separately for exactly that reason (B3).
|
||||
WireDeclineTally::Count(WireDeclineSite::UploadLevelExtentMismatch);
|
||||
MGL_WIRE_DECLINE_AT(UploadLevelExtentMismatch,
|
||||
"texture {slot=%u, gen=%u} level %u: the staged extent does not match the "
|
||||
"image's extent for that level; left pending and NOT uploaded",
|
||||
handle.Slot, handle.Gen, static_cast<Uint32>(level));
|
||||
continue;
|
||||
}
|
||||
if (texelSize.x() <= 0 || texelSize.y() <= 0 || byteSize == 0) {
|
||||
WireDeclineTally::Count(WireDeclineSite::UploadEmptyLevel);
|
||||
MGL_WIRE_DECLINE_AT(UploadEmptyLevel, "texture {slot=%u, gen=%u} level %u is empty",
|
||||
handle.Slot, handle.Gen, static_cast<Uint32>(level));
|
||||
incomplete = true;
|
||||
continue;
|
||||
}
|
||||
@@ -2445,7 +2477,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
(resource.aspect & VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
if (vkuFormatIsCompressed(resource.format) || !levelTexels ||
|
||||
item.byteSize % levelTexels != 0 || item.byteSize / levelTexels == 0) {
|
||||
WireDeclineTally::Count(WireDeclineSite::UploadTexelArithmetic);
|
||||
MGL_WIRE_DECLINE_AT(UploadTexelArithmetic,
|
||||
"texture {slot=%u, gen=%u} level %u: compressed, or its byte size is not a "
|
||||
"whole number of texels",
|
||||
handle.Slot, handle.Gen, static_cast<Uint32>(level));
|
||||
incomplete = true;
|
||||
continue;
|
||||
}
|
||||
@@ -2465,7 +2500,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (offset[axis] < 0 || extent[axis] <= 0 ||
|
||||
static_cast<Uint64>(offset[axis]) + static_cast<Uint64>(extent[axis]) >
|
||||
static_cast<Uint64>(texelSize[axis])) {
|
||||
WireDeclineTally::Count(WireDeclineSite::UploadRegionOutOfBounds);
|
||||
MGL_WIRE_DECLINE_AT(UploadRegionOutOfBounds,
|
||||
"texture {slot=%u, gen=%u} level %u: a staged region lies outside "
|
||||
"the level",
|
||||
handle.Slot, handle.Gen, static_cast<Uint32>(level));
|
||||
incomplete = true;
|
||||
return;
|
||||
}
|
||||
@@ -2521,7 +2559,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
WireDeclineTally::SetPendingGauge(static_cast<Uint64>(record.PendingUploads.size()), pendingBytes);
|
||||
}
|
||||
if (incomplete) {
|
||||
WireDeclineTally::Count(WireDeclineSite::UploadIncomplete);
|
||||
MGL_WIRE_DECLINE_AT(UploadIncomplete,
|
||||
"texture {slot=%u, gen=%u}: at least one pending level could not be staged; "
|
||||
"every draw that samples it is declined until it can",
|
||||
handle.Slot, handle.Gen);
|
||||
return false;
|
||||
}
|
||||
if (items.empty()) {
|
||||
@@ -2533,7 +2574,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// otherwise Draw(old T), TexSubImage(T), Draw(new T) can upload before
|
||||
// the first draw. A clean texture never reaches this submission boundary.
|
||||
if (pVulkanRenderer && !pVulkanRenderer->FlushWirePendingCommandsForTextureUpdate()) {
|
||||
WireDeclineTally::Count(WireDeclineSite::UploadFlushFailed);
|
||||
MGL_WIRE_DECLINE_AT(UploadFlushFailed,
|
||||
"texture {slot=%u, gen=%u}: earlier renderer work could not be submitted before "
|
||||
"its upload batch",
|
||||
handle.Slot, handle.Gen);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2690,7 +2734,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkFormat viewFormat = VK_FORMAT_UNDEFINED;
|
||||
const auto storage = ResolveWireTextureStorage(handle, level, layer, &viewFormat);
|
||||
if (MG_Pipe::MGPipeHandleIsNull(storage)) {
|
||||
WireDeclineTally::Count(WireDeclineSite::TexResolveStorage);
|
||||
MGL_WIRE_DECLINE_AT(TexResolveStorage,
|
||||
"texture {slot=%u, gen=%u}: no storage owner resolved", handle.Slot,
|
||||
handle.Gen);
|
||||
return nullptr;
|
||||
}
|
||||
if (storage != handle) {
|
||||
@@ -2701,6 +2747,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
vkuFormatCompatibilityClass(viewFormat) != vkuFormatCompatibilityClass(resource->format))) {
|
||||
MGLOG_E_ONCE("Magma wire view: format %d cannot reinterpret storage format %d",
|
||||
static_cast<Int>(viewFormat), static_cast<Int>(resource->format));
|
||||
WireDeclineTally::Count(WireDeclineSite::TexViewFormat);
|
||||
return nullptr;
|
||||
}
|
||||
return resource;
|
||||
@@ -2711,6 +2758,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (handle.Slot >= records.size()) {
|
||||
MGLOG_E_ONCE("Magma wire texture {slot=%u, gen=%u}: no applier record at that slot; declined",
|
||||
handle.Slot, handle.Gen);
|
||||
WireDeclineTally::Count(WireDeclineSite::TexNoApplierRecord);
|
||||
return nullptr;
|
||||
}
|
||||
auto& record = records[handle.Slot];
|
||||
@@ -2720,6 +2768,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MGLOG_E_ONCE("Magma wire texture {slot=%u, gen=%u}: the applier's record is %s; declined",
|
||||
handle.Slot, handle.Gen,
|
||||
!record.Live ? "dead" : "of another generation");
|
||||
WireDeclineTally::Count(WireDeclineSite::TexRecordDeadOrStale);
|
||||
return nullptr;
|
||||
}
|
||||
const Uint64 key = MG_Remote::Server::StagedTextureStore::KeyForHandle(handle);
|
||||
@@ -2731,15 +2780,22 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return &resource;
|
||||
}
|
||||
if (!SyncWireTextureShape(record, resource, requireStorage)) {
|
||||
WireDeclineTally::Count(WireDeclineSite::TexShapeSync);
|
||||
MGL_WIRE_DECLINE_AT(TexShapeSync, "texture {slot=%u, gen=%u}: no backing image; see the Shape* tally",
|
||||
handle.Slot, handle.Gen);
|
||||
return nullptr;
|
||||
}
|
||||
if (!renderbuffer && !UploadPendingWireLevels(handle, record, resource)) {
|
||||
WireDeclineTally::Count(WireDeclineSite::TexUploadPendingLevels);
|
||||
MGL_WIRE_DECLINE_AT(TexUploadPendingLevels,
|
||||
"texture {slot=%u, gen=%u}: pending levels could not be uploaded; see the "
|
||||
"Upload* tally",
|
||||
handle.Slot, handle.Gen);
|
||||
return nullptr;
|
||||
}
|
||||
if (requireStorage && (resource.usageFlags & VK_IMAGE_USAGE_STORAGE_BIT) == 0) {
|
||||
WireDeclineTally::Count(WireDeclineSite::TexStorageUsage);
|
||||
MGL_WIRE_DECLINE_AT(TexStorageUsage,
|
||||
"texture {slot=%u, gen=%u} is bound as a shader image but its allocation has no "
|
||||
"STORAGE usage",
|
||||
handle.Slot, handle.Gen);
|
||||
return nullptr;
|
||||
}
|
||||
resource.syncedWireSerial = record.Serial;
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
// counts, so "which exit did this frame take" is answerable from a counter dump instead of
|
||||
// from a bisect. Rows are append-only: the integration lane asserts specific counters moved.
|
||||
//
|
||||
// EVERY ROW HAS A SITE AND EVERY SITE HAS A LINE. A row with no site is a name that can never
|
||||
// be counted - it reads as "this cannot happen here" when it only means "nobody wired it up" -
|
||||
// and a site with no line puts the reader back on a bisect. Sites reached through a macro
|
||||
// (MGL_WIRE_DECLINE_AT) get both at once; the few that use WireDeclineTally::Count directly do
|
||||
// so ONLY because the statement above them already carries the same reason as an _ONCE log.
|
||||
// scripts/ci/wire_declines_audit.py holds both halves.
|
||||
//
|
||||
// MGL_WIRE_DECLINE(Name)
|
||||
|
||||
// ---- SetupWireDraw, in statement order -------------------------------------------------
|
||||
@@ -88,3 +95,6 @@ MGL_WIRE_DECLINE(ShapeSampleCount)
|
||||
MGL_WIRE_DECLINE(ShapePreserveFlushFailed)
|
||||
MGL_WIRE_DECLINE(ShapeImageFlagsUnsupported)
|
||||
MGL_WIRE_DECLINE(ShapeCreateImageFailed)
|
||||
// Appended by the B3 review round: the preserve-copy arm of a reallocation was the one exit in
|
||||
// SyncWireTextureShape still leaving no trace at all.
|
||||
MGL_WIRE_DECLINE(ShapePreserveCopyFailed)
|
||||
|
||||
Executable
+100
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3
|
||||
"""P7 wave 2 package B3: WireDeclines.def rows and their sites must agree.
|
||||
|
||||
CONTRACT-P7 §0 rule I admits two shapes for a wire-arm refusal, a decline and a named Fatal.
|
||||
The decline half is only real if:
|
||||
|
||||
(1) every row in WireDeclines.def is actually counted somewhere - a row with no site is a
|
||||
name that can never move, which reads in a report as "this cannot happen here" when it
|
||||
only means "nobody wired it up"; and
|
||||
(2) every site emits a line - a counter with no log puts the next reader back on a bisect,
|
||||
which is the thing the package exists to remove.
|
||||
|
||||
Rows are APPEND-ONLY (the lanes assert specific counters), so (1) cannot be fixed later by
|
||||
deleting a row once a release has shipped it. This check is why it cannot rot.
|
||||
|
||||
Sites reached through MGL_WIRE_DECLINE_AT satisfy both at once. A bare
|
||||
WireDeclineTally::Count(WireDeclineSite::X) is allowed ONLY when an MGLOG_ statement carrying
|
||||
the same reason already stands just above it.
|
||||
|
||||
usage: wire_declines_audit.py [repo-root]
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
RENDERER = "MobileGL/MG_Backend/DirectVulkan/Renderer"
|
||||
DEF = os.path.join(RENDERER, "WireDeclines.def")
|
||||
SOURCES = (".cpp", ".inc", ".h")
|
||||
# How far above a bare Count() an MGLOG_ may stand and still be "the line for this site".
|
||||
LOG_WINDOW = 8
|
||||
|
||||
ROW = re.compile(r"^\s*MGL_WIRE_DECLINE\(([A-Za-z][A-Za-z0-9]*)\)\s*$")
|
||||
AT_SITE = re.compile(r"MGL_WIRE_DECLINE_AT\(\s*([A-Za-z][A-Za-z0-9]*)\s*,")
|
||||
COUNT_SITE = re.compile(r"WireDeclineTally::Count\(\s*WireDeclineSite::([A-Za-z][A-Za-z0-9]*)\s*\)")
|
||||
# Warning or error only: an MGLOG_D / MGLOG_V is compiled away in the Release builds that ship,
|
||||
# so it is not a line anybody can read off a device.
|
||||
LOGGED = re.compile(r"MGLOG_[WE](_ONCE)?\s*\(")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
root = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else ".")
|
||||
def_path = os.path.join(root, DEF)
|
||||
if not os.path.isfile(def_path):
|
||||
print("wire-declines: %s not found" % DEF, file=sys.stderr)
|
||||
return 2
|
||||
|
||||
rows = []
|
||||
for line in open(def_path, encoding="utf-8"):
|
||||
m = ROW.match(line)
|
||||
if m:
|
||||
rows.append(m.group(1))
|
||||
if len(rows) != len(set(rows)):
|
||||
dupes = sorted({r for r in rows if rows.count(r) > 1})
|
||||
print("wire-declines: duplicate rows: %s" % ", ".join(dupes), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
counted = {} # name -> [(file, line)]
|
||||
unlogged_counts = [] # (file, line, name)
|
||||
src_dir = os.path.join(root, RENDERER)
|
||||
for entry in sorted(os.listdir(src_dir)):
|
||||
if not entry.endswith(SOURCES):
|
||||
continue
|
||||
# The header that DEFINES the macro and the enum names them all without being a site.
|
||||
if entry == "WireDeclineTally.h":
|
||||
continue
|
||||
path = os.path.join(src_dir, entry)
|
||||
lines = open(path, encoding="utf-8", errors="replace").read().splitlines()
|
||||
for i, line in enumerate(lines):
|
||||
for m in AT_SITE.finditer(line):
|
||||
counted.setdefault(m.group(1), []).append((entry, i + 1))
|
||||
for m in COUNT_SITE.finditer(line):
|
||||
name = m.group(1)
|
||||
counted.setdefault(name, []).append((entry, i + 1))
|
||||
window = lines[max(0, i - LOG_WINDOW):i]
|
||||
if not any(LOGGED.search(w) for w in window):
|
||||
unlogged_counts.append((entry, i + 1, name))
|
||||
|
||||
orphan_rows = [r for r in rows if r not in counted]
|
||||
unknown_sites = sorted(set(counted) - set(rows))
|
||||
|
||||
for name in orphan_rows:
|
||||
print("wire-declines: row %s has NO SITE - it can never be counted" % name, file=sys.stderr)
|
||||
for name in unknown_sites:
|
||||
for where in counted[name]:
|
||||
print("wire-declines: %s:%d counts %s, which is not a row in WireDeclines.def"
|
||||
% (where[0], where[1], name), file=sys.stderr)
|
||||
for entry, line, name in unlogged_counts:
|
||||
print("wire-declines: %s:%d counts %s with no MGLOG_ within %d lines above it - a decline "
|
||||
"must be readable from the log, not only from a counter"
|
||||
% (entry, line, name, LOG_WINDOW), file=sys.stderr)
|
||||
|
||||
bad = len(orphan_rows) + len(unknown_sites) + len(unlogged_counts)
|
||||
print("wire-declines: %d rows, %d with sites, %d site(s) total, %d unlogged, %d unknown"
|
||||
% (len(rows), len(rows) - len(orphan_rows), sum(len(v) for v in counted.values()),
|
||||
len(unlogged_counts), len(unknown_sites)))
|
||||
return 1 if bad else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user