ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
MMappedCircuit.h
Go to the documentation of this file.
1/**
2 * @file MMappedCircuit.h
3 * @brief Persistent, mmap-backed storage for the full provenance circuit.
4 *
5 * @c MMappedCircuit is the authoritative store for all provenance circuit
6 * data that must survive transaction boundaries and be accessible across
7 * multiple PostgreSQL backends. It composes three @c MMappedVector
8 * instances plus one @c MMappedUUIDHashTable:
9 *
10 * | Component | Contents |
11 * |---------------------|-----------------------------------------------|
12 * | @c mapping | UUID → gate index (hash table) |
13 * | @c gates | @c GateInformation records, one per gate |
14 * | @c wires | Flattened child-UUID lists for all gates |
15 * | @c extra | Variable-length string data (e.g. provenance labels) |
16 *
17 * All four backing files live in the database's directory inside the
18 * PostgreSQL data directory, and are opened/created by the ProvSQL
19 * background worker on the first message for that database.
20 *
21 * The free-function @c createGenericCircuit() traverses the mmap data
22 * starting from a given root UUID to construct an in-memory
23 * @c GenericCircuit for evaluation.
24 *
25 * @warning ON-DISK ABI: the layouts of @c GateInformation, of the
26 * @c gate_type enum (defined in @c provsql_utils.h), of @c pg_uuid_t,
27 * and of @c MMappedUUIDHashTable's slot structure are all serialised
28 * verbatim into the four @c provsql_*.mmap backing files. ProvSQL
29 * supports in-place extension upgrades (@c ALTER @c EXTENSION @c provsql
30 * @c UPDATE) only because these layouts have been stable since
31 * ProvSQL 1.0.0. Any change that adds, removes, reorders, or resizes
32 * a field -- or that renumbers a @c gate_type enumerator -- silently
33 * breaks every existing installation's on-disk mmap files. If such a
34 * change is necessary, bump an explicit format-version header in the
35 * mmap files, write a migration path, and call it out in a release note.
36 */
37#ifndef MMAPPED_CIRCUIT_H
38#define MMAPPED_CIRCUIT_H
39
40#include <cmath>
41#include <cstdint>
42#include <string>
43#include <vector>
44
45#include "GenericCircuit.h"
47#include "MMappedVector.hpp"
48
49extern "C" {
50#include "provsql_utils.h"
51}
52
53/**
54 * @brief Per-gate metadata stored in the @c gates @c MMappedVector.
55 *
56 * Each gate in the persistent circuit has exactly one @c GateInformation
57 * record. The @c children_idx and @c nb_children fields together index
58 * into the @c wires @c MMappedVector to find the gate's children.
59 * Similarly, @c extra_idx and @c extra_len index into the @c extra vector
60 * for variable-length string annotations.
61 */
62typedef struct GateInformation
63{
64 gate_type type; ///< Kind of gate (input, plus, times…)
65 unsigned nb_children; ///< Number of children
66 unsigned long children_idx;///< Start index of this gate's children in @c wires
67 double prob; ///< Associated probability, @c NaN when unset
68 unsigned info1; ///< General-purpose integer annotation 1
69 unsigned info2; ///< General-purpose integer annotation 2
70 unsigned long extra_idx; ///< Start index in @c extra for string data
71 unsigned extra_len; ///< Byte length of the string data in @c extra
72
73 /**
74 * @brief Construct a @c GateInformation with mandatory fields.
75 * @param t Gate type.
76 * @param n Number of children.
77 * @param i Start index of children in the @c wires vector.
78 */
79 GateInformation(gate_type t, unsigned n, unsigned long i) :
80 type(t), nb_children(n), children_idx(i), prob(NAN), info1(0), info2(0), extra_idx(0), extra_len(0) {
81 }
83
84/**
85 * @brief Persistent mmap-backed representation of the provenance circuit.
86 *
87 * @c MMappedCircuit is the single writer for circuit data; only the
88 * background worker should call its mutating methods. Reading methods
89 * may be called from any process that has mapped the files read-only.
90 */
92private:
93MMappedUUIDHashTable mapping; ///< UUID → gate-index hash table
94MMappedVector<GateInformation> gates; ///< Gate metadata array
95MMappedVector<pg_uuid_t> wires; ///< Flattened child UUID array
96MMappedVector<char> extra; ///< Variable-length string data
97
98static constexpr const char *GATES_FILENAME="provsql_gates.mmap"; ///< Backing file for @c gates
99static constexpr const char *WIRES_FILENAME="provsql_wires.mmap"; ///< Backing file for @c wires
100static constexpr const char *MAPPING_FILENAME="provsql_mapping.mmap"; ///< Backing file for @c mapping
101static constexpr const char *EXTRA_FILENAME="provsql_extra.mmap"; ///< Backing file for @c extra
102
103/** @brief Append a complete gate record, then publish @p token for it. */
104void appendGate(pg_uuid_t token, gate_type type,
105 const std::vector<pg_uuid_t> &children);
106
107/** @brief Whether the gate record at index @p idx holds a written
108 * probability (see @c GATES_VERSION for the version-1 leniency). */
109bool hasProbAt(unsigned long idx) const;
110
111
112
113/** @brief Delegating constructor that accepts pre-built paths. */
114MMappedCircuit(const std::string &mp, const std::string &gp,
115 const std::string &wp, const std::string &ep,
116 bool read_only) :
117 mapping(mp.c_str(), read_only, MAGIC_MAPPING),
118 gates (gp.c_str(), read_only, MAGIC_GATES, GATES_VERSION),
119 wires (wp.c_str(), read_only, MAGIC_WIRES),
120 extra (ep.c_str(), read_only, MAGIC_EXTRA) {}
121
122public:
123/**
124 * @brief Format version of the @c gates file this build writes.
125 *
126 * Version 1 stored @c 1.0 in @c GateInformation::prob both for a gate
127 * whose probability had been set to 1 and for one that had never been
128 * given a probability at all. Version 2 writes @c NaN for the latter,
129 * which is what lets a probability be written once and refused
130 * afterwards. A version-1 file is still read: @c 1.0 on a
131 * probability-bearing gate is then treated as unset, so a store
132 * carried across an upgrade keeps accepting the probabilities its
133 * owner has always been allowed to write. The ambiguity lasts until
134 * @c circuit_cleanup rewrites the file, which normalises those
135 * @c 1.0 values and stamps the file version 2.
136 */
137static constexpr uint16_t GATES_VERSION = 2;
138
139/**
140 * @brief Outcome of @c setProb.
141 *
142 * @c Written and @c Unchanged are both successes; only @c Written
143 * needs undoing if the writing transaction rolls back.
144 */
145enum class SetProbResult {
146 NotProbGate, ///< The token names a gate that carries no probability
147 Written, ///< The gate had no probability and now holds the given one
148 Unchanged, ///< The gate already held exactly this probability
149 AlreadySet ///< The gate holds a different probability; refused
150};
151
152
153/** @brief Build the full path of a file in a database's store directory,
154 * the one @c GetDatabasePath resolves for @p db_oid in @p db_tablespace. */
155static std::string storePath(Oid db_oid, Oid db_tablespace,
156 const char *filename);
157
158/**
159 * @brief Outcome of @c setInfos or @c setExtra.
160 *
161 * Same discipline as @c setProb: an annotation is a fact appended to the
162 * gate, written once and idempotent on the same value.
163 */
165 NoSuchGate, ///< The token names no gate
166 Written, ///< The gate had none and now holds the given annotation
167 Unchanged, ///< The gate already held exactly this annotation
168 AlreadySet ///< The gate holds a different annotation; refused
169};
170
171/** @brief 8-byte magic constants identifying each mmap file type. */
172static constexpr uint64_t MAGIC_GATES =
173 uint64_t('P') | uint64_t('v') << 8 | uint64_t('S') << 16 | uint64_t('G') << 24 |
174 uint64_t('a') << 32 | uint64_t('t') << 40 | uint64_t('e') << 48 | uint64_t('s') << 56;
175static constexpr uint64_t MAGIC_WIRES =
176 uint64_t('P') | uint64_t('v') << 8 | uint64_t('S') << 16 | uint64_t('W') << 24 |
177 uint64_t('i') << 32 | uint64_t('r') << 40 | uint64_t('e') << 48 | uint64_t('s') << 56;
178static constexpr uint64_t MAGIC_MAPPING =
179 uint64_t('P') | uint64_t('v') << 8 | uint64_t('S') << 16 | uint64_t('M') << 24 |
180 uint64_t('a') << 32 | uint64_t('p') << 40 | uint64_t('n') << 48 | uint64_t('g') << 56;
181static constexpr uint64_t MAGIC_EXTRA =
182 uint64_t('P') | uint64_t('v') << 8 | uint64_t('S') << 16 | uint64_t('E') << 24 |
183 uint64_t('x') << 32 | uint64_t('t') << 40 | uint64_t('r') << 48 | uint64_t('a') << 56;
184
185/**
186 * @brief Open all four mmap backing files for the given database.
187 * @param db_oid OID of the target database.
188 * @param db_tablespace OID of that database's default tablespace; the
189 * files go in the directory @c GetDatabasePath
190 * resolves for the pair.
191 * @param read_only If @c true, all files are mapped read-only.
192 */
193MMappedCircuit(Oid db_oid, Oid db_tablespace, bool read_only = false);
194
195/** @brief Sync all backing files before destruction. */
197 sync();
198}
199
200/**
201 * @brief Persist a new gate to the mmap store.
202 *
203 * Allocates a @c GateInformation record, appends the children to the
204 * @c wires vector, and records the UUID→index mapping. Existing gates
205 * with the same @p token are silently skipped.
206 *
207 * @param token UUID identifying the new gate.
208 * @param type Gate type.
209 * @param children Ordered list of child gate UUIDs.
210 */
211void createGate(pg_uuid_t token, gate_type type, const std::vector<pg_uuid_t> &children);
212
213/**
214 * @brief Write the @c info1 / @c info2 annotations of a gate, once.
215 *
216 * The two fields are written once **each**, with @c 0 meaning "nothing
217 * recorded": a field goes from @c 0 to a value once, accepts that value
218 * again, and refuses a different one; writing @c 0 over a value records
219 * nothing and leaves it alone. Per field rather than per pair because
220 * the two are written by different parties -- a certified @c plus gate
221 * is marked as certified when it is built and tagged with the route that
222 * made it a query's root afterwards.
223 *
224 * @param token UUID of the gate to annotate.
225 * @param info1 Value for @c info1, or @c 0 to leave it alone.
226 * @param info2 Value for @c info2, or @c 0 to leave it alone.
227 * @param existing On @c AlreadySet, the pair the gate holds.
228 */
229SetAnnotationResult setInfos(pg_uuid_t token, unsigned info1, unsigned info2,
230 std::pair<unsigned, unsigned> *existing = nullptr);
231
232/**
233 * @brief Attach a variable-length string annotation to a gate, once.
234 *
235 * A gate with no annotation has an empty one, and an empty string is not
236 * an annotation, so "nothing recorded" and "recorded as nothing"
237 * coincide and the question of an unset marker does not arise. Offering
238 * the bytes the gate already holds is a no-op rather than a fresh
239 * append, which is what keeps the @c extra file from accumulating
240 * abandoned copies of the same string.
241 *
242 * @param token UUID of the gate.
243 * @param s String to store.
244 * @param existing On @c AlreadySet, the string the gate holds.
245 */
246SetAnnotationResult setExtra(pg_uuid_t token, const std::string &s,
247 std::string *existing = nullptr);
248
249/**
250 * @brief Write a gate's probability, once.
251 *
252 * A probability is a fact appended to the circuit, like the gate
253 * itself: it can be written when the gate has none, re-written with
254 * the identical value (so setup scripts and notebook cells stay
255 * re-runnable), and otherwise refused. Changing one means minting a
256 * fresh input gate and rewriting the rows that carry the old token --
257 * see @c provsql.replace_input.
258 *
259 * Passing @c NaN clears the probability unconditionally; that is how a
260 * transaction that rolls back drops the probabilities it wrote, and it
261 * is not reachable from SQL.
262 *
263 * If the token is not yet in the circuit, an input gate is created
264 * lazily.
265 *
266 * @param token UUID of the gate.
267 * @param prob Probability value in [0, 1], or @c NaN to clear.
268 * @param existing On @c AlreadySet, the probability the gate holds.
269 * @return Which of the four cases applied.
270 */
271SetProbResult setProb(pg_uuid_t token, double prob, double *existing = nullptr);
272
273/**
274 * @brief Report whether @p token names a gate that holds a probability.
275 * @param token UUID of the gate.
276 * @param prob On @c true return, the stored probability.
277 * @return @c true when the gate exists, carries probabilities, and one
278 * has been written to it.
279 */
280bool hasProb(pg_uuid_t token, double *prob) const;
281
282/**
283 * @brief Flush all backing files to disk with @c msync().
284 */
285void sync();
286
287/**
288 * @brief Force every backing file to stable storage.
289 *
290 * @c sync() pushes the regions' bytes into the files; this pushes the
291 * files out of the kernel's page cache, which is what a crash of the
292 * machine can otherwise lose.
293 */
294void flush();
295
296/**
297 * @brief Whether any backing file was found still marked open-for-writing
298 * when it was opened -- the previous writer died mid-write.
299 */
300bool uncleanShutdown() const;
301
302/**
303 * @brief What @c provsql.check_store() reports about a store.
304 *
305 * Every count but @c unclean is zero for a store nothing has damaged.
306 * A non-zero one means a write was interrupted at a point the ordering
307 * rules do not cover, or a set of files was copied at different instants
308 * (a file-level backup of a running server); @c provsql.circuit_cleanup()
309 * rebuilds the store from what is still reachable.
310 */
311struct Check {
312 bool unclean; ///< A file was left marked open-for-writing
313 unsigned long nb_gates; ///< Gate records
314 unsigned long nb_mapping; ///< Mapping entries
315 unsigned long next_value; ///< Next index the mapping would assign
316 unsigned long dangling_indices; ///< Mapping entries indexing past the records
317 unsigned long unreferenced; ///< Records no mapping entry points at
318 unsigned long bad_wires; ///< Records whose children run past the wires
319 unsigned long bad_extra; ///< Records whose extra runs past the extra file
320};
321
322/** @brief Walk the store and report what does not add up. */
323Check check() const;
324
325/**
326 * @brief Mark every gate reachable from @p roots.
327 *
328 * @param roots Token UUIDs to start from; unknown ones are ignored.
329 * @param live Filled with one flag per gate record.
330 * @return The number of live gates.
331 */
332unsigned long mark(const std::vector<pg_uuid_t> &roots,
333 std::vector<bool> &live) const;
334
335/** @brief The size of a store, in the three units that matter. */
336struct Counts {
337 unsigned long gates; ///< Gate records
338 unsigned long wires; ///< Child wires
339 unsigned long extra_bytes; ///< Bytes of variable-length annotation
340};
341
342/** @brief This store's current size. */
343inline Counts counts() const {
344 return { gates.nbElements(), wires.nbElements(), extra.nbElements() };
345}
346
347/**
348 * @brief Copy the gates flagged in @p live into a fresh set of files
349 * beside the current ones (suffix @c ".new").
350 *
351 * Child indices, extra offsets and the token table are all rebuilt, so
352 * the result is a compact, freshly hashed store. A version-1 @c gates
353 * file also gets its probabilities normalised on the way through: the
354 * @c 1.0 that used to mean both "written as certain" and "never written"
355 * becomes @c NaN on gates the file cannot prove were written, and the new
356 * file is stamped version 2, after which the ambiguity is gone.
357 *
358 * @return The gate, wire and extra-byte counts of the new files.
359 */
360Counts sweepInto(const std::vector<bool> &live,
361 const std::string &mp, const std::string &gp,
362 const std::string &wp, const std::string &ep) const;
363
364/** @brief Whether this store's @c gates file predates the @c NaN
365 * unset-probability convention (see @c GATES_VERSION). */
366inline bool legacyProbabilities() const {
367 return gates.version() < GATES_VERSION;
368}
369
370
371
372/**
373 * @brief Return the type of the gate identified by @p token.
374 * @param token UUID of the gate.
375 * @return The gate's type, or @c gate_input if not found (lazy default).
376 */
377gate_type getGateType(pg_uuid_t token) const;
378
379/**
380 * @brief Return the child UUIDs of the gate identified by @p token.
381 * @param token UUID of the gate.
382 * @return Ordered vector of child UUIDs.
383 */
384std::vector<pg_uuid_t> getChildren(pg_uuid_t token) const;
385
386/**
387 * @brief Return the probability an evaluation would use for @p token.
388 *
389 * A gate nobody has given a probability evaluates as certain, and a
390 * repaired row nobody has given one evaluates at the uniform weight of
391 * its @c repair_key block; either way this answers a number, not "unset".
392 * Use @c hasProb to tell the two apart.
393 *
394 * @param token UUID of the gate.
395 * @return The probability; @c NaN when @p token names no gate, or
396 * one that carries no probability at all.
397 */
398double getProb(pg_uuid_t token) const;
399
400/**
401 * @brief Return the @c info1 / @c info2 pair for the gate @p token.
402 * @param token UUID of the gate.
403 * @return Pair @c {info1, info2}, or @c {0,0} if not found.
404 */
405std::pair<unsigned, unsigned> getInfos(pg_uuid_t token) const;
406
407/**
408 * @brief Return the variable-length string annotation for gate @p token.
409 * @param token UUID of the gate.
410 * @return The stored string, or empty if none.
411 */
412std::string getExtra(pg_uuid_t token) const;
413
414/**
415 * @brief Return the total number of gates stored in the circuit.
416 * @return Total gate count.
417 */
418inline unsigned long getNbGates() const {
419 return gates.nbElements();
420}
421
422/**
423 * @brief Build an in-memory @c GenericCircuit rooted at @p token.
424 *
425 * Performs a depth-first traversal of the mmap-backed circuit starting
426 * from @p token and copies all reachable gates and wires into a newly
427 * constructed @c GenericCircuit.
428 *
429 * @param token UUID of the root gate.
430 * @return An in-memory @c GenericCircuit containing the sub-circuit.
431 */
433
434/**
435 * @brief Build an in-memory @c GenericCircuit reachable from any of
436 * @p roots.
437 *
438 * Multi-root variant of @c createGenericCircuit. Seeds the BFS with
439 * every UUID in @p roots so a shared subgraph reachable from more
440 * than one root is represented by a single @c gate_t (the
441 * @c GenericCircuit::setGate / @c getGate pair is idempotent on the
442 * UUID key). Used by @c getJointCircuit to load an RV's sub-DAG
443 * together with a conditioning gate that sits above it in the
444 * persisted DAG.
445 *
446 * @param roots UUIDs whose reachable closure to load. Order is
447 * irrelevant; identical UUIDs collapse via the
448 * @c std::set deduplication of the work list.
449 * @return An in-memory @c GenericCircuit containing every gate
450 * reachable from any root.
451 */
453 const std::vector<pg_uuid_t> &roots) const;
454};
455
456#ifdef PROVSQL_INPROCESS_STORE
457/**
458 * @brief Build a @c GenericCircuit rooted at @p token directly from the
459 * current backend's store.
460 *
461 * Single-process replacement for the @c 'g' IPC round-trip: there is no
462 * worker/backend boundary to ship a Boost-serialised copy across, so the
463 * backend constructs the circuit in place.
464 */
465GenericCircuit provsql_inproc_generic_circuit(pg_uuid_t token);
466/** @brief Multi-root variant (single-process replacement for @c 'j'). */
467GenericCircuit provsql_inproc_joint_circuit(
468 const std::vector<pg_uuid_t> &roots);
469#endif
470
471
472#endif /* MMAPPED_CIRCUIT_H */
Semiring-agnostic in-memory provenance circuit.
Open-addressing hash table mapping UUIDs to integers, backed by an mmap file.
Template implementation of MMappedVector<T>.
In-memory provenance circuit with semiring-generic evaluation.
static constexpr uint16_t GATES_VERSION
Format version of the gates file this build writes.
unsigned long mark(const std::vector< pg_uuid_t > &roots, std::vector< bool > &live) const
Mark every gate reachable from roots.
SetAnnotationResult setInfos(pg_uuid_t token, unsigned info1, unsigned info2, std::pair< unsigned, unsigned > *existing=nullptr)
Write the info1 / info2 annotations of a gate, once.
MMappedUUIDHashTable mapping
UUID → gate-index hash table.
void createGate(pg_uuid_t token, gate_type type, const std::vector< pg_uuid_t > &children)
Persist a new gate to the mmap store.
Counts counts() const
This store's current size.
std::string getExtra(pg_uuid_t token) const
Return the variable-length string annotation for gate token.
bool legacyProbabilities() const
Whether this store's gates file predates the NaN unset-probability convention (see GATES_VERSION).
SetProbResult setProb(pg_uuid_t token, double prob, double *existing=nullptr)
Write a gate's probability, once.
void appendGate(pg_uuid_t token, gate_type type, const std::vector< pg_uuid_t > &children)
Append a complete gate record, then publish token for it.
unsigned long getNbGates() const
Return the total number of gates stored in the circuit.
SetProbResult
Outcome of setProb.
@ NotProbGate
The token names a gate that carries no probability.
@ Unchanged
The gate already held exactly this probability.
@ Written
The gate had no probability and now holds the given one.
@ AlreadySet
The gate holds a different probability; refused.
static constexpr const char * GATES_FILENAME
Backing file for gates.
Counts sweepInto(const std::vector< bool > &live, const std::string &mp, const std::string &gp, const std::string &wp, const std::string &ep) const
Copy the gates flagged in live into a fresh set of files beside the current ones (suffix "....
gate_type getGateType(pg_uuid_t token) const
Return the type of the gate identified by token.
Check check() const
Walk the store and report what does not add up.
void sync()
Flush all backing files to disk with msync().
static std::string storePath(Oid db_oid, Oid db_tablespace, const char *filename)
Build the full path of a file in a database's store directory, the one GetDatabasePath resolves for d...
static constexpr const char * WIRES_FILENAME
Backing file for wires.
MMappedCircuit(const std::string &mp, const std::string &gp, const std::string &wp, const std::string &ep, bool read_only)
Delegating constructor that accepts pre-built paths.
GenericCircuit createGenericCircuit(pg_uuid_t token) const
Build an in-memory GenericCircuit rooted at token.
bool uncleanShutdown() const
Whether any backing file was found still marked open-for-writing when it was opened – the previous wr...
static constexpr const char * EXTRA_FILENAME
Backing file for extra.
static constexpr uint64_t MAGIC_WIRES
static constexpr uint64_t MAGIC_GATES
8-byte magic constants identifying each mmap file type.
static constexpr const char * MAPPING_FILENAME
Backing file for mapping.
bool hasProb(pg_uuid_t token, double *prob) const
Report whether token names a gate that holds a probability.
MMappedVector< char > extra
Variable-length string data.
static constexpr uint64_t MAGIC_EXTRA
double getProb(pg_uuid_t token) const
Return the probability an evaluation would use for token.
std::vector< pg_uuid_t > getChildren(pg_uuid_t token) const
Return the child UUIDs of the gate identified by token.
MMappedVector< GateInformation > gates
Gate metadata array.
SetAnnotationResult setExtra(pg_uuid_t token, const std::string &s, std::string *existing=nullptr)
Attach a variable-length string annotation to a gate, once.
SetAnnotationResult
Outcome of setInfos or setExtra.
@ NoSuchGate
The token names no gate.
~MMappedCircuit()
Sync all backing files before destruction.
bool hasProbAt(unsigned long idx) const
Whether the gate record at index idx holds a written probability (see GATES_VERSION for the version-1...
MMappedVector< pg_uuid_t > wires
Flattened child UUID array.
static constexpr uint64_t MAGIC_MAPPING
std::pair< unsigned, unsigned > getInfos(pg_uuid_t token) const
Return the info1 / info2 pair for the gate token.
void flush()
Force every backing file to stable storage.
Persistent open-addressing hash table mapping UUIDs to integers.
Append-only, mmap-backed vector of elements of type T.
Core types, constants, and utilities shared across ProvSQL.
Per-gate metadata stored in the gates MMappedVector.
double prob
Associated probability, NaN when unset.
unsigned info2
General-purpose integer annotation 2.
unsigned long children_idx
Start index of this gate's children in wires.
unsigned info1
General-purpose integer annotation 1.
unsigned long extra_idx
Start index in extra for string data.
unsigned extra_len
Byte length of the string data in extra.
GateInformation(gate_type t, unsigned n, unsigned long i)
Construct a GateInformation with mandatory fields.
unsigned nb_children
Number of children.
gate_type type
Kind of gate (input, plus, times…).
What provsql.check_store() reports about a store.
unsigned long dangling_indices
Mapping entries indexing past the records.
unsigned long nb_gates
Gate records.
unsigned long bad_extra
Records whose extra runs past the extra file.
bool unclean
A file was left marked open-for-writing.
unsigned long nb_mapping
Mapping entries.
unsigned long unreferenced
Records no mapping entry points at.
unsigned long bad_wires
Records whose children run past the wires.
unsigned long next_value
Next index the mapping would assign.
The size of a store, in the three units that matter.
unsigned long extra_bytes
Bytes of variable-length annotation.
unsigned long gates
Gate records.
unsigned long wires
Child wires.