Interface EntryFactory
-
- All Known Implementing Classes:
EntryFactoryImpl
public interface EntryFactory
A factory for constructingMVCCEntry
instances for use in theInvocationContext
. Implementations of this interface would typically wrap an internalCacheEntry
with anMVCCEntry
.Expected wrapping patterns
EntryWrappingInterceptor
checksCacheTopology.getReadConsistentHash()
and if this node is an owner of the key, it loads the entry fromDataContainer
. On the way back through interceptor stack, the entry is committed fromEntryWrappingInterceptor
throughClusteringDependentLogic
which checksCacheTopology.getWriteConsistentHash()
.Entry being wrapped is a prerequisite for the command to run and therefore commit the entry, but it's not up to
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)
If the entry should be read locally but it's not found in DC, the entry will be wrapped by
EntryWrappingInterceptor
(either asNullCacheEntry
for reads or other appropriate type for writes). Such entry returnsfalse
onCacheEntry.skipLookup()
as it's value is unsure (subsequent interceptors can retrieve the new value from the cache store or remote node and callwrapExternalEntry(org.infinispan.context.InvocationContext, java.lang.Object, org.infinispan.container.entries.CacheEntry, boolean, boolean)
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
EntryWrappingInterceptor
callsCacheEntry.setSkipLookup(boolean)
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
EntryWrappingInterceptor
. When repeatable reads are in use,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
- 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
OutdatedTopologyException
is thrown) - backup owner and
VisitableCommand.loadType()
isOWNER
: 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 the origin, fetch the entry from remote node
- If this is not the origin, the command must have different topologyId and we retry
- primary owner: that should not happen as command.topologyId is outdated (the topology is checked
before executing the command and
- 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.
- Since:
- 4.0
- Author:
- Manik Surtani (manik@jboss.org), Galder ZamarreƱo, Mircea.Markus@jboss.com
-
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Modifier and Type Method Description static CompletionStage<Void>
expirationCheckDelay(CompletionStage<Void> currentStage, CompletableFuture<Void> initialStage)
Use to synchronize multiple#wrapEntryForReading(InvocationContext, Object, int, boolean, boolean, CompletionStage)
orwrapEntryForWriting(InvocationContext, Object, int, boolean, boolean, CompletionStage)
calls.void
wrapEntryForExpired(InvocationContext ctx, Object key, int segment)
Insert an entry that exists in the data container into the context, even if it is expired Doesn't do anything if the key was already wrappedCompletionStage<Void>
wrapEntryForReading(InvocationContext ctx, Object key, int segment, boolean isOwner, CompletionStage<Void> previousStage)
Wraps an entry for reading.CompletionStage<Void>
wrapEntryForWriting(InvocationContext ctx, Object key, int segment, boolean isOwner, boolean isRead, CompletionStage<Void> previousStage)
Insert an entry that exists in the data container into the context.void
wrapExternalEntry(InvocationContext ctx, Object key, CacheEntry externalEntry, boolean isRead, boolean isWrite)
Insert an external entry (e.g.
-
-
-
Method Detail
-
expirationCheckDelay
static CompletionStage<Void> expirationCheckDelay(CompletionStage<Void> currentStage, CompletableFuture<Void> initialStage)
Use to synchronize multiple#wrapEntryForReading(InvocationContext, Object, int, boolean, boolean, CompletionStage)
orwrapEntryForWriting(InvocationContext, Object, int, boolean, boolean, CompletionStage)
calls.The basic pattern is:
CompletableFuture<Void> initialStage = new CompletableFuture<>(); CompletionStage<Void> currentStage = initialStage; for (Object key : ...) { currentStage = entryFactory.wrapEntryForWriting(..., currentStage); } return asyncInvokeNext(ctx, command, expirationCheckDelay(currentStage, initialStage));
The effect
expirationCheckDelay(currentStage, initialStage)
call is equivalent to completing theinitialStage
and returningcurrentStage
, but it optimizes the common case wherecurrentStage
andinitialStage
are the same.
-
wrapEntryForReading
CompletionStage<Void> wrapEntryForReading(InvocationContext ctx, Object key, int segment, boolean isOwner, CompletionStage<Void> previousStage)
Wraps an entry for reading. Usually this is just a rawCacheEntry
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.- Parameters:
ctx
- current invocation contextkey
- key to look up and wrapsegment
- segment for the keyisOwner
- true if this node is current owner in readCH (or we ignore CH)previousStage
- if wrapping can't be performed synchronously, only access the invocation context from another thread after this stage is complete- Returns:
- stage that when complete the value should be in the context
-
wrapEntryForWriting
CompletionStage<Void> wrapEntryForWriting(InvocationContext ctx, Object key, int segment, boolean isOwner, boolean isRead, CompletionStage<Void> previousStage)
Insert an entry that exists in the data container into the context. Doesn't do anything if the key was already wrapped.The returned stage will always be complete if isOwner is false.
- Parameters:
ctx
- current invocation contextkey
- key to look up and wrapsegment
- segment for the keyisOwner
- true if this node is current owner in readCH (or we ignore CH)isRead
- true if this operation is expected to read the value of the entrypreviousStage
- if wrapping can't be performed synchronously, only access the invocation context from another thread after this stage is complete- Since:
- 8.1
-
wrapEntryForExpired
void wrapEntryForExpired(InvocationContext ctx, Object key, int segment)
Insert an entry that exists in the data container into the context, even if it is expired Doesn't do anything if the key was already wrapped- Parameters:
ctx
- current invocation contextkey
- key to look up and wrapsegment
- segment for the key
-
wrapExternalEntry
void wrapExternalEntry(InvocationContext ctx, Object key, CacheEntry externalEntry, boolean isRead, boolean isWrite)
Insert an external entry (e.g. loaded from a cache loader or from a remote node) into the context.- Parameters:
ctx
- current invocation contextkey
- key to look up and wrapexternalEntry
- the value to be inserted into contextisRead
- true if this operation is expected to read the value of the entryisWrite
- if this is executed within a write command- Since:
- 8.1
-
-