Class SharedBoundedContainer<K,V>

Type Parameters:
K - The key type
V - The value type
All Implemented Interfaces:
Iterable<InternalCacheEntry<K,V>>, Consumer<Iterable<InternalCacheEntry<K,V>>>, DataContainer<K,V>, EvictionListener<K,V>, InternalDataContainer<K,V>

public class SharedBoundedContainer<K,V> extends DefaultSegmentedDataContainer<K,V> implements EvictionListener<K,V>, Consumer<Iterable<InternalCacheEntry<K,V>>>
A shared container where all of the entries are stored in the caffeine map, but they are indexed in the map segment container of the DefaultsegmentedDataContainer. The onEntryChosenForEviction(boolean, Object, InternalCacheEntry) must be invoked externally whenever an entry is evicted from the provided caffeineMap.

To guarantee consistency any write operations must be done while in the lock for the corresponding key of the provided caffeineMap. This means any writes to any of the maps per segment must only be done while in this secured region.

This class is implemented so that every single key read and write operation are constant time and iteration is O(N) where N is the size of the entries in the individual container and not the shared. However, due to this the clear() and clear(IntSet) methods are not O(1) as in many other implementations but rather are O(N). Please see them respectively for more details.

  • Constructor Details

  • Method Details

    • start

      public void start()
      Overrides:
      start in class DefaultSegmentedDataContainer<K,V>
    • getMapForSegment

      public PeekableTouchableMap<K,V> getMapForSegment(int segment)
      Overrides:
      getMapForSegment in class DefaultSegmentedDataContainer<K,V>
    • computeEntryRemoved

      protected void computeEntryRemoved(int segment, K key, InternalCacheEntry<K,V> value)
      Description copied from class: AbstractInternalDataContainer
      This method is invoked every time an entry is removed inside a compute block
      Overrides:
      computeEntryRemoved in class AbstractInternalDataContainer<K,V>
      Parameters:
      segment - the segment for the key
      key - key passed to compute method
      value - the old value
    • computeEntryWritten

      protected void computeEntryWritten(int segment, K key, InternalCacheEntry<K,V> value)
      Description copied from class: AbstractInternalDataContainer
      This method is invoked every time an entry is written inside a compute block
      Overrides:
      computeEntryWritten in class AbstractInternalDataContainer<K,V>
      Parameters:
      segment - the segment for the key
      key - key passed to compute method
      value - the new value
    • putEntryInMap

      protected void putEntryInMap(PeekableTouchableMap<K,V> map, int segment, K key, InternalCacheEntry<K,V> ice)
      Overrides:
      putEntryInMap in class AbstractInternalDataContainer<K,V>
    • removeEntryInMap

      protected InternalCacheEntry<K,V> removeEntryInMap(PeekableTouchableMap<K,V> map, int segment, Object key)
      Overrides:
      removeEntryInMap in class AbstractInternalDataContainer<K,V>
    • clear

      public void clear()
      Removes all entries that map only to this container and its map entries. To not clear the underlying caffeineMap completely we must do additional work, see clear(IntSet) for implementation and performance details.
      Specified by:
      clear in interface DataContainer<K,V>
      Overrides:
      clear in class DefaultSegmentedDataContainer<K,V>
    • clear

      public void clear(org.infinispan.commons.util.IntSet segments)
      Clears only the entries that map to the given segments. Note that to ensure the shared caffeineMap is not adversely affected we have to iterate over all of the entries in the map segment storage and then individually remove those values from the caffeineMap. This way we still have consistency as the caffeineMap lock is acquired before removing from the map segment.

      This iteration means that this clear operation performs with O(N) time complexity as we must only remove the entries we control from the caffeineMap and our segment maps.

      Due to clearing a map or its segments should be done much less frequently than other operations in this implementation, these two clear methods have increased time complexity to allow all other operations to have their best respective time complexity implementations.

      Specified by:
      clear in interface InternalDataContainer<K,V>
      Overrides:
      clear in class AbstractInternalDataContainer<K,V>
      Parameters:
      segments - segments of entries to remove
    • accept

      public void accept(Iterable<InternalCacheEntry<K,V>> internalCacheEntries)
      Specified by:
      accept in interface Consumer<K>
    • removeSegments

      public void removeSegments(org.infinispan.commons.util.IntSet segments)
      Description copied from interface: InternalDataContainer
      Removes and un-associates the given segments. This will notify any listeners registered via InternalDataContainer.addRemovalListener(Consumer) of entries that were removed due to no longer being associated with this container. There is no guarantee if the consumer is invoked once or multiple times for a given group of segments and could be in any order.

      When this method is invoked an implementation is free to remove any entries that don't map to segments currently associated with this container. Note that entries that were removed due to their segments never being associated with this container do not notify listeners registered via InternalDataContainer.addRemovalListener(Consumer).

      Specified by:
      removeSegments in interface InternalDataContainer<K,V>
      Overrides:
      removeSegments in class DefaultSegmentedDataContainer<K,V>
      Parameters:
      segments - segments that should no longer be associated with this container
    • peek

      public InternalCacheEntry<K,V> peek(Object k)
      Description copied from interface: DataContainer
      Retrieves a cache entry. This method does not update or reorder any of the internal constructs. I.e., expiration does not happen, and in the case of the LRU container, the entry is not moved to the end of the chain.
      Specified by:
      peek in interface DataContainer<K,V>
      Overrides:
      peek in class AbstractInternalDataContainer<K,V>
      Parameters:
      k - key under which entry is stored
      Returns:
      entry, if it exists, or null if not
    • containsKey

      public boolean containsKey(Object k)
      Description copied from interface: DataContainer
      Tests whether an entry exists in the container
      Specified by:
      containsKey in interface DataContainer<K,V>
      Overrides:
      containsKey in class AbstractInternalDataContainer<K,V>
      Parameters:
      k - key to test
      Returns:
      true if entry exists and has not expired; false otherwise
    • cleanUp

      public void cleanUp()
      Description copied from interface: InternalDataContainer
      Method used to cleanup any pending data, such as evictions
      Specified by:
      cleanUp in interface InternalDataContainer<K,V>
    • capacity

      public long capacity()
      Description copied from interface: DataContainer
      Returns the capacity of the underlying container. This is only supported if the container is bounded. An UnsupportedOperationException is thrown otherwise.
      Specified by:
      capacity in interface DataContainer<K,V>
      Returns:
      the capacity of a bounded container
    • resize

      public void resize(long newSize)
      Description copied from interface: DataContainer
      Resizes the capacity of the underlying container. This is only supported if the container is bounded. An UnsupportedOperationException is thrown otherwise.
      Specified by:
      resize in interface DataContainer<K,V>
      Parameters:
      newSize - the new size
    • evictionSize

      public long evictionSize()
      Description copied from interface: DataContainer
      Returns how large the eviction size is currently. This is only supported if the container is bounded. An UnsupportedOperationException is thrown otherwise. This value will always be lower than the value returned from DataContainer.capacity()
      Specified by:
      evictionSize in interface DataContainer<K,V>
      Returns:
      how large the counted eviction is
    • onEntryChosenForEviction

      public void onEntryChosenForEviction(boolean pre, K key, InternalCacheEntry<K,V> value)
      Description copied from interface: EvictionListener
      Method invoked every time an entry is evicted from the cache along with its key. Note that when the pre value is true the entry is still in the cache and the lock is held for this entry. When invoked with pre being false is after the fact without the lock held. If any exception is thrown during this invocation it is not deterministic if it will stop the operation and may only be logged.
      Specified by:
      onEntryChosenForEviction in interface EvictionListener<K,V>
      Parameters:
      pre - Whether this is just before the eviction completes or not.
      key - The key tied the removed entry
      value - The entry that is removed due to eviction