/* * 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.client.impl.protocol.ClientMessage; import com.hazelcast.nio.serialization.Data; import java.util.ArrayList; import java.util.List; import java.util.UUID; public abstract class AbstractBaseNearCacheInvalidationListener { /** * This listener is called by member and in the listener we are sending invalidations to client. * `batchOrderKey` is used by clients'-striped-executor to find a worker for processing invalidation. * By using `batchOrderKey` we are putting all invalidations coming from the same member into the same workers' queue. * So if there is more than one member all members will have their own worker to process invalidations. This provides * more granular processing. */ private final int batchOrderKey; public AbstractBaseNearCacheInvalidationListener(String localMemberUuid) { this.batchOrderKey = localMemberUuid.hashCode(); } protected abstract ClientMessage encodeBatchInvalidation(String name, List<Data> keys, List<String> sourceUuids, List<UUID> partitionUuids, List<Long> sequences); protected abstract ClientMessage encodeSingleInvalidation(String name, Data key, String sourceUuid, UUID partitionUuid, long sequence); protected abstract void sendMessageWithOrderKey(ClientMessage clientMessage, Object orderKey); protected abstract boolean canSendInvalidation(Invalidation invalidation); protected final void sendInvalidation(Invalidation invalidation) { if (invalidation instanceof BatchNearCacheInvalidation) { ExtractedParams params = extractParams(((BatchNearCacheInvalidation) invalidation)); ClientMessage message = encodeBatchInvalidation(invalidation.getName(), params.keys, params.sourceUuids, params.partitionUuids, params.sequences); sendMessageWithOrderKey(message, batchOrderKey); return; } if (invalidation instanceof SingleNearCacheInvalidation) { if (canSendInvalidation(invalidation)) { ClientMessage message = encodeSingleInvalidation(invalidation.getName(), invalidation.getKey(), invalidation.getSourceUuid(), invalidation.getPartitionUuid(), invalidation.getSequence()); sendMessageWithOrderKey(message, invalidation.getKey()); } return; } throw new IllegalArgumentException("Unknown invalidation message type " + invalidation); } private ExtractedParams extractParams(BatchNearCacheInvalidation batch) { List<Invalidation> invalidations = batch.getInvalidations(); int size = invalidations.size(); List<Data> keys = new ArrayList<Data>(size); List<String> sourceUuids = new ArrayList<String>(size); List<UUID> partitionUuids = new ArrayList<UUID>(size); List<Long> sequences = new ArrayList<Long>(size); for (Invalidation invalidation : invalidations) { if (canSendInvalidation(invalidation)) { keys.add(invalidation.getKey()); sourceUuids.add(invalidation.getSourceUuid()); partitionUuids.add(invalidation.getPartitionUuid()); sequences.add(invalidation.getSequence()); } } return new ExtractedParams(keys, sourceUuids, partitionUuids, sequences); } private static final class ExtractedParams { private final List<Data> keys; private final List<String> sourceUuids; private final List<UUID> partitionUuids; private final List<Long> sequences; ExtractedParams(List<Data> keys, List<String> sourceUuids, List<UUID> partitionUuids, List<Long> sequences) { this.keys = keys; this.sourceUuids = sourceUuids; this.partitionUuids = partitionUuids; this.sequences = sequences; } } }