@Override public final void beforeExecutions() throws CacheException { // we need to obtain the lock before any actions are executed, since this may be an inverse="true" // bidirectional association and it is one of the earlier entity actions which actually updates // the database (this action is responsible for second-level cache invalidation only) if ( persister.hasCache() ) { final CacheKey ck = session.generateCacheKey( key, persister.getKeyType(), persister.getRole() ); final SoftLock lock = persister.getCacheAccessStrategy().lockItem( ck, null ); // the old behavior used key as opposed to getKey() afterTransactionProcess = new CacheCleanupProcess( key, persister, lock ); } }
@Override public void doAfterTransactionCompletion(boolean success, SessionImplementor session) throws CacheException { final EntityPersister persister = getPersister(); if ( persister.hasCache() ) { final CacheKey ck = getSession().generateCacheKey( getId(), persister.getIdentifierType(), persister.getRootEntityName() ); if ( success && cacheEntry!=null /*!persister.isCacheInvalidationRequired()*/ ) { final boolean put = cacheAfterUpdate( persister, ck ); if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) { getSession().getFactory().getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() ); } } else { persister.getCacheAccessStrategy().unlockItem( ck, lock ); } } postCommitUpdate( success ); }
@Override public void write(ObjectDataOutput out, CacheKey object) throws IOException { try { Object key = UNSAFE.getObject(object, KEY_OFFSET); Type type = (Type) UNSAFE.getObject(object, TYPE_OFFSET); String entityOrRoleName = (String) UNSAFE.getObject(object, ENTITY_OR_ROLE_NAME_OFFSET); String tenantId = (String) UNSAFE.getObject(object, TENANT_ID_OFFSET); int hashCode = UNSAFE.getInt(object, HASH_CODE_OFFSET); out.writeObject(key); out.writeObject(type); out.writeUTF(entityOrRoleName); out.writeUTF(tenantId); out.writeInt(hashCode); } catch (Exception e) { if (e instanceof IOException) { throw (IOException) e; } throw new IOException(e); } }
@Override public CacheKey read(ObjectDataInput in) throws IOException { try { Object key = in.readObject(); Type type = in.readObject(); String entityOrRoleName = in.readUTF(); String tenantId = in.readUTF(); int hashCode = in.readInt(); CacheKey cacheKey = (CacheKey) UNSAFE.allocateInstance(CacheKey.class); UNSAFE.putObjectVolatile(cacheKey, KEY_OFFSET, key); UNSAFE.putObjectVolatile(cacheKey, TYPE_OFFSET, type); UNSAFE.putObjectVolatile(cacheKey, ENTITY_OR_ROLE_NAME_OFFSET, entityOrRoleName); UNSAFE.putObjectVolatile(cacheKey, TENANT_ID_OFFSET, tenantId); UNSAFE.putIntVolatile(cacheKey, HASH_CODE_OFFSET, hashCode); return cacheKey; } catch (Exception e) { if (e instanceof IOException) { throw (IOException) e; } throw new IOException(e); } }
@Test public void testAutoregistrationOnHibernate4Available() throws Exception { HazelcastInstance hz = Hazelcast.newHazelcastInstance(); HazelcastInstanceImpl impl = (HazelcastInstanceImpl) ORIGINAL.get(hz); SerializationService ss = impl.getSerializationService(); ConcurrentMap<Class, ?> typeMap = (ConcurrentMap<Class, ?>) TYPE_MAP.get(ss); boolean cacheKeySerializerFound = false; boolean cacheEntrySerializerFound = false; for (Class clazz : typeMap.keySet()) { if (clazz == CacheKey.class) { cacheKeySerializerFound = true; } else if (clazz == CacheEntry.class) { cacheEntrySerializerFound = true; } } assertTrue("CacheKey serializer not found", cacheKeySerializerFound); assertTrue("CacheEntry serializer not found", cacheEntrySerializerFound); }
private void removeCache(String cacheRegion, Serializable key) { String cacheName = cacheRegion; if (key instanceof CacheKey) { cacheName = ((CacheKey) key).getEntityOrRoleName(); key = ((CacheKey) key).getKey(); } if (containsCache(cacheRegion, cacheName)) { HydratedCache cache = hydratedCacheContainer.get(cacheRegion + "_" + cacheName); String myKey = cacheRegion + "_" + cacheName + "_" + key; if (cache.containsKey(myKey)) { if (LOG.isInfoEnabled()) { LOG.info("Clearing hydrated cache for cache name: " + cacheRegion + "_" + cacheName + "_" + key); } cache.removeCacheElement(cacheRegion, cacheName, key); } } }
protected void removeCache(String cacheRegion, Serializable key) { String cacheName = cacheRegion; if (key instanceof CacheKey) { cacheName = ((CacheKey) key).getEntityOrRoleName(); key = ((CacheKey) key).getKey(); } String nameKey = cacheRegion + '_' + cacheName + '_' + key; if (cacheMembersByEntity.containsKey(nameKey)) { String[] members = new String[cacheMembersByEntity.get(nameKey).size()]; members = cacheMembersByEntity.get(nameKey).toArray(members); for (String myMember : members) { String itemKey = cacheRegion + '_' + cacheName + '_' + myMember + '_' + key; getHeap().remove(itemKey); } cacheMembersByEntity.remove(nameKey); } }
protected void removeCache(String cacheRegion, Serializable key) { String cacheName = cacheRegion; if (key instanceof CacheKey) { cacheName = ((CacheKey) key).getEntityOrRoleName(); key = ((CacheKey) key).getKey(); } String nameKey = cacheRegion + '_' + cacheName + '_' + key; if (cacheMemberNamesByEntity.containsKey(nameKey)) { String[] members = new String[cacheMemberNamesByEntity.get(nameKey).size()]; members = cacheMemberNamesByEntity.get(nameKey).toArray(members); for (String myMember : members) { String itemKey = cacheRegion + '_' + myMember + '_' + key; removeKeys.add(itemKey); } cacheMemberNamesByEntity.remove(nameKey); } }
public Object initializeLazyProperty(String fieldName, Object entity, SessionImplementor session) throws HibernateException { final Serializable id = session.getContextEntityIdentifier( entity ); final EntityEntry entry = session.getPersistenceContext().getEntry( entity ); if ( entry == null ) { throw new HibernateException( "entity is not associated with the session: " + id ); } if ( LOG.isTraceEnabled() ) { LOG.tracev( "Initializing lazy properties of: {0}, field access: {1}", MessageHelper.infoString( this, id, getFactory() ), fieldName ); } if ( session.getCacheMode().isGetEnabled() && hasCache() ) { final CacheKey cacheKey = session.generateCacheKey( id, getIdentifierType(), getEntityName() ); final Object ce = CacheHelper.fromSharedCache( session, cacheKey, getCacheAccessStrategy() ); if ( ce != null ) { final CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure(ce, factory); if ( !cacheEntry.areLazyPropertiesUnfetched() ) { //note early exit here: return initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry ); } } } return initializeLazyPropertiesFromDatastore( fieldName, entity, session, id, entry ); }
private boolean isCached(EntityKey entityKey, EntityPersister persister) { if ( context.getSession().getCacheMode().isGetEnabled() && persister.hasCache() ) { final CacheKey key = context.getSession().generateCacheKey( entityKey.getIdentifier(), persister.getIdentifierType(), entityKey.getEntityName() ); return CacheHelper.fromSharedCache( context.getSession(), key, persister.getCacheAccessStrategy() ) != null; } return false; }
private boolean isCached(Serializable collectionKey, CollectionPersister persister) { if ( context.getSession().getCacheMode().isGetEnabled() && persister.hasCache() ) { CacheKey cacheKey = context.getSession().generateCacheKey( collectionKey, persister.getKeyType(), persister.getRole() ); return CacheHelper.fromSharedCache( context.getSession(), cacheKey, persister.getCacheAccessStrategy() ) != null; } return false; }
public Map getEntries() { Map map = new HashMap(); Iterator iter = region.toMap().entrySet().iterator(); while (iter.hasNext()) { Map.Entry me = (Map.Entry) iter.next(); map.put(((CacheKey) me.getKey()).getKey(), me.getValue()); } return map; }
private CacheKey buildCacheKey(Serializable identifier, EntityPersister p) { return new CacheKey( identifier, p.getIdentifierType(), p.getRootEntityName(), null, // have to assume non tenancy sessionFactory ); }
@Override public void evictCollection(String role, Serializable ownerIdentifier) { CollectionPersister p = sessionFactory.getCollectionPersister( role ); if ( p.hasCache() ) { if ( LOG.isDebugEnabled() ) { LOG.debugf( "Evicting second-level cache: %s", MessageHelper.collectionInfoString( p, ownerIdentifier, sessionFactory ) ); } CacheKey cacheKey = buildCacheKey( ownerIdentifier, p ); p.getCacheAccessStrategy().evict( cacheKey ); } }
private CacheKey buildCacheKey(Serializable ownerIdentifier, CollectionPersister p) { return new CacheKey( ownerIdentifier, p.getKeyType(), p.getRole(), null, // have to assume non tenancy sessionFactory ); }
@Override public void refresh(String entityName, Object entity, LockMode lockMode) { final EntityPersister persister = this.getEntityPersister( entityName, entity ); final Serializable id = persister.getIdentifier( entity, this ); if ( LOG.isTraceEnabled() ) { LOG.tracev( "Refreshing transient {0}", MessageHelper.infoString( persister, id, this.getFactory() ) ); } // TODO : can this ever happen??? // EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); // if ( source.getPersistenceContext().getEntry( key ) != null ) { // throw new PersistentObjectException( // "attempted to refresh transient instance when persistent " + // "instance was already associated with the Session: " + // MessageHelper.infoString( persister, id, source.getFactory() ) // ); // } if ( persister.hasCache() ) { final CacheKey ck = generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() ); persister.getCacheAccessStrategy().evict( ck ); } String previousFetchProfile = this.getFetchProfile(); Object result = null; try { this.setFetchProfile( "refresh" ); result = persister.load( id, entity, lockMode, this ); } finally { this.setFetchProfile( previousFetchProfile ); } UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() ); }
/** * If the class to be loaded has been configured with a cache, then lock * given id in that cache and then perform the load. * * @param event The initiating load request event * @param persister The persister corresponding to the entity to be loaded * @param keyToLoad The key of the entity to be loaded * @param options The defined load options * @param source The originating session * * @return The loaded entity * * @throws HibernateException */ protected Object lockAndLoad( final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options, final SessionImplementor source) { SoftLock lock = null; final CacheKey ck; if ( persister.hasCache() ) { ck = source.generateCacheKey( event.getEntityId(), persister.getIdentifierType(), persister.getRootEntityName() ); lock = persister.getCacheAccessStrategy().lockItem( ck, null ); } else { ck = null; } Object entity; try { entity = load( event, persister, keyToLoad, options ); } finally { if ( persister.hasCache() ) { persister.getCacheAccessStrategy().unlockItem( ck, lock ); } } return event.getSession().getPersistenceContext().proxyFor( persister, keyToLoad, entity ); }
@Override public void doAfterTransactionCompletion(boolean success, SessionImplementor session) throws HibernateException { if ( getPersister().hasCache() ) { final CacheKey ck = getSession().generateCacheKey( getId(), getPersister().getIdentifierType(), getPersister().getRootEntityName() ); getPersister().getCacheAccessStrategy().unlockItem( ck, lock ); } postCommitDelete( success ); }
private boolean cacheInsert(EntityPersister persister, CacheKey ck) { try { getSession().getEventListenerManager().cachePutStart(); return persister.getCacheAccessStrategy().insert( ck, cacheEntry, version ); } finally { getSession().getEventListenerManager().cachePutEnd(); } }
@Override public void doAfterTransactionCompletion(boolean success, SessionImplementor session) throws HibernateException { final EntityPersister persister = getPersister(); if ( success && isCachePutEnabled( persister, getSession() ) ) { final CacheKey ck = getSession().generateCacheKey( getId(), persister.getIdentifierType(), persister.getRootEntityName() ); final boolean put = cacheAfterInsert( persister, ck ); if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) { getSession().getFactory().getStatisticsImplementor() .secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() ); } } postCommitInsert( success ); }
private boolean cacheAfterInsert(EntityPersister persister, CacheKey ck) { try { getSession().getEventListenerManager().cachePutStart(); return persister.getCacheAccessStrategy().afterInsert( ck, cacheEntry, version ); } finally { getSession().getEventListenerManager().cachePutEnd(); } }
protected final void evict() throws CacheException { if ( persister.hasCache() ) { final CacheKey ck = session.generateCacheKey( key, persister.getKeyType(), persister.getRole() ); persister.getCacheAccessStrategy().remove( ck ); } }
@Override public void doAfterTransactionCompletion(boolean success, SessionImplementor session) { final CacheKey ck = session.generateCacheKey( key, persister.getKeyType(), persister.getRole() ); persister.getCacheAccessStrategy().unlockItem( ck, lock ); }
private boolean cacheUpdate(EntityPersister persister, Object previousVersion, CacheKey ck) { try { getSession().getEventListenerManager().cachePutStart(); return persister.getCacheAccessStrategy().update( ck, cacheEntry, nextVersion, previousVersion ); } finally { getSession().getEventListenerManager().cachePutEnd(); } }
private boolean cacheAfterUpdate(EntityPersister persister, CacheKey ck) { try { getSession().getEventListenerManager().cachePutStart(); return persister.getCacheAccessStrategy().afterUpdate( ck, cacheEntry, nextVersion, previousVersion, lock ); } finally { getSession().getEventListenerManager().cachePutEnd(); } }
@Override public Object transform(Object key) { if (key instanceof CacheKey) { CacheKey cacheKey = (CacheKey)key; return new HibernateKeyWrapper( cacheKey.getKey(), cacheKey.getEntityOrRoleName(), cacheKey.getTenantId() ); } return key; }
private CacheKey cacheKey(Serializable identifier, EntityPersister p) { return new CacheKey( identifier, p.getIdentifierType(), p.getRootEntityName(), null, (SessionFactoryImplementor) getSessionFactory() ); }
@Override public CacheKey generateCacheKey(Serializable id, Type type, String entityOrRoleName) { return sessionImplementor.generateCacheKey( id, type, entityOrRoleName ); }
public static Serializable fromSharedCache( SessionImplementor session, CacheKey cacheKey, RegionAccessStrategy cacheAccessStrategy) { return fromSharedCache( session, (Object) cacheKey, cacheAccessStrategy ); }
@Override public CacheKey generateCacheKey(Serializable id, Type type, String entityOrRoleName) { return new CacheKey( id, type, entityOrRoleName, getTenantIdentifier(), getFactory() ); }
private void evict(Serializable id, CollectionPersister collectionPersister, EventSource session) { LOG.debug( "Evict CollectionRegion " + collectionPersister.getRole() + " for id " + id ); CacheKey key = session.generateCacheKey( id, collectionPersister.getKeyType(), collectionPersister.getRole() ); collectionPersister.getCacheAccessStrategy().evict( key ); }
/** * Performs a pessimistic lock upgrade on a given entity, if needed. * * @param object The entity for which to upgrade the lock. * @param entry The entity's EntityEntry instance. * @param lockOptions contains the requested lock mode. * @param source The session which is the source of the event being processed. */ protected void upgradeLock(Object object, EntityEntry entry, LockOptions lockOptions, EventSource source) { LockMode requestedLockMode = lockOptions.getLockMode(); if ( requestedLockMode.greaterThan( entry.getLockMode() ) ) { // The user requested a "greater" (i.e. more restrictive) form of // pessimistic lock if ( entry.getStatus() != Status.MANAGED ) { throw new ObjectDeletedException( "attempted to lock a deleted instance", entry.getId(), entry.getPersister().getEntityName() ); } final EntityPersister persister = entry.getPersister(); if ( log.isTraceEnabled() ) { log.tracev( "Locking {0} in mode: {1}", MessageHelper.infoString( persister, entry.getId(), source.getFactory() ), requestedLockMode ); } final SoftLock lock; final CacheKey ck; if ( persister.hasCache() ) { ck = source.generateCacheKey( entry.getId(), persister.getIdentifierType(), persister.getRootEntityName() ); lock = persister.getCacheAccessStrategy().lockItem( ck, entry.getVersion() ); } else { ck = null; lock = null; } try { if ( persister.isVersioned() && requestedLockMode == LockMode.FORCE ) { // todo : should we check the current isolation mode explicitly? Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), source ); entry.forceLocked( object, nextVersion ); } else { persister.lock( entry.getId(), entry.getVersion(), object, lockOptions, source ); } entry.setLockMode(requestedLockMode); } finally { // the database now holds a lock + the object is flushed from the cache, // so release the soft lock if ( persister.hasCache() ) { persister.getCacheAccessStrategy().unlockItem( ck, lock ); } } } }
/** * Try to initialize a collection from the cache * * @param id The id of the collection of initialize * @param persister The collection persister * @param collection The collection to initialize * @param source The originating session * * @return true if we were able to initialize the collection from the cache; * false otherwise. */ private boolean initializeCollectionFromCache( Serializable id, CollectionPersister persister, PersistentCollection collection, SessionImplementor source) { if ( !source.getLoadQueryInfluencers().getEnabledFilters().isEmpty() && persister.isAffectedByEnabledFilters( source ) ) { LOG.trace( "Disregarding cached version (if any) of collection due to enabled filters" ); return false; } final boolean useCache = persister.hasCache() && source.getCacheMode().isGetEnabled(); if ( !useCache ) { return false; } final SessionFactoryImplementor factory = source.getFactory(); final CacheKey ck = source.generateCacheKey( id, persister.getKeyType(), persister.getRole() ); final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() ); if ( factory.getStatistics().isStatisticsEnabled() ) { if ( ce == null ) { factory.getStatisticsImplementor() .secondLevelCacheMiss( persister.getCacheAccessStrategy().getRegion().getName() ); } else { factory.getStatisticsImplementor() .secondLevelCacheHit( persister.getCacheAccessStrategy().getRegion().getName() ); } } if ( ce == null ) { return false; } CollectionCacheEntry cacheEntry = (CollectionCacheEntry) persister.getCacheEntryStructure().destructure( ce, factory ); final PersistenceContext persistenceContext = source.getPersistenceContext(); cacheEntry.assemble( collection, persister, persistenceContext.getCollectionOwner( id, persister ) ); persistenceContext.getCollectionEntry( collection ).postInitialize( collection ); // addInitializedCollection(collection, persister, id); return true; }
/** * Attempts to load the entity from the second-level cache. * * @param event The load event * @param persister The persister for the entity being requested for load * @param options The load options. * * @return The entity from the second-level cache, or null. */ protected Object loadFromSecondLevelCache( final LoadEvent event, final EntityPersister persister, final LoadEventListener.LoadType options) { final SessionImplementor source = event.getSession(); final boolean useCache = persister.hasCache() && source.getCacheMode().isGetEnabled() && event.getLockMode().lessThan( LockMode.READ ); if ( !useCache ) { // we can't use cache here return null; } final SessionFactoryImplementor factory = source.getFactory(); final CacheKey ck = source.generateCacheKey( event.getEntityId(), persister.getIdentifierType(), persister.getRootEntityName() ); final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() ); if ( factory.getStatistics().isStatisticsEnabled() ) { if ( ce == null ) { factory.getStatisticsImplementor().secondLevelCacheMiss( persister.getCacheAccessStrategy().getRegion().getName() ); } else { factory.getStatisticsImplementor().secondLevelCacheHit( persister.getCacheAccessStrategy().getRegion().getName() ); } } if ( ce == null ) { // nothing was found in cache return null; } CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory ); Object entity = convertCacheEntryToEntity( entry, event.getEntityId(), persister, event ); if ( !persister.isInstance( entity ) ) { throw new WrongClassException( "loaded object was of wrong class " + entity.getClass(), event.getEntityId(), persister.getEntityName() ); } return entity; }