\Drupal\strata\Delta Reanchorer

Breaks delta chains that have grown too long by rewriting a link standalone.

Delta coding trades storage for a dependency. A frame coded against the version before it is 63.70x smaller on the rewrite class, and reading it reads its parent, and that parent's parent. The chain is what makes the saving and it is also the whole risk: a long chain multiplies read cost and turns one lost frame into the loss of everything derived from it.

So a chain is capped, and this is what enforces the cap after the fact. The writer refuses to extend a chain past the limit, which keeps new frames in bounds; a chain can still be over the limit because the limit was lowered, or because a chain was built by an older release. Rewriting the deepest link standalone cuts the chain there: everything above it keeps its parent, everything below it becomes reachable in fewer reads.

Nothing is deleted. The rewritten frame keeps its content address, because the address is the digest of the decoded bytes and those are unchanged - only the encoding changes. Every frame that named it still names it, and the old bytes are superseded rather than orphaned.

Summary

Methods
Properties
Constants
__construct
run
reanchor
overDeep
deepest
No public properties found
TOO_DEEP
DEFAULT_BUDGET
No protected methods found
No protected properties found
No protected constants found
No private methods found
index
store
policy
ledger
logger
No private constants found

Constant

TOO_DEEP

TOO_DEEP = 'delta.chain_too_deep'

Code raised when a chain is found past the cap.

DEFAULT_BUDGET

DEFAULT_BUDGET = 200

Frames rewritten in one pass by default.

Each one is a read of its whole chain and a write, so a pass is bounded and the next cron run continues. A cap that let one pass rewrite an unbounded number of frames would be the slowest thing in the cron queue on the one site that needed it most.

Properties

$store

$store : \Drupal\strata\Cas\ObjectStore

Type

ObjectStore

$logger

$logger : \Psr\Log\LoggerInterface

Type

LoggerInterface

Methods

__construct()

__construct(\Drupal\strata\Cas\FrameIndexInterface  $index, \Drupal\strata\Cas\ObjectStore  $store, \Drupal\strata\Delta\ChainDepthPolicy  $policy, \Drupal\strata\Health\HealthLedgerInterface  $ledger, \Psr\Log\LoggerInterface  $logger) : mixed

Constructs a reanchorer.

Parameters

\Drupal\strata\Cas\FrameIndexInterface $index

Where chain depths are read from and written back.

\Drupal\strata\Cas\ObjectStore $store

Reads a frame through its chain and writes the standalone replacement.

\Drupal\strata\Delta\ChainDepthPolicy $policy

The cap being enforced.

\Drupal\strata\Health\HealthLedgerInterface $ledger

Where a chain past the cap is recorded.

\Psr\Log\LoggerInterface $logger

Records what a pass did.

Returns

mixed —

run()

run(int  $budget = 0) : array{examined: int, reanchored: int, deepest: int, saved: int, problems: list<string>}

Rewrites the frames whose chains are past the cap.

Parameters

int $budget

Most frames to rewrite, or zero for the default.

Returns

array{examined: int, reanchored: int, deepest: int, saved: int, problems: list} —

How many frames were looked at, how many were rewritten, the deepest chain found, how many stored bytes the rewrites cost or saved, and anything that could not be done.

reanchor()

reanchor(\Drupal\strata\Cas\FrameRecord  $record) : int

Rewrites one frame so it no longer depends on a parent.

Parameters

\Drupal\strata\Cas\FrameRecord $record

The frame to re-anchor.

Throws

\RuntimeException

When the frame cannot be read through its chain, or the rewrite cannot be stored.

Returns

int —

Stored bytes saved, which is negative when the standalone form is larger - and it usually is. The point of a re-anchor is bounding the read, not saving bytes, and reporting the cost honestly is what lets an operator judge the cap.

overDeep()

overDeep(int  $limit) : list<\Drupal\strata\Cas\FrameRecord>

Frames whose chains are past the cap, deepest first.

Parameters

int $limit

Most records to return.

Returns

list<\Drupal\strata\Cas\FrameRecord> —

The records.

deepest()

deepest() : int

The deepest chain in the index.

What the health dashboard shows next to the cap, so an operator can see how close the store is running to it rather than only hearing about it once it is past.

Returns

int —

The depth, zero when nothing is delta coded.