All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.container.EntryFactory Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
package org.infinispan.container;

import org.infinispan.commands.VisitableCommand;
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.container.entries.NullCacheEntry;
import org.infinispan.context.InvocationContext;
import org.infinispan.interceptors.impl.EntryWrappingInterceptor;
import org.infinispan.interceptors.locking.ClusteringDependentLogic;
import org.infinispan.topology.CacheTopology;

/**
 * A factory for constructing {@link org.infinispan.container.entries.MVCCEntry} instances for use in the {@link org.infinispan.context.InvocationContext}.
 * Implementations of this interface would typically wrap an internal {@link org.infinispan.container.entries.CacheEntry}
 * with an {@link org.infinispan.container.entries.MVCCEntry}.
 *
 * 

Expected wrapping patterns

* * {@link EntryWrappingInterceptor} checks {@link CacheTopology#getReadConsistentHash()} and if this node is an owner * of the key, it loads the entry from {@link DataContainer}. On the way back through interceptor stack, the entry is * committed from {@link EntryWrappingInterceptor} through {@link ClusteringDependentLogic} which checks * {@link CacheTopology#getWriteConsistentHash()}. *

* Entry being wrapped is a prerequisite for the command to run and therefore commit the entry, but it's not up to * {@link EntryWrappingInterceptor} to make sure the entry is always wrapped - all the interceptors below can expect * is (key is in readCH) => (entry is wrapped). The entry may be wrapped by EWI or other interceptors later, * e.g. (but not limited to) when: *

    *
  • entry is in L1 *
  • entry is fetched from remote node *
  • the cache is transactional and command should be executed on origin (but it does not need previous value * - it is then wrapped as null entry) *
* It is the distribution interceptor that enforces that (entry is read/written by command) => (entry is wrapped), * by fetching the remote value, limiting the set of keys in given command (narrowing it) or not executing the command * locally at all. *

* If the entry should be read locally but it's not found in DC, the entry will be wrapped by * {@link EntryWrappingInterceptor} (either as {@link NullCacheEntry} for reads or other appropriate type for writes). * Such entry returns false on {@link CacheEntry#skipLookup()} as it's value is unsure (subsequent * interceptors can retrieve the new value from the cache store or remote node and call * {@link EntryFactory#wrapExternalEntry} to update the context. *

* With repeatable reads, the value that is context must not be overwritten by value out of the transaction * (only commands in this transaction can change the context entry. That's why {@link EntryWrappingInterceptor} * calls {@link CacheEntry#setSkipLookup} from the return handler for every command. *

* When a command is retried and repeatable reads are not used, the entry is removed from the context completely * and wrapped again by {@link EntryWrappingInterceptor}. When repeatable reads are in use, * {@link org.infinispan.container.entries.RepeatableReadEntry} entry keeps the value before the command was executed * and the context is reset to this value. *

* This summarizes expected behaviour of interceptors loading from persistence layer: *

    *
  • entry == null: don't load the entry because this node is not a read owner *
  • entry.skipLookup == false: attempt to load the entry *
  • entry.skipLookup == true: don't load the entry because it was already published *
* Distribution interceptor should behave as follows: *
    *
  • entry == null: If this is a write command, check writeCH and if this node is *
      *
    • primary owner: that should not happen as command.topologyId is outdated (the topology is checked * before executing the command and {@link org.infinispan.statetransfer.OutdatedTopologyException} is thrown) *
    • backup owner and {@link VisitableCommand#loadType()} is {@link org.infinispan.commands.VisitableCommand.LoadType#OWNER OWNER}: * retrieve the value from remote node *
    • backup owner that does not need previous value: wrap null *
    • non-owner: don't execute the command (or narrow the set of keys in it) *
    * If this is a read-only command: *
      *
    • If this is the origin, fetch the entry from remote node *
    • If this is not the origin, the command must have different topologyId and we retry *
    *
  • entry != null: don't do any remote retrieval because the value is known *
*

* In local mode, the data can be always read and written, so there is no risk that a command won't have the entry * wrapped. * * @author Manik Surtani ([email protected]) * @author Galder Zamarreño * @author [email protected] * @since 4.0 */ public interface EntryFactory { /** * Wraps an entry for reading. Usually this is just a raw {@link CacheEntry} but certain combinations of isolation * levels and the presence of an ongoing JTA transaction may force this to be a proper, wrapped MVCCEntry. The entry * is also typically placed in the invocation context. * * @param ctx current invocation context * @param key key to look up and wrap * @param isOwner true if this node is current owner in readCH (or we ignore CH) */ void wrapEntryForReading(InvocationContext ctx, Object key, boolean isOwner); /** * Insert an entry that exists in the data container into the context. * * Doesn't do anything if the key was already wrapped. * * @param ctx current invocation context * @param key key to look up and wrap * @param isOwner true if this node is current owner in readCH (or we ignore CH) * @param isRead true if this operation is expected to read the value of the entry * @since 8.1 */ void wrapEntryForWriting(InvocationContext ctx, Object key, boolean isOwner, boolean isRead); /** * Insert an external entry (e.g. loaded from a cache loader or from a remote node) into the context. * * @param ctx current invocation context * @param key key to look up and wrap * @param externalEntry the value to be inserted into context * @param isRead true if this operation is expected to read the value of the entry * @param isWrite if this is executed within a write command * @since 8.1 */ void wrapExternalEntry(InvocationContext ctx, Object key, CacheEntry externalEntry, boolean isRead, boolean isWrite); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy