/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.ignite.internal.processors.cache.distributed.dht;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.GridCacheCompoundIdentityFuture;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.GridCacheFuture;
import org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy;
import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.lang.IgniteUuid;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_NEAR_GET_MAX_REMAPS;
import static org.apache.ignite.IgniteSystemProperties.getInteger;
import static org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionState.OWNING;
/**
*
*/
public abstract class CacheDistributedGetFutureAdapter<K, V> extends GridCacheCompoundIdentityFuture<Map<K, V>>
implements GridCacheFuture<Map<K, V>>, CacheGetFuture {
/** Default max remap count value. */
public static final int DFLT_MAX_REMAP_CNT = 3;
/** Maximum number of attempts to remap key to the same primary node. */
protected static final int MAX_REMAP_CNT = getInteger(IGNITE_NEAR_GET_MAX_REMAPS, DFLT_MAX_REMAP_CNT);
/** Remap count updater. */
protected static final AtomicIntegerFieldUpdater<CacheDistributedGetFutureAdapter> REMAP_CNT_UPD =
AtomicIntegerFieldUpdater.newUpdater(CacheDistributedGetFutureAdapter.class, "remapCnt");
/** Context. */
protected final GridCacheContext<K, V> cctx;
/** Keys. */
protected Collection<KeyCacheObject> keys;
/** Read through flag. */
protected boolean readThrough;
/** Force primary flag. */
protected boolean forcePrimary;
/** Future ID. */
protected IgniteUuid futId;
/** Trackable flag. */
protected boolean trackable;
/** Remap count. */
@SuppressWarnings("UnusedDeclaration")
protected volatile int remapCnt;
/** Subject ID. */
protected UUID subjId;
/** Task name. */
protected String taskName;
/** Whether to deserialize binary objects. */
protected boolean deserializeBinary;
/** Skip values flag. */
protected boolean skipVals;
/** Expiry policy. */
protected IgniteCacheExpiryPolicy expiryPlc;
/** Flag indicating that get should be done on a locked topology version. */
protected boolean canRemap;
/** */
protected final boolean needVer;
/** */
protected final boolean keepCacheObjects;
/** */
protected final boolean recovery;
/**
* @param cctx Context.
* @param keys Keys.
* @param readThrough Read through flag.
* @param forcePrimary If {@code true} then will force network trip to primary node even
* if called on backup node.
* @param subjId Subject ID.
* @param taskName Task name.
* @param deserializeBinary Deserialize binary flag.
* @param expiryPlc Expiry policy.
* @param skipVals Skip values flag.
* @param canRemap Flag indicating whether future can be remapped on a newer topology version.
* @param needVer If {@code true} returns values as tuples containing value and version.
* @param keepCacheObjects Keep cache objects flag.
*/
protected CacheDistributedGetFutureAdapter(
GridCacheContext<K, V> cctx,
Collection<KeyCacheObject> keys,
boolean readThrough,
boolean forcePrimary,
@Nullable UUID subjId,
String taskName,
boolean deserializeBinary,
@Nullable IgniteCacheExpiryPolicy expiryPlc,
boolean skipVals,
boolean canRemap,
boolean needVer,
boolean keepCacheObjects,
boolean recovery
) {
super(CU.<K, V>mapsReducer(keys.size()));
assert !F.isEmpty(keys);
this.cctx = cctx;
this.keys = keys;
this.readThrough = readThrough;
this.forcePrimary = forcePrimary;
this.subjId = subjId;
this.taskName = taskName;
this.deserializeBinary = deserializeBinary;
this.expiryPlc = expiryPlc;
this.skipVals = skipVals;
this.canRemap = canRemap;
this.needVer = needVer;
this.keepCacheObjects = keepCacheObjects;
this.recovery = recovery;
futId = IgniteUuid.randomUuid();
}
/**
* Affinity node to send get request to.
*
* @param affNodes All affinity nodes.
* @return Affinity node to get key from.
*/
protected final ClusterNode affinityNode(List<ClusterNode> affNodes) {
if (!canRemap) {
for (ClusterNode node : affNodes) {
if (cctx.discovery().alive(node))
return node;
}
return null;
}
else
return affNodes.get(0);
}
/**
* @param part Partition.
* @return {@code True} if partition is in owned state.
*/
protected final boolean partitionOwned(int part) {
return cctx.topology().partitionState(cctx.localNodeId(), part) == OWNING;
}
/**
* @param topVer Topology version.
* @return Exception.
*/
protected final ClusterTopologyServerNotFoundException serverNotFoundError(AffinityTopologyVersion topVer) {
return new ClusterTopologyServerNotFoundException("Failed to map keys for cache " +
"(all partition nodes left the grid) [topVer=" + topVer + ", cache=" + cctx.name() + ']');
}
}