Search in sources :

Example 1 with CacheKey

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);
}
Also used : IdentityMapAccessor(org.eclipse.persistence.sessions.IdentityMapAccessor) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Example 2 with CacheKey

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;
    }
}
Also used : ConcurrencyManager(org.eclipse.persistence.internal.helper.ConcurrencyManager) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Example 3 with CacheKey

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;
}
Also used : PersistenceEntity(org.eclipse.persistence.internal.descriptors.PersistenceEntity) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey) Session(org.eclipse.persistence.sessions.Session)

Example 4 with CacheKey

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() });
    }
}
Also used : CommandManager(org.eclipse.persistence.sessions.coordination.CommandManager) MergeChangeSetCommand(org.eclipse.persistence.sessions.coordination.MergeChangeSetCommand) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Example 5 with CacheKey

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() });
    }
}
Also used : IdentityMap(org.eclipse.persistence.internal.identitymaps.IdentityMap) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Aggregations

CacheKey (org.eclipse.persistence.internal.identitymaps.CacheKey)54 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)21 AbstractSession (org.eclipse.persistence.internal.sessions.AbstractSession)9 InvalidObject (org.eclipse.persistence.internal.helper.InvalidObject)7 UnitOfWorkImpl (org.eclipse.persistence.internal.sessions.UnitOfWorkImpl)7 CacheId (org.eclipse.persistence.internal.identitymaps.CacheId)5 FetchGroupManager (org.eclipse.persistence.descriptors.FetchGroupManager)4 ObjectBuilder (org.eclipse.persistence.internal.descriptors.ObjectBuilder)4 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)4 DatabaseMapping (org.eclipse.persistence.mappings.DatabaseMapping)4 Vector (java.util.Vector)3 FetchGroup (org.eclipse.persistence.queries.FetchGroup)3 ArrayList (java.util.ArrayList)2 Iterator (java.util.Iterator)2 CacheIndex (org.eclipse.persistence.descriptors.CacheIndex)2 ObjectChangePolicy (org.eclipse.persistence.descriptors.changetracking.ObjectChangePolicy)2 QueryException (org.eclipse.persistence.exceptions.QueryException)2 Expression (org.eclipse.persistence.expressions.Expression)2 PersistenceEntity (org.eclipse.persistence.internal.descriptors.PersistenceEntity)2 QueryKeyExpression (org.eclipse.persistence.internal.expressions.QueryKeyExpression)2