$seenFrames
$seenFrames : array
Frame addresses already verified in this pass.
Reads the backup back and reports what does not come out.
The claim a backup system makes is that its history can be restored, and the only evidence for that is having read it. This walks a ref back through history and fetches every object each commit depends on: the parent commit, the base anchors its index resolves through, the frames each anchor entry names, the segment the flush wrote. In its deep mode it also decodes every frame and checks the bytes hash back to the address they are filed under, which catches silent corruption.
Nothing here repairs anything. Findings go to the ledger, where the repair ladder decides what runs automatically and what waits for a human. That separation is why this is safe to run from cron on a schedule.
Two things keep the cost sane on a large site. Frames and anchors are verified once no matter how many commits name them, and the commits between two anchors name the same one, so a pass over a day of history reads six anchors rather than one per flush. And a bounded pass walks a fixed number of commits back from the head and says so in the report, rather than reporting a clean result for a run that stopped early.
$findings : list<\Drupal\strata\Health\Finding>
Findings raised so far, in the order they were found.
$provider : \Drupal\strata\Storage\StorageProviderInterface
$index : \Drupal\strata\Cas\FrameIndexInterface
$store : \Drupal\strata\Cas\ObjectStore
$commits : \Drupal\strata\Tree\CommitLog
$refs : \Drupal\strata\Tree\RefStore
$bases : \Drupal\strata\Tree\BaseReader
$segments : \Drupal\strata\Segment\SegmentReader
$tripwires : \Drupal\strata\Health\TripwireRegistry
$ledger : \Drupal\strata\Health\HealthLedgerInterface
$commitIndex : ?\Drupal\strata\Tree\CommitIndex
$tiers : ?\Drupal\strata\Tier\TierStatusInterface
__construct(\Drupal\strata\Storage\StorageProviderInterface $provider, \Drupal\strata\Cas\FrameIndexInterface $index, \Drupal\strata\Cas\ObjectStore $store, \Drupal\strata\Tree\CommitLog $commits, \Drupal\strata\Tree\RefStore $refs, \Drupal\strata\Tree\BaseReader $bases, \Drupal\strata\Segment\SegmentReader $segments, \Drupal\strata\Health\TripwireRegistry $tripwires, \Drupal\strata\Health\HealthLedgerInterface $ledger, int $maxDeltaDepth = 32, \Drupal\strata\Tree\CommitIndex|null $commitIndex = null, \Drupal\strata\Tier\TierStatusInterface|null $tiers = null) : mixed
Constructs a verifier.
| \Drupal\strata\Storage\StorageProviderInterface | $provider | Where objects live; asked whether each one is present. |
| \Drupal\strata\Cas\FrameIndexInterface | $index | Consulted for what the site believes about each frame. |
| \Drupal\strata\Cas\ObjectStore | $store | Fetches and decodes frames in a deep pass. |
| \Drupal\strata\Tree\CommitLog | $commits | Walks history. |
| \Drupal\strata\Tree\RefStore | $refs | Resolves the ref to start from. |
| \Drupal\strata\Tree\BaseReader | $bases | Reads the base anchors history resolves against. |
| \Drupal\strata\Segment\SegmentReader | $segments | Reads segment manifests. |
| \Drupal\strata\Health\TripwireRegistry | $tripwires | The checks each observation is run through. |
| \Drupal\strata\Health\HealthLedgerInterface | $ledger | Where findings are recorded. |
| int | $maxDeltaDepth | The configured chain-depth cap, so a chain past it is reported. |
| \Drupal\strata\Tree\CommitIndex|null | $commitIndex | The local index, consulted only to tell a store whose objects are gone from one that never had any. NULL leaves that question unasked, which is what a unit lane with no database does. |
| \Drupal\strata\Tier\TierStatusInterface|null | $tiers | The store's tiers, asked at the start of every pass which of them can be reached. NULL is a store with one destination, where the provider's own reachability is the whole answer. |
verify(string $ref = \Drupal\strata\Tree\RefStore::MAIN, int|null $limit = null, bool $deep = true) : \Drupal\strata\Verify\VerifyReport
Verifies history reachable from a ref.
| string | $ref | Ref to walk back from. |
| int|null | $limit | Stop after this many commits, or NULL to walk to the root of history. |
| bool | $deep | TRUE to fetch and decode every frame; FALSE to check only that each object is present and indexed, which costs one HEAD per object instead of a GET and a decode. |
What the pass found.
verifyFrom(string $head, int|null $limit = null, bool $deep = true) : \Drupal\strata\Verify\VerifyReport
Verifies history reachable from one commit.
| string | $head | Commit id to start at. |
| int|null | $limit | Stop after this many commits, or NULL to walk to the root. |
| bool | $deep | TRUE to decode every frame. |
What the pass found.
verifyAnchor(string $commit, string $address, bool $deep) : void
Walks an anchor chain and verifies the frames its entries name.
Every link is verified, not only the resolved index: a frame named by an entry a later anchor replaced is still what that older anchor restores from, and an anchor is a restore target.
| string | $commit | The commit that points at this anchor, for the finding's context. |
| string | $address | Anchor address. |
| bool | $deep | TRUE to decode every frame. |
verifyFrame(string $hash, bool $deep) : void
Verifies one frame.
The order is deliberate: what the index knows, then whether the object is there, then whether the things it needs to decode are there, and only then the decode itself. Each step's failure makes the next step meaningless, so reporting all of them for one broken frame would turn a single fault into a wall of findings.
| string | $hash | Frame content address. |
| bool | $deep | TRUE to fetch and decode. |
sweepTiers() : void
Reports every tier of the store that cannot be reached.
Run before the walk rather than derived from it. A tier that is down produces a read failure per object, and the finding an operator needs is that one bucket is unreachable, not a thousand findings about the objects in it. A store with one destination raises nothing here, since its own reachability is reported by hook_requirements().
reportLostRef(string $ref) : \Drupal\strata\Verify\VerifyReport
What to report when a ref resolves to nothing.
A ref that was never written and a ref whose object was deleted look the same from the bucket, and the difference is the whole answer: one is a site that has not flushed yet, the other is a site whose history is gone. The local index decides which, because it is derived from the bucket and cannot hold rows for commits that were never sealed.
| string | $ref | The ref that did not resolve. |
An empty clean pass, or one carrying ref.missing.