329
part of the transaction but is required to allocate the log extensions if they are needed.
Without the internal redo log, it would be impossible to reserve and then publish a new
log object in a transaction that already had user-made allocator actions in the external
redo log.
All three logs have individual operation-context instances that are stored in runtime
state of the lanes. This state is initialized when the pool is opened, and that is also when
all the logs of the prior instance of the application are either processed or discarded.
There is no special persistent variable that indicates whether past transactions in the log
were successful or not. That information is directly derived from checksums stored in
the log.
When a transaction begins, and it is not a nested transaction, it acquires a lane,
which must not contain any valid uncomitted logs. The runtime state of the transaction
is stored in a thread-local variable, and that is where the lane variable is stored once
acquired.
Transactional allocator operations use the external redo log and its associated
operation context to call the appropriate reservation method which in turn creates an
allocator action to be published at the time of transaction commit. The allocator actions
are stored in a volatile array. If the transaction is aborted, all the actions are canceled,
and the associated state is discarded. The complete redo log for memory allocations is
created only at the time of transaction commit. If the library is interrupted while creating
the redo log, the next time the pool is opened, the checksum will not match, and the
transaction will be aborted by rolling back using the undo log.
Transactional snapshots use the undo log and its context. The first time a snapshot
is created, a new memory modification action is created in the external redo log. When
published, that action increments the generation number of the associated undo log,
invalidating its contents. This guarantees that if the external log is fully written and
processed, it automatically discards the undo log, committing the entire transaction. If
the external log is discarded, the undo log is processed, and the transaction is aborted.
To ensure that there are never two snapshots of the same memory location (this
would be an inefficient use of space), there is a runtime range tree that is queried every
time the application wants to create an undo log entry. If the new range overlaps with an
existing snapshot, adjustments to the input arguments are made to avoid duplication.
The same mechanism is also used to prevent snapshots of newly allocated data.
Whenever new memory in a transaction is allocated, the reserved memory range is
inserted into the ranges tree. Snapshotting new objects is redundant because they will be
discarded automatically in the case of an abort.
Chapter 16 pMDK Internals: IMportant algorIthMs anD Data struCtures
part of the transaction but is required to allocate the log extensions if they are needed.
Without the internal redo log, it would be impossible to reserve and then publish a new
log object in a transaction that already had user-made allocator actions in the external
redo log.
All three logs have individual operation-context instances that are stored in runtime
state of the lanes. This state is initialized when the pool is opened, and that is also when
all the logs of the prior instance of the application are either processed or discarded.
There is no special persistent variable that indicates whether past transactions in the log
were successful or not. That information is directly derived from checksums stored in
the log.
When a transaction begins, and it is not a nested transaction, it acquires a lane,
which must not contain any valid uncomitted logs. The runtime state of the transaction
is stored in a thread-local variable, and that is where the lane variable is stored once
acquired.
Transactional allocator operations use the external redo log and its associated
operation context to call the appropriate reservation method which in turn creates an
allocator action to be published at the time of transaction commit. The allocator actions
are stored in a volatile array. If the transaction is aborted, all the actions are canceled,
and the associated state is discarded. The complete redo log for memory allocations is
created only at the time of transaction commit. If the library is interrupted while creating
the redo log, the next time the pool is opened, the checksum will not match, and the
transaction will be aborted by rolling back using the undo log.
Transactional snapshots use the undo log and its context. The first time a snapshot
is created, a new memory modification action is created in the external redo log. When
published, that action increments the generation number of the associated undo log,
invalidating its contents. This guarantees that if the external log is fully written and
processed, it automatically discards the undo log, committing the entire transaction. If
the external log is discarded, the undo log is processed, and the transaction is aborted.
To ensure that there are never two snapshots of the same memory location (this
would be an inefficient use of space), there is a runtime range tree that is queried every
time the application wants to create an undo log entry. If the new range overlaps with an
existing snapshot, adjustments to the input arguments are made to avoid duplication.
The same mechanism is also used to prevent snapshots of newly allocated data.
Whenever new memory in a transaction is allocated, the reserved memory range is
inserted into the ranges tree. Snapshotting new objects is redundant because they will be
discarded automatically in the case of an abort.
Chapter 16 pMDK Internals: IMportant algorIthMs anD Data struCtures
