SwarmOps
ReferenceCommandsswarmops verify
View as Markdown

swarmops verify#

Check the store's consistency.

Metadata
Group
integrity
Since
0.1.0
Mutates
no
Identity required
no
MCP tool
verify
Envelope op
verify
Exit codes
01

Syntax#

swarmops verify [OPTIONS]

Required arguments#

None.

Optional arguments#

The command also takes the global options.

Syntax: --deep.

Re-hash every object, and check the derived values against the objects, too.

Examples#

swarmops --repo [tmp]/store verify
{
  "ok": true,
  "op": "verify",
  "api": 1,
  "result": {
    "objects_checked": 3,
    "changesets_checked": 1,
    "problems": [],
    "findings": []
  },
  "meta": {
    "repo": "[tmp]/store",
    "elapsed_ms": "[elapsed_ms]",
    "resolved": {},
    "auth": "trust"
  }
}

Exit code 0. Recorded by the CLI tests. A name in square brackets, such as [tmp] or [c1], stands for what differs from run to run: the test's temporary directory, an id, a time.

No recorded example yet.

Details#

verify reads the whole store once and reports what it finds damaged. It succeeds on a sound store and fails with E_STORE_CORRUPT (exit 1) on a damaged one, the whole report in the error's details. It takes no lock, writes nothing and needs no identity, so it can run while agents commit and land: it reads the store's files in an order that keeps a commit made meanwhile from looking like damage.

What each check covers#

Without --deep, verify checks the structure:

  • The metadata. The lock file; the changeset index against the journal, record by record, and the sorted views against the index columns; every frame of the journal.
  • The refs. Each ref file reads as one and names a changeset the store holds.
  • Every changeset, in the order it was recorded: its object, its metadata record against the object (parents, delta hash, generation), its parents, every tree under its root, and its root against its first parent's root with its delta applied.
  • The external id index (the git import and export's map of git commits to changesets): each entry reads as one, names a changeset the store holds, and, for git, matches the changeset's git.oid.
  • The blobs: each blob a tree names exists. Its bytes are not read.

--deep also re-hashes every object file, referenced or not, and checks every derived value the store holds (the first-parent skip lists, the last touches of paths, and the git export's oid memos) against what the objects give, as well as the external id entries of changesets made in the store against their export. A shallow check reads the changeset and tree objects it walks, and checks those, so it misses a damaged blob; --deep finds it.

Reading the report#

objects_checked counts the objects examined (deep: every object file; shallow: the changeset and tree objects read and the blobs looked for), changesets_checked the changesets. problems has one line per problem, for a person; findings the same problems at the same indexes, for a program, each with its kind and the ids it names:

kindWhat is damagedNames
corrupt_objectAn object whose content does not hash to its id, or does not decodeobject
missing_objectAn object a changeset references that the store lacks or holds as another kindobject, changeset
missing_parentA parent a changeset names that the store does not holdchangeset, parent
root_mismatchA changeset whose root is not its first parent's root with its delta appliedchangeset
dangling_refA ref that names no changeset in the storeref
corrupt_refA ref file that does not read as oneref
index_mismatchA changeset record that disagrees with the journal, the sorted views or its objectseq, cause
journal_corruptA journal frame that does not read; nothing after it is readoffset
meta_corruptA metadata file that does not read as one, so what depends on it goes unchecked—
external_id_corruptAn external id entry that is not onesystem, key
external_id_danglingAn external id entry that names a changeset the store does not holdsystem, key, changeset
external_id_mismatchAn external id entry whose changeset stands for another commitsystem, key, changeset
derived_mismatchA derived value that is not the one the objects give (deep only)derivation, changeset or object, key

An object is reported once, against the first changeset that references it. cause of an index_mismatch says what would mend it: journal (rebuild the index from the journal), sorted_view (rebuild the sorted views from the index columns) or object (derive the record from its object again). kind is a string, so a client can read kinds newer than its own list.

What to do with a failure#

The hint says the next step. After a shallow check it is swarmops verify --deep, which finds damaged bytes too. After a deep check it says to restore the damaged objects, records or refs from a backup: there is no repair command yet. A derived_mismatch is the one exception: the value is a cache, and removing its file under meta/derived/<derivation>/, or all of meta/derived/, has it derived again (Making room).

Not every failure is a report. A directory that is not a store fails with E_NOT_A_REPO (exit 6) before any check. A file that verify cannot read past fails the command with the store's own error instead, such as E_STORE_CORRUPT with details.store_file naming the file, and no findings. For example, on a store whose meta/refs/main is not a ref file, verify reports a corrupt_ref finding, while verify --deep fails with E_STORE_CORRUPT, details.store_file: meta/refs/main and the hint swarmops verify.

Patterns#

Check a store on a schedule and keep the findings:

swarmops verify --deep > verify.json || jq -c '.error | {code, findings: .details.findings, store_file: .details.store_file}' verify.json

A report fills findings; a failure to read fills store_file instead.

Run verify --deep after a crash or a power loss, on every backup, before an upgrade, and on a schedule (When to run it).

Caveats#

  • No cap on the report. A store damaged in many places gives a report as long as its damage, and through MCP twice that, since a tool result holds its envelope twice.
  • Memory. verify holds the journal and the index in memory; a deep check of a store with derived values also holds the first-parent forest and every last_modified value.
  • What it skips. Temp files of interrupted writes (objects/tmp/) and object files that are symlinks are passed over.

These are listed, with their targets, in Known limitations: Verification and repair.

Through MCP#

The MCP tool is verify, with deep. A damaged store fails the call the same way, with E_STORE_CORRUPT and the report in details.

Performance#

The performance ledger's v0.1.0 run checked a store of 32,101 changesets and 128,306 objects with verify --deep in 1,758 ms (v0.1.0 run). Verify and repair gives the times on SwarmOps' own history, shallow and deep.

Guides#

Return information#

result is a VerifyReport (swarmops schema VerifyReport prints its JSON Schema).

FieldTypeRequiredDescription
changesets_checkedintegeryesHow many changesets were checked.
findingsarray of VerifyFindingnoOne finding per problem found, for a program to act on: findings[i] is the problem that the line problems[i] describes. Empty for a clean store; a report without it reads as having none.
objects_checkedintegeryesHow many objects were checked.
problemsarray of stringyesOne line per problem found, for a reader of lines; empty for a clean store. findings holds the same problems, at the same indexes, for a program.

Envelope op: verify.

Exit codes:

  • 0: Success.
  • 1: The operation failed.

Errors#

Any command that opens a store may also fail with a store error, such as E_NOT_A_REPO, E_IO or E_STORE_CORRUPT; a command line the grammar refuses is E_INVALID_ARG (exit 2).

See also#

Edit on GitHub

On this page