/* * 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.map.impl.querycache.publisher; import com.hazelcast.map.impl.querycache.QueryCacheContext; import com.hazelcast.map.impl.querycache.accumulator.Accumulator; import com.hazelcast.map.impl.querycache.event.QueryCacheEventData; import com.hazelcast.map.impl.querycache.event.QueryCacheEventDataBuilder; import java.util.Map; import java.util.concurrent.TimeUnit; /** * Responsible for sweeping all registered accumulators of a {@link PublisherContext}. * This is needed in situations like ownership changes/graceful shutdown. */ public final class AccumulatorSweeper { private AccumulatorSweeper() { } public static void flushAllAccumulators(PublisherContext publisherContext) { QueryCacheContext context = publisherContext.getContext(); EventPublisherAccumulatorProcessor processor = new EventPublisherAccumulatorProcessor(context.getQueryCacheEventService()); PublisherAccumulatorHandler handler = new PublisherAccumulatorHandler(context, processor); MapPublisherRegistry mapPublisherRegistry = publisherContext.getMapPublisherRegistry(); Map<String, PublisherRegistry> allPublisherRegistryMap = mapPublisherRegistry.getAll(); for (PublisherRegistry publisherRegistry : allPublisherRegistryMap.values()) { Map<String, PartitionAccumulatorRegistry> accumulatorRegistryMap = publisherRegistry.getAll(); for (PartitionAccumulatorRegistry accumulatorRegistry : accumulatorRegistryMap.values()) { Map<Integer, Accumulator> accumulatorMap = accumulatorRegistry.getAll(); for (Map.Entry<Integer, Accumulator> entry : accumulatorMap.entrySet()) { Integer partitionId = entry.getKey(); Accumulator accumulator = entry.getValue(); processor.setInfo(accumulator.getInfo()); // give 0 to delay-time in order to fetch all events in the accumulator accumulator.poll(handler, 0, TimeUnit.SECONDS); // send end event QueryCacheEventData eventData = createEndOfSequenceEvent(partitionId); processor.process(eventData); } } } } public static void flushAccumulator(PublisherContext publisherContext, int partitionId) { QueryCacheContext context = publisherContext.getContext(); EventPublisherAccumulatorProcessor processor = new EventPublisherAccumulatorProcessor(context.getQueryCacheEventService()); PublisherAccumulatorHandler handler = new PublisherAccumulatorHandler(context, processor); MapPublisherRegistry mapPublisherRegistry = publisherContext.getMapPublisherRegistry(); Map<String, PublisherRegistry> allPublisherRegistryMap = mapPublisherRegistry.getAll(); for (PublisherRegistry publisherRegistry : allPublisherRegistryMap.values()) { Map<String, PartitionAccumulatorRegistry> accumulatorRegistryMap = publisherRegistry.getAll(); for (PartitionAccumulatorRegistry accumulatorRegistry : accumulatorRegistryMap.values()) { Map<Integer, Accumulator> accumulatorMap = accumulatorRegistry.getAll(); Accumulator accumulator = accumulatorMap.get(partitionId); if (accumulator == null) { continue; } processor.setInfo(accumulator.getInfo()); // give 0 to delay-time in order to fetch all events in the accumulator accumulator.poll(handler, 0, TimeUnit.SECONDS); // send end event QueryCacheEventData eventData = createEndOfSequenceEvent(partitionId); processor.process(eventData); } } } public static void removeAccumulator(PublisherContext publisherContext, int partitionId) { MapPublisherRegistry mapPublisherRegistry = publisherContext.getMapPublisherRegistry(); Map<String, PublisherRegistry> allPublisherRegistryMap = mapPublisherRegistry.getAll(); for (PublisherRegistry publisherRegistry : allPublisherRegistryMap.values()) { Map<String, PartitionAccumulatorRegistry> accumulatorRegistryMap = publisherRegistry.getAll(); for (PartitionAccumulatorRegistry accumulatorRegistry : accumulatorRegistryMap.values()) { accumulatorRegistry.remove(partitionId); } } } /** * In graceful shutdown, we are flushing all unsent events in an {@code Accumulator}. This event * will be the last event of an {@code Accumulator} upon flush and it is used to inform subscriber-side * to state that we reached the end of event sequence for the relevant partition. * <p/> * After this event received by subscriber-side, subscriber resets its next-expected-sequence counter to zero for the * corresponding partition. */ private static QueryCacheEventData createEndOfSequenceEvent(int partitionId) { return QueryCacheEventDataBuilder.newQueryCacheEventDataBuilder(false) .withSequence(-1).withPartitionId(partitionId).build(); } }