@Override protected void commitContextEntry( CacheEntry entry, InvocationContext ctx, FlagAffectedCommand command, Metadata metadata, Flag stateTransferFlag, boolean l1Invalidation) { if (ctx.isInTxScope() && stateTransferFlag == null) { Metadata commitMetadata; // If user provided version, use it, otherwise generate/increment accordingly ClusteredRepeatableReadEntry clusterMvccEntry = (ClusteredRepeatableReadEntry) entry; EntryVersion existingVersion = clusterMvccEntry.getMetadata().version(); EntryVersion newVersion; if (existingVersion == null) { newVersion = versionGenerator.generateNew(); } else { newVersion = versionGenerator.increment((IncrementableEntryVersion) existingVersion); } if (metadata == null) commitMetadata = new EmbeddedMetadata.Builder().version(newVersion).build(); else commitMetadata = metadata.builder().version(newVersion).build(); cdl.commitEntry(entry, commitMetadata, command, ctx, null, l1Invalidation); } else { // This could be a state transfer call! cdl.commitEntry(entry, entry.getMetadata(), command, ctx, stateTransferFlag, l1Invalidation); } }
private void raiseEventForInitialTransfer(UUID identifier, CacheEntry entry, boolean clustered) { EventImpl preEvent; if (clustered) { // In clustered mode we only send post event preEvent = null; } else { preEvent = EventImpl.createEvent(cache, CACHE_ENTRY_CREATED); preEvent.setKey(entry.getKey()); preEvent.setPre(true); } EventImpl postEvent = EventImpl.createEvent(cache, CACHE_ENTRY_CREATED); postEvent.setKey(entry.getKey()); postEvent.setValue(entry.getValue()); postEvent.setMetadata(entry.getMetadata()); postEvent.setPre(false); for (CacheEntryListenerInvocation<K, V> invocation : cacheEntryCreatedListeners) { // Now notify all our methods of the creates if (invocation.getIdentifier() == identifier) { if (preEvent != null) { // Non clustered notifications are done twice invocation.invokeNoChecks(preEvent, true, true); } invocation.invokeNoChecks(postEvent, true, true); } } }
private void configureEvent( EventImpl<K, V> e, K key, V value, boolean pre, InvocationContext ctx, FlagAffectedCommand command, V previousValue, Metadata previousMetadata) { boolean originLocal = ctx.isOriginLocal(); e.setOriginLocal(originLocal); e.setValue(pre ? previousValue : value); e.setPre(pre); e.setOldValue(previousValue); e.setOldMetadata(previousMetadata); CacheEntry entry = ctx.lookupEntry(key); if (entry != null) { e.setMetadata(entry.getMetadata()); } Set<Flag> flags; if (command != null && (flags = command.getFlags()) != null && flags.contains(Flag.COMMAND_RETRY)) { e.setCommandRetried(true); } e.setKey(key); setTx(ctx, e); }
protected Object performRemove(CacheEntry e, InvocationContext ctx) { final Object removedValue = e.getValue(); notify(ctx, removedValue, e.getMetadata(), true); e.setRemoved(true); e.setValid(false); e.setChanged(true); if (valueMatcher != ValueMatcher.MATCH_EXPECTED_OR_NEW) { return isConditional() ? true : removedValue; } else { // Return the expected value when retrying return isConditional() ? true : value; } }
@Override protected void commitSingleEntry( CacheEntry entry, Metadata metadata, FlagAffectedCommand command, InvocationContext ctx, Flag trackFlag, boolean l1Invalidation) { // Don't allow the CH to change (and state transfer to invalidate entries) // between the ownership check and the commit stateTransferLock.acquireSharedTopologyLock(); try { boolean doCommit = true; // ignore locality for removals, even if skipOwnershipCheck is not true boolean skipOwnershipCheck = command != null && command.hasFlag(Flag.SKIP_OWNERSHIP_CHECK); boolean isForeignOwned = !skipOwnershipCheck && !localNodeIsOwner(entry.getKey()); if (isForeignOwned && !entry.isRemoved()) { if (configuration.clustering().l1().enabled()) { // transform for L1 long lifespan; if (metadata != null) { lifespan = metadata.lifespan(); } else { lifespan = entry.getLifespan(); } if (lifespan < 0 || lifespan > configuration.clustering().l1().lifespan()) { Metadata.Builder builder; if (metadata != null) { builder = metadata.builder(); } else { builder = entry.getMetadata().builder(); } metadata = builder.lifespan(configuration.clustering().l1().lifespan()).build(); } } else { doCommit = false; } } boolean created = false; boolean removed = false; boolean expired = false; if (!isForeignOwned) { created = entry.isCreated(); removed = entry.isRemoved(); if (removed && entry instanceof MVCCEntry) { expired = ((MVCCEntry) entry).isExpired(); } } if (doCommit) { InternalCacheEntry previousEntry = dataContainer.peek(entry.getKey()); Object previousValue = null; Metadata previousMetadata = null; if (previousEntry != null) { previousValue = previousEntry.getValue(); previousMetadata = previousEntry.getMetadata(); } commitManager.commit(entry, metadata, trackFlag, l1Invalidation); if (!isForeignOwned) { notifyCommitEntry( created, removed, expired, entry, ctx, command, previousValue, previousMetadata); } } else entry.rollback(); } finally { stateTransferLock.releaseSharedTopologyLock(); } }
protected void notifyCommitEntry( boolean created, boolean removed, boolean expired, CacheEntry entry, InvocationContext ctx, FlagAffectedCommand command, Object previousValue, Metadata previousMetadata) { boolean isWriteOnly = (command instanceof WriteCommand) && ((WriteCommand) command).isWriteOnly(); if (removed) { if (command instanceof RemoveCommand) { ((RemoveCommand) command).notify(ctx, previousValue, previousMetadata, false); } else { if (expired) { notifier.notifyCacheEntryExpired(entry.getKey(), previousValue, previousMetadata, ctx); } else { notifier.notifyCacheEntryRemoved( entry.getKey(), previousValue, previousMetadata, false, ctx, command); } // A write-only command only writes and so can't 100% guarantee // to be able to retrieve previous value when removed, so only // send remove event when the command is read-write. if (!isWriteOnly) functionalNotifier.notifyOnRemove( EntryViews.readOnly(entry.getKey(), previousValue, previousMetadata)); functionalNotifier.notifyOnWrite(() -> EntryViews.noValue(entry.getKey())); } } else { // Notify entry event after container has been updated if (created) { notifier.notifyCacheEntryCreated( entry.getKey(), entry.getValue(), entry.getMetadata(), false, ctx, command); // A write-only command only writes and so can't 100% guarantee // that an entry has been created, so only send create event // when the command is read-write. if (!isWriteOnly) functionalNotifier.notifyOnCreate(EntryViews.readOnly(entry)); functionalNotifier.notifyOnWrite(() -> EntryViews.readOnly(entry)); } else { notifier.notifyCacheEntryModified( entry.getKey(), entry.getValue(), entry.getMetadata(), previousValue, previousMetadata, false, ctx, command); // A write-only command only writes and so can't 100% guarantee // that an entry has been created, so only send modify when the // command is read-write. if (!isWriteOnly) functionalNotifier.notifyOnModify( EntryViews.readOnly(entry.getKey(), previousValue, previousMetadata), EntryViews.readOnly(entry)); functionalNotifier.notifyOnWrite(() -> EntryViews.readOnly(entry)); } } }