@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 SoftLock tryLock(final Object key, final Object version) { ExpiryMarker marker; String markerId = nextMarkerId(); while (true) { final Expirable original = cache.get(key); long timeout = nextTimestamp() + CacheEnvironment.getDefaultCacheTimeoutInMillis(); if (original == null) { marker = new ExpiryMarker(version, timeout, markerId); if (cache.putIfAbsent(key, marker) == null) { break; } } else { marker = original.markForExpiration(timeout, markerId); if (cache.replace(key, original, marker)) { break; } } } return new MarkerWrapper(marker); }
public SoftLock tryLock(final Object key, final Object version) { ExpiryMarker marker; String markerId = nextMarkerId(); while (true) { final Expirable original = cache.get(key); long timeout = nextTimestamp() + CacheEnvironment.getDefaultCacheTimeoutInMillis(); if (original == null) { marker = new ExpiryMarker(version, timeout, markerId); if (cache.putIfAbsent(key, marker) == null) { break; } } else { marker = original.markForExpiration(timeout, markerId); if (cache.replace(key, original, marker)) { break; } } } return new MarkerWrapper(marker); }
public void unlock(final Object key, SoftLock lock) { while (true) { final Expirable original = cache.get(key); if (original != null) { if (!(lock instanceof MarkerWrapper)) { break; } final ExpiryMarker unwrappedMarker = ((MarkerWrapper) lock).getMarker(); if (original.matches(unwrappedMarker)) { final Expirable revised = ((ExpiryMarker) original).expire(nextTimestamp()); if (cache.replace(key, original, revised)) { break; } } else if (original.getValue() != null) { if (cache.remove(key, original)) { break; } } else { break; } } else { break; } } maybeNotifyTopic(key, null, null); }
/** * Called when we have finished the attempted update/delete (which may or * may not have been successful), after transaction completion. This method * is used by "asynchronous" concurrency strategies. * * @param key The item key * @param lock The lock previously obtained from {@link #lockItem} * @throws org.hibernate.cache.CacheException Propogated from underlying * {@link org.hibernate.cache.spi.Region} */ @Override public void unlockItem(Object key, SoftLock lock) throws CacheException { try { _region.getCache().lock(key); Lockable lockable = (Lockable) _region.getCache().get(key); if (isUnlockable(lock, lockable)) { ((Lock) lockable).unlock(_region.nextTimestamp()); _region.getCache().put(key, lockable); } else { handleLockExpiry(key); } } finally { _region.getCache().unlock(key); } }
/** * {@inheritDoc} * <p> * Updates will only succeed if this entry was locked by this transaction and exclusively this transaction for the * duration of this transaction. It is important to also note that updates will fail if the soft-lock expired during * the course of this transaction. */ @Override public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException { //what should we do with previousVersion here? region.getCache().lock(key); try { final Lockable item = (Lockable) region().get(key); if (item != null && item.isUnlockable(lock)) { final Lock lockItem = (Lock) item; if (lockItem.wasLockedConcurrently()) { decrementLock(key, lockItem); return false; } else { region().put(key, new Item(value, currentVersion, region.nextTimestamp())); return true; } } else { handleLockExpiry(key, item); return false; } } finally { region.getCache().unlock(key); } }
/** * {@inheritDoc} * <p> * Updates will only succeed if this entry was locked by this transaction and exclusively this transaction for the * duration of this transaction. It is important to also note that updates will fail if the soft-lock expired during * the course of this transaction. */ @Override public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) throws CacheException { //what should we do with previousVersion here? region.getCache().lock(key); try { final Lockable item = (Lockable) region().get(key); if (item != null && item.isUnlockable(lock)) { final Lock lockItem = (Lock) item; if (lockItem.wasLockedConcurrently()) { decrementLock(key, lockItem); return false; } else { region().put(key, new Item(value, null, region.nextTimestamp())); return true; } } else { handleLockExpiry(key, item); return false; } } finally { region.getCache().unlock(key); } }
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException { if(region.writeLock(key)) { try { Item item = (Item) region.get(key); if(item == null || item.isWriteable(currentVersion, versionCompator)) { region.put(key, new Item(currentVersion, region.nextTimestamp(), value)); return true; } else { return false; } } finally { region.releaseLock(key); } } return false; }
/** * Soft-unlock a cache item. */ public final void unlockItem(Object key, SoftLock lock) throws CacheException { try { log.debug("unlocking key[{}] in region[{}]", key, getInternalRegion().getName()); writeLock.lock(); Lockable item = (Lockable) getInternalRegion().get(key); if ((item != null) && item.isUnlockable(lock)) { decrementLock(key, (Lock) item); } else { handleLockExpiry(key, item); } } finally { writeLock.unlock(); } }
@Override public boolean afterUpdate(Object key, Object value, SoftLock lock) throws CacheException { try { writeLock.lock(); Lockable item = (Lockable) region.get( key ); if ( item != null && item.isUnlockable( lock ) ) { Lock lockItem = (Lock) item; if ( lockItem.wasLockedConcurrently() ) { decrementLock( key, lockItem ); return false; } else { region.put( key, new Item( value, null, region.nextTimestamp() ) ); return true; } } else { handleLockExpiry( key, item ); return false; } } finally { writeLock.unlock(); } }
/** * 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 unlock(final Object key, final SoftLock lock) { while (true) { final Expirable original = cache.get(key); if (original != null) { if (!(lock instanceof MarkerWrapper)) { break; } final ExpiryMarker unwrappedMarker = ((MarkerWrapper) lock).getMarker(); if (original.matches(unwrappedMarker)) { final Expirable revised = ((ExpiryMarker) original).expire(nextTimestamp()); if (cache.replace(key, original, revised)) { break; } } else if (original.getValue() != null) { if (cache.remove(key, original)) { break; } } else { break; } } else { break; } } maybeNotifyTopic(key, null, null); }
/** * {@inheritDoc} * <p/> * Called after <code>com.hazelcast.ReadWriteAccessDelegate.lockItem()</code> */ @Override public boolean afterUpdate(final Object key, final Object value, final Object currentVersion, final Object previousVersion, final SoftLock lock) throws CacheException { try { return cache.update(key, value, currentVersion, lock); } catch (HazelcastException e) { if (log.isFinestEnabled()) { log.finest("Could not update Cache[" + hazelcastRegion.getName() + "]: " + e.getMessage()); } return false; } }
/** * @throws UnsupportedOperationException */ @Override public boolean afterUpdate(final Object key, final Object value, final Object currentVersion, final Object previousVersion, final SoftLock lock) throws CacheException { throw new UnsupportedOperationException("Cannot update an item in a read-only cache: " + getHazelcastRegion().getName()); }
/** * {@inheritDoc} * <p/> * Should be a no-op since this cache is read-only */ @Override public void unlockItem(final Object key, final SoftLock lock) throws CacheException { /* * To err on the safe side though, follow ReadOnlyEhcacheEntityRegionAccessStrategy which nevertheless evicts * the key. */ evict(key); }
@Override public boolean update(final Object key, final Object newValue, final Object newVersion, final SoftLock lock) { if (lock instanceof MarkerWrapper) { final ExpiryMarker unwrappedMarker = ((MarkerWrapper) lock).getMarker(); return (Boolean) map.executeOnKey(key, new UpdateEntryProcessor(unwrappedMarker, newValue, newVersion, nextMarkerId(), nextTimestamp(hazelcastInstance))); } else { return false; } }
@Override public SoftLock tryLock(final Object key, final Object version) { long timeout = nextTimestamp(hazelcastInstance) + lockTimeout; final ExpiryMarker marker = (ExpiryMarker) map.executeOnKey(key, new LockEntryProcessor(nextMarkerId(), timeout, version)); return new MarkerWrapper(marker); }
@Override public void unlock(final Object key, final SoftLock lock) { if (lock instanceof MarkerWrapper) { final ExpiryMarker unwrappedMarker = ((MarkerWrapper) lock).getMarker(); map.executeOnKey(key, new UnlockEntryProcessor(unwrappedMarker, nextMarkerId(), nextTimestamp(hazelcastInstance))); } }
/** * {@inheritDoc} * <p> * Called after <code>com.hazelcast.ReadWriteAccessDelegate.lockItem()</code> * </p> */ @Override public boolean afterUpdate(final Object key, final Object value, final Object currentVersion, final Object previousVersion, final SoftLock lock) throws CacheException { try { return cache.update(key, value, currentVersion, lock); } catch (HazelcastException e) { if (log.isFinestEnabled()) { log.finest("Could not update Cache[" + hazelcastRegion.getName() + "]: " + e.getMessage()); } return false; } }
/** * @throws UnsupportedOperationException Always thrown as we cannot update an item in a read-only cache */ @Override public boolean afterUpdate(final Object key, final Object value, final Object currentVersion, final Object previousVersion, final SoftLock lock) throws CacheException { throw new UnsupportedOperationException("Cannot update an item in a read-only cache: " + getHazelcastRegion().getName()); }
/** * {@inheritDoc} * <p> * Should be a no-op since this cache is read-only * </p> */ @Override public void unlockItem(final Object key, final SoftLock lock) throws CacheException { /* * To err on the safe side though, follow ReadOnlyEhcacheEntityRegionAccessStrategy which nevertheless evicts * the key. */ evict(key); }
public boolean update(final Object key, final Object newValue, final Object newVersion, final SoftLock lock) { if (lock instanceof MarkerWrapper) { final ExpiryMarker unwrappedMarker = ((MarkerWrapper) lock).getMarker(); return (Boolean) map.executeOnKey(key, new UpdateEntryProcessor(unwrappedMarker, newValue, newVersion, nextMarkerId(), nextTimestamp(hazelcastInstance))); } else { return false; } }
public void unlock(final Object key, SoftLock lock) { if (lock instanceof MarkerWrapper) { final ExpiryMarker unwrappedMarker = ((MarkerWrapper) lock).getMarker(); map.executeOnKey(key, new UnlockEntryProcessor(unwrappedMarker, nextMarkerId(), nextTimestamp(hazelcastInstance))); } }
/** * Soft-unlock a cache item. */ public final void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { region.getCache().lock(key); try { final Lockable item = (Lockable) region().get(key); if ((item != null) && item.isUnlockable(lock)) { decrementLock(key, (Lock) item); } else { handleLockExpiry(key, item); } } finally { region.getCache().unlock(key); } }
@Override public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException { try { writeLock.lock(); Lockable item = (Lockable) region.get( key ); if ( item != null && item.isUnlockable( lock ) ) { Lock lockItem = (Lock) item; if ( lockItem.wasLockedConcurrently() ) { decrementLock( key, lockItem ); return false; } else { region.put( key, new Item( value, currentVersion, region.nextTimestamp() ) ); return true; } } else { handleLockExpiry( key, item ); return false; } } finally { writeLock.unlock(); } }
/** * Throws UnsupportedOperationException since this cache is read-only * * @throws UnsupportedOperationException always */ @Override public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException { LOG.invalidEditOfReadOnlyItem( key ); throw new UnsupportedOperationException( "Can't write to a readonly object" ); }
/** * need evict the key, after update. * * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy */ @Override public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException { log.debug("region access strategy nonstrict-read-write entity afterUpdate() {} {}", getInternalRegion().getCacheNamespace(), key); getInternalRegion().evict(key); return false; }
/** * need evict the key, after update. * * @see org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy */ @Override public boolean afterUpdate(Object key, Object value, SoftLock lock) throws CacheException { log.debug("region access strategy nonstrict-read-write naturalId afterUpdate() {} {}", getInternalRegion().getCacheNamespace(), key); getInternalRegion().evict(key); return false; }
/** * 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 ); } } } }
private CacheCleanupProcess(Serializable key, CollectionPersister persister, SoftLock lock) { this.key = key; this.persister = persister; this.lock = lock; }
@Override public boolean update(final Object key, final Object newValue, final Object newVersion, final SoftLock softLock) { boolean updated = false; while (true) { Expirable original = cache.get(key); Expirable revised; long timestamp = nextTimestamp(); if (original == null) { // The entry must have expired. it should be safe to update revised = new Value(newVersion, timestamp, newValue); updated = true; if (cache.putIfAbsent(key, revised) == null) { break; } } else { if (softLock instanceof MarkerWrapper) { final ExpiryMarker unwrappedMarker = ((MarkerWrapper) softLock).getMarker(); if (original.matches(unwrappedMarker)) { // The lock matches final ExpiryMarker marker = (ExpiryMarker) original; if (marker.isConcurrent()) { revised = marker.expire(timestamp); updated = false; } else { revised = new Value(newVersion, timestamp, newValue); updated = true; } if (cache.replace(key, original, revised)) { break; } } else if (original.getValue() == null) { // It's marked for expiration, leave it as is updated = false; break; } else { // It's a value. Instead of removing it, expire it to prevent stale from in progress // transactions being put in the cache revised = new ExpiryMarker(newVersion, timestamp, nextMarkerId()).expire(timestamp); updated = false; if (cache.replace(key, original, revised)) { break; } } } else { break; } } } maybeNotifyTopic(key, newValue, newVersion); return updated; }
@Override public SoftLock lockItem(final Object key, final Object version) throws CacheException { return cache.tryLock(key, version); }
@Override public void unlockItem(final Object key, final SoftLock lock) throws CacheException { cache.unlock(key, lock); }
@Override public SoftLock lockItem(final Object key, final Object version) throws CacheException { return null; }
/** * @throws UnsupportedOperationException */ @Override public SoftLock lockRegion() throws CacheException { throw new UnsupportedOperationException("Attempting to lock a read-only cache region: " + getHazelcastRegion().getName()); }
/** * This will issue a log warning stating that an attempt was made to unlock a read-only cache region. */ @Override public void unlockRegion(final SoftLock lock) throws CacheException { log.warning("Attempting to unlock a read-only cache region"); }
@Override public boolean afterUpdate(final Object key, final Object value, final Object currentVersion, final Object previousVersion, final SoftLock lock) throws CacheException { unlockItem(key, lock); return false; }
@Override public void unlockItem(final Object key, final SoftLock lock) throws CacheException { remove(key); }
/** * NO-OP */ @Override public SoftLock lockRegion() throws CacheException { return null; }