public class EntryOperation extends MutatingKeyBasedMapOperation implements BackupAwareOperation, BlockingOperation
### Overview
Implementation of the the Offloadable contract for the EntryProcessor execution on a single key.
Allows off-loading the processing unit implementing this interface to the specified or default Executor. Currently supported in:
IMap.executeOnKey(Object, EntryProcessor) IMap.submitToKey(Object, EntryProcessor) IMap.submitToKey(Object, EntryProcessor, ExecutionCallback)
### Offloadable (for reading & writing)
If the EntryProcessor implements the Offloadable interface the processing will be offloaded to the given ExecutorService allowing unblocking the partition-thread. The key will be locked for the time-span of the processing in order to not generate a write-conflict.
If the EntryProcessor implements Offloadable the invocation scenario looks as follows: - EntryOperation fetches the entry and locks the given key on partition-thread - Then the processing is offloaded to the given executor - When the processing finishes if there is a change to the entry, a EntryOffloadableSetUnlockOperation is spawned which sets the new value and unlocks the given key on partition-thread if there is no change to the entry, a UnlockOperation is spawned, which just unlocks the kiven key on partition thread
There will not be a conflict on a write due to the pessimistic locking of the key. The threading looks as follows:
1. partition-thread (fetch & lock) 2. execution-thread (process) 3. partition-thread (set & unlock, or just unlock if no changes)
### Offloadable (for reading only)
If the EntryProcessor implements the Offloadable and ReadOnly interfaces the processing will be offloaded to the givenExecutorService allowing unblocking the partition-thread. Since the EntryProcessor is not supposed to do any changes to the Entry the key will NOT be locked for the time-span of the processing.
If the EntryProcessor implements Offloadable and ReadOnly the invocation scenario looks as follows: - EntryOperation fetches the entry and DOES NOT lock the given key on partition-thread - Then the processing is offloaded to the given executor - When the processing finishes if there is a change to the entry -> exception is thrown if there is no change to the entry -> the result is returned to the user from the executor-thread.
In the read-only case the threading looks as follows:
1. partition-thread (fetch) 2. execution-thread (process)
### Primary partition - main actors
- EntryOperation - EntryOffloadableSetUnlockOperation
### Backup partitions
Offloading will not be applied to backup partitions. It is possible to initialize the EntryBackupProcessor with some input provided by the EntryProcessor in the EntryProcessor.getBackupProcessor() method. The input allows providing context to the EntryBackupProcessor - for example the "delta" so that the EntryBackupProcessor does not have to calculate the "delta" but it may just apply it.
### Locking
The locking takes place only locally. If a partition locked by an off-loaded task gets migrated, the lock will not be migrated. In this situation the off-loaded task "relying" on the lock will fail on the unlock operation, since it will notice that there is no such a lock and therefore the processing for the key will get retried. The reason behind is that the off-loadable backup-processing does not use locking there cannot be any transfer of off-loadable locks from the primary replica to backup replicas.
GOTCHA: This operation LOADS missing keys from map-store, in contrast with PartitionWideEntryOperation.
dataKey, dataValue, threadId, ttl
createRecordStoreOnDemand, mapContainer, mapEventPublisher, mapService, mapServiceContext, recordStore
name
GENERIC_PARTITION_ID
Constructor and Description |
---|
EntryOperation() |
EntryOperation(String name,
Data dataKey,
EntryProcessor entryProcessor) |
Modifier and Type | Method and Description |
---|---|
int |
getAsyncBackupCount()
The asynchronous backup count.
|
Operation |
getBackupOperation()
Creates the
BackupOperation responsible for making the backup. |
int |
getId()
Returns type identifier for this class.
|
Object |
getResponse() |
int |
getSyncBackupCount()
The synchronous backup count.
|
WaitNotifyKey |
getWaitKey() |
void |
innerBeforeRun() |
void |
onExecutionFailure(Throwable e)
Called when an Exception/Error is thrown during operation execution.
|
void |
onWaitExpire() |
protected void |
readInternal(ObjectDataInput in) |
boolean |
returnsResponse() |
void |
run() |
void |
runOffloaded() |
boolean |
shouldBackup()
Checks if a backup needs to be made.
|
boolean |
shouldWait() |
protected void |
writeInternal(ObjectDataOutput out) |
getKey, getThreadId, getTtl, getValue, setThreadId
beforeRun, evict, getFactoryId, getServiceName, getServiceNamespace, invalidateAllKeysInNearCaches, invalidateNearCache, invalidateNearCache, isPostProcessing, setMapContainer, setMapService
getName, toString
afterRun, executedLocally, getCallerAddress, getCallerUuid, getCallId, getCallTimeout, getConnection, getInvocationTime, getLogger, getNodeEngine, getOperationResponseHandler, getPartitionId, getReplicaIndex, getService, getWaitTimeout, isUrgent, logError, onInvocationException, onSetCallId, readData, sendResponse, setCallerUuid, setNodeEngine, setOperationResponseHandler, setPartitionId, setReplicaIndex, setService, setServiceName, setValidateTarget, setWaitTimeout, toString, validatesTarget, writeData
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
getPartitionId
getWaitTimeout
readData, writeData
public EntryOperation()
public EntryOperation(String name, Data dataKey, EntryProcessor entryProcessor)
public void innerBeforeRun() throws Exception
innerBeforeRun
in class MapOperation
Exception
public void runOffloaded()
public void onExecutionFailure(Throwable e)
Operation
onExecutionFailure
in class Operation
e
- Exception/Error thrown during operation executionpublic boolean returnsResponse()
returnsResponse
in class Operation
public WaitNotifyKey getWaitKey()
getWaitKey
in interface BlockingOperation
public boolean shouldWait()
shouldWait
in interface BlockingOperation
public void onWaitExpire()
onWaitExpire
in interface BlockingOperation
public Object getResponse()
getResponse
in class Operation
public Operation getBackupOperation()
BackupAwareOperation
BackupOperation
responsible for making the backup.getBackupOperation
in interface BackupAwareOperation
BackupOperation
responsible for making the backup.public boolean shouldBackup()
BackupAwareOperation
shouldBackup
in interface BackupAwareOperation
public int getAsyncBackupCount()
BackupAwareOperation
getAsyncBackupCount
in interface BackupAwareOperation
public int getSyncBackupCount()
BackupAwareOperation
getSyncBackupCount
in interface BackupAwareOperation
protected void readInternal(ObjectDataInput in) throws IOException
readInternal
in class MutatingKeyBasedMapOperation
IOException
protected void writeInternal(ObjectDataOutput out) throws IOException
writeInternal
in class MutatingKeyBasedMapOperation
IOException
public int getId()
IdentifiedDataSerializable
getId
in interface IdentifiedDataSerializable
Copyright © 2017 Hazelcast, Inc.. All Rights Reserved.