org.infinispan.interceptors.CacheWriterInterceptor Maven / Gradle / Ivy
package org.infinispan.interceptors;
import org.infinispan.atomic.impl.AtomicHashMap;
import org.infinispan.commands.AbstractVisitor;
import org.infinispan.commands.FlagAffectedCommand;
import org.infinispan.commands.tx.CommitCommand;
import org.infinispan.commands.tx.PrepareCommand;
import org.infinispan.commands.write.*;
import org.infinispan.commons.marshall.StreamingMarshaller;
import org.infinispan.configuration.cache.PersistenceConfiguration;
import org.infinispan.container.InternalEntryFactory;
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.container.entries.DeltaAwareCacheEntry;
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.container.entries.InternalCacheValue;
import org.infinispan.container.versioning.EntryVersion;
import org.infinispan.container.versioning.EntryVersionsMap;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.impl.TxInvocationContext;
import org.infinispan.factories.annotations.ComponentName;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.Start;
import org.infinispan.interceptors.base.JmxStatsCommandInterceptor;
import org.infinispan.jmx.annotations.MBean;
import org.infinispan.jmx.annotations.ManagedAttribute;
import org.infinispan.jmx.annotations.ManagedOperation;
import org.infinispan.jmx.annotations.MeasurementType;
import org.infinispan.persistence.manager.PersistenceManager;
import org.infinispan.marshall.core.MarshalledEntryImpl;
import org.infinispan.metadata.EmbeddedMetadata;
import org.infinispan.metadata.Metadata;
import org.infinispan.transaction.xa.GlobalTransaction;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import javax.transaction.InvalidTransactionException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import static org.infinispan.factories.KnownComponentNames.CACHE_MARSHALLER;
import static org.infinispan.persistence.PersistenceUtil.internalMetadata;
import static org.infinispan.persistence.manager.PersistenceManager.AccessMode.BOTH;
import static org.infinispan.persistence.manager.PersistenceManager.AccessMode.PRIVATE;
/**
* Writes modifications back to the store on the way out: stores modifications back through the CacheLoader, either
* after each method call (no TXs), or at TX commit.
*
* Only used for LOCAL and INVALIDATION caches.
*
* @author Bela Ban
* @author Dan Berindei
* @author Mircea Markus
* @since 4.0
*/
@MBean(objectName = "CacheStore", description = "Component that handles storing of entries to a CacheStore from memory.")
public class CacheWriterInterceptor extends JmxStatsCommandInterceptor {
PersistenceConfiguration loaderConfig = null;
final AtomicLong cacheStores = new AtomicLong(0);
protected PersistenceManager persistenceManager;
private InternalEntryFactory entryFactory;
private TransactionManager transactionManager;
private StreamingMarshaller marshaller;
protected volatile boolean enabled = true;
private static final Log log = LogFactory.getLog(CacheWriterInterceptor.class);
@Override
protected Log getLog() {
return log;
}
@Inject
protected void init(PersistenceManager pm, InternalEntryFactory entryFactory, TransactionManager transactionManager,
@ComponentName(CACHE_MARSHALLER) StreamingMarshaller marshaller) {
this.persistenceManager = pm;
this.entryFactory = entryFactory;
this.transactionManager = transactionManager;
this.marshaller = marshaller;
}
@Start(priority = 15)
protected void start() {
this.setStatisticsEnabled(cacheConfiguration.jmxStatistics().enabled());
loaderConfig = cacheConfiguration.persistence();
}
@Override
public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command) throws Throwable {
if (isStoreEnabled())
commitCommand(ctx);
return invokeNextInterceptor(ctx, command);
}
@Override
public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable {
if (isStoreEnabled() && command.isOnePhaseCommit()) {
commitCommand(ctx);
}
return invokeNextInterceptor(ctx, command);
}
protected void commitCommand(TxInvocationContext ctx) throws Throwable {
if (!ctx.getCacheTransaction().getAllModifications().isEmpty()) {
// this is a commit call.
GlobalTransaction tx = ctx.getGlobalTransaction();
if (getLog().isTraceEnabled()) getLog().tracef("Calling loader.commit() for transaction %s", tx);
Transaction xaTx = null;
try {
xaTx = suspendRunningTx(ctx);
store(ctx);
} finally {
resumeRunningTx(xaTx);
}
} else {
if (getLog().isTraceEnabled()) getLog().trace("Commit called with no modifications; ignoring.");
}
}
private void resumeRunningTx(Transaction xaTx) throws InvalidTransactionException, SystemException {
if (transactionManager != null && xaTx != null) {
transactionManager.resume(xaTx);
}
}
private Transaction suspendRunningTx(TxInvocationContext ctx) throws SystemException {
Transaction xaTx = null;
if (transactionManager != null) {
xaTx = transactionManager.suspend();
if (xaTx != null && !ctx.isOriginLocal())
throw new IllegalStateException("It is only possible to be in the context of an JRA transaction in the local node.");
}
return xaTx;
}
@Override
public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
Object retval = invokeNextInterceptor(ctx, command);
if (!isStoreEnabled(command) || ctx.isInTxScope() || !command.isSuccessful()) return retval;
if (!isProperWriter(ctx, command, command.getKey())) return retval;
Object key = command.getKey();
boolean resp = persistenceManager.deleteFromAllStores(key, BOTH);
if (getLog().isTraceEnabled()) getLog().tracef("Removed entry under key %s and got response %s from CacheStore", key, resp);
return retval;
}
@Override
public Object visitClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable {
if (isStoreEnabled(command) && !ctx.isInTxScope())
persistenceManager.clearAllStores(ctx.isOriginLocal() ? BOTH : PRIVATE);
return invokeNextInterceptor(ctx, command);
}
@Override
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
Object returnValue = invokeNextInterceptor(ctx, command);
if (!isStoreEnabled(command) || ctx.isInTxScope() || !command.isSuccessful()) return returnValue;
if (!isProperWriter(ctx, command, command.getKey())) return returnValue;
Object key = command.getKey();
storeEntry(ctx, key, command);
if (getStatisticsEnabled()) cacheStores.incrementAndGet();
return returnValue;
}
@Override
public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable {
Object returnValue = invokeNextInterceptor(ctx, command);
if (!isStoreEnabled(command) || ctx.isInTxScope() || !command.isSuccessful()) return returnValue;
if (!isProperWriter(ctx, command, command.getKey())) return returnValue;
Object key = command.getKey();
storeEntry(ctx, key, command);
if (getStatisticsEnabled()) cacheStores.incrementAndGet();
return returnValue;
}
@Override
public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
Object returnValue = invokeNextInterceptor(ctx, command);
if (!isStoreEnabled(command) || ctx.isInTxScope()) return returnValue;
Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy