package org.infinispan.counter.impl.interceptor; import java.util.Collection; import java.util.EnumSet; import org.infinispan.commands.write.PutKeyValueCommand; import org.infinispan.commons.logging.LogFactory; import org.infinispan.commons.util.EnumUtil; import org.infinispan.container.entries.CacheEntry; import org.infinispan.context.Flag; import org.infinispan.context.InvocationContext; import org.infinispan.counter.api.Storage; import org.infinispan.counter.impl.metadata.ConfigurationMetadata; import org.infinispan.counter.logging.Log; import org.infinispan.functional.impl.MetaParamsInternalMetadata; import org.infinispan.interceptors.BaseCustomAsyncInterceptor; import org.infinispan.metadata.Metadata; /** * Interceptor for the counters cache. * <p> * Since the state transfer doesn't know about the {@link Flag#SKIP_CACHE_STORE} and {@link Flag#SKIP_CACHE_LOAD} flags, * all the counters are persisted. However, we only want the {@link Storage#PERSISTENT} configurations to be persisted. * <p> * This interceptor checks the configuration's {@link Storage} and sets the {@link Flag#SKIP_CACHE_LOAD} and {@link * Flag#SKIP_CACHE_STORE} flags. * * @author Pedro Ruivo * @since 9.0 */ public class CounterInterceptor extends BaseCustomAsyncInterceptor { private static final Log log = LogFactory.getLog(CounterInterceptor.class, Log.class); private static final boolean trace = log.isTraceEnabled(); private static final Collection<Flag> FLAGS_TO_SKIP_PERSISTENCE = EnumSet .of(Flag.SKIP_CACHE_LOAD, Flag.SKIP_CACHE_STORE); private static ConfigurationMetadata extract(Metadata metadata) { return metadata instanceof MetaParamsInternalMetadata ? ((MetaParamsInternalMetadata) metadata).findMetaParam(ConfigurationMetadata.class).orElse(null) : null; } private static boolean isVolatile(ConfigurationMetadata metadata) { return metadata != null && metadata.get().storage() == Storage.VOLATILE; } @Override public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable { //State Transfer puts doesn't use the skip_cache_load/store and the volatile counters are stored. //interceptor should be between the entry wrapping and the cache loader/writer interceptors. CacheEntry entry = ctx.lookupEntry(command.getKey()); ConfigurationMetadata entryMetadata = entry == null ? null : extract(entry.getMetadata()); ConfigurationMetadata commandMetadata = extract(command.getMetadata()); if (isVolatile(entryMetadata) || isVolatile(commandMetadata)) { if (trace) { log.tracef("Setting skip persistence for %s", command.getKey()); } command.setFlagsBitSet(EnumUtil.setEnums(command.getFlagsBitSet(), FLAGS_TO_SKIP_PERSISTENCE)); } return invokeNext(ctx, command); } }