use of org.eclipse.persistence.internal.identitymaps.CacheKey in project eclipselink by eclipse-ee4j.
the class CacheImpl method contains.
/**
* Returns true if the cache contains an Object with the id and Class type, and is valid.
* @see Cache#contains(Class, Object)
*/
@Override
@SuppressWarnings({ "rawtypes" })
public boolean contains(Class cls, Object id) {
getEntityManagerFactory().verifyOpen();
Object pk = createPrimaryKeyFromId(cls, id);
if (null == pk) {
return false;
}
// getDescriptor() is the same call
ClassDescriptor descriptor = getSession().getClassDescriptor(cls);
/**
* Check for no descriptor associated with the class parameter.
* This will occur if the class represents a MappedSuperclass (concrete or abstract class),
* an interface or Embeddable class.
*/
if (null == descriptor) {
// do not throw an IAException: cache_impl_class_has_no_descriptor_is_not_a_persistent_type - just return false
return false;
}
// we can assume that all implementors of IdentityMapAccessor implement getCacheKeyforObject
CacheKey key = ((org.eclipse.persistence.internal.sessions.IdentityMapAccessor) getAccessor()).getCacheKeyForObject(pk, cls, descriptor, false);
return key != null && key.getObject() != null && !descriptor.getCacheInvalidationPolicy().isInvalidated(key);
}
use of org.eclipse.persistence.internal.identitymaps.CacheKey in project eclipselink by eclipse-ee4j.
the class UnitOfWorkImpl method verifyMutexThreadIntegrityBeforeRelease.
/**
* INTERNAL:
* 272022: Avoid releasing locks on the wrong server thread.
* If the current thread and the active thread on the mutex do not match - switch them
* Before we release acquired locks (do the same as we do for mergeClonesBeforeCompletion())
* Check that the current thread is the active thread on all lock managers by
* checking the cached lockThread on the mergeManager.
* If we find that these 2 threads are different - then all threads in the acquired locks list are different.
* Switch the activeThread on the mutex to this current thread for each lock.
* @return true if threads were switched
*/
public boolean verifyMutexThreadIntegrityBeforeRelease() {
if (this.lastUsedMergeManager != null) {
// mergeManager may be null in a com.ibm.tx.jta.RegisteredSyncs.coreDistributeAfter() afterCompletion() callback
Thread currentThread = Thread.currentThread();
Thread lockThread = this.lastUsedMergeManager.getLockThread();
if (currentThread != lockThread) {
if (ConcurrencyManager.getDeferredLockManager(lockThread) != null) {
// check for transitioned old deferred lock manager and switch to the new thread.
ConcurrencyManager.DEFERRED_LOCK_MANAGERS.put(currentThread, ConcurrencyManager.DEFERRED_LOCK_MANAGERS.remove(lockThread));
}
ArrayList<CacheKey> locks = this.getMergeManager().getAcquiredLocks();
if (null != locks) {
Iterator<CacheKey> locksIterator = locks.iterator();
log(SessionLog.FINER, AbstractSessionLog.CACHE, "active_thread_is_different_from_current_thread", lockThread, getMergeManager(), currentThread);
while (locksIterator.hasNext()) {
ConcurrencyManager lockMutex = locksIterator.next();
if (null != lockMutex) {
Thread activeThread = lockMutex.getActiveThread();
// check for different acquire and release threads
if (currentThread != activeThread) {
// Switch activeThread to currentThread - we will release the lock later
lockMutex.setActiveThread(currentThread);
}
}
}
}
}
return true;
} else {
return false;
}
}
use of org.eclipse.persistence.internal.identitymaps.CacheKey in project eclipselink by eclipse-ee4j.
the class UnitOfWorkImpl method registerExistingObject.
/**
* INTERNAL:
* Register the existing object with the unit of work.
* This is a advanced API that can be used if the application can guarantee the object exists on the database.
* When registerObject is called the unit of work determines existence through the descriptor's doesExist setting.
*
* @return The clone of the original object, the return value must be used for editing.
* Editing the original is not allowed in the unit of work.
*/
public Object registerExistingObject(Object objectToRegister, ClassDescriptor descriptor, Object queryPrimaryKey, boolean isFromSharedCache) {
if (this.isClassReadOnly(descriptor.getJavaClass(), descriptor)) {
return objectToRegister;
}
if (isAfterWriteChangesButBeforeCommit()) {
throw ValidationException.illegalOperationForUnitOfWorkLifecycle(this.lifecycle, "registerExistingObject");
}
if (descriptor.isDescriptorTypeAggregate()) {
throw ValidationException.cannotRegisterAggregateObjectInUnitOfWork(objectToRegister.getClass());
}
CacheKey cacheKey = null;
Object objectToRegisterId = null;
Thread currentThread = Thread.currentThread();
if (project.allowExtendedCacheLogging()) {
// Not null if objectToRegister exist in cache
Session rootSession = this.getRootSession(null).getParent() == null ? this.getRootSession(null) : this.getRootSession(null).getParent();
cacheKey = ((org.eclipse.persistence.internal.sessions.IdentityMapAccessor) rootSession.getIdentityMapAccessor()).getCacheKeyForObject(objectToRegister);
objectToRegisterId = this.getId(objectToRegister);
if (cacheKey != null) {
log(SessionLog.FINEST, SessionLog.CACHE, "cache_hit", new Object[] { objectToRegister.getClass(), objectToRegisterId });
} else {
log(SessionLog.FINEST, SessionLog.CACHE, "cache_miss", new Object[] { objectToRegister.getClass(), objectToRegisterId });
}
if (cacheKey != null && currentThread.hashCode() != cacheKey.CREATION_THREAD_HASHCODE) {
log(SessionLog.FINEST, SessionLog.CACHE, "cache_thread_info", new Object[] { objectToRegister.getClass(), objectToRegisterId, cacheKey.CREATION_THREAD_ID, cacheKey.CREATION_THREAD_NAME, currentThread.getId(), currentThread.getName() });
}
}
if (project.allowExtendedThreadLogging()) {
if (this.CREATION_THREAD_HASHCODE != currentThread.hashCode()) {
log(SessionLog.SEVERE, SessionLog.THREAD, "unit_of_work_thread_info", new Object[] { this.getName(), this.CREATION_THREAD_ID, this.CREATION_THREAD_NAME, currentThread.getId(), currentThread.getName() });
if (project.allowExtendedThreadLoggingThreadDump()) {
log(SessionLog.SEVERE, SessionLog.THREAD, "unit_of_work_thread_info_thread_dump", new Object[] { this.CREATION_THREAD_ID, this.CREATION_THREAD_NAME, this.creationThreadStackTrace, currentThread.getId(), currentThread.getName(), ConcurrencyUtil.SINGLETON.enrichGenerateThreadDumpForCurrentThread() });
}
}
}
// CR#2272
logDebugMessage(objectToRegister, "register_existing");
Object registeredObject;
try {
startOperationProfile(SessionProfiler.Register);
registeredObject = checkIfAlreadyRegistered(objectToRegister, descriptor);
if (registeredObject == null) {
// Check if object is existing, if it is it must be cloned into the unit of work
// otherwise it is a new object
Object primaryKey = queryPrimaryKey;
if (primaryKey == null) {
primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(objectToRegister, this, true);
}
if (descriptor.shouldLockForClone() || !isFromSharedCache || (descriptor.isProtectedIsolation() && !(objectToRegister instanceof PersistenceEntity))) {
// The primary key may be null for a new object in a nested unit of work (is existing in nested, new in parent).
if (primaryKey != null) {
// Always check the cache first.
registeredObject = getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, objectToRegister, objectToRegister.getClass(), true, descriptor);
}
} else {
// perform a check of the UOW identitymap. This would be done by getFromIdentityMap
// but that method also calls back up to the shared cache in case it is not found locally.
// and we wish to avoid checking the shared cache twice.
CacheKey localCacheKey = getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, objectToRegister.getClass(), descriptor, false);
if (localCacheKey != null) {
registeredObject = localCacheKey.getObject();
}
}
if (registeredObject == null) {
// This is a case where the object is not in the session cache, or the session lookup has been bypassed
// check object for cachekey otherwise
// a new cache-key is used as there is no original to use for locking.
// It read time must be set to avoid it being invalidated.
cacheKey = null;
if (objectToRegister instanceof PersistenceEntity) {
cacheKey = ((PersistenceEntity) objectToRegister)._persistence_getCacheKey();
}
if (cacheKey == null) {
cacheKey = new CacheKey(primaryKey);
cacheKey.setReadTime(System.currentTimeMillis());
// if the cache does not have a version then this must be built from the supplied version
cacheKey.setIsolated(true);
}
registeredObject = cloneAndRegisterObject(objectToRegister, cacheKey, descriptor);
}
}
// fetch group manager control fetch group support
if (descriptor.hasFetchGroupManager()) {
// if the object is already registered in uow, but it's partially fetched (fetch group case)
if (descriptor.getFetchGroupManager().shouldWriteInto(objectToRegister, registeredObject)) {
// there might be cases when reverting/refreshing clone is needed.
descriptor.getFetchGroupManager().writePartialIntoClones(objectToRegister, registeredObject, this.getBackupClone(registeredObject, descriptor), this);
}
}
} finally {
endOperationProfile(SessionProfiler.Register);
}
return registeredObject;
}
use of org.eclipse.persistence.internal.identitymaps.CacheKey in project eclipselink by eclipse-ee4j.
the class IdentityMapAccessor method invalidateObject.
/**
* ADVANCED:
* Set an object to be invalid in the cache.
* @param invalidateCluster if true the invalidation will be broadcast to each server in the cluster.
*/
@Override
public void invalidateObject(Object primaryKey, Class<?> theClass, boolean invalidateCluster) {
if (primaryKey == null) {
return;
}
ClassDescriptor descriptor = getSession().getDescriptor(theClass);
// forward the call to getCacheKeyForObject locally in case subclasses overload
CacheKey key = getCacheKeyForObjectForLock(primaryKey, theClass, descriptor);
if (key != null) {
key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
}
if (invalidateCluster) {
CommandManager rcm = getSession().getCommandManager();
if (rcm != null) {
UnitOfWorkChangeSet changeSet = new UnitOfWorkChangeSet(getSession());
ObjectChangeSet objectChangeSet = new ObjectChangeSet(primaryKey, descriptor, null, changeSet, false);
objectChangeSet.setSynchronizationType(ClassDescriptor.INVALIDATE_CHANGED_OBJECTS);
changeSet.getAllChangeSets().put(objectChangeSet, objectChangeSet);
MergeChangeSetCommand command = new MergeChangeSetCommand();
command.setChangeSet(changeSet);
rcm.propagateCommand(command);
}
}
if (session.getProject().allowExtendedCacheLogging()) {
session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_item_invalidation", new Object[] { theClass, primaryKey, Thread.currentThread().getId(), Thread.currentThread().getName() });
}
}
use of org.eclipse.persistence.internal.identitymaps.CacheKey in project eclipselink by eclipse-ee4j.
the class IdentityMapAccessor method invalidateClass.
/**
* ADVANCED:
* Set all of the objects of a specific class to be invalid in the cache.
* User can set the recurse flag to false if they do not want to invalidate
* all the classes within an inheritance tree and instead invalidate the subtree rooted at myClass.
* @param myClass - the class where we start invalidation
* @param recurseAndInvalidateToParentRoot - default is true where we invalidate
* up the inheritance tree to the root descriptor
*/
@Override
public void invalidateClass(Class<?> myClass, boolean recurseAndInvalidateToParentRoot) {
// forward the call to getIdentityMap locally in case subclasses overload
// will always return the root IdentityMap
IdentityMap identityMap = this.getIdentityMap(myClass);
// bug 227430: Deadlock in IdentityMapAccessor.
// removed synchronization that would result in deadlock
// no need to synchronize as changes to identity map will not aversely affect this code
// bug 275724: IdentityMapAccessor.invalidateClass() should not check ReadLock when invalidating
// do not check readlock
Enumeration<CacheKey> keys = identityMap.keys(false);
while (keys.hasMoreElements()) {
CacheKey key = keys.nextElement();
Object obj = key.getObject();
// 312503: When recurse is false we also invalidate all assignable implementing subclasses of [obj]
if (recurseAndInvalidateToParentRoot || ((obj != null) && (null != myClass) && myClass.isAssignableFrom(obj.getClass()))) {
key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
}
}
invalidateQueryCache(myClass);
if (session.getProject().allowExtendedCacheLogging()) {
session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_class_invalidation", new Object[] { myClass, Thread.currentThread().getId(), Thread.currentThread().getName() });
}
}
Aggregations