public final class TransactionManager
extends java.lang.Object
Scopeable
interface.
Undoable
for externally driven rollback and see the
Commitable
for rollback notifications and custom rollback
support. See registerNext(com.goldencode.p2j.util.LazyUndoable...)
, registerCurrent(com.goldencode.p2j.util.LazyUndoable...)
and
registerCommit(com.goldencode.p2j.util.Commitable)
.
Commitable
and
registerCommit(com.goldencode.p2j.util.Commitable)
for commit notifications.
Finalizable
interface and registerFinalizable(com.goldencode.p2j.util.Finalizable, boolean)
.
Finalizable
interface
and registerFinalizable(com.goldencode.p2j.util.Finalizable, boolean)
.
Finalizable
interface
and registerFinalizable(com.goldencode.p2j.util.Finalizable, boolean)
.
registerFinalizable(com.goldencode.p2j.util.Finalizable, boolean)
and note the use of the
global
option.
interrupted status
is checked and if the thread
has been previously interrupted, a StopConditionException
will be thrown. See honorStopCondition()
.
The following is the mapping of Progress language features to the corresponding feature in this class:
Progress Name Type Method --------------- -------------- ----------------------------------- transaction functionisTransactionActive()
retry functionisRetry()
This class minimizes the amount and complexity of client code by using lists of objects to notify of specific events. The following is a summary of the event processing:
Interface Registration Method ------------ --------------------------- UndoableregisterNext(com.goldencode.p2j.util.LazyUndoable...)
registerCurrent(com.goldencode.p2j.util.LazyUndoable...)
CommitableregisterCommit(com.goldencode.p2j.util.Commitable)
FinalizableregisterFinalizable(com.goldencode.p2j.util.Finalizable, boolean)
ScopeableregisterScopeable(com.goldencode.p2j.util.Scopeable)
BatchListenerregisterBatchListener(com.goldencode.p2j.util.BatchListener)
Interface Notify Method(s) Event ------------ ------------------- ------------------------ UndoablepushScope(java.lang.String, int, boolean, boolean, boolean, boolean)
Undoable.deepCopy()
blockSetup()
Undoable.deepCopy()
rollback()
Undoable.assign(com.goldencode.p2j.util.Undoable)
popScope()
Undoable.assign(com.goldencode.p2j.util.Undoable)
CommitableblockSetup()
Commitable.commit(boolean)
popScope()
Commitable.commit(boolean)
rollback()
Commitable.rollback(boolean)
popScope()
Commitable.rollback(boolean)
FinalizablepopScope()
Finalizable.finished()
blockSetup()
Finalizable.iterate()
ScopeablepushScope(java.lang.String, int, boolean, boolean, boolean, boolean)
Scopeable.scopeStart()
popScope()
Scopeable.scopeFinished()
BatchListenerbatchStart()
BatchListener.batchNotify(boolean)
batchStop()
BatchListener.batchNotify(boolean)
Modifier and Type | Class and Description |
---|---|
private static class |
TransactionManager.ContextContainer
Simple container that stores and returns a context-local instance of
the global work area.
|
(package private) static class |
TransactionManager.UndoableHelper
Helper class to expose context-local state for undoable support.
|
private static class |
TransactionManager.WorkArea
Stores global data relating to the state of the current context's
transactions.
|
Modifier and Type | Field and Description |
---|---|
private static java.util.logging.Logger |
LOG
Logger (this is JVM-wide rather than being context-local).
|
private static java.util.Map<java.lang.String,TransactionListener> |
metaListeners
Map of primary database IDs to
TransactionListener objects |
private static java.util.concurrent.atomic.AtomicLong |
nextTransId
Next available transaction ID for metadata updates
|
static int |
NO_TRANSACTION
The block won't start a transaction or sub-transaction.
|
static int |
OP_FINISHED
finished processing is currently occurring. |
static int |
OP_ITERATE
iterate processing is currently occurring. |
static int |
OP_NONE
No
Finalizable processing is currently occurring. |
static int |
OP_RETRY
retry processing is currently occurring. |
static int |
PROP_ENDKEY
ENDKEY property.
|
static int |
PROP_ERROR
ERROR property.
|
static int |
PROP_NONE
Indicates that the block has no properties.
|
static int |
PROP_QUIT
QUIT property.
|
static int |
PROP_STOP
STOP property.
|
private static java.util.List<ScopeableFactory> |
scopeableFactories
JVM-wide list of objects which create Scopeable objects to be registered in each user's
session.
|
static int |
SUB_TRANSACTION
The block will start a sub-transaction if a transaction is active.
|
static int |
TRANSACTION
The block will start a transaction or sub-transaction.
|
private static TransactionManager.ContextContainer |
workArea
Context-local global data area for transaction state.
|
Constructor and Description |
---|
TransactionManager() |
Modifier and Type | Method and Description |
---|---|
static boolean |
_isHeadless()
Worker for reporting if this context should be treated as headless.
|
static boolean |
_isRetry()
Reports if the current iteration of this block or loop is a retry.
|
static void |
abnormalEnd(java.lang.Throwable thr)
Notifies the transaction manager that an unexpected exception or error
has occurred and that any transaction must be aborted.
|
static void |
abnormalEnd(java.lang.Throwable thr,
boolean needsNotify)
Notifies the transaction manager that an unexpected exception or error
has occurred and that any transaction must be aborted.
|
static void |
abortProcessing()
Method called when the processing needs to be terminated.
|
private static void |
backupWorker(TransactionManager.WorkArea wa,
BlockDefinition blk)
Creates or updates the backup set for all objects needing rollback
support in the current block, if a transaction is active.
|
static void |
batchStart()
Notify all registered
BatchListener objects that a batch is
starting. |
static void |
batchStop()
Notify all registered
BatchListener objects that a batch is
stopping. |
static boolean |
blockInitialized()
Check if the latest block has initialized.
|
static void |
blockSetup()
Provides a callback entry point for the top of the loop.
|
static void |
cleanupPending()
Allow finalizables to do their cleanup (
Finalizable.initFailure() ) now since the
scoped they were designed was aborted and there won't be other chance to call their
Finalizable.finished() . |
static int |
currentOperation()
Reports on the current
Finalizable operation being
executed. |
static int |
currentTransactionLevel()
Reports the transaction level of the current block.
|
static java.lang.String |
decodeLevel(int level)
Generate a string representation of the given transaction level.
|
static java.lang.String |
decodeProperties(int props)
Generate a string representation of the block properties of a block.
|
static void |
deferError(java.lang.String action,
java.lang.Throwable thr)
Defer handling of an exception thrown by a commit/rollback notification
callback on a registered
Commitable , so that iteration or pop
scope processing can be continued without interruption. |
static void |
deferError(java.lang.String action,
java.lang.Throwable thr,
boolean silent)
Defer handling of an exception thrown by a commit/rollback notification
callback on a registered
Commitable , so that iteration or pop
scope processing can be continued without interruption. |
(package private) static void |
deregister(TransactionManager.WorkArea wa,
java.util.IdentityHashMap<LazyUndoable,java.lang.Object> undoables)
Deregister the specified undoables from all tx blocks.
|
static void |
deregisterGlobalFinalizable(Finalizable target)
Remove the given finalizable from the global list of finalizables.
|
(package private) static OutputParameterAssigner |
deregisterOutputParameterAssigner()
Deregister the output parameter assigner for the current block, if any.
|
static void |
disableLoopProtection(BlockDefinition blk)
Disables infinite loop protection for the remainder of the current
iteration of the innermost block.
|
private static BlockDefinition |
findBlock(java.lang.String label)
Find the nearest enclosing block associated with the given label.
|
static int |
findNearestExternal()
Search the stack of scopes and return the level of the first external
block found.
|
static int |
findNearestTopLevel()
Search the stack of scopes and return the level of the first top level
block found.
|
private static int |
findNearestTopLevel(TransactionManager.WorkArea wa)
Search the stack of scopes and return the level of the first top level block found.
|
private static int |
findStackLevel(TransactionManager.WorkArea wa,
java.lang.String label)
Find the stack level of the nearest enclosing block associated with the
given label.
|
static void |
forceRetry()
Force a retry of the current block (if there is no pending rollback)
or retry the same block as the pending rollback, in either case
ensure that the flow of control will not naturally continue.
|
static void |
forceRetry(java.lang.String label)
Force a retry of the current block or the scope named by the given
label, ensuring that the flow of control will not naturally continue.
|
static BlockType |
getBlockType()
Returns the current block type.
|
static int |
getFullTransactionBlock()
Returns the index of the full transaction block, or -1 if none exists.
|
static int |
getInteractions()
Gets the number of interactive language statements (statements which
took user input except for PAUSE) that have executed in the current
block since the most recent start scope, iterate or retry.
|
static BlockType |
getNearestTopLevelType()
Search the stack of scopes and return the type of first top level block found.
|
private static BlockType |
getNearestTopLevelType(TransactionManager.WorkArea wa)
Search the stack of scopes and return the type of first top level block found.
|
static int |
getNestingLevel()
Returns the current nesting level.
|
static java.util.Set<QueryOffEndListener> |
getOffEndListeners(boolean clear)
Get the topmost set of off-end
listeners . |
(package private) static int |
getTransDepth()
Get the current transaction depth.
|
static TransactionManager.UndoableHelper |
getUndoableHelper()
Get a helper to access certain context-local state required for undoable support.
|
static void |
hadPause()
Notifies this class that an interactive pause has occurred.
|
static boolean |
hadRollback()
Reports whether the current block was just rolled back or a containing
block has a pending rollback.
|
static boolean |
hasEndkeyProp()
Reports if the current block has the ENDKEY property.
|
static boolean |
hasErrorProp()
Reports if the current block has the ERROR property.
|
static boolean |
hasParentIteratedBlock()
This checks if any of the enclosing loops has iterated at least once.
|
private static boolean |
hasProperty(int prop)
Reports if the current block has the given property.
|
static boolean |
hasQuitProp()
Reports if the current block has the QUIT property.
|
static boolean |
hasStopProp()
Reports if the current block has the STOP property.
|
static void |
honorError(ErrorConditionException err)
Check if the current error must unwind all the way to the caller of
the top-level block in this method (if the ignore flag is set).
|
static boolean |
honorNext(java.lang.String label)
Determines if a NEXT operation with the given target block should
be honored or if the NEXT should be converted to a LEAVE.
|
static void |
honorRetry(RetryUnwindException rue)
Check if there is a pending retry of the current block and if so then
enable retry.
|
static void |
honorStop(StopConditionException exc)
Dispatch the given exception to all registered stop condition handlers
to see if any requires that the STOP condition be vetoed at the
current scope.
|
static void |
honorStopCondition()
Tests the interrupted status of the current thread using
Thread.interrupted , if true then a
StopConditionException will be thrown. |
static void |
incrementInteractions()
Increases the number (by 1) of interactive language statements
(statements which took user input except for PAUSE) that have executed
in the current block since the most recent start scope, iterate or
retry.
|
static void |
initializeMeta(Database primaryDB,
Database metaDB)
Initialize a metaschema database by initializing a transaction listener and storing it for
later use.
|
static boolean |
isBreakPending()
Accesses the state of whether there is a pending break that must be
honored.
|
static boolean |
isEnclosingRollup()
Get the rollup value for the enclosing block.
|
static boolean |
isExternalBlock()
Reports if the current block is a external block (this corresponds
with a method-level block that was derived from a Progress external
procedure).
|
static boolean |
isFullTransaction()
Reports if the current scope defines the outermost transaction block
(which is the scope at which final commit processing must occur).
|
static boolean |
isGlobalBlock()
Reports if the current block is a global scoped block.
|
private static boolean |
isGlobalBlock(TransactionManager.WorkArea wa)
Reports if the current block is a global scoped block.
|
static boolean |
isHeadless()
Report if this context should be treated as headless.
|
static boolean |
isNestedMode()
Reports on the enable/disable state of nested error mode.
|
static boolean |
isNoTransactionLevel(int lvl)
Reports if the given transaction level represents the case where the
block has no effect on transaction processing.
|
static boolean |
isOffEndListener(QueryOffEndListener listener)
Check if the given listener is registered for query off-end events and
can override the default END-KEY action (which is UNDO, LEAVE), when
the current block is FOR or FOR EACH.
|
static boolean |
isProcessingQuit()
During global finish processing, this reports if the exit was caused
by a
QuitConditionException . |
static logical |
isRetry()
Reports if the current iteration of this block or loop is a retry.
|
static boolean |
isRollup()
Get the rollup value for the current block.
|
static boolean |
isSubTransactionLevel(int lvl)
Reports if the given transaction level represents the case where the
block has creates a sub-transaction when a transaction is active.
|
static boolean |
isSuppressError()
Check if this block's caller requires errors to be suppressed.
|
static boolean |
isTopLevelBlock()
Reports if the current block is a top-level block (this corresponds
with a method-level block).
|
private static boolean |
isTopLevelBlock(TransactionManager.WorkArea wa)
Reports if the current block is a top-level block (this corresponds
with a method-level block).
|
static boolean |
isTransaction()
Reports if there is a current transaction which is active.
|
static logical |
isTransactionActive()
Reports if there is a current transaction which is active.
|
static boolean |
isTransactionAt(int blockDepth)
Reports if there is a current active transaction at the specified block depth.
|
static boolean |
isTransactionLevel(int lvl)
Reports if the given transaction level represents the case where the
block has creates a new transaction if a transaction is not active or
creates a sub-transaction when a transaction is active.
|
private static void |
iterateWorker(TransactionManager.WorkArea wa)
Allows a loop iteration event to occur in the transaction manager,
which triggers commit processing before the next iteration of the
loop begins.
|
private static void |
log(java.util.logging.Level lvl,
java.lang.String location,
java.lang.String txt)
Write a formatted log entry with the error text and some state based
on the current block.
|
private static void |
log(java.util.logging.Level lvl,
java.lang.String location,
java.lang.String txt,
java.lang.Throwable trw)
Write a formatted log entry with the error text and some state based
on the current block.
|
static void |
makeBackup()
Creates or updates the backup set for all objects needing rollback
support in the current block, if a transaction is active.
|
static void |
markEndkeyRetry()
Records the fact that the pending RETRY is being caused by an ENDKEY
condition.
|
(package private) static BlockDefinition |
nearestExecutingBlock()
Get the BlockDefinition instance of the nearest block of one of the
following types:
external procedure
internal procedure
user-defined function
trigger
editing
|
private static BlockDefinition |
nearestTopLevel(TransactionManager.WorkArea wa)
Search the stack of scopes and return the first top level block found.
|
static boolean |
needsRetry()
Determines if the currently executing block should be retried.
|
static void |
notifyCondition(BlockManager.Condition condition)
Notify
ConditionListener instances about condition. |
static void |
notifyCondition(ConditionException condition)
Notify
ConditionListener instances about exception condition. |
static void |
popScope()
Remove the current block from the stack of scopes, process any pending
rollbacks (if the current block is the proper target), notify any
objects needing commits (if the block finished successfully) and handle
finish processing for the block.
|
private static void |
processBatchNotifications(boolean start)
Notify all registered
BatchListener objects that a batch is
either starting or stopping. |
private static void |
processCommit(TransactionManager.WorkArea wa,
BlockDefinition blk)
Worker that notifies all objects in the commit list that they must
commit (persist any state).
|
private static void |
processFinalizables(TransactionManager.WorkArea wa,
BlockDefinition blk,
boolean iterate)
Worker that notifies all objects in the finalize list that the block
is being exited or iterated.
|
static void |
processOffEndListeners(boolean init)
Iterate all registered off-end listeners and call the
initialize or
finish method, depending on the
flag. |
private static void |
processResettables(TransactionManager.WorkArea wa,
boolean clearOnly)
Resets all registered
Resettable objects or makes them
clear their lists of changes that should be reset. |
private static void |
processRetry(TransactionManager.WorkArea wa,
BlockDefinition blk)
Worker that notifies all objects in the finalize list that the block
is being retried.
|
private static void |
processRollback(TransactionManager.WorkArea wa,
BlockDefinition blk)
Worker that actually implements rollback by copying the backed up
values into the original reference.
|
private static void |
processRollbackPending(TransactionManager.WorkArea wa,
BlockDefinition blk)
Notify a block that a rollback is pending to be processed by one of
its parent blocks.
|
private static void |
processScopeNotifications(TransactionManager.WorkArea wa,
BlockDefinition blk,
boolean start)
Worker that notifies all objects in the scopeable list that a block
scope is being started or ended.
|
(package private) static void |
processValidate()
Worker that notifies all objects in the commit list that they must
commit (persist any state).
|
static void |
pushScope(java.lang.String label,
int level,
boolean external,
boolean topLevel,
boolean loop,
boolean next)
Initializes a new scope, the associated block definition data
structures.
|
static void |
pushScope(java.lang.String label,
int level,
boolean external,
boolean topLevel,
boolean loop,
boolean next,
Block block)
Initializes a new scope, the associated block definition data
structures.
|
static void |
pushScope(java.lang.String label,
int level,
boolean external,
boolean topLevel,
boolean loop,
boolean next,
BlockType blockType,
Block block)
Initializes a new scope, the associated block definition data
structures.
|
static void |
pushScope(java.lang.String label,
int level,
int props,
boolean external,
boolean topLevel,
boolean loop,
boolean next,
BlockType blockType,
Block block)
Initializes a new scope, the associated block definition data
structures.
|
(package private) static void |
registerAt(int transLevel,
boolean persistent,
LazyUndoable... undoTargets)
Adds the object into a scoped dictionary of objects requiring UNDO support.
|
(package private) static void |
registerAt(ScopeLevel scope,
LazyUndoable... target)
Adds the given object into the list of objects which require undo
notifications for the next block that is opened.
|
static void |
registerBatchListener(BatchListener target)
Adds the given object into the batch notifier list.
|
static void |
registerCommit(Commitable target)
Adds the given object into the list of objects for the current block
which require commit notification.
|
static void |
registerCommitAt(int blockDepth,
Commitable target)
Adds the given object into the list of objects which require commit notification for the
block at the specified depth This form of registration is useful for objects whose natural
lifetime are scoped to a different block than the block in which they must be committed.
|
static void |
registerCurrent(LazyUndoable... undoTargets)
Register the specified targets as undoables.
|
static void |
registerFinalizable(Finalizable target,
boolean global)
Adds the given object into the list of objects for the specified block
which require iterate/retry/finish notification.
|
static void |
registerFinalizableAt(int blockDepth,
Finalizable target)
Adds the given object into the list of objects for the specified block
which require iterate/retry/finish notification.
|
static void |
registerNearestLoopFinalizable(Finalizable target)
Adds the given object into the list of objects which require
iterate/retry/finish notification for the nearest enclosing, looping
block.
|
(package private) static void |
registerNext(LazyUndoable... target)
Adds the given object into the list of objects which require undo
notifications for the next block that is opened.
|
static void |
registerNextExternal(Finalizable target)
Adds the given object into the list of objects which require
iterate/retry/finish notifications for the next block that is opened
which is a top-level block that corresponds to a Progress external
procedure.
|
static void |
registerOffEndQuery(P2JQuery query)
Register the passed query for query off-end events.
|
static void |
registerOutputParameterAssigner(OutputParameterAssigner opa)
Register the single output parameter assigner for the current block.
|
static void |
registerResettable(Resettable resettable)
Register the given
Resettable object in order to reset it
at specific points of block processing. |
static void |
registerScopeable(Scopeable target)
Adds the given object into the list of global objects needing scope
related notifications upon the entry and exit from every block.
|
static void |
registerScopeableFactory(ScopeableFactory factory)
Register an object which will be asked to provide a
Scopeable each time a new work area context is created. |
static void |
registerStopVetoHandler(StopConditionVetoHandler h)
Register the given object as a handler which can veto the processing of
STOP condition processing at the current scope.
|
static void |
registerTopLevelFinalizable(Finalizable target,
boolean external)
Adds the given object into the list of objects which require
iterate/retry/finish notifications for the nearest enclosing
top-level block.
|
static void |
registerTransactionCommit(Commitable target,
boolean remove)
Adds the given object as the transaction level reference which will get
a single, "master" commit call after all other commits have been
processed at the full transaction level.
|
static void |
registerTransactionFinish(Finalizable target,
boolean remove)
Adds the given object as the transaction level reference which will get
a "master" finish call after all other finish notifications have been
processed at the full transaction level.
|
private static void |
registerUndo(LazyUndoable undoTarget,
int transLevel,
boolean persistent)
Adds the object into a scoped dictionary of objects requiring UNDO support.
|
static boolean |
removeFinalizable(Finalizable target)
Removes the given object from the list of objects which require
iterate/retry/finish notifications.
|
static void |
resetInteractions()
Resets the number of interactive language statements (statements which
took user input except for PAUSE) that have executed in the current
block to 0.
|
static void |
rollback()
Trigger a rollback for all registered
Undoable objects
inside the current active transaction at the scope defined by the
current block. |
static void |
rollback(java.lang.String label)
Trigger a rollback for all registered
Undoable objects
inside the current active transaction at the scope defined
explicitly by the given label or implicitly if the label is
null . |
static void |
rollback(java.lang.String label,
java.lang.Throwable cause)
Trigger a rollback for all registered
Undoable objects
inside the current active transaction at the scope defined
explicitly by the given label or implicitly if the label is
null . |
private static boolean |
rollbackCurrentScope(TransactionManager.WorkArea wa,
int level)
Determine if the current scope represents a transaction or
sub-transaction and if so, whether the given level explicitly refers
to this scope OR if the given level is -1, then this implicitly refers
to this scope.
|
static void |
rollbackTopLevel()
Trigger a rollback for all registered
Undoable objects
inside the current active transaction at the nearest top level scope. |
private static void |
rollbackWorker(TransactionManager.WorkArea wa,
int level,
java.lang.Throwable cause)
Trigger a rollback for all registered
Undoable objects
inside the current active transaction at the scope defined by the
specified stack level. |
static void |
saveNestedError(ConditionException err)
Store the given exception for re-throwing during
honorError(com.goldencode.p2j.util.ErrorConditionException) if
nested error mode is enabled. |
static void |
setHeadless(boolean headless)
Control the headless state of this context.
|
static void |
setNestedMode(boolean mode)
Enable/disable nested error mode.
|
static void |
setProcessingQuit(boolean quit)
During global finish processing, this sets the flag for an exit that
was caused by a
QuitConditionException . |
static void |
setRollup(boolean rollup)
Set the new rollup value for the current block.
|
static void |
startOffEndRegistration()
This method is called before the initialization of a FOR or FOR EACH
block.
|
static void |
stopOffEndRegistration()
This method is called after the initialization of a FOR or FOR EACH
block is finished.
|
(package private) static void |
trackUndoables()
Enable tracking of all the undaobles defined in the next instantiating external program.
|
static void |
triggerErrorInCaller()
Force an error to be generated such that it will be caught in the
caller of this method.
|
static void |
triggerErrorInCaller(java.lang.String text)
Force an error to be generated such that it will be caught in the
caller of this method.
|
static void |
triggerRetry()
Force a retry of the current block (if there is no pending rollback)
or the block targeted for a pending rollback.
|
static void |
triggerRetry(java.lang.String label)
Force a retry of the current block or the scope named by the given
label.
|
(package private) static void |
untrackUndoables(java.lang.Object referent)
Untrack (by removing from all the tx blocks) all the undoables defined and registered for
the specified external program.
|
private static void |
updateBackupSet(java.util.List<UndoablePair> backup)
Walk through the current backup set and refresh the stored value for
each one.
|
public static final int NO_TRANSACTION
public static final int SUB_TRANSACTION
public static final int TRANSACTION
public static final int OP_NONE
Finalizable
processing is currently occurring.public static final int OP_ITERATE
iterate
processing is currently occurring.public static final int OP_RETRY
retry
processing is currently occurring.public static final int OP_FINISHED
finished
processing is currently occurring.public static final int PROP_NONE
public static final int PROP_ERROR
public static final int PROP_ENDKEY
public static final int PROP_STOP
public static final int PROP_QUIT
private static final java.util.List<ScopeableFactory> scopeableFactories
private static final java.util.logging.Logger LOG
private static TransactionManager.ContextContainer workArea
private static java.util.concurrent.atomic.AtomicLong nextTransId
private static java.util.Map<java.lang.String,TransactionListener> metaListeners
TransactionListener
objectspublic static void initializeMeta(Database primaryDB, Database metaDB)
Called only at server startup.
primaryDB
- Primary database for which metaschema information is being managed.metaDB
- Metaschema database for the given primary database.public static java.lang.String decodeLevel(int level)
level
- The transaction level to be decoded. Must be one of
NO_TRANSACTION
, SUB_TRANSACTION
or
TRANSACTION
.public static java.lang.String decodeProperties(int props)
props
- The block properties to decode.public static int currentOperation()
Finalizable
operation being
executed.OP_NONE
OP_ITERATE
OP_RETRY
OP_FINISHED
public static void registerScopeableFactory(ScopeableFactory factory)
Scopeable
each time a new work area context is created.
The resulting object is added to the work area's list of objects to
be notified as runtime scopes are started and finished.
These factories typically are registered during server bootstrap and are not removed during the lifetime of the server process. A factory should only be registered once per server process.
factory
- Factory to be registered.public static void registerCommit(Commitable target)
registerCurrent(com.goldencode.p2j.util.LazyUndoable...)
processing to control the commit points.
This notification will ONLY occur when there is an active transaction.
Notifications occur in LIFO order; thus, commitables which depend upon others being committed first must be registered before the objects upon which they are dependent.
These registrations naturally are removed when the associated scope is removed.
target
- The object reference to be committed on success. This
cannot be null
.public static void registerCommitAt(int blockDepth, Commitable target)
registerCurrent(com.goldencode.p2j.util.LazyUndoable...)
processing to
control the commit points.
This notification will ONLY occur when there is an active transaction.
Notifications occur in LIFO order; thus, commitables which depend upon others being committed first must be registered before the objects upon which they are dependent.
These registrations naturally are removed when the associated scope is removed.
blockDepth
- Zero-based depth of the target block, starting from the outermost block.target
- The object reference to be committed on success. This cannot be
null
.public static void registerTransactionCommit(Commitable target, boolean remove)
This notification will ONLY occur when there is an active transaction and it only will be called at the exit of the block that corresponds to the full transaction.
If the full transaction block is also an iterating block, this notification will occur for each iteration of the block.
target
- The object reference to be committed on success. This
can be null
if one intends to clear the current
reference.remove
- If true
automatically remove this registration
after the full transaction scope has ended (whether or not
the commit occurs). If false
, this reference
will remain globally until replaced.public static void registerStopVetoHandler(StopConditionVetoHandler h)
h
- The stop condition veto handler.public static void registerScopeable(Scopeable target)
WARNING: this method should be called before the first call to
pushScope(java.lang.String, int, boolean, boolean, boolean, boolean)
. This is necessary since this list is global and
there is no history of which notifications have been provided. Thus,
if pushScope
has been called before this method, then
the notifications of scope start for any scopes that have already been
added will never be seen by the target AND more importantly the
registered target will receive end scope notifications for those
scopes even though there was no matching start scope notification!
If this method can't be called from the static initializer of this
class, the target must implement a facility that is safe with this
limitation (scopeFinished
being called for scopes that
never had a matching scopeStart
).
These registrations are global and will not be removed.
target
- The object reference to be notified on scope start and end.
This cannot be null
.public static void registerResettable(Resettable resettable)
Resettable
object in order to reset it
at specific points of block processing.resettable
- Resettable
to be registered.public static void registerFinalizable(Finalizable target, boolean global)
This notification will occur whether or not a transaction is active.
These registrations naturally are removed when the associated scope
is removed (after the Finalizable.finished()
method is called)
in the case of a non-global scope OR at the moment that the last
scope has been removed in the case of the global scope.
The given object will only be added if it is not already in the list.
Finalizables for a scope are processed in the same order as they were registered.
target
- The object reference to be notified on any exit from the
block specified. This cannot be null
.global
- Specifies the target scope. false
specifies the
current scope, and true
specifies the global
scope.public static void deregisterGlobalFinalizable(Finalizable target)
target
- Finalizable to be removed from the global list.public static void registerFinalizableAt(int blockDepth, Finalizable target)
This notification will occur whether or not a transaction is active.
These registrations naturally are removed when the associated scope
is removed (after the Finalizable.finished()
method is called)
in the case of a non-global scope OR at the moment that the last
scope has been removed in the case of the global scope.
The given object will only be added if it is not already in the list.
Finalizables for a scope are processed in the same order as they were registered.
blockDepth
- zero-based depth of target block, starting from the outermost
block. 0
indicates the global block.target
- The object reference to be notified on any exit from the
block specified. This cannot be null
.public static void registerNextExternal(Finalizable target)
This form of registration is useful for objects whose natural lifetime is scoped to the top-level block and which need a hook for cleaning up resources or handling other block termination processing. In particular, it is necessary for objects that are constructed during a class' constructor/initializer (before the external procedure block has opened). Such objects cannot simply register since their construction is not actually enclosed by the block.
This notification will occur whether or not a transaction is active.
These registrations naturally are removed when the associated scope
is removed (after the Finalizable.finished()
method is called).
The given object will only be added if it is not already in the list.
target
- The object reference to be notified on any exit from the
top-level external block. This cannot be null
.java.lang.IllegalStateException
- if the top-level block cannot be identified.public static void cleanupPending()
Finalizable.initFailure()
) now since the
scoped they were designed was aborted and there won't be other chance to call their
Finalizable.finished()
.
After iteration the list is deleted.
Also, cleanup all other pending state being collected while the external program was instantiating.
public static void registerTopLevelFinalizable(Finalizable target, boolean external)
This form of registration is useful for objects whose natural lifetime is scoped to the top-level block and which need a hook for cleaning up resources or handling other block termination processing.
This notification will occur whether or not a transaction is active.
These registrations naturally are removed when the associated scope
is removed (after the Finalizable.finished()
method is called).
The given object will only be added if it is not already in the list.
Finalizables for a scope are processed in the same order as they were registered.
target
- The object reference to be notified on any exit from the
top-level block. This cannot be null
.external
- If true
, register with the nearest enclosing
external block (external procedure), otherwise register with
the nearest enclosing top-level block (which may be but is
not guaranteed to be the external block).java.lang.IllegalStateException
- if the top-level block cannot be identified.public static void registerNearestLoopFinalizable(Finalizable target)
This form of registration is useful for objects whose natural lifetime is scoped to the nearest enclosing, looping block and which need a hook for cleaning up resources or handling other block termination processing.
This notification will occur whether or not a transaction is active.
These registrations naturally are removed when the associated scope
is removed (after the Finalizable.finished()
method is called).
The given object will only be added if it is not already in the list.
target
- The object reference to be notified on any exit from or
iteration of the target block. This cannot be
null
.java.lang.IllegalStateException
- if no enclosing, looping block can be identified.public static boolean removeFinalizable(Finalizable target)
After this call, no notifications will be received.
target
- The object reference to be removed.true
if the target instance was found and
removed.public static void registerTransactionFinish(Finalizable target, boolean remove)
This notification will ONLY occur when there is an active transaction and it only will be called at the exit of the block that corresponds to the full transaction.
Multiple targets may be registered by invoking this method multiple times. However, the same object registered multiple times will receive the notification only once per full transaction block exit. If multple targets are registered, they will be called in the order in which they were registered.
target
- The object reference to be finished at full transaction block
end.remove
- If true
automatically remove this registration
after the full transaction scope has ended. If
false
, this reference will remain globally until
replaced.public static void registerBatchListener(BatchListener target)
batchStart()
and batchStop()
. Every object
in the list will be notified in the order in which they were added to
the list.target
- The object reference to be notified of any batch start and
stop.public static boolean hadRollback()
true
if there was or will be a rollback.public static void rollback()
Undoable
objects
inside the current active transaction at the scope defined by the
current block. All objects that are rolled back will have their
values assigned based on the values backed up at the start of the
specified scope. A flow control change MUST always immediately follow
this method otherwise undefined results can occur.
This caller-driven control flow is required to properly duplicate the semantics of Progress 4GL condition processing which always generates an implicit or explicit flow control action after every UNDO. Since the flow of control change can reference a different scope than that of the rollback, this can't be handled by re-throwing the exception but must instead be separately driven by a deferred rollback and a caller driven flow control statement such as break, continue or return. The key limitation that makes this possible is the fact that the UNDO (rollback) scope MUST ALWAYS BE equivalent to or more specific than the scope to which flow of control will be changed. This means that one can rollback at a more deeply nested scope but change flow of control to resume processing at a different (less deeply nested) scope. The reverse is not possible.
public static void rollback(java.lang.String label)
Undoable
objects
inside the current active transaction at the scope defined
explicitly by the given label or implicitly if the label is
null
. All objects that are rolled back will have their
values assigned based on the values backed up at the start of the
specified scope. If the current scope is not the target scope, the
given exception will be stored, the rollback will be deferred and
the rollback will be processed as the scopes naturally unwind. This
unwinding must be generated by a change in flow of control by the
calling code. This flow control change MUST always immediately follow
this method otherwise undefined results can occur.
This caller-driven control flow is required to properly duplicate the semantics of Progress 4GL condition processing which always generates an implicit or explicit flow control action after every UNDO. Since the flow of control change can reference a different scope than that of the rollback, this can't be handled by re-throwing the exception but must instead be separately driven by a deferred rollback and a caller driven flow control statement such as break, continue or return. The key limitation that makes this possible is the fact that the UNDO (rollback) scope MUST ALWAYS BE equivalent to or more specific than the scope to which flow of control will be changed. This means that one can rollback at a more deeply nested scope but change flow of control to resume processing at a different (less deeply nested) scope. The reverse is not possible.
label
- Specifies the name of the scope at which to rollback or
null
if the scope should be implicitly
determined.public static void rollback(java.lang.String label, java.lang.Throwable cause)
Undoable
objects
inside the current active transaction at the scope defined
explicitly by the given label or implicitly if the label is
null
. All objects that are rolled back will have their
values assigned based on the values backed up at the start of the
specified scope. If the current scope is not the target scope, the
given exception will be stored, the rollback will be deferred and
the rollback will be processed as the scopes naturally unwind. This
unwinding must be generated by a change in flow of control by the
calling code. This flow control change MUST always immediately follow
this method otherwise undefined results can occur.
This caller-driven control flow is required to properly duplicate the semantics of Progress 4GL condition processing which always generates an implicit or explicit flow control action after every UNDO. Since the flow of control change can reference a different scope than that of the rollback, this can't be handled by re-throwing the exception but must instead be separately driven by a deferred rollback and a caller driven flow control statement such as break, continue or return. The key limitation that makes this possible is the fact that the UNDO (rollback) scope MUST ALWAYS BE equivalent to or more specific than the scope to which flow of control will be changed. This means that one can rollback at a more deeply nested scope but change flow of control to resume processing at a different (less deeply nested) scope. The reverse is not possible.
label
- Specifies the name of the scope at which to rollback or
null
if the scope should be implicitly
determined.cause
- The exceptional cause, if any, of the rollback.public static void rollbackTopLevel()
Undoable
objects
inside the current active transaction at the nearest top level scope.
All objects that are rolled back will have their values assigned based
on the values backed up at the start of the specified scope. If the
current scope is not the target scope, the given exception will be
stored, the rollback will be deferred and the rollback will be processed
as the scopes naturally unwind. This unwinding must be generated by a
change in flow of control by the calling code. This flow control change
MUST always immediately follow this method otherwise undefined results
can occur.
This caller-driven control flow is required to properly duplicate the semantics of Progress 4GL condition processing which always generates an implicit or explicit flow control action after every UNDO. Since the flow of control change can reference a different scope than that of the rollback, this can't be handled by re-throwing the exception but must instead be separately driven by a deferred rollback and a caller driven flow control statement such as break, continue or return. The key limitation that makes this possible is the fact that the UNDO (rollback) scope MUST ALWAYS BE equivalent to or more specific than the scope to which flow of control will be changed. This means that one can rollback at a more deeply nested scope but change flow of control to resume processing at a different (less deeply nested) scope. The reverse is not possible.
public static void pushScope(java.lang.String label, int level, boolean external, boolean topLevel, boolean loop, boolean next)
blockSetup()
and
makeBackup()
).
In the case of a block which is defined as NO_TRANSACTION
,
the core data structures are initialized but no rollback support will
be provided.
This method will honor any pending thread interruption by throwing
a StopConditionException
using honorStopCondition()
.
This will create a block of BlockType.UNKNOWN
and block
properties PROP_NONE
.
label
- The text label associated with the block. This usually
should correspond with the label used in the source file
to identify the block for purposes of the break and continue
statements.level
- One of NO_TRANSACTION
, SUB_TRANSACTION
or
TRANSACTION
. This code defines the level of
rollback and transaction support which should be provided.external
- true
if this block is associated with the
external procedure (in Progress terms). This controls the
cleanup of certain resources such as temp-tables, frames
and streams.topLevel
- true
if this block is a method.loop
- Defines if this block is a loop or not.next
- true
if this infinite loop protection should
convert a retry into a next (continue), otherwise the retry
will be converted into a leave (break).StopConditionException
- If the current thread's was previously interrupted.public static void pushScope(java.lang.String label, int level, boolean external, boolean topLevel, boolean loop, boolean next, Block block)
blockSetup()
and
makeBackup()
).
In the case of a block which is defined as NO_TRANSACTION
,
the core data structures are initialized but no rollback support will
be provided.
This method will honor any pending thread interruption by throwing
a StopConditionException
using honorStopCondition()
.
This will create a block of BlockType.UNKNOWN
and block
properties PROP_NONE
.
label
- The text label associated with the block. This usually
should correspond with the label used in the source file
to identify the block for purposes of the break and continue
statements.level
- One of NO_TRANSACTION
, SUB_TRANSACTION
or
TRANSACTION
. This code defines the level of
rollback and transaction support which should be provided.external
- true
if this block is associated with the
external procedure (in Progress terms). This controls the
cleanup of certain resources such as temp-tables, frames
and streams.topLevel
- true
if this block is a method.loop
- Defines if this block is a loop or not.next
- true
if this infinite loop protection should
convert a retry into a next (continue), otherwise the retry
will be converted into a leave (break).block
- The Block instance to be executed. May be null, if no Block
instance is needed (i.e. this is an internal P2J call).StopConditionException
- If the current thread's was previously interrupted.public static void pushScope(java.lang.String label, int level, boolean external, boolean topLevel, boolean loop, boolean next, BlockType blockType, Block block)
blockSetup()
and
makeBackup()
).
In the case of a block which is defined as NO_TRANSACTION
,
the core data structures are initialized but no rollback support will
be provided.
This method will honor any pending thread interruption by throwing
a StopConditionException
using honorStopCondition()
.
This will create a block with block properties PROP_NONE
.
label
- The text label associated with the block. This usually
should correspond with the label used in the source file
to identify the block for purposes of the break and continue
statements.level
- One of NO_TRANSACTION
, SUB_TRANSACTION
or
TRANSACTION
. This code defines the level of
rollback and transaction support which should be provided.external
- true
if this block is associated with the
external procedure (in Progress terms). This controls the
cleanup of certain resources such as temp-tables, frames
and streams.topLevel
- true
if this block is a method.loop
- Defines if this block is a loop or not.next
- true
if this infinite loop protection should
convert a retry into a next (continue), otherwise the retry
will be converted into a leave (break).blockType
- Specifies this block's type.block
- The Block instance to be executed.StopConditionException
- If the current thread's was previously interrupted.public static void pushScope(java.lang.String label, int level, int props, boolean external, boolean topLevel, boolean loop, boolean next, BlockType blockType, Block block)
blockSetup()
and
makeBackup()
).
In the case of a block which is defined as NO_TRANSACTION
,
the core data structures are initialized but no rollback support will
be provided.
This method will honor any pending thread interruption by throwing
a StopConditionException
using honorStopCondition()
label
- The text label associated with the block. This usually
should correspond with the label used in the source file
to identify the block for purposes of the break and continue
statements.level
- One of NO_TRANSACTION
, SUB_TRANSACTION
or
TRANSACTION
. This code defines the level of
rollback and transaction support which should be provided.props
- A bitfield storing block properties which will be a
combination of PROP_NONE
, PROP_ERROR
,
PROP_ENDKEY
, PROP_STOP
or
PROP_QUIT
.external
- true
if this block is associated with the
external procedure (in Progress terms). This controls the
cleanup of certain resources such as temp-tables, frames
and streams.topLevel
- true
if this block is a method.loop
- Defines if this block is a loop or not.next
- true
if this infinite loop protection should
convert a retry into a next (continue), otherwise the retry
will be converted into a leave (break).blockType
- Specifies this block's type.block
- The Block instance to be executed.StopConditionException
- If the current thread's was previously interrupted.public static void popScope() throws StopConditionException
finally
block such that this is guaranteed to be called
no matter how the flow of control exits the associated block (exception,
break, return or the flow of control naturally passing through the
end of the block).
Rollback and commit processing only occur when there is an active transaction. Otherwise this processing is bypassed. Finish processing is always called.
This method implements global finish processing (as the last action before returning) when the last scope is popped from the stack of scopes. For this reason, the current implementation assumes that the session is over at the moment that the top-most user-defined scope exits.
This method will honor any pending thread interruption by throwing
a StopConditionException
using honorStopCondition()
StopConditionException
- If the current thread's was previously interrupted.public static void notifyCondition(BlockManager.Condition condition)
ConditionListener
instances about condition.condition
- The condition the listeners will be notified.public static void notifyCondition(ConditionException condition)
ConditionListener
instances about exception condition.condition
- The instance of ConditionException
.public static boolean blockInitialized()
public static TransactionManager.UndoableHelper getUndoableHelper()
public static void blockSetup() throws StopConditionException
makeBackup()
. On the second and subsequent executions of this
method for a given block, this method handles iterate
notifications.
It is important to note that continue
can be called from
nested blocks at arbitrary depths. This method can handle such nesting
at any level.
This method will honor any pending thread interruption by throwing
a StopConditionException
using honorStopCondition()
StopConditionException
- If the current thread's was previously interrupted.public static void makeBackup()
pushScope(java.lang.String, int, boolean, boolean, boolean, boolean)
and blockSetup()
due to the
semantics of Progress in which the backup set is created or refreshed
after the loop control variables have been modified.public static logical isTransactionActive()
true
if a transaction is active.public static boolean _isRetry()
true
if this is a retry of this block or loop
(as opposed to the first time through this iteration).public static logical isRetry()
true
if this is a retry of this block or loop
(as opposed to the first time through this iteration).public static void markEndkeyRetry()
public static void disableLoopProtection(BlockDefinition blk)
isRetry()
method.blk
- The block on which to operator or null
to
operate on the current (innermost) block.public static boolean hasParentIteratedBlock()
true
if any of the enclosing loops has iterated
at least once.public static boolean honorNext(java.lang.String label)
A NEXT is converted into a LEAVE when all of the following conditions are true:
Since NEXT is only possible on a looping block, if the target block
is not a looping block then this method will return false
.
label
- The label of the target block for the NEXT action.true
for NEXT, false
for LEAVE.public static boolean needsRetry()
true
if the block (whether or not it is a loop)
should be retried.public static boolean isBreakPending()
true
if a break is pending for this block.public static void triggerErrorInCaller(java.lang.String text) throws ErrorConditionException
honorError(com.goldencode.p2j.util.ErrorConditionException)
.
In the case where silent error mode is enabled in the calling method,
the "normal" stack unwinding approach cannot be used because the
exception cannot be thrown. Instead, the error manager will be updated
with the error data and this method will silently return. It is
critical that in such cases the calling code must immediately execute a
return
statement which will maintain the proper Progress
behavior. The caller can check the error manager to determine that an
error occurred.
Detecting the silent error mode in the caller requires that the top level block be found. The silent error flag of the caller is cached there.
text
- The text to use as the error message in the exception.ErrorConditionException
public static boolean isSuppressError()
public static void triggerErrorInCaller() throws ErrorConditionException
honorError(com.goldencode.p2j.util.ErrorConditionException)
.
In the case where silent error mode is enabled in the calling method,
the "normal" stack unwinding approach cannot be used because the
exception cannot be thrown. Instead, the error manager will be updated
with the error data and this method will silently return. It is
critical that in such cases the calling code must immediately execute a
return
statement which will maintain the proper Progress
behavior. The caller can check the error manager to determine that an
error occurred.
Detecting the silent error mode in the caller requires that the top level block be found. The silent error flag of the caller is cached there.
ErrorConditionException
public static void forceRetry() throws RetryUnwindException
A RetryUnwindException
will be thrown to unwind the stack
to the given scope, even if the scope is the current block. This
unwinding is dependent upon catch blocks being implemented with a
corresponding call to honorRetry(com.goldencode.p2j.util.RetryUnwindException)
.
This method will NEVER naturally return since an exception is ALWAYS
thrown. This method should generally not be called from within a
catch block if the intention is to retry the current block since it
would be outside of the block's associated try
. In that
case, only an enclosing block could be retried.
RetryUnwindException
- This method always generates this exception to ensure that
natural processing will not continue.public static void forceRetry(java.lang.String label) throws RetryUnwindException
RetryUnwindException
will be thrown to unwind the stack
to the given scope, even if the scope is the current block. This
unwinding is dependent upon catch blocks being implemented with a
corresponding call to honorRetry(com.goldencode.p2j.util.RetryUnwindException)
.
This method will NEVER naturally return since an exception is ALWAYS
thrown. This method should generally not be called from within a
catch block if the intention is to retry the current block since it
would be outside of the block's associated try
. In that
case, only an enclosing block could be retried.
label
- The name of the scope to retry. Specify null
to
retry the scope that has a pending rollback OR to retry
the current scope if there is no pending rollback.RetryUnwindException
- This method always generates this exception to ensure that
natural processing will not continue.public static void triggerRetry() throws RetryUnwindException
RetryUnwindException
will be
thrown to unwind the stack to the given scope. This unwinding is
dependent upon catch blocks being implemented with a corresponding call
to honorRetry(com.goldencode.p2j.util.RetryUnwindException)
.
If the current block is not the target, the retry is deferred by
marking the target block and then unwinding the stack. Otherwise,
this method will return naturally. This method is only appropriate
to be called from within catch
blocks since a natural
return within a catch
block will fall through to allow
the retry loop to engage.
RetryUnwindException
public static void triggerRetry(java.lang.String label) throws RetryUnwindException
RetryUnwindException
will be thrown to unwind the stack
to the given scope. This unwinding is dependent upon catch blocks
being implemented with a corresponding call to honorRetry(com.goldencode.p2j.util.RetryUnwindException)
.
If the current block is not the target, the retry is deferred by
marking the target block and then unwinding the stack. Otherwise,
this method will return naturally. This method is only appropriate
to be called from within catch
blocks since a natural
return within a catch
block will fall through to allow
the retry loop to engage.
label
- The name of the scope to retry. Specify null
to
retry the scope of that has a pending rollback OR to retry
the current scope if there is no pending rollback.RetryUnwindException
public static void honorStop(StopConditionException exc) throws StopConditionException
exc
- The exception to be checked.StopConditionException
- if the STOP condition is not honored at this scope.public static void honorRetry(RetryUnwindException rue) throws RetryUnwindException
RetryUnwindException
. This unwinding is dependent upon catch
blocks being implemented to call this method.
If the current block is not the target for the pending retry, the exception is re-thrown.
rue
- The exception to honor or ignore.RetryUnwindException
public static void honorError(ErrorConditionException err) throws ErrorConditionException
false
then this method returns silently.
This code also honors any nested error that was generated while another error was being processed AND while nested error mode was enabled. Any such stored error will be re-thrown here.
err
- The exception to honor or ignore.ErrorConditionException
public static void abnormalEnd(java.lang.Throwable thr) throws java.lang.RuntimeException
Throwable
will be re-thrown as a
RuntimeException
.
If the exception is of type ConditionException
or
RetryUnwindException
, this method will do nothing since
these are used for normal flow of control purposes and are used in
close coordination with the transaction manager's state. They need
no other special behavior to be safe. This method is designed to
handle exceptions (like NullPointerException
) which are
not valid in a converted 4GL program.
thr
- The unexpected exception or error.java.lang.RuntimeException
public static void abnormalEnd(java.lang.Throwable thr, boolean needsNotify) throws java.lang.RuntimeException
Throwable
will be re-thrown as a
RuntimeException
.
If the exception is of type ConditionException
or
RetryUnwindException
, this method will do nothing since
these are used for normal flow of control purposes and are used in
close coordination with the transaction manager's state. They need
no other special behavior to be safe. This method is designed to
handle exceptions (like NullPointerException
) which are
not valid in a converted 4GL program.
thr
- The unexpected exception or error.needsNotify
- true
if condition notification must be executed
(only happens if the thr
is a condition).java.lang.RuntimeException
public static boolean isNoTransactionLevel(int lvl)
lvl
- The transaction level to test.true
if the level is NO_TRANSACTION
.public static boolean isSubTransactionLevel(int lvl)
lvl
- The transaction level to test.true
if the level is
SUB_TRANSACTION
.public static boolean isTransactionLevel(int lvl)
lvl
- The transaction level to test.true
if the level is TRANSACTION
.public static int currentTransactionLevel()
public static boolean isFullTransaction()
true
if the current scope defines the top-level
transaction.public static boolean isTransaction()
true
if a transaction is active.public static boolean isTransactionAt(int blockDepth)
blockDepth
- Zero-based block depth starting from the outermost block at which transaction
status is checked.true
if a transaction is active at the specified block depth.public static boolean isTopLevelBlock()
true
if top-level block, else false
.public static boolean isExternalBlock()
false
for blocks derived from
internal procedures, functions and triggers.true
if it is an external block, else
false
.public static boolean isGlobalBlock()
true
if the current block is the only block on the stack of block scopes; for
appserver agent contexts: true
if the current block is one of two outermost
blocks ("appserver-agent" and "startup") on the stack of block scopes.public static boolean hasErrorProp()
true
if the current block has the
PROP_ERROR
bit set in its properties bitmap.public static boolean hasEndkeyProp()
true
if the current block has the
PROP_ENDKEY
bit set in its properties bitmap.public static boolean hasStopProp()
true
if the current block has the
PROP_STOP
bit set in its properties bitmap.public static boolean hasQuitProp()
true
if the current block has the
PROP_QUIT
bit set in its properties bitmap.public static boolean isProcessingQuit()
QuitConditionException
.true
if this exit is due to a quit condition.public static void setProcessingQuit(boolean quit)
QuitConditionException
.quit
- true
if this exit is due to a quit condition.public static boolean isHeadless()
true
if this session is headless.public static void setHeadless(boolean headless)
headless
- true
if this session must be headless.public static void incrementInteractions()
public static void resetInteractions()
public static int getInteractions()
public static boolean isRollup()
true
,
then any contained blocks that exit will cause the current (containing)
block's interactions counter to be increased by the contained block's
interactions counter. Otherwise, no aggregation will occur.public static boolean isEnclosingRollup()
true
,
then the current block's exit will cause the enclosing (containing)
block's interactions counter to be increased by the current block's
interactions counter. Otherwise, no aggregation will occur.public static void setRollup(boolean rollup)
true
,
then any contained blocks that exit will cause the current (containing)
block's interactions counter to be increased by the contained block's
interactions counter. Otherwise, no aggregation will occur.rollup
- The new rollup value.public static void batchStart()
BatchListener
objects that a batch is
starting.public static void batchStop()
BatchListener
objects that a batch is
stopping.public static void honorStopCondition() throws StopConditionException, SilentUnwindException
Thread.interrupted
, if true
then a
StopConditionException
will be thrown. The interrupted status
will be true
if a call to Thread.interrupt
was previously made.
The thread's interrupted status is cleared by this method before the
StopConditionException
is thrown.
StopConditionException
- If the current thread's was previously interrupted.SilentUnwindException
- If the connection ended prematurely end the current thread
needs to stop.public static void abortProcessing()
error
, on the next honorStopCondition()
call.public static void setNestedMode(boolean mode)
honorError(com.goldencode.p2j.util.ErrorConditionException)
this can be re-thrown. This duplicates some
obscure behavior seen in Progress.mode
- true
to enable, false
to disable.public static boolean isNestedMode()
honorError(com.goldencode.p2j.util.ErrorConditionException)
this can be
re-thrown.true
if nested error mode is enabled.public static BlockType getBlockType()
public static int getFullTransactionBlock()
public static int getNestingLevel()
public static void saveNestedError(ConditionException err)
honorError(com.goldencode.p2j.util.ErrorConditionException)
if
nested error mode is enabled. Note that only 1 error can ever be nested
and the last one set via this method will be the one that is honored.err
- The error to store.public static void hadPause()
public static int findNearestExternal()
public static void startOffEndRegistration()
TransactionManager.WorkArea.offEndQueries
set and will
set the TransactionManager.WorkArea.offEndRegistration
flag to ON. While this flag
is ON, all created queries will be collected in the
TransactionManager.WorkArea.offEndQueries
set.
After the block initialization is finished, the
stopOffEndRegistration()
will be called.
public static void stopOffEndRegistration()
QueryOffEndListener
s
associated with the registered queries
.public static void registerOffEndQuery(P2JQuery query)
These queries will be able to end the loop when the last record is reached, by overriding any user-defined END-KEY action. The action wich is executed is the default UNDO, LEAVE action for END-KEY.
query
- The query which needs to be registered.public static boolean isOffEndListener(QueryOffEndListener listener)
listener
- A listener to be checked if is registered for off-end events.true
if the listener is registered for query
off-end event.public static void processOffEndListeners(boolean init)
initialize
or
finish
method, depending on the
flag.init
- true
if the listeners are initialized; else, the
QueryOffEndListener.finish()
method is called.public static java.util.Set<QueryOffEndListener> getOffEndListeners(boolean clear)
listeners
.clear
- true
if the top-most off-end listeners set
should be cleared.public static void registerOutputParameterAssigner(OutputParameterAssigner opa)
BlockManager
when it is
time to process assign-backs from function/procedure output parameters
to the database record fields with which they are associated.opa
- An output parameter assigner.java.lang.IllegalStateException
- if a second output parameter assigner is registered for a block
before the current one is deregistered. There can be only one.public static void deferError(java.lang.String action, java.lang.Throwable thr)
Commitable
, so that iteration or pop
scope processing can be continued without interruption. This ensures
that all Commitable
s registered after the errant one still
receive their commit/rollback notifications, and that (in the case of
popping a scope), registered Scopeable
s still receive their
scope finished notifications.
If no error is already pending, exc
is stored, to be thrown
upon conclusion of processing the current block scope or iteration. If
an error is already pending, exc
is discarded. In either
case, exc
is logged if error-level logging is enabled.
action
- A brief description of the action occurring at the time the
error was encountered, such as "commit" or "master rollback".thr
- The error caught during processing of a commit or rollback
notification.TransactionManager.WorkArea.handleDeferredError()
public static void deferError(java.lang.String action, java.lang.Throwable thr, boolean silent)
Commitable
, so that iteration or pop
scope processing can be continued without interruption. This ensures
that all Commitable
s registered after the errant one still
receive their commit/rollback notifications, and that (in the case of
popping a scope), registered Scopeable
s still receive their
scope finished notifications.
If no error is already pending, exc
is stored, to be thrown
upon conclusion of processing the current block scope or iteration. If
an error is already pending, exc
is discarded. In either
case, exc
is logged if error-level logging is enabled.
action
- A brief description of the action occurring at the time the
error was encountered, such as "commit" or "master rollback".thr
- The error caught during processing of a commit or rollback
notification.silent
- If true
then exception is not logged.TransactionManager.WorkArea.handleDeferredError()
public static int findNearestTopLevel()
public static BlockType getNearestTopLevelType()
BlockType.UNKNOWN
if
there is no block marked as a top level block.public static boolean _isHeadless()
To determine if the current context is headless the method uses the following algorithm:
SecurityManager.isServerAccount()
. Server sessions are implicit
headless;
boolean
value set to true
for a
given context's account in one of the following paths, then the context is
headless. This allows the user interface client to be an optional part of any
account. In other words, process accounts can be run in a "headless" mode with no
requirement for any user interface. These are the paths (in order in which they
are searched):
/server/<serverID>/runtime/<account_or_group>/headless
;
/server/<serverID>/runtime/default/headless
;
/server/default/runtime/<account_or_group>/headless
;
/server/default/runtime/default/headless
;
true
if this session is headless.static void processValidate() throws ErrorConditionException
On the last iteration of a loop or block which ends in success (in
which the flow of control reaches the natural end of the block), both
will be called in succession. However, other forms of exit which are
still considered successful (i.e. return and break which are not the
result of condition processing) will only execute popScope
and iterate
will be bypassed.
It is important to note that the list of commitables in blk is
iterated in reverse order from that in which they are registered with
the TransactionManager
. This is done to ensure that
database transactions (which are registered before their corresponding
buffers) are always committed after all buffers are committed.
ErrorConditionException
- If validation fails.static BlockDefinition nearestExecutingBlock()
static OutputParameterAssigner deregisterOutputParameterAssigner()
BlockManager
will invoke this
method.null
if none was registered.static void registerNext(LazyUndoable... target)
This form of registration is useful for objects whose natural lifetime is scoped to the top-level block. In particular, it is necessary for objects that are constructed during a class' constructor/initializer (before the external procedure block has opened). Such objects cannot simply register since their construction is not actually enclosed by the block.
When the deferred registration occurs, it will NOT be global and will NOT be added to registered Commitables.
This notification will occur whether or not a transaction is active.
These registrations naturally are removed when the associated scope is removed.
The given object will only be added if it is not already in the list.
target
- The object references to be registered. This cannot be
null
.static void registerAt(ScopeLevel scope, LazyUndoable... target)
This form of registration is useful for objects whose natural lifetime is scoped to the top-level block. In particular, it is necessary for objects that are constructed during a class' constructor/initializer (before the external procedure block has opened). Such objects cannot simply register since their construction is not actually enclosed by the block.
When the deferred registration occurs, it will NOT be global and will NOT be added to registered Commitables.
This notification will occur whether or not a transaction is active.
These registrations naturally are removed when the associated scope is removed.
The given object will only be added if it is not already in the list.
scope
- The scope where to register the undoable targets.target
- The object references to be registered. This cannot be
null
.public static void registerCurrent(LazyUndoable... undoTargets)
undoTargets
- List of object references to be registered. This cannot be
null
.static void registerAt(int transLevel, boolean persistent, LazyUndoable... undoTargets)
These registrations naturally are removed when the associated scope is removed. However, the global scope is long-lived. Special care is necessary to prevent the same instance of global shared variables being added multiple times.
transLevel
- The transaction level to set for this undoable.persistent
- Flag indicating if the undoable is defined in a persistent procedureundoTargets
- The object references to be rolled back on failure. This
cannot be null
.static void deregister(TransactionManager.WorkArea wa, java.util.IdentityHashMap<LazyUndoable,java.lang.Object> undoables)
wa
- The TransactionManager.WorkArea
instance; if null
, it will be resolved.undoables
- The undoables to be deregistered.static int getTransDepth()
TransactionManager.WorkArea.txNestingLevel
field.static void trackUndoables()
static void untrackUndoables(java.lang.Object referent)
referent
- The external program instance.private static void rollbackWorker(TransactionManager.WorkArea wa, int level, java.lang.Throwable cause)
Undoable
objects
inside the current active transaction at the scope defined by the
specified stack level. All objects that are rolled back will have their
values assigned based on the values backed up at the start of the
specified scope. If the current scope is not the target scope, the
given exception will be stored, the rollback will be deferred and
the rollback will be processed as the scopes naturally unwind. This
unwinding must be generated by a change in flow of control by the
calling code. This flow control change MUST always immediately follow
this method otherwise undefined results can occur.
This caller-driven control flow is required to properly duplicate the semantics of Progress 4GL condition processing which always generates an implicit or explicit flow control action after every UNDO. Since the flow of control change can reference a different scope than that of the rollback, this can't be handled by re-throwing the exception but must instead be separately driven by a deferred rollback and a caller driven flow control statement such as break, continue or return. The key limitation that makes this possible is the fact that the UNDO (rollback) scope MUST ALWAYS BE equivalent to or more specific than the scope to which flow of control will be changed. This means that one can rollback at a more deeply nested scope but change flow of control to resume processing at a different (less deeply nested) scope. The reverse is not possible.
wa
- Context local work area.level
- Specifies the stack level of the scope at which to rollback or
-1 if the current scope should be the target.cause
- The exceptional cause, if any, of the rollback.private static boolean isTopLevelBlock(TransactionManager.WorkArea wa)
wa
- Context local work area.true
if top-level block, else false
.private static boolean isGlobalBlock(TransactionManager.WorkArea wa)
true
if the current block is the only block on the stack of block scopes; for
appserver agent contexts: true
if the current block is one of two outermost
blocks ("appserver-agent" and "startup") on the stack of block scopes.wa
- Context local work area.private static int findNearestTopLevel(TransactionManager.WorkArea wa)
wa
- Context local work area.private static void processResettables(TransactionManager.WorkArea wa, boolean clearOnly)
Resettable
objects or makes them
clear their lists of changes that should be reset.wa
- The TransactionManager.WorkArea
instance.clearOnly
- If true
then clear the lists of changes that should
be reset, otherwise perform reset of these changes.private static void registerUndo(LazyUndoable undoTarget, int transLevel, boolean persistent)
These registrations naturally are removed when the associated scope is removed. However, the global scope is long-lived. Special care is necessary to prevent the same instance of global shared variables being added multiple times.
undoTarget
- The object reference to be rolled back on failure. This
cannot be null
.transLevel
- The transaction level to set for this undoable.persistent
- Flag indicating if the undoable is defined in a persistent procedureprivate static BlockType getNearestTopLevelType(TransactionManager.WorkArea wa)
wa
- Context local work area.BlockType.UNKNOWN
if
there is no block marked as a top level block.private static BlockDefinition nearestTopLevel(TransactionManager.WorkArea wa)
wa
- Context local work area.null
if
there is no block marked as a top level block.private static void processBatchNotifications(boolean start)
BatchListener
objects that a batch is
either starting or stopping.start
- true
if this is the start of a batch, otherwise
false
.private static void iterateWorker(TransactionManager.WorkArea wa) throws StopConditionException
This hook is called at the top of the loop, just after the loop test has been passed. If the loop test fails, then this will not be called. This code will be called inside the block itself, as the first thing that is done.
Note that this is only called on the second and subsequent iterations
of the block, no matter how the iteration occurred (via natural control
flow through the bottom of an iterating block OR via a Java
continue
statement that caused a jump to the top of the
loop). Clearing the retry logic and rollback logic is important
whether or not this is a loop since non-loops can be retried (via
condition processing) or iterated via continue
.
All registered Finalizables
are notified of the
iteration via their Finalizable.iterate()
callback method.
If the block is not a loop, commit/rollback processing and
Finalizable
processing will NOT be executed.
This must never be called outside of a bracketed pair of
pushScope(java.lang.String, int, boolean, boolean, boolean, boolean)
and popScope()
calls.
This method will honor any pending thread interruption by throwing
a StopConditionException
using honorStopCondition()
wa
- The TransactionManager.WorkArea
instance.StopConditionException
- If the current thread's was previously interrupted.private static void backupWorker(TransactionManager.WorkArea wa, BlockDefinition blk)
pushScope(java.lang.String, int, boolean, boolean, boolean, boolean)
and blockSetup()
due to the
semantics of Progress in which the backup set is created or refreshed
after the loop control variables have been modified.wa
- The TransactionManager.WorkArea
instance.blk
- The block for which a backup must be made or null
to use the current block on top of the stack.private static boolean rollbackCurrentScope(TransactionManager.WorkArea wa, int level)
Even if the level is not -1 (it must refer to an enclosing block), if the given block is a full transaction block (the block at which the transaction is scoped), then the rollback must occur at this point instead of deferring the rollback until the transaction is no longer active.
wa
- The TransactionManager.WorkArea
instance.level
- The stack level of the scope to be rolled back.true
if the above conditions hold.private static BlockDefinition findBlock(java.lang.String label)
label
- The block label to search for.null
if there is no enclosing
block with that label.private static int findStackLevel(TransactionManager.WorkArea wa, java.lang.String label)
wa
- Context local work area.label
- The block label to search for.private static void processRollbackPending(TransactionManager.WorkArea wa, BlockDefinition blk)
wa
- The TransactionManager.WorkArea
instance.blk
- The block to be notified about a pending rollback.private static void processRollback(TransactionManager.WorkArea wa, BlockDefinition blk)
Undoable
interface) is done,
notifications are provided to all registered Commitable
instances in the current block's commitable list.
If the block is also the full transaction block, the last thing
done is a single master rollback call to the instance registered
for the registerTransactionCommit(com.goldencode.p2j.util.Commitable, boolean)
.
wa
- The TransactionManager.WorkArea
instance.blk
- The block to be rolled back.private static void processCommit(TransactionManager.WorkArea wa, BlockDefinition blk)
On the last iteration of a loop or block which ends in success (in
which the flow of control reaches the natural end of the block), both
will be called in succession. However, other forms of exit which are
still considered successful (i.e. return and break which are not the
result of condition processing) will only execute popScope
and iterate
will be bypassed.
It is important to note that the list of commitables in blk is
iterated in reverse order from that in which they are registered with
the TransactionManager
. This is done to ensure that
database transactions (which are registered before their corresponding
buffers) are always committed after all buffers are committed.
wa
- The TransactionManager.WorkArea
instance.blk
- The scope to be committed.private static void processFinalizables(TransactionManager.WorkArea wa, BlockDefinition blk, boolean iterate)
wa
- Context-local work area.blk
- The scope to be finalized.iterate
- true
to call each target's iterate
method or false
to call finished
.private static void processRetry(TransactionManager.WorkArea wa, BlockDefinition blk)
wa
- The TransactionManager.WorkArea
instance.blk
- The scope to be retried.private static void processScopeNotifications(TransactionManager.WorkArea wa, BlockDefinition blk, boolean start)
wa
- Context-local work area.blk
- The scope to be finalized.start
- If true
generate a start scope notification,
otherwise generate an end scope notification.private static void updateBackupSet(java.util.List<UndoablePair> backup)
blockSetup()
).private static boolean hasProperty(int prop)
prop
- The property bit flag to test. Should be one of the constants
PROP_ERROR, PROP_ENDKEY, PROP_STOP or PROP_QUIT
.true
if the current block has the given
property bit set in its properties bitmap.private static void log(java.util.logging.Level lvl, java.lang.String location, java.lang.String txt)
lvl
- The logging level.location
- The event or call site from which the log entry was
generated.txt
- The text to insert into the log. May be null
.private static void log(java.util.logging.Level lvl, java.lang.String location, java.lang.String txt, java.lang.Throwable trw)
lvl
- The logging level.location
- The event or call site from which the log entry was
generated.txt
- The text to insert into the log. May be null
.trw
- The throwable that caused this logging to occur or
null
if no exception is present.