/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.internal.nearcache.impl.invalidation; import com.hazelcast.core.IFunction; import com.hazelcast.logging.ILogger; import com.hazelcast.nio.serialization.Data; import com.hazelcast.spi.EventRegistration; import com.hazelcast.spi.EventService; import com.hazelcast.spi.ManagedService; import com.hazelcast.spi.NodeEngine; import com.hazelcast.spi.partition.IPartitionService; import java.util.Collection; import java.util.UUID; import static com.hazelcast.internal.nearcache.impl.invalidation.ToHeapDataConverter.toHeapData; import static java.lang.String.format; /** * Contains shared functionality for Near Cache invalidation. */ public abstract class Invalidator { protected final int partitionCount; protected final String serviceName; protected final ILogger logger; protected final NodeEngine nodeEngine; protected final EventService eventService; protected final MetaDataGenerator metaDataGenerator; protected final IPartitionService partitionService; protected final IFunction<EventRegistration, Boolean> eventFilter; public Invalidator(String serviceName, IFunction<EventRegistration, Boolean> eventFilter, NodeEngine nodeEngine) { this.serviceName = serviceName; this.eventFilter = eventFilter; this.nodeEngine = nodeEngine; this.logger = nodeEngine.getLogger(getClass()); this.partitionService = nodeEngine.getPartitionService(); this.eventService = nodeEngine.getEventService(); this.partitionCount = nodeEngine.getPartitionService().getPartitionCount(); this.metaDataGenerator = new MetaDataGenerator(partitionCount); } protected abstract void invalidateInternal(Invalidation invalidation, int orderKey); /** * Invalidates supplied key from Near Caches of supplied data structure name. * * @param key key of the entry to be removed from Near Cache * @param dataStructureName name of the data structure to be invalidated */ public final void invalidateKey(Data key, String dataStructureName, String sourceUuid) { assert key != null; assert dataStructureName != null; assert sourceUuid != null; Invalidation invalidation = newKeyInvalidation(key, dataStructureName, sourceUuid); invalidateInternal(invalidation, getPartitionId(key)); } /** * Invalidates all keys from Near Caches of supplied data structure name. * * @param dataStructureName name of the data structure to be cleared */ public final void invalidateAllKeys(String dataStructureName, String sourceUuid) { assert dataStructureName != null; assert sourceUuid != null; int orderKey = getPartitionId(dataStructureName); Invalidation invalidation = newClearInvalidation(dataStructureName, sourceUuid); sendImmediately(invalidation, orderKey); } public final MetaDataGenerator getMetaDataGenerator() { return metaDataGenerator; } private Invalidation newKeyInvalidation(Data key, String dataStructureName, String sourceUuid) { int partitionId = getPartitionId(key); long sequence = metaDataGenerator.nextSequence(dataStructureName, partitionId); UUID partitionUuid = metaDataGenerator.getOrCreateUuid(partitionId); if (logger.isFinestEnabled()) { logger.finest(format("dataStructureName=%s, partition=%d, sequence=%d, uuid=%s", dataStructureName, partitionId, sequence, partitionUuid)); } return new SingleNearCacheInvalidation(toHeapData(key), dataStructureName, sourceUuid, partitionUuid, sequence); } protected final Invalidation newClearInvalidation(String dataStructureName, String sourceUuid) { int partitionId = getPartitionId(dataStructureName); long sequence = metaDataGenerator.nextSequence(dataStructureName, partitionId); UUID partitionUuid = metaDataGenerator.getOrCreateUuid(partitionId); return new SingleNearCacheInvalidation(null, dataStructureName, sourceUuid, partitionUuid, sequence); } private int getPartitionId(Data o) { return partitionService.getPartitionId(o); } private int getPartitionId(Object o) { return partitionService.getPartitionId(o); } protected final void sendImmediately(Invalidation invalidation, int orderKey) { String dataStructureName = invalidation.getName(); Collection<EventRegistration> registrations = eventService.getRegistrations(serviceName, dataStructureName); for (EventRegistration registration : registrations) { if (eventFilter.apply(registration)) { eventService.publishEvent(serviceName, registration, invalidation, orderKey); } } } /** * Removes supplied data structures invalidation queues and flushes their content. * This method is called when removing a Near Cache for example with * {@link com.hazelcast.map.impl.MapRemoteService#destroyDistributedObject(String)} * * @param dataStructureName name of the data structure. * @see com.hazelcast.map.impl.MapRemoteService#destroyDistributedObject(String) */ public void destroy(String dataStructureName, String sourceUuid) { metaDataGenerator.destroyMetaDataFor(dataStructureName); } /** * Resets this invalidator back to its initial state. * Aimed to call with {@link ManagedService#reset()} * * @see ManagedService#reset() */ public void reset() { // nop } /** * Shuts down this invalidator and releases used resources. * Aimed to call with {@link com.hazelcast.spi.ManagedService#shutdown(boolean)} * * @see ManagedService#shutdown(boolean) */ public void shutdown() { // nop } }