Class TransactionalCache<K extends java.io.Serializable,​V>

  • All Implemented Interfaces:
    org.alfresco.repo.cache.LockingCache<K,​V>, org.alfresco.repo.cache.SimpleCache<K,​V>, TransactionListener, org.alfresco.util.transaction.TransactionListener, org.springframework.beans.factory.InitializingBean

    public class TransactionalCache<K extends java.io.Serializable,​V>
    extends java.lang.Object
    implements org.alfresco.repo.cache.LockingCache<K,​V>, TransactionListener, org.springframework.beans.factory.InitializingBean
    A 2-level cache that maintains both a transaction-local cache and wraps a non-transactional (shared) cache.

    It uses the shared SimpleCache for it's per-transaction caches as these can provide automatic size limitations, etc.

    Instances of this class do not require a transaction. They will work directly with the shared cache when no transaction is present. There is virtually no overhead when running out-of-transaction.

    The first phase of the commit ensures that any values written to the cache in the current transaction are not already superseded by values in the shared cache. In this case, the transaction is failed for concurrency reasons and will have to retry. The second phase occurs post-commit. We are sure that the transaction committed correctly, but things may have changed in the cache between the commit and post-commit. If this is the case, then the offending values are merely removed from the shared cache.

    When the cache is cleared, a flag is set on the transaction. The shared cache, instead of being cleared itself, is just ignored for the remainder of the tranasaction. At the end of the transaction, if the flag is set, the shared transaction is cleared before updates are added back to it.

    Because there is a limited amount of space available to the in-transaction caches, when either of these becomes full, the cleared flag is set. This ensures that the shared cache will not have stale data in the event of the transaction-local caches dropping items. It is therefore important to size the transactional caches correctly.

    Author:
    Derek Hulley
    • Constructor Detail

      • TransactionalCache

        public TransactionalCache()
        Public constructor.
    • Method Detail

      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
        See Also:
        setName(String)
      • equals

        public boolean equals​(java.lang.Object obj)
        Overrides:
        equals in class java.lang.Object
      • hashCode

        public int hashCode()
        Overrides:
        hashCode in class java.lang.Object
      • setSharedCache

        public void setSharedCache​(org.alfresco.repo.cache.SimpleCache<java.io.Serializable,​TransactionalCache.ValueHolder<V>> sharedCache)
        Set the shared cache to use during transaction synchronization or when no transaction is present.
        Parameters:
        sharedCache - underlying cache shared by transactions
      • setDisableSharedCache

        public void setDisableSharedCache​(boolean disableSharedCache)
        Set whether values must be written through to the shared cache or not
        Parameters:
        disableSharedCache - true to prevent values from being written to the shared cache
      • setMutable

        public void setMutable​(boolean isMutable)
        Parameters:
        isMutable - true if the data stored in the cache is modifiable
      • setAllowEqualsChecks

        public void setAllowEqualsChecks​(boolean allowEqualsChecks)
        Allow equality checking of values before they are written to the shared cache on commit. This allows some caches to bypass unnecessary cache updates when the values remain unchanged. Typically, this setting should be applied only to mutable caches and only where the values being stored have a fast and reliable equality check.
        Parameters:
        allowEqualsChecks - true if value comparisons can be made between values stored in the transactional cache and those stored in the shared cache
      • setMaxCacheSize

        public void setMaxCacheSize​(int maxCacheSize)
        Set the maximum number of elements to store in the update and remove caches. The maximum number of elements stored in the transaction will be twice the value given.

        The removed list will overflow to disk in order to ensure that deletions are not lost.

        Parameters:
        maxCacheSize - maximum number of items to be held in-transaction
      • setName

        public void setName​(java.lang.String name)
        Set the name that identifies this cache from other instances.
      • setTenantAware

        public void setTenantAware​(boolean isTenantAware)
      • setCacheStats

        public void setCacheStats​(CacheStatistics cacheStats)
      • setCacheStatsEnabled

        public void setCacheStatsEnabled​(boolean cacheStatsEnabled)
      • afterPropertiesSet

        public void afterPropertiesSet()
                                throws java.lang.Exception
        Ensures that all properties have been set
        Specified by:
        afterPropertiesSet in interface org.springframework.beans.factory.InitializingBean
        Throws:
        java.lang.Exception
      • setDisableSharedCacheReadForTransaction

        public void setDisableSharedCacheReadForTransaction​(boolean noSharedCacheRead)
        Transaction-long setting to force all the share cache to be bypassed for the current transaction.

        This setting is like having a null shared cache, but only lasts for the transaction.

        Use this when a read transaction must see consistent and current data i.e. go to the database. While this is active, write operations will also not be committed to the shared cache.

        Parameters:
        noSharedCacheRead - true to avoid reading from the shared cache for the transaction
      • contains

        public boolean contains​(K key)
        Checks the transactional removed and updated caches before checking the shared cache.
        Specified by:
        contains in interface org.alfresco.repo.cache.SimpleCache<K extends java.io.Serializable,​V>
      • getKeys

        public java.util.Collection<K> getKeys()
        The keys returned are a union of the set of keys in the current transaction and those in the backing cache.
        Specified by:
        getKeys in interface org.alfresco.repo.cache.SimpleCache<K extends java.io.Serializable,​V>
      • getSharedCacheValue

        public static <KEY extends java.io.Serializable,​VAL> VAL getSharedCacheValue​(org.alfresco.repo.cache.SimpleCache<KEY,​TransactionalCache.ValueHolder<VAL>> sharedCache,
                                                                                           KEY key,
                                                                                           TransactionStats stats)
        Fetches a value from the shared cache. If values were wrapped, then they will be unwrapped before being returned. If code requires direct access to the wrapper object as well, then this call should not be used.

        If a TransactionStats instance is passed in, then cache access stats are tracked, otherwise - if null is passed in then stats are not tracked.

        Parameters:
        key - the key
        Returns:
        Returns the value or null
      • putSharedCacheValue

        public static <KEY extends java.io.Serializable,​VAL> void putSharedCacheValue​(org.alfresco.repo.cache.SimpleCache<KEY,​TransactionalCache.ValueHolder<VAL>> sharedCache,
                                                                                            KEY key,
                                                                                            VAL value,
                                                                                            TransactionStats stats)
        Values written to the backing cache need proper wrapping and unwrapping
        Parameters:
        sharedCache - the cache to operate on
        key - the key
        value - the value to wrap
        Since:
        4.2.3
      • isValueLocked

        public boolean isValueLocked​(K keyIn)
        Specified by:
        isValueLocked in interface org.alfresco.repo.cache.LockingCache<K extends java.io.Serializable,​V>
      • lockValue

        public void lockValue​(K keyIn)
        Specified by:
        lockValue in interface org.alfresco.repo.cache.LockingCache<K extends java.io.Serializable,​V>
      • unlockValue

        public void unlockValue​(K keyIn)
        Specified by:
        unlockValue in interface org.alfresco.repo.cache.LockingCache<K extends java.io.Serializable,​V>
      • get

        public V get​(K keyIn)
        Checks the per-transaction caches for the object before going to the shared cache. If the thread is not in a transaction, then the shared cache is accessed directly.
        Specified by:
        get in interface org.alfresco.repo.cache.SimpleCache<K extends java.io.Serializable,​V>
      • put

        public void put​(K keyIn,
                        V value)
        Goes direct to the shared cache in the absence of a transaction.

        Where a transaction is present, a cache of updated items is lazily added to the thread and the Object put onto that.

        Specified by:
        put in interface org.alfresco.repo.cache.SimpleCache<K extends java.io.Serializable,​V>
      • remove

        public void remove​(K keyIn)
        Goes direct to the shared cache in the absence of a transaction.

        Where a transaction is present, a cache of removed items is lazily added to the thread and the Object put onto that.

        Specified by:
        remove in interface org.alfresco.repo.cache.SimpleCache<K extends java.io.Serializable,​V>
      • clear

        public void clear()
        Clears out all the caches.
        Specified by:
        clear in interface org.alfresco.repo.cache.SimpleCache<K extends java.io.Serializable,​V>
      • beforeCompletion

        public void beforeCompletion()
        NO-OP
        Specified by:
        beforeCompletion in interface TransactionListener
        Specified by:
        beforeCompletion in interface org.alfresco.util.transaction.TransactionListener
      • beforeCommit

        public void beforeCommit​(boolean readOnly)
        Merge the transactional caches into the shared cache
        Specified by:
        beforeCommit in interface TransactionListener
        Specified by:
        beforeCommit in interface org.alfresco.util.transaction.TransactionListener
        Parameters:
        readOnly - true if the transaction is read-only
      • afterCommit

        public void afterCommit()
        Merge the transactional caches into the shared cache
        Specified by:
        afterCommit in interface TransactionListener
        Specified by:
        afterCommit in interface org.alfresco.util.transaction.TransactionListener
      • afterRollback

        public void afterRollback()
        Transfers cache removals or clears. This allows explicit cache cleanup to be propagated to the shared cache even in the event of rollback - useful if the cause of a problem is the shared cache value.
        Specified by:
        afterRollback in interface TransactionListener
        Specified by:
        afterRollback in interface org.alfresco.util.transaction.TransactionListener