Documentation
¶
Overview ¶
Package simfdb is a deterministic, in-memory MVCC implementation of the fdb.BackendDatabase contract (RFC-199 Tier 1 — "SimFDB"). It is the third backend alongside the pure-Go client and libfdb_c, wired via recordlayer.NewFDBDatabaseWithBackend, so the entire record + relational stack can run single-goroutine, with no cluster and no Docker, reproducibly from one seed.
Everything resolves synchronously: futures carry a ready value (no goroutine, no channel), the store is a sorted in-memory keyspace, and versions come from a monotonic logical counter. Conflict detection is serializable-snapshot-isolation over read/write conflict ranges, resolved against commit-version ordering (see conflict.go).
Index ¶
- Constants
- type SimDB
- func (db *SimDB) Close()
- func (db *SimDB) CreateWritableTransaction() (fdb.WritableTransaction, error)
- func (db *SimDB) InjectOnce(code int)
- func (db *SimDB) InjectSequence(codes ...int)
- func (db *SimDB) LastCommitUnknownApplied() bool
- func (db *SimDB) LocalityGetBoundaryKeys(_ fdb.ExactRange, _ int, _ int64) ([]fdb.Key, error)
- func (db *SimDB) ReadTransact(fn func(fdb.ReadTransaction) (any, error)) (any, error)
- func (db *SimDB) Transact(fn func(fdb.WritableTransaction) (any, error)) (any, error)
Constants ¶
const ( CommitUnknownApplied = injectCommitUnknownApplied CommitUnknownDiscarded = injectCommitUnknownDiscarded )
CommitUnknownApplied and CommitUnknownDiscarded name the two real outcomes behind commit_unknown_result(1021): the mutations were durable but the answer was lost, or the commit never reached the proxy. Pass either to InjectOnce/InjectSequence to pin the branch; a plain 1021 leaves the choice to the run's seed.
Both are real FDB. A harness that only ever exercises one of them is not testing 1021 handling, it is testing half of it.
const DockerRequired = false
DockerRequired is false without the `fdbdocker` build tag: a missing container takes the sanctioned skip. See differential_docker_required.go for why the tagged build exists.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type SimDB ¶
type SimDB struct {
// contains filtered or unexported fields
}
SimDB is a deterministic, in-memory MVCC FoundationDB backend — the third fdb.BackendDatabase alongside the pure-Go client and libfdb_c (RFC-199 Tier 1). It mints versions from a monotonic logical counter, resolves serializable-snapshot-isolation conflicts in-process, and stores data in a sorted keyspace, so the whole record + relational stack runs single-goroutine, no cluster, no Docker, reproducibly.
Commits are serialized: the whole commit (conflict resolution + version assignment + apply) holds db.mu, so there is one committing transaction at a time and each gets one monotonic commit version. This sidesteps FDB's batch/MiniConflictSet intra-batch path (RFC-199 Tier 1 item 1) — any serial order is a valid batch order, so the verdict is identical.
func New ¶
New returns an empty SimDB. env supplies the Buggify fault points for commit-time injection (nil = production, no faults). The sim clock/randomness in env are for the record-layer persisted-byte sites (Tier 0), not the store itself, which uses only logical versions.
A SimDB stands in for an *opened* FDB database, and fdb.OpenDatabase refuses to construct one without a selected API version (api_version_unset, 2200) — the versionstamp path reads that global. Since New cannot return an error, it enforces the same precondition by selecting the default version when the process hasn't already chosen one (idempotent; an already-selected version is respected). Without this, the first versionstamp/VERSION-index write over SimFDB fails 2200 — a fidelity gap surfaced by the DST hunt (pkg/simfdb/hunt).
func (*SimDB) Close ¶
func (db *SimDB) Close()
Close releases the store. The sim holds no OS resources, so this only marks the db closed.
func (*SimDB) CreateWritableTransaction ¶
func (db *SimDB) CreateWritableTransaction() (fdb.WritableTransaction, error)
CreateWritableTransaction returns a standalone, non-retry writable transaction whose lifecycle the caller owns (Commit / Cancel) — the interface path used by SQL BeginTx, explicit transactions, and the FDBDatabaseRunner (RFC-199 Q1: load-bearing for SimFDB).
func (*SimDB) InjectOnce ¶
InjectOnce schedules fault code to be returned by the NEXT commit. Deterministic (no seed): 1020 (not_committed) / 1007 (transaction_too_old) fire before apply; 1021 (commit_unknown) resolves its applied/discarded branch by the run's seeded coin, or by the branch named with CommitUnknownApplied / CommitUnknownDiscarded. Use to reproduce a precise fault at a chosen point when hunting real record-layer retry/idempotency bugs.
func (*SimDB) InjectSequence ¶
InjectSequence schedules faults for successive commits (codes[0] on the next commit, codes[1] on the one after, etc.). A zero in the sequence means "no fault on that commit". Lets a hunt drive a whole workload through a fixed fault schedule.
func (*SimDB) LastCommitUnknownApplied ¶
LastCommitUnknownApplied reports, for the most recent commit that returned commit_unknown_result(1021), whether that commit's mutations were applied.
This is SIMULATOR GROUND TRUTH. No FDB client can learn it — the impossibility is the entire reason the error exists — and it is exposed here for one purpose: a model-based oracle has to predict the store's contents, and after a 1021 the contents depend on a branch the seed chose. A harness that could not ask would have to either guess (and start certifying wrong verdicts again) or drop the fault dimension.
It is an ORACLE input, never a control input: nothing in the system under test may consult it to decide what to do, or the run stops modelling a real client.
SINGLE-COMMIT SCOPE. It reports the LAST 1021, not the one you are asking about, and the mutex protects the field, not that correspondence. Two goroutines committing concurrently can both take the 1021 branch, and whichever commits second overwrites the answer the first is about to read — a data race the race detector cannot see, because there is no unsynchronised access, only a stale one. Read it from the same goroutine that made the commit, before that goroutine issues another, which is what a sim driver does anyway: SimFDB's transactions are single-goroutine by construction (see simTxn) and the whole point of the sim is a serialized driver. The exported name is where this has to be said, because a caller holding a *SimDB has no other reason to look at simTxn.
func (*SimDB) LocalityGetBoundaryKeys ¶
LocalityGetBoundaryKeys returns shard boundaries within r. SimFDB is a single logical shard, so v1 returns no interior boundaries (the whole range is one shard). This satisfies the interface method that the constructor's capability check requires (RFC-199 Q1); real shard boundaries are deferrable (online MUTUAL indexing then builds a single fragment).
func (*SimDB) ReadTransact ¶
ReadTransact runs fn inside a read-only transaction. Reads retry on a retryable error for symmetry with Transact, though the sim's synchronous reads rarely produce one.
func (*SimDB) Transact ¶
Transact runs fn inside a writable transaction with the retry loop the real backends' Transact also provides (recordlayer.Run delegates to it): run fn, commit, and on a retryable error (conflict 1020 / too_old 1007 / commit_unknown 1021) reset and retry, up to maxRetries. A non-retryable error or exhausted retries propagates. This is what makes SimFDB a drop-in backend — the record layer relies on Transact retrying, exactly as with the pure-Go client.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package hunt is a brute-force, seed-driven bug hunter for the record layer.
|
Package hunt is a brute-force, seed-driven bug hunter for the record layer. |
|
atomicops
Package atomicops is a DST driver that differentials FoundationDB's ten atomic mutation types (Add / And / Or / Xor / Max / Min / ByteMax / ByteMin / AppendIfFits / CompareAndClear) end-to-end through the SimFDB backend against an INDEPENDENT Go reference model.
|
Package atomicops is a DST driver that differentials FoundationDB's ten atomic mutation types (Add / And / Or / Xor / Max / Min / ByteMax / ByteMin / AppendIfFits / CompareAndClear) end-to-end through the SimFDB backend against an INDEPENDENT Go reference model. |
|
continuation
Package continuation is RFC-199 Tier 2's continuation-under-fault replay driver.
|
Package continuation is RFC-199 Tier 2's continuation-under-fault replay driver. |
|
golden
Package golden is a characterization ("golden master") harness for the SQL engine over SimFDB.
|
Package golden is a characterization ("golden master") harness for the SQL engine over SimFDB. |
|
interleave
Package interleave is RFC-199 Tier 2's concurrent-open-transaction interleaving driver.
|
Package interleave is RFC-199 Tier 2's concurrent-open-transaction interleaving driver. |
|
metamorphic
Package metamorphic is the WRONG-catching SQL oracle for the DST harness (RFC-199 Tier 2).
|
Package metamorphic is the WRONG-catching SQL oracle for the DST harness (RFC-199 Tier 2). |
|
rangeconflict
Package rangeconflict is RFC-199 Tier 2's range-conflict interleaving driver.
|
Package rangeconflict is RFC-199 Tier 2's range-conflict interleaving driver. |
|
sqlhunt
This file adds a SECOND SQL workload to the DST bug hunter, focused on SECONDARY-INDEX maintenance under the commit-fault schedule (commit_unknown / not_committed / too_old retry).
|
This file adds a SECOND SQL workload to the DST bug hunter, focused on SECONDARY-INDEX maintenance under the commit-fault schedule (commit_unknown / not_committed / too_old retry). |
|
sqlpage
Package sqlpage is RFC-199 Tier 2's SQL-query pagination oracle.
|
Package sqlpage is RFC-199 Tier 2's SQL-query pagination oracle. |