Please enable JavaScript.
Coggle requires JavaScript to display documents.
stellar-core Ledger (LedgerTxn (The LedgerTxnEntry handles that clients…
stellar-core Ledger
-
-
Ledger state entries
-
AccountEntry
-
In Stellar, everything is centered around accounts: transactions are performed by an account.
-
-
source code organization
-
LedgerDelta
-
LedgerDelta is a nestable structure, which allows fine grain control of which subset of changes to include or not in the final set of changes that will be commited to the ledger.
It keeps tracks of creation, modification and deletion of Ledger Entries as well as changes to the ledgerHeader.
LedgerEntry
The leaf elements are what we call "Ledger Entries", this is the bulk of the data contained in a ledger.
Closing a ledger
When closing a ledger, the engine needs to apply the consensus transaction set to the last closed ledger to produce a new closed ledger.
-
-
LedgerTxn
A LedgerTxn is an in-memory transaction-in-progress against the ledger in the database. Its ultimate purpose is to model a collection of LedgerEntry (XDR) objects to commit to the database.
At any given time, a LedgerTxn may have zero-or-one active sub-transactions, arranged in a parent/child relationship. The terms "parent" and "child" refer exclusively to this nesting-relationship of transactions. The presence of an active sub-LedgerTxn is indicated by a non-null mChild pointer.
Once a child is closed and the mChild pointer is reset to null, a new child may be opened. Attempting to open two children at once will throw an exception.
The entries to be committed in each transaction are stored in the mEntry map, keyed by LedgerKey. This much is straightforward!
Committing any LedgerTxn merges its entries into its parent. In the case where the parent is simply another in-memory LedgerTxn, this means writing the entries into the parent's mEntries map. In the case where the parent is the LedgerTxnRoot(see LedgerTxnRoot), this means opening a Real SQL Transaction against the database and writing the entries to it.
Each entry may also be designated as active in a given LedgerTxn; tracking active-ness is the purpose of the other (mActive) map in the diagram above. Active-ness is a logical state that simply means "it is ok, from a concurrency-control perspective, for a client to access this entry in this LedgerTxn."
Entries are made-active by calling load() or create(), each of which returns a LedgerTxnEntry(see LedgerTxnEntry) which is a handle that can be used to get at the underlying LedgerEntry. References to the underlying LedgerEntries should generally not be retained anywhere, because the LedgerTxnEntry(see LedgerTxnEntry) handles may be "deactivated", and access to a deactivated entry is a logic error in the client that this machinery is set up to try to trap. If you hold a reference to the underlying entry, you're bypassing the checking machinery that is here to catch such errors. Don't do it.
load()ing an entry will either check the current LedgerTxn for an entry, or if none is found it will ask its parent. This process recurses until it hits an entry or terminates at the root, where an LRU cache is consulted and then (finally!) the database itself.
-
The purpose of the double-indirection is to maintain one critical invariant in the system: clients can only access the entries in the innermost (child-most) LedgerTxn open at any given time. This is enforced by deactivating all the entries in a parent LedgerTxn when a child is opened. The entries in the parent still exist in its mEntry map (and will be committed to the parent's parent when the parent commits); but they are not active, meaning that attempts to access them through any LedgerTxnEntry handles will throw an exception.
-
-
-
-