even, "fcs1" -> odd, ...
function fcs_parity($fcs) {
if (preg_match('/(\d+)\s*$/', strtolower(trim((string)$fcs)), $m)) {
return (intval($m[1]) % 2 === 0) ? 'even' : 'odd';
}
return 'unknown';
}
$rawRows = Invoke_Infra("SELECT * FROM x_cmdb_VIO");
if (!$rawRows) $rawRows = [];
// Grouping
$groupedData = [];
foreach ($rawRows as $row) {
$key = $row['clintname'];
if (empty($key)) $key = "[No Client Name]";
if (!isset($groupedData[$key])) $groupedData[$key] = [];
$groupedData[$key][] = $row;
}
// Flattening for Display (1 Row per Client)
$displayRows = [];
foreach ($groupedData as $clientKey => $rows) {
// 1. Sort by date desc
usort($rows, function($a, $b) {
return strcmp($b['ts'], $a['ts']);
});
// 2. Keep max 2
if (count($rows) > 2) {
$rows = array_slice($rows, 0, 2);
}
$names = []; $inerrs = []; $vfcs = []; $vios = [];
$clintids = []; $fcnames = []; $tss = []; $vioerrs = [];
$parities = [];
$hasError = false;
$maxVioErr = 0;
foreach ($rows as $r) {
if ($r['inerr'] != 0 && $r['inerr'] != '0') $hasError = true;
// Track VIOErr
$errVal = (int)($r['VIOErr'] ?? 0);
if ($errVal > $maxVioErr) $maxVioErr = $errVal;
// Format VIOErr for display (Red badge if > 0)
$vioerrs[] = ($errVal > 0) ? "$errVal" : $errVal;
$names[] = $r['name'] ?? '-';
$inerrs[] = $r['inerr'] ?? '-';
$vfcs[] = $r['vfcclientname'] ?? '-';
$vios[] = $r['vio'] ?? '-';
$clintids[] = $r['clintid'] ?? '-';
$fcnames[] = $r['fcname'] ?? '-';
$tss[] = $r['ts'] ?? '-';
// Redundancy check is on the physical fc port (fcname).
$parities[] = fcs_parity($r['fcname'] ?? '');
}
// Parity issue = exactly 2 known fcs parities and they are identical
// (both even or both odd -> no fabric redundancy).
$hasParityIssue = false;
$knownParities = array_values(array_filter($parities, fn($p) => $p !== 'unknown'));
if (count($knownParities) === 2 && $knownParities[0] === $knownParities[1]) {
$hasParityIssue = true;
}
$displayRows[] = [
'clintname' => $clientKey,
'hasError' => $hasError,
'hasParityIssue' => $hasParityIssue,
'maxVioErr' => $maxVioErr,
'name' => implode('
', $names),
'inerr' => implode('
', $inerrs),
'vfc' => implode('
', $vfcs),
'vio' => implode('
', $vios),
'clintid' => implode('
', $clintids),
'fcname' => implode('
', $fcnames),
'ts' => implode('
', $tss),
'vioerr' => implode('
', $vioerrs),
];
}
// 4. Final Sort:
// 1. Top tier: InErr (table-warning) OR parity issue (table-danger)
// 2. VIOErr > 0
// 3. Alpha
usort($displayRows, function($a, $b) {
// Priority 1: warning OR parity issue -> floated to the top, same standing
$aTop = $a['hasError'] || $a['hasParityIssue'];
$bTop = $b['hasError'] || $b['hasParityIssue'];
if ($aTop && !$bTop) return -1;
if (!$aTop && $bTop) return 1;
// Priority 2: VIOErr count
if ($a['maxVioErr'] > 0 && $b['maxVioErr'] == 0) return -1;
if ($a['maxVioErr'] == 0 && $b['maxVioErr'] > 0) return 1;
if ($a['maxVioErr'] != $b['maxVioErr']) return $b['maxVioErr'] - $a['maxVioErr'];
// Priority 3: Alphabetical
return strcasecmp($a['clintname'], $b['clintname']);
});
?>
| Clint Name |
|
VIOErr |
InErr |
VFC Client Name |
VIO |
ClintID |
FC Name |
|
|
|
|
|
|
|
|
même parité
|
|