Class PutFromLoadValidator

java.lang.Object
org.infinispan.hibernate.cache.commons.access.PutFromLoadValidator

public class PutFromLoadValidator extends Object
Encapsulates logic to allow a InvalidationCacheAccessDelegate to determine whether a InvalidationCacheAccessDelegate.putFromLoad(Object, Object, Object, long, Object, boolean) call should be allowed to update the cache. A putFromLoad has the potential to store stale data, since the data may have been removed from the database and the cache between the time when the data was read from the database and the actual call to putFromLoad.

The expected usage of this class by a thread that read the cache and did not find data is:

  1. Call registerPendingPut(Object, Object, long)
  2. Read the database
  3. Call acquirePutFromLoadLock(Object, Object, long)
  4. if above returns null, the thread should not cache the data; only if above returns instance of AcquiredLock, put data in the cache and...
  5. then call releasePutFromLoadLock(Object, Lock)

The expected usage by a thread that is taking an action such that any pending putFromLoad may have stale data and should not cache it is to either call

After transaction commit (when the DB is updated) endInvalidatingKey(Object, Object) should be called in order to allow further attempts to cache entry.

This class also supports the concept of "naked puts", which are calls to acquirePutFromLoadLock(Object, Object, long) without a preceding registerPendingPut(Object, Object, long). Besides not acquiring lock in registerPendingPut(Object, Object, long) this can happen when collection elements are loaded after the collection has not been found in the cache, where the elements don't have their own table but can be listed as 'select ... from Element where collection_id = ...'. Naked puts are handled according to txTimestamp obtained by calling RegionFactory.nextTimestamp() before the transaction is started. The timestamp is compared with timestamp of last invalidation end time and the write to the cache is denied if it is lower or equal.

Version:
$Revision: $
Author:
Brian Stansberry
  • Constructor Details

    • PutFromLoadValidator

      public PutFromLoadValidator(org.infinispan.AdvancedCache cache, TimeSource timeSource, org.infinispan.configuration.cache.Configuration pendingPutsConfiguration)
      Creates a new put from load validator instance.
      Parameters:
      cache - Cache instance on which to store pending put information.
      pendingPutsConfiguration -
    • PutFromLoadValidator

      public PutFromLoadValidator(org.infinispan.AdvancedCache cache, TimeSource timeSource, org.infinispan.manager.EmbeddedCacheManager cacheManager, org.infinispan.configuration.cache.Configuration pendingPutsConfiguration)
      Creates a new put from load validator instance.
      Parameters:
      cache - Cache instance on which to store pending put information.
      timeSource -
      cacheManager - where to find a cache to store pending put information
      pendingPutsConfiguration -
  • Method Details

    • addToCache

      public static void addToCache(org.infinispan.AdvancedCache cache, PutFromLoadValidator validator)
      Besides the call from constructor, this should be called only from tests when mocking the validator.
    • removeFromCache

      public static PutFromLoadValidator removeFromCache(org.infinispan.AdvancedCache cache)
      This methods should be called only from tests; it removes existing validator from the cache structures in order to replace it with new one.
      Parameters:
      cache -
    • destroy

      public void destroy()
    • acquirePutFromLoadLock

      public PutFromLoadValidator.Lock acquirePutFromLoadLock(Object session, Object key, long txTimestamp)
      Acquire a lock giving the calling thread the right to put data in the cache for the given key.

      NOTE: A call to this method that returns true should always be matched with a call to releasePutFromLoadLock(Object, Lock).

      Parameters:
      session -
      key - the key
      txTimestamp -
      Returns:
      AcquiredLock if the lock is acquired and the cache put can proceed; null if the data should not be cached
    • releasePutFromLoadLock

      public void releasePutFromLoadLock(Object key, PutFromLoadValidator.Lock lock)
      Releases the lock previously obtained by a call to acquirePutFromLoadLock(Object, Object, long).
      Parameters:
      key - the key
    • beginInvalidatingRegion

      public boolean beginInvalidatingRegion()
      Invalidates all previously registered pending puts ensuring a subsequent call to acquirePutFromLoadLock(Object, Object, long) will return false.

      This method will block until any concurrent thread that has acquired the putFromLoad lock for the any key has released the lock. This allows the caller to be certain the putFromLoad will not execute after this method returns, possibly caching stale data.

      Returns:
      true if the invalidation was successful; false if a problem occurred (which the caller should treat as an exception condition)
    • endInvalidatingRegion

      public void endInvalidatingRegion()
      Called when the region invalidation is finished.
    • registerPendingPut

      public void registerPendingPut(Object session, Object key, long txTimestamp)
      Notifies this validator that it is expected that a database read followed by a subsequent acquirePutFromLoadLock(Object, Object, long) call will occur. The intent is this method would be called following a cache miss wherein it is expected that a database read plus cache put will occur. Calling this method allows the validator to treat the subsequent acquirePutFromLoadLock as if the database read occurred when this method was invoked. This allows the validator to compare the timestamp of this call against the timestamp of subsequent removal notifications.
      Parameters:
      session -
      key - key that will be used for subsequent cache put
      txTimestamp -
    • beginInvalidatingKey

      public boolean beginInvalidatingKey(Object lockOwner, Object key)
      Invalidates any previously registered pending puts and disables further registrations ensuring a subsequent call to acquirePutFromLoadLock(Object, Object, long) will return false.

      This method will block until any concurrent thread that has acquired the putFromLoad lock for the given key has released the lock. This allows the caller to be certain the putFromLoad will not execute after this method returns, possibly caching stale data.

      After this transaction completes, endInvalidatingKey(Object, Object) needs to be called }
      Parameters:
      key - key identifying data whose pending puts should be invalidated
      Returns:
      true if the invalidation was successful; false if a problem occurred (which the caller should treat as an exception condition)
    • beginInvalidatingWithPFER

      public boolean beginInvalidatingWithPFER(Object lockOwner, Object key, Object valueForPFER)
    • endInvalidatingKey

      public boolean endInvalidatingKey(Object lockOwner, Object key)
    • endInvalidatingKey

      public boolean endInvalidatingKey(Object lockOwner, Object key, boolean doPFER)
      Called after the transaction completes, allowing caching of entries. It is possible that this method is called without previous invocation of beginInvalidatingKey(Object, Object), then it should be a no-op.
      Parameters:
      lockOwner - owner of the invalidation - transaction or thread
      key -
      Returns:
    • removePendingPutsCache

      public void removePendingPutsCache()