public final class DefaultDirtyShareContext extends java.lang.Object implements DirtyShareContext
This implementation maintains state specific to the current context, in order both to filter information appropriately, and to be able to clean up shared data when the current context's transactions are completed.
Modifier and Type | Field and Description |
---|---|
private java.util.Map<java.lang.String,java.util.Set<java.io.Serializable>> |
changes
Map of entity names to sets of IDs inserted/updated by this context
|
private java.util.Set<RecordIdentifier> |
deadInserts
Identifiers of records inserted by this context, which deletes have rolled back
|
private java.util.Map<java.lang.String,java.util.Set<java.io.Serializable>> |
deletes
Map of entity names to sets of IDs deleted by this context
|
private java.util.Set<RecordIdentifier> |
dirtySnapshots
Set of IDs of DMOs changed since last updateSnapshots() call
|
private java.util.Set<RecordIdentifier> |
inserts
Identifiers of records inserted by this context
|
private java.util.Set<java.lang.String> |
leakedEntities
DMO entities which have had uncommitted updates "leaked"
|
private DirtyShareManager |
manager
Object which manages dirty reads for the database
|
private java.util.Map<RecordIdentifier,RecordBuffer> |
unvalidatedInserts
Buffers holding newly created records, which have not yet been validated/flushed
|
Constructor and Description |
---|
DefaultDirtyShareContext(DirtyShareManager manager)
Constructor which stores a reference to the dirty share manager for the
associated database.
|
Modifier and Type | Method and Description |
---|---|
void |
cleanup()
Clean up all information contributed to the dirty share manager by this
context for the current transaction.
|
void |
delete(java.lang.String entity,
java.io.Serializable id,
boolean rollback,
boolean lock)
Mark a record as having been deleted in an uncommitted transaction, or
unmark a record which previously was so marked.
|
void |
deregisterForGlobalEvents(long registerID)
Deregister with a global event clearinghouse an interest in insert,
delete, and update events which affect a particular DMO type.
|
RecordBuffer |
getCreatingBuffer(java.lang.String entity,
java.io.Serializable id)
If the specified record is an unvalidated insert created by a buffer local to this context,
get the buffer which created it.
|
Persistable |
getDirtyDMO(java.lang.String entity,
java.io.Serializable id)
Retrieve from the dirty database the record specified by the given
entity and primary key, if it exists, and if it was not put there by the
current context.
|
DirtyInfo |
getDirtyInfo(RecordBuffer buffer,
java.lang.String index,
int queryType,
HQLBundle bundle,
java.lang.Object[] params,
org.hibernate.type.Type[] types,
Persistable found,
boolean byRowid)
Given certain search criteria and possibly a potential DMO match in the
primary database, report any significant information currently being
tracked for uncommitted transactions, which might override data (or the
lack thereof) found in the primary database.
|
GlobalChangeEvent[] |
getGlobalEvents(long registerID,
long lastID)
Retrieve any new events that have been collected by a global event
clearinghouse, representing inserts, deletes, and updates made to
record types for which the caller previously has registered interest.
|
void |
insert(RecordBuffer buffer,
Persistable dmo,
java.lang.reflect.Method setter,
BaseDataType datum,
java.util.Collection<java.lang.String> uniqueIndexes,
boolean lock)
Begin tracking a newly inserted record in the dirty database.
|
boolean |
isDirtyDelete(java.lang.String entity,
java.io.Serializable id,
boolean ignoreLocal)
Indicate whether the record specified by the given entity and primary key has
been deleted within an uncommitted transaction within a context, optionally
ignoring deletes in the current context.
|
boolean |
isEntityDirty(java.lang.String entity)
Indicate whether there are currently any uncommitted changes (inserts,
updates, or deletes) in the table represented by the given DMO entity
name.
|
boolean |
isForeignUnvalidatedIndex(RecordIdentifier ident,
java.lang.String index)
Indicate whether the record identified by
ident represents a newly inserted
record, in a different context than that of the caller, which has an unvalidated index,
index . |
boolean |
isLocalInsert(java.lang.String entity,
java.io.Serializable id)
Indicate whether the specified record is being tracked as newly inserted
by this context.
|
java.util.List |
list(java.lang.String entity,
java.lang.String hql,
java.lang.Object[] params,
org.hibernate.type.Type[] types,
int maxResults,
int startOffset,
boolean readOnly)
Execute an HQL query and return the results as a list.
|
void |
lockAllIndexes(java.lang.String entity,
LockType lockType)
Lock or unlock all indexes associated with the given DMO entity.
|
java.lang.Long |
registerForGlobalEvents(java.lang.String entity)
Register with a global event clearinghouse an interest in insert,
delete, and update events which affect the given DMO entity.
|
void |
rollbackInsert(RecordIdentifier ident,
boolean lock)
Rollback the insert of a record previously introduced with the
insert(RecordBuffer, Persistable, Method, BaseDataType, Collection, boolean)
method. |
private void |
trackChange(java.lang.String entity,
java.io.Serializable id)
Remember that the record represented by the given entity and primary key
ID has been modified in the current context.
|
void |
update(RecordBuffer buffer,
java.lang.String[] properties,
int[] extIndexes,
BaseDataType[] values,
java.util.Collection<java.lang.String> validatedUniqueIndexes,
boolean transientIndexValidated)
Track an update to one or more indexed, DMO properties, as indicated by the
properties , extIndexes and values arguments. |
void |
update(java.lang.String entity,
java.io.Serializable id,
java.lang.String[] properties,
int[] extIndexes,
BaseDataType[] values,
boolean lock)
Track an update to one or more indexed, DMO properties, as indicated by the
properties , extIndexes and values arguments. |
java.util.List<Persistable> |
updateSnapshots(java.util.List<java.lang.String> entities,
Persistence persistence)
Overwrite the state of the records in the dirty database which match the
IDs of all DMOs for the given entities, which have been modified by the
current context.
|
private final DirtyShareManager manager
private java.util.Set<RecordIdentifier> inserts
private java.util.Set<RecordIdentifier> deadInserts
private java.util.Map<RecordIdentifier,RecordBuffer> unvalidatedInserts
private java.util.Map<java.lang.String,java.util.Set<java.io.Serializable>> changes
private java.util.Map<java.lang.String,java.util.Set<java.io.Serializable>> deletes
private java.util.Set<RecordIdentifier> dirtySnapshots
private java.util.Set<java.lang.String> leakedEntities
DefaultDirtyShareContext(DirtyShareManager manager)
manager
- Dirty share manager for the associated database.public java.lang.Long registerForGlobalEvents(java.lang.String entity)
registerForGlobalEvents
in interface DirtyShareContext
entity
- DMO entity for which the caller is interested in tracking
change.getGlobalEvents(long, long)
,
deregisterForGlobalEvents(long)
public void deregisterForGlobalEvents(long registerID)
deregisterForGlobalEvents
in interface DirtyShareContext
registerID
- A unique identifier for the registrant being deregistered.getGlobalEvents(long, long)
,
registerForGlobalEvents(String)
public GlobalChangeEvent[] getGlobalEvents(long registerID, long lastID) throws EventRegistrationException
getGlobalEvents
in interface DirtyShareContext
registerID
- A unique identifier for an object which has registered interest
in record-changing events.lastID
- A unique identifier representing the last event retrieved by
the caller. If less than 0, it is assumed no events have yet
been retrieved since the caller registered interest in these
events.null
if no
such events have been collected.EventRegistrationException
- if registerID
is invalid or has expired.public void lockAllIndexes(java.lang.String entity, LockType lockType) throws PersistenceException
lockAllIndexes
in interface DirtyShareContext
entity
- Name of an entity, which is the name of the DMO implementation
class associated with a table being tracked for uncommitted
changes.lockType
- Type of lock to acquire, or NONE
to release
existing locks. NO_WAIT
variants will be treated
as regular, blocking variants.PersistenceException
- if there is an error querying JDBC metadata while retrieving
index information.public void insert(RecordBuffer buffer, Persistable dmo, java.lang.reflect.Method setter, BaseDataType datum, java.util.Collection<java.lang.String> uniqueIndexes, boolean lock) throws PersistenceException
This record is removed when the adding context's current transaction is committed or rolled back.
insert
in interface DirtyShareContext
buffer
- Record buffer responsible for the insert.dmo
- Record to be tracked.setter
- Optional setter method for a property which must be updated in
the DMO copy before it is inserted into the dirty database.
May be null
.datum
- Updated value to apply to property
. May be
null
.uniqueIndexes
- If the insertion is happening at record creation, and the record has not yet been
validated, this will represent the collection of unique indexes that will need to
be validated before the record can safely be persisted. If null
, this
indicates the record has been fully validated and should no longer be tracked as
unvalidated.lock
- true
to acquire write locks to insert the record;
false
to assume write locks are acquired by
calling code.PersistenceException
- if there is any database error.public boolean isLocalInsert(java.lang.String entity, java.io.Serializable id)
isLocalInsert
in interface DirtyShareContext
entity
- Name of an entity, which is the name of the DMO implementation
class associated with a table being tracked for uncommitted
changes.id
- Primary key of the record to be checked.true
if this record is newly inserted by this
context, else false
.public boolean isForeignUnvalidatedIndex(RecordIdentifier ident, java.lang.String index)
ident
represents a newly inserted
record, in a different context than that of the caller, which has an unvalidated index,
index
. Assumes appropriate indexes already are locked by the caller.isForeignUnvalidatedIndex
in interface DirtyShareContext
ident
- Record identifier (using entity name and primary key).index
- Index to be checked for validation.true
if ident
represents a new record in a foreign
context with unvalidated index index
.public RecordBuffer getCreatingBuffer(java.lang.String entity, java.io.Serializable id)
getCreatingBuffer
in interface DirtyShareContext
entity
- Name of an entity, which is the name of the DMO implementation class associated
with a table being tracked for uncommitted changes.id
- Primary key of the record to be checked.null
if the record is not a locally created,
unvalidated insert.public void rollbackInsert(RecordIdentifier ident, boolean lock) throws PersistenceException
insert(RecordBuffer, Persistable, Method, BaseDataType, Collection, boolean)
method.rollbackInsert
in interface DirtyShareContext
ident
- Identifier for the target record, which encapsulates its entity
name and primary key.lock
- true
to acquire write locks;
false
to assume write locks are acquired by
calling code.java.lang.IllegalStateException
- if the record was not inserted in this context during the
current transactionPersistenceException
- if there is any database error.public void update(RecordBuffer buffer, java.lang.String[] properties, int[] extIndexes, BaseDataType[] values, java.util.Collection<java.lang.String> validatedUniqueIndexes, boolean transientIndexValidated) throws PersistenceException
properties
, extIndexes
and values
arguments.
Any record added to the dirty database as a result of this method is removed when the adding context's current transaction is committed or rolled back.
Assumes appropriate indexes have been locked by the caller.
update
in interface DirtyShareContext
buffer
- Record buffer responsible for the update.properties
- Array of names of those DMO properties which were updated. These should represent
columns which participate in one or more indexes.extIndexes
- In case of EXTENT fields this array contains their index. Otherwise -1.values
- Updated DMO property values. Each value in the array corresponds positionally with
its matching property name in the properties
array.validatedUniqueIndexes
- Collection of unique indexes which have been checked successfully for this update
to have passed validation.transientIndexValidated
- true
if the update was caused by an index validation of a transient record.PersistenceException
- if there is any database error.public void update(java.lang.String entity, java.io.Serializable id, java.lang.String[] properties, int[] extIndexes, BaseDataType[] values, boolean lock) throws PersistenceException
properties
, extIndexes
and values
arguments.
It is assumed the record identified by entity
and
id
already is present in the dirty database due to a
previous update or insert event.
update
in interface DirtyShareContext
entity
- Name of an entity, which is the name of the DMO implementation
class associated with a table being tracked for uncommitted changes.id
- Primary key of the target record.properties
- Array of names of those DMO properties which were updated.
These should represent columns which participate in one or more indexes.extIndexes
- In case of EXTENT fields this array contains their index. Otherwise -1.values
- Updated DMO property values. Each value in the array
corresponds positionally with its matching property name in the
properties
array.lock
- true
to acquire write locks to update the record;
false
to assume write locks are acquired by calling code.PersistenceException
- if there is any database error.public java.util.List<Persistable> updateSnapshots(java.util.List<java.lang.String> entities, Persistence persistence) throws PersistenceException
This is necessary to support a quirk/bug in Progress which compromises transaction isolation by leaking uncommitted changes (even non-indexed data) under certain conditions.
updateSnapshots
in interface DirtyShareContext
entities
- List of entities, which are the names of the DMO implementation
classes associated with tables being tracked for uncommitted
changes. Only those records which match these entities will
have their current state leaked.persistence
- Persistence service object to be used to retrieved the latest
version of the target records in the current context.null
.PersistenceException
- if there is any database error.public void delete(java.lang.String entity, java.io.Serializable id, boolean rollback, boolean lock) throws PersistenceException
If marking a record as deleted, that was earlier inserted by the current context, rollback the insert, but do not mark the record as deleted.
A record is unmarked when the adding context's current transaction is committed or rolled back.
delete
in interface DirtyShareContext
entity
- Name of an entity, which is the name of the DMO implementation
class associated with a table being tracked for uncommitted
changes.id
- Primary key of deleted record.rollback
- If false
, the target record is marked as deleted;
if true
, it is unmarked.lock
- true
to acquire write locks to delete the record;
false
to assume write locks are acquired by
calling code.PersistenceException
- if a database error occurs rolling back an earlier insert.public boolean isEntityDirty(java.lang.String entity)
isEntityDirty
in interface DirtyShareContext
entity
- Fully qualified name of the DMO entity to be checked.true
if there any pending, uncommitted changes in
the backing table, else false
.public boolean isDirtyDelete(java.lang.String entity, java.io.Serializable id, boolean ignoreLocal)
isDirtyDelete
in interface DirtyShareContext
entity
- Name of an entity, which is the name of the DMO implementation
class associated with a table being tracked for uncommitted
changes.id
- Primary key of the record to be checked.ignoreLocal
- Ignore a delete if it occurred in the current context and only report
whether a delete of the given record occurred in a different context.true
if the specified record has been deleted, else false
.public Persistable getDirtyDMO(java.lang.String entity, java.io.Serializable id) throws PersistenceException
getDirtyDMO
in interface DirtyShareContext
entity
- Name of an entity, which is the name of the DMO implementation
class associated with a table being tracked for uncommitted
changes.id
- Primary key of the record to be retrieved.null
.PersistenceException
- if there is any database error.public java.util.List list(java.lang.String entity, java.lang.String hql, java.lang.Object[] params, org.hibernate.type.Type[] types, int maxResults, int startOffset, boolean readOnly) throws PersistenceException
Object
s.
No locking is attempted.
list
in interface DirtyShareContext
entity
- Name of an entity, which is the name of the DMO implementation class associated
with a table being tracked for uncommitted changes. Should be null
for a multi-table query.hql
- HQL query statement passed to Hibernate. This method makes no assumptions as to
the types of object(s) returned.params
- Substitution values for the query. If none, this should be an empty array.types
- Hibernate types for the values
array. If none, this should be an
empty array.maxResults
- The maximum number of elements to be returned in the list. If this value is
non-positive, no upper limit is applied.startOffset
- The 0-based offset of the first record to retrieve. If this value is non-positive,
an offset of 0 is used by default.readOnly
- true
to execute the query in read-only mode, else false
.null
if no result was found.PersistenceException
- if there was an error executing the query.public DirtyInfo getDirtyInfo(RecordBuffer buffer, java.lang.String index, int queryType, HQLBundle bundle, java.lang.Object[] params, org.hibernate.type.Type[] types, Persistable found, boolean byRowid) throws PersistenceException
If a DirtyInfo
object is returned by this method, it will
contain overriding information, such as a dirty DMO which matched the
search criteria, whether that record was newly inserted, or the fact
that the candidate record found in the primary search has been deleted
or modified in an uncommitted transaction. A null
return
indicates no overriding information was available.
getDirtyInfo
in interface DirtyShareContext
buffer
- Record buffer associated with the current query.index
- Name of index which governs the ordering of data in the current query.queryType
- Type of query.bundle
- An object containing one or more HQL statements to be executed
against the dirty database to find a record which matches the
current query criteria. The list is in order of most specific
to least specific search criteria.params
- Query substitution parameters which match placeholders in the
most specific HQL statement.types
- Hibernate data types of the query substitution parameters.found
- DMO, if any, found in the primary database, which matches the
current query criteria.byRowid
- The predicate of the query does a lookup for ROWID/RECID of the table. In case of
transient records they are accessible without the need of having a full matched
index.null
if no uncommitted change information was available for the
given arguments.PersistenceException
- if there is any database error.public void cleanup()
cleanup
in interface DirtyShareContext
StopConditionException
- if a critical database error occurs that would leave the dirty
database in an improper state.private void trackChange(java.lang.String entity, java.io.Serializable id)
entity
- Name of an entity, which is the name of the DMO implementation
class associated with a table being tracked for uncommitted
changes.id
- Primary key ID of the modified record.