http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/GridCacheWriteSynchronizationMode.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/GridCacheWriteSynchronizationMode.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/GridCacheWriteSynchronizationMode.java
deleted file mode 100644
index 4585ea9..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/GridCacheWriteSynchronizationMode.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.cache;
-
-import org.apache.ignite.transactions.*;
-import org.jetbrains.annotations.*;
-
-/**
- * Mode indicating how GridGain should wait for write replies from other 
nodes. Default
- * value is {@link #FULL_ASYNC}}, which means that GridGain will not wait for 
responses from
- * participating nodes. This means that by default remote nodes may get their 
state updated slightly after
- * any of the cache write methods complete, or after {@link IgniteTx#commit()} 
method completes.
- * <p>
- * Note that regardless of write synchronization mode, cache data will always 
remain fully
- * consistent across all participating nodes.
- * <p>
- * Write synchronization mode may be configured via {@link 
org.apache.ignite.cache.CacheConfiguration#getWriteSynchronizationMode()}
- * configuration property.
- */
-public enum GridCacheWriteSynchronizationMode {
-    /**
-     * Flag indicating that GridGain should wait for write or commit replies 
from all nodes.
-     * This behavior guarantees that whenever any of the atomic or 
transactional writes
-     * complete, all other participating nodes which cache the written data 
have been updated.
-     */
-    FULL_SYNC,
-
-    /**
-     * Flag indicating that GridGain will not wait for write or commit 
responses from participating nodes,
-     * which means that remote nodes may get their state updated a bit after 
any of the cache write methods
-     * complete, or after {@link IgniteTx#commit()} method completes.
-     */
-    FULL_ASYNC,
-
-    /**
-     * This flag only makes sense for {@link CacheMode#PARTITIONED} mode. When 
enabled, GridGain
-     * will wait for write or commit to complete on {@code primary} node, but 
will not wait for
-     * backups to be updated.
-     */
-    PRIMARY_SYNC;
-
-    /** Enumerated values. */
-    private static final GridCacheWriteSynchronizationMode[] VALS = values();
-
-    /**
-     * Efficiently gets enumerated value from its ordinal.
-     *
-     * @param ord Ordinal value.
-     * @return Enumerated value or {@code null} if ordinal out of range.
-     */
-    @Nullable public static GridCacheWriteSynchronizationMode fromOrdinal(int 
ord) {
-        return ord >= 0 && ord < VALS.length ? VALS[ord] : null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinity.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinity.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinity.java
new file mode 100644
index 0000000..dc81a20
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinity.java
@@ -0,0 +1,262 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.cache.*;
+import org.apache.ignite.cluster.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+/**
+ * Provides affinity information to detect which node is primary and which 
nodes are
+ * backups for a partitioned cache. You can get an instance of this interface 
by calling
+ * {@code Cache.affinity()} method.
+ * <p>
+ * Mapping of a key to a node is a three-step operation. First step will get 
an affinity key for given key
+ * using {@link CacheAffinityKeyMapper}. If mapper is not specified, the 
original key will be used. Second step
+ * will map affinity key to partition using {@link 
CacheAffinityFunction#partition(Object)} method. Third step
+ * will map obtained partition to nodes for current grid topology version.
+ * <p>
+ * Interface provides various {@code 'mapKeysToNodes(..)'} methods which 
provide node affinity mapping for
+ * given keys. All {@code 'mapKeysToNodes(..)'} methods are not transactional 
and will not enlist
+ * keys into ongoing transaction.
+ */
+public interface CacheAffinity<K> {
+    /**
+     * Gets number of partitions in cache according to configured affinity 
function.
+     *
+     * @return Number of cache partitions.
+     * @see CacheAffinityFunction
+     * @see CacheConfiguration#getAffinity()
+     * @see CacheConfiguration#setAffinity(CacheAffinityFunction)
+     */
+    public int partitions();
+
+    /**
+     * Gets partition id for the given key.
+     *
+     * @param key Key to get partition id for.
+     * @return Partition id.
+     * @see CacheAffinityFunction
+     * @see CacheConfiguration#getAffinity()
+     * @see CacheConfiguration#setAffinity(CacheAffinityFunction)
+     */
+    public int partition(K key);
+
+    /**
+     * Returns {@code true} if given node is the primary node for given key.
+     * To check if local node is primary for given key, pass
+     * {@link org.apache.ignite.Ignite#localNode()} as first parameter.
+     *
+     * @param n Node to check.
+     * @param key Key to check.
+     * @return {@code True} if local node is the primary node for given key.
+     */
+    public boolean isPrimary(ClusterNode n, K key);
+
+    /**
+     * Returns {@code true} if local node is one of the backup nodes for given 
key.
+     * To check if local node is primary for given key, pass {@link 
org.apache.ignite.Ignite#localNode()}
+     * as first parameter.
+     *
+     * @param n Node to check.
+     * @param key Key to check.
+     * @return {@code True} if local node is one of the backup nodes for given 
key.
+     */
+    public boolean isBackup(ClusterNode n, K key);
+
+    /**
+     * Returns {@code true} if local node is primary or one of the backup nodes
+     * for given key. To check if local node is primary or backup for given 
key, pass
+     * {@link org.apache.ignite.Ignite#localNode()} as first parameter.
+     * <p>
+     * This method is essentially equivalent to calling
+     * <i>"{@link #isPrimary(org.apache.ignite.cluster.ClusterNode, Object)} 
|| {@link #isBackup(org.apache.ignite.cluster.ClusterNode, Object)})"</i>,
+     * however it is more efficient as it makes both checks at once.
+     *
+     * @param n Node to check.
+     * @param key Key to check.
+     * @return {@code True} if local node is primary or backup for given key.
+     */
+    public boolean isPrimaryOrBackup(ClusterNode n, K key);
+
+    /**
+     * Gets partition ids for which nodes of the given projection has primary
+     * ownership.
+     * <p>
+     * Note that since {@link org.apache.ignite.cluster.ClusterNode} 
implements {@link org.apache.ignite.cluster.ClusterGroup},
+     * to find out primary partitions for a single node just pass
+     * a single node into this method.
+     * <p>
+     * This method may return an empty array if none of nodes in the projection
+     * have nearOnly disabled.
+     *
+     * @param n Grid node.
+     * @return Partition ids for which given projection has primary ownership.
+     * @see CacheAffinityFunction
+     * @see CacheConfiguration#getAffinity()
+     * @see CacheConfiguration#setAffinity(CacheAffinityFunction)
+     */
+    public int[] primaryPartitions(ClusterNode n);
+
+    /**
+     * Gets partition ids for which nodes of the given projection has backup
+     * ownership. Note that you can find a back up at a certain level, e.g.
+     * {@code first} backup or {@code third} backup by specifying the
+     * {@code 'levels} parameter. If no {@code 'level'} is specified then
+     * all backup partitions are returned.
+     * <p>
+     * Note that since {@link org.apache.ignite.cluster.ClusterNode} 
implements {@link org.apache.ignite.cluster.ClusterGroup},
+     * to find out backup partitions for a single node, just pass that single
+     * node into this method.
+     * <p>
+     * This method may return an empty array if none of nodes in the projection
+     * have nearOnly disabled.
+     *
+     * @param n Grid node.
+     * @return Partition ids for which given projection has backup ownership.
+     * @see CacheAffinityFunction
+     * @see CacheConfiguration#getAffinity()
+     * @see CacheConfiguration#setAffinity(CacheAffinityFunction)
+     */
+    public int[] backupPartitions(ClusterNode n);
+
+    /**
+     * Gets partition ids for which nodes of the given projection has ownership
+     * (either primary or backup).
+     * <p>
+     * Note that since {@link org.apache.ignite.cluster.ClusterNode} 
implements {@link org.apache.ignite.cluster.ClusterGroup},
+     * to find out all partitions for a single node, just pass that single
+     * node into this method.
+     * <p>
+     * This method may return an empty array if none of nodes in the projection
+     * have nearOnly disabled.
+     *
+     * @param n Grid node.
+     * @return Partition ids for which given projection has ownership.
+     * @see CacheAffinityFunction
+     * @see CacheConfiguration#getAffinity()
+     * @see CacheConfiguration#setAffinity(CacheAffinityFunction)
+     */
+    public int[] allPartitions(ClusterNode n);
+
+    /**
+     * Maps passed in key to a key which will be used for node affinity. The 
affinity
+     * key may be different from actual key if some field in the actual key was
+     * designated for affinity mapping via {@link CacheAffinityKeyMapped} 
annotation
+     * or if a custom {@link CacheAffinityKeyMapper} was configured.
+     *
+     * @param key Key to map.
+     * @return Key to be used for node-to-affinity mapping (may be the same
+     *      key as passed in).
+     */
+    public Object affinityKey(K key);
+
+    /**
+     * This method provides ability to detect which keys are mapped to which 
nodes.
+     * Use it to determine which nodes are storing which keys prior to sending
+     * jobs that access these keys.
+     * <p>
+     * This method works as following:
+     * <ul>
+     * <li>For local caches it returns only local node mapped to all keys.</li>
+     * <li>
+     *      For fully replicated caches {@link CacheAffinityFunction} is
+     *      used to determine which keys are mapped to which nodes.
+     * </li>
+     * <li>For partitioned caches, the returned map represents node-to-key 
affinity.</li>
+     * </ul>
+     *
+     * @param keys Keys to map to nodes.
+     * @return Map of nodes to keys or empty map if there are no alive nodes 
for this cache.
+     */
+    public Map<ClusterNode, Collection<K>> mapKeysToNodes(@Nullable 
Collection<? extends K> keys);
+
+    /**
+     * This method provides ability to detect to which primary node the given 
key
+     * is mapped. Use it to determine which nodes are storing which keys prior 
to sending
+     * jobs that access these keys.
+     * <p>
+     * This method works as following:
+     * <ul>
+     * <li>For local caches it returns only local node ID.</li>
+     * <li>
+     *      For fully replicated caches first node ID returned by {@link 
CacheAffinityFunction}
+     *      is returned.
+     * </li>
+     * <li>For partitioned caches, primary node for the given key is 
returned.</li>
+     * </ul>
+     *
+     * @param key Keys to map to a node.
+     * @return Primary node for the key or {@code null} if there are no alive 
nodes for this cache.
+     */
+    @Nullable public ClusterNode mapKeyToNode(K key);
+
+    /**
+     * Gets primary and backup nodes for the key. Note that primary node is 
always
+     * first in the returned collection.
+     * <p>
+     * If there are only cache nodes in the projection with
+     * {@link CacheConfiguration#getDistributionMode()} property set to {@code 
NEAR_ONLY}, then this
+     * method will return an empty collection.
+     *
+     * @param key Key to get affinity nodes for.
+     * @return Collection of primary and backup nodes for the key with primary 
node
+     *      always first, or an empty collection if this projection contains 
only nodes with
+     *      {@link CacheConfiguration#getDistributionMode()} property set to 
{@code NEAR_ONLY}.
+     */
+    public Collection<ClusterNode> mapKeyToPrimaryAndBackups(K key);
+
+    /**
+     * Gets primary node for the given partition.
+     *
+     * @param part Partition id.
+     * @return Primary node for the given partition.
+     * @see CacheAffinityFunction
+     * @see CacheConfiguration#getAffinity()
+     * @see CacheConfiguration#setAffinity(CacheAffinityFunction)
+     */
+    public ClusterNode mapPartitionToNode(int part);
+
+    /**
+     * Gets primary nodes for the given partitions.
+     *
+     * @param parts Partition ids.
+     * @return Mapping of given partitions to their primary nodes.
+     * @see CacheAffinityFunction
+     * @see CacheConfiguration#getAffinity()
+     * @see CacheConfiguration#setAffinity(CacheAffinityFunction)
+     */
+    public Map<Integer, ClusterNode> mapPartitionsToNodes(Collection<Integer> 
parts);
+
+    /**
+     * Gets primary and backup nodes for partition. Note that primary node is 
always
+     * first in the returned collection.
+     * <p>
+     * If there are only cache nodes in the projection with
+     * {@link CacheConfiguration#getDistributionMode()} property set to {@code 
NEAR_ONLY}, then this
+     * method will return an empty collection.
+     *
+     * @param part Partition to get affinity nodes for.
+     * @return Collection of primary and backup nodes for partition with 
primary node
+     *      always first, or an empty collection if this projection contains 
only nodes with
+     *      {@link CacheConfiguration#getDistributionMode()} property set to 
{@code NEAR_ONLY}.
+     */
+    public Collection<ClusterNode> mapPartitionToPrimaryAndBackups(int part);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityFunction.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityFunction.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityFunction.java
new file mode 100644
index 0000000..d573795
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityFunction.java
@@ -0,0 +1,111 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.cache.*;
+import org.apache.ignite.cluster.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Cache key affinity which maps keys to nodes. This interface is utilized for
+ * both, replicated and partitioned caches. Cache affinity can be configured
+ * for individual caches via {@link CacheConfiguration#getAffinity()} method.
+ * <p>
+ * Whenever a key is given to cache, it is first passed to a pluggable
+ * {@link CacheAffinityKeyMapper} which may potentially map this key to an 
alternate
+ * key which should be used for affinity. The key returned from
+ * {@link CacheAffinityKeyMapper#affinityKey(Object)} method is then passed to
+ * {@link #partition(Object) partition(Object)} method to find out the 
partition for the key.
+ * On each topology change, partition-to-node mapping is calculated using
+ * {@link #assignPartitions(CacheAffinityFunctionContext)} method, which 
assigns a collection
+ * of nodes to each partition.
+ * This collection of nodes is used for node affinity. In {@link 
org.apache.ignite.cache.CacheMode#REPLICATED REPLICATED}
+ * cache mode the key will be cached on all returned nodes; generally, all 
caching nodes
+ * participate in caching every key in replicated mode. In {@link 
org.apache.ignite.cache.CacheMode#PARTITIONED PARTITIONED}
+ * mode, only primary and backup nodes are returned with primary node always 
in the
+ * first position. So if there is {@code 1} backup node, then the returned 
collection will
+ * have {@code 2} nodes in it - {@code primary} node in first position, and 
{@code backup}
+ * node in second.
+ * <p>
+ * For more information about cache affinity and examples refer to {@link 
CacheAffinityKeyMapper} and
+ * {@link CacheAffinityKeyMapped @CacheAffinityKeyMapped} documentation.
+ * @see CacheAffinityKeyMapped
+ * @see CacheAffinityKeyMapper
+ */
+public interface CacheAffinityFunction extends Serializable {
+    /**
+     * Resets cache affinity to its initial state. This method will be called 
by
+     * the system any time the affinity has been sent to remote node where
+     * it has to be reinitialized. If your implementation of affinity function
+     * has no initialization logic, leave this method empty.
+     */
+    public void reset();
+
+    /**
+     * Gets total number of partitions available. All caches should always 
provide
+     * correct partition count which should be the same on all participating 
nodes.
+     * Note that partitions should always be numbered from {@code 0} 
inclusively to
+     * {@code N} exclusively without any gaps.
+     *
+     * @return Total partition count.
+     */
+    public int partitions();
+
+    /**
+     * Gets partition number for a given key starting from {@code 0}. 
Partitioned caches
+     * should make sure that keys are about evenly distributed across all 
partitions
+     * from {@code 0} to {@link #partitions() partition count} for best 
performance.
+     * <p>
+     * Note that for fully replicated caches it is possible to segment key 
sets among different
+     * grid node groups. In that case each node group should return a unique 
partition
+     * number. However, unlike partitioned cache, mappings of keys to nodes in
+     * replicated caches are constant and a node cannot migrate from one 
partition
+     * to another.
+     *
+     * @param key Key to get partition for.
+     * @return Partition number for a given key.
+     */
+    public int partition(Object key);
+
+    /**
+     * Gets affinity nodes for a partition. In case of replicated cache, all 
returned
+     * nodes are updated in the same manner. In case of partitioned cache, the 
returned
+     * list should contain only the primary and back up nodes with primary 
node being
+     * always first.
+     * <p>
+     * Note that partitioned affinity must obey the following contract: given 
that node
+     * <code>N</code> is primary for some key <code>K</code>, if any other 
node(s) leave
+     * grid and no node joins grid, node <code>N</code> will remain primary 
for key <code>K</code>.
+     *
+     * @param affCtx Affinity function context. Will provide all required 
information to calculate
+     *      new partition assignments.
+     * @return Unmodifiable list indexed by partition number. Each element of 
array is a collection in which
+     *      first node is a primary node and other nodes are backup nodes.
+     */
+    public List<List<ClusterNode>> 
assignPartitions(CacheAffinityFunctionContext affCtx);
+
+    /**
+     * Removes node from affinity. This method is called when it is safe to 
remove left node from
+     * affinity mapping.
+     *
+     * @param nodeId ID of node to remove.
+     */
+    public void removeNode(UUID nodeId);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityFunctionContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityFunctionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityFunctionContext.java
new file mode 100644
index 0000000..70a0c2d
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityFunctionContext.java
@@ -0,0 +1,71 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.events.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+/**
+ * Affinity function context. This context is passed to {@link 
CacheAffinityFunction} for
+ * partition reassignment on every topology change event.
+ */
+public interface CacheAffinityFunctionContext {
+    /**
+     * Gets affinity assignment for given partition on previous topology 
version. First node in returned list is
+     * a primary node, other nodes are backups.
+     *
+     * @param part Partition to get previous assignment for.
+     * @return List of nodes assigned to given partition on previous topology 
version or {@code null}
+     *      if this information is not available.
+     */
+    @Nullable public List<ClusterNode> previousAssignment(int part);
+
+    /**
+     * Gets number of backups for new assignment.
+     *
+     * @return Number of backups for new assignment.
+     */
+    public int backups();
+
+    /**
+     * Gets current topology snapshot. Snapshot will contain only nodes on 
which particular cache is configured.
+     * List of passed nodes is guaranteed to be sorted in a same order on all 
nodes on which partition assignment
+     * is performed.
+     *
+     * @return Cache topology snapshot.
+     */
+    public List<ClusterNode> currentTopologySnapshot();
+
+    /**
+     * Gets current topology version number.
+     *
+     * @return Current topology version number.
+     */
+    public long currentTopologyVersion();
+
+    /**
+     * Gets discovery event caused topology change.
+     *
+     * @return Discovery event caused latest topology change or {@code null} 
if this information is
+     *      not available.
+     */
+    @Nullable public IgniteDiscoveryEvent discoveryEvent();
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKey.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKey.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKey.java
new file mode 100644
index 0000000..39bd049
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKey.java
@@ -0,0 +1,189 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.internal.processors.cache.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.internal.util.tostring.*;
+
+import java.io.*;
+
+/**
+ * Optional wrapper for cache keys to provide support
+ * for custom affinity mapping. The value returned by
+ * {@link #affinityKey(Object)} method will be used for key-to-node
+ * affinity.
+ * <p>
+ * Note that the {@link #equals(Object)} and {@link #hashCode()} methods
+ * delegate directly to the wrapped cache key provided by {@link #key()}
+ * method.
+ * <p>
+ * This class is optional and does not have to be used. It only provides
+ * extra convenience whenever custom affinity mapping is required. Here is
+ * an example of how {@code Person} objects can be collocated with
+ * {@code Company} objects they belong to:
+ * <pre name="code" class="java">
+ * Object personKey = new CacheAffinityKey(myPersonId, myCompanyId);
+ *
+ * // Both, the company and the person objects will be cached on the same node.
+ * cache.put(myCompanyId, new Company(..));
+ * cache.put(personKey, new Person(..));
+ * </pre>
+ * <p>
+ * For more information and examples of cache affinity refer to
+ * {@link CacheAffinityKeyMapper} and {@link CacheAffinityKeyMapped 
@CacheAffinityKeyMapped}
+ * documentation.
+ * @see CacheAffinityKeyMapped
+ * @see CacheAffinityKeyMapper
+ * @see CacheAffinityFunction
+ */
+public class CacheAffinityKey<K> implements Externalizable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Key. */
+    @GridToStringInclude
+    private K key;
+
+    /** Affinity key. */
+    @GridToStringInclude
+    private Object affKey;
+
+    /**
+     * Empty constructor.
+     */
+    public CacheAffinityKey() {
+        // No-op.
+    }
+
+    /**
+     * Initializes key wrapper for a given key. If affinity key
+     * is not initialized, then this key will be used for affinity.
+     *
+     * @param key Key.
+     */
+    public CacheAffinityKey(K key) {
+        A.notNull(key, "key");
+
+        this.key = key;
+    }
+
+    /**
+     * Initializes key together with its affinity key counter-part.
+     *
+     * @param key Key.
+     * @param affKey Affinity key.
+     */
+    public CacheAffinityKey(K key, Object affKey) {
+        A.notNull(key, "key");
+
+        this.key = key;
+        this.affKey = affKey;
+    }
+
+    /**
+     * Gets wrapped key.
+     *
+     * @return Wrapped key.
+     */
+    public K key() {
+        return key;
+    }
+
+    /**
+     * Sets wrapped key.
+     *
+     * @param key Wrapped key.
+     */
+    public void key(K key) {
+        this.key = key;
+    }
+
+    /**
+     * Gets affinity key to use for affinity mapping. If affinity key is not 
provided,
+     * then {@code key} value will be returned.
+     * <p>
+     * This method is annotated with {@link CacheAffinityKeyMapped} and will 
be picked up
+     * by {@link GridCacheDefaultAffinityKeyMapper} automatically.
+     *
+     * @return Affinity key to use for affinity mapping.
+     */
+    @CacheAffinityKeyMapped
+    @SuppressWarnings({"unchecked"})
+    public <T> T affinityKey() {
+        A.notNull(key, "key");
+
+        return (T)(affKey == null ? key : affKey);
+    }
+
+    /**
+     * Sets affinity key to use for affinity mapping. If affinity key is not 
provided,
+     * then {@code key} value will be returned.
+     *
+     * @param affKey Affinity key to use for affinity mapping.
+     */
+    public void affinityKey(Object affKey) {
+        this.affKey = affKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(key);
+        out.writeObject(affKey);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        key = (K)in.readObject();
+        affKey = in.readObject();
+    }
+
+    /**
+     * Hash code implementation which delegates to the underlying {@link 
#key()}. Note, however,
+     * that different subclasses of {@code CacheAffinityKey} will produce 
different hash codes.
+     * <p>
+     * Users should override this method if different behavior is desired.
+     *
+     * @return Hash code.
+     */
+    @Override public int hashCode() {
+        A.notNull(key, "key");
+
+        return 31 * key.hashCode() + getClass().getName().hashCode();
+    }
+
+    /**
+     * Equality check which delegates to the underlying key equality. Note, 
however, that
+     * different subclasses of {@code CacheAffinityKey} will never be equal.
+     * <p>
+     * Users should override this method if different behavior is desired.
+     *
+     * @param obj Object to check for equality.
+     * @return {@code True} if objects are equal.
+     */
+    @Override public boolean equals(Object obj) {
+        A.notNull(key, "key");
+
+        return obj != null && getClass() == obj.getClass() && 
key.equals(((CacheAffinityKey)obj).key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(CacheAffinityKey.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKeyMapped.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKeyMapped.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKeyMapped.java
new file mode 100644
index 0000000..2642ac8
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKeyMapped.java
@@ -0,0 +1,156 @@
+/*
+ * 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.cache.affinity;
+
+import java.lang.annotation.*;
+import java.util.concurrent.*;
+
+/**
+ * Optional annotation to specify custom key-to-node affinity. Affinity key is 
a key
+ * which will be used to determine a node on which given cache key will be 
stored. This
+ * annotation allows to mark a field or a method in the cache key object that 
will be
+ * used as an affinity key (instead of the entire cache key object that is 
used for
+ * affinity by default). Note that a class can have only one field or method 
annotated
+ * with {@code @CacheAffinityKeyMapped} annotation.
+ * <p>
+ * One of the major use cases for this annotation is the routing of grid 
computations
+ * to the nodes where the data for this computation is cached, the concept
+ * otherwise known as {@code Collocation Of Computations And Data}.
+ * <p>
+ * <h1 class="header">Mapping Cache Keys</h1>
+ * The default implementation of {@link CacheAffinityKeyMapper}, which will be 
used
+ * if no explicit affinity mapper is specified in cache configuration, will 
first look
+ * for any field or method annotated with {@code @CacheAffinityKeyMapped} 
annotation.
+ * If such field or method is not found, then the cache key itself will be 
used for
+ * key-to-node affinity (this means that all objects with the same cache key 
will always
+ * be routed to the same node). If such field or method is found, then the 
value of this
+ * field or method will be used for key-to-node affinity. This allows to 
specify alternate
+ * affinity key, other than the cache key itself, whenever needed.
+ * <p>
+ * For example, if a {@code Person} object is always accessed together with a 
{@code Company} object
+ * for which this person is an employee, then for better performance and 
scalability it makes sense to
+ * collocate {@code Person} objects together with their {@code Company} object 
when storing them in
+ * cache. To achieve that, cache key used to cache {@code Person} objects 
should have a field or method
+ * annotated with {@code @CacheAffinityKeyMapped} annotation, which will 
provide the value of
+ * the company key for which that person works, like so:
+ * <pre name="code" class="java">
+ * public class PersonKey {
+ *     // Person ID used to identify a person.
+ *     private String personId;
+ *
+ *     // Company ID which will be used for affinity.
+ *     &#64;CacheAffinityKeyMapped
+ *     private String companyId;
+ *     ...
+ * }
+ * ...
+ * // Instantiate person keys.
+ * Object personKey1 = new PersonKey("myPersonId1", "myCompanyId");
+ * Object personKey2 = new PersonKey("myPersonId2", "myCompanyId");
+ *
+ * // Both, the company and the person objects will be cached on the same node.
+ * cache.put("myCompanyId", new Company(..));
+ * cache.put(personKey1, new Person(..));
+ * cache.put(personKey2, new Person(..));
+ * </pre>
+ * <p>
+ * <h2 class="header">CacheAffinityKey</h2>
+ * For convenience, you can also optionally use {@link CacheAffinityKey} 
class. Here is how a
+ * {@code PersonKey} defined above would look using {@link CacheAffinityKey}:
+ * <pre name="code" class="java">
+ * Object personKey1 = new CacheAffinityKey("myPersonId1", "myCompanyId");
+ * Object personKey2 = new CacheAffinityKey("myPersonId2", "myCompanyId");
+ *
+ * // Both, the company and the person objects will be cached on the same node.
+ * cache.put(myCompanyId, new Company(..));
+ * cache.put(personKey1, new Person(..));
+ * cache.put(personKey2, new Person(..));
+ * </pre>
+ * <p>
+ * <h1 class="header">Collocating Computations And Data</h1>
+ * It is also possible to route computations to the nodes where the data is 
cached. This concept
+ * is otherwise known as {@code Collocation Of Computations And Data}. In this 
case,
+ * {@code @CacheAffinityKeyMapped} annotation allows to specify a routing 
affinity key for a
+ * {@link org.apache.ignite.compute.ComputeJob} or any other grid computation, 
such as {@link Runnable}, {@link Callable}, or
+ * {@link org.apache.ignite.lang.IgniteClosure}. It should be attached to a 
method or field that provides affinity key
+ * for the computation. Only one annotation per class is allowed. Whenever 
such annotation is detected,
+ * then {@link org.apache.ignite.spi.loadbalancing.LoadBalancingSpi} will be 
bypassed, and computation will be routed to the grid node
+ * where the specified affinity key is cached. You can also use optional 
{@link org.apache.ignite.cache.CacheName @CacheName}
+ * annotation whenever non-default cache name needs to be specified.
+ * <p>
+ * Here is how this annotation can be used to route a job to a node where 
Person object
+ * is cached with ID "1234":
+ * <pre name="code" class="java">
+ * G.grid().run(new Runnable() {
+ *     // This annotation is optional. If omitted, then default
+ *     // no-name cache will be used.
+ *     &#64;CacheName
+ *     private String cacheName = "myCache";
+ *
+ *     // This annotation specifies that computation should be routed
+ *     // precisely to the node where key '1234' is cached.
+ *     &#64;CacheAffinityKeyMapped
+ *     private String personKey = "1234";
+ *
+ *     &#64;Override public void run() {
+ *         // Some computation logic here.
+ *         ...
+ *     }
+ * };
+ * </pre>
+ * The same can be achieved by annotating method instead of field as follows:
+ * <pre name="code" class="java">
+ * G.grid().run(new Runnable() {
+ *     &#64;Override public void run() {
+ *         // Some computation logic here.
+ *         ...
+ *     }
+ *
+ *     // This annotation is optional. If omitted, then default
+ *     // no-name cache will be used.
+ *     &#64;CacheName
+ *     public String cacheName() {
+ *         return "myCache";
+ *     }
+ *
+ *     // This annotation specifies that computation should be routed
+ *     // precisely to the node where key '1234' is cached.
+ *     &#64;CacheAffinityKeyMapped
+ *     public String personKey() {
+ *         return "1234";
+ *     }
+ * };
+ * </pre>
+ * <p>
+ * For more information about cache affinity also see {@link 
CacheAffinityKeyMapper} and
+ * {@link CacheAffinityFunction} documentation.
+ * Affinity for a key can be found from any node, regardless of whether it has 
cache started
+ * or not. If cache is not started, affinity function will be fetched from the 
remote node
+ * which does have the cache running.
+ *
+ * @see org.apache.ignite.cache.CacheName
+ * @see CacheAffinityFunction
+ * @see CacheAffinityKeyMapper
+ * @see CacheAffinityKey
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+public @interface CacheAffinityKeyMapped {
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKeyMapper.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKeyMapper.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKeyMapper.java
new file mode 100644
index 0000000..f01631a
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityKeyMapper.java
@@ -0,0 +1,64 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.cache.*;
+
+import java.io.*;
+
+/**
+ * Affinity mapper which maps cache key to an affinity key. Affinity key is a 
key which will be
+ * used to determine a node on which this key will be cached. Every cache key 
will first be passed
+ * through {@link #affinityKey(Object)} method, and the returned value of this 
method
+ * will be given to {@link CacheAffinityFunction} implementation to find out 
key-to-node affinity.
+ * <p>
+ * The default implementation, which will be used if no explicit affinity 
mapper is specified
+ * in cache configuration, will first look for any field or method annotated 
with
+ * {@link CacheAffinityKeyMapped @CacheAffinityKeyMapped} annotation. If such 
field or method
+ * is not found, then the cache key itself will be returned from {@link 
#affinityKey(Object) affinityKey(Object)}
+ * method (this means that all objects with the same cache key will always be 
routed to the same node).
+ * If such field or method is found, then the value of this field or method 
will be returned from
+ * {@link #affinityKey(Object) affinityKey(Object)} method. This allows to 
specify alternate affinity key, other
+ * than the cache key itself, whenever needed.
+ * <p>
+ * A custom (other than default) affinity mapper can be provided
+ * via {@link CacheConfiguration#getAffinityMapper()} configuration property.
+ * <p>
+ * For more information on affinity mapping and examples refer to {@link 
CacheAffinityFunction} and
+ * {@link CacheAffinityKeyMapped @CacheAffinityKeyMapped} documentation.
+ * @see CacheAffinityFunction
+ * @see CacheAffinityKeyMapped
+ */
+public interface CacheAffinityKeyMapper extends Serializable {
+    /**
+     * Maps passed in key to an alternate key which will be used for node 
affinity.
+     *
+     * @param key Key to map.
+     * @return Key to be used for node-to-affinity mapping (may be the same
+     *      key as passed in).
+     */
+    public Object affinityKey(Object key);
+
+    /**
+     * Resets cache affinity mapper to its initial state. This method will be 
called by
+     * the system any time the affinity mapper has been sent to remote node 
where
+     * it has to be reinitialized. If your implementation of affinity mapper
+     * has no initialization logic, leave this method empty.
+     */
+    public void reset();
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeAddressHashResolver.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeAddressHashResolver.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeAddressHashResolver.java
new file mode 100644
index 0000000..70f20ba
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeAddressHashResolver.java
@@ -0,0 +1,39 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+
+/**
+ * Node hash resolver which uses {@link 
org.apache.ignite.cluster.ClusterNode#consistentId()} as alternate hash value.
+ */
+public class CacheAffinityNodeAddressHashResolver implements 
CacheAffinityNodeHashResolver {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** {@inheritDoc} */
+    @Override public Object resolve(ClusterNode node) {
+        return node.consistentId();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(CacheAffinityNodeAddressHashResolver.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeHashResolver.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeHashResolver.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeHashResolver.java
new file mode 100644
index 0000000..79489cf
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeHashResolver.java
@@ -0,0 +1,43 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.cluster.*;
+
+import java.io.*;
+
+/**
+ * Resolver which is used to provide node hash value for affinity function.
+ * <p>
+ * Node IDs constantly change when nodes get restarted, which causes affinity 
mapping to change between restarts,
+ * and hence causing redundant repartitioning. Providing an alternate node 
hash value, which survives node restarts,
+ * will help to map keys to the same nodes whenever possible.
+ * <p>
+ * Note that on case clients exist they will query this object from the server 
and use it for affinity calculation.
+ * Therefore you must ensure that server and clients can marshal and unmarshal 
this object in portable format,
+ * i.e. all parties have object class(es) configured as portable.
+ */
+public interface CacheAffinityNodeHashResolver extends Serializable {
+    /**
+     * Resolve alternate hash value for the given Grid node.
+     *
+     * @param node Grid node.
+     * @return Resolved hash ID.
+     */
+    public Object resolve(ClusterNode node);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeIdHashResolver.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeIdHashResolver.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeIdHashResolver.java
new file mode 100644
index 0000000..3de9220
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheAffinityNodeIdHashResolver.java
@@ -0,0 +1,40 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+
+/**
+ * Node hash resolver which uses generated node ID as node hash value. As new 
node ID is generated
+ * on each node start, this resolver do not provide ability to map keys to the 
same nodes after restart.
+ */
+public class CacheAffinityNodeIdHashResolver implements 
CacheAffinityNodeHashResolver {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** {@inheritDoc} */
+    @Override public Object resolve(ClusterNode node) {
+        return node.id();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(CacheAffinityNodeIdHashResolver.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheCentralizedAffinityFunction.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheCentralizedAffinityFunction.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheCentralizedAffinityFunction.java
new file mode 100644
index 0000000..0df8ffe
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/CacheCentralizedAffinityFunction.java
@@ -0,0 +1,31 @@
+/*
+ * 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.cache.affinity;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation marker which identifies affinity function that must be 
calculated on one centralized node
+ * instead of independently on each node. In many cases it happens because it 
requires previous affinity state
+ * in order to calculate new one.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface CacheCentralizedAffinityFunction {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinity.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinity.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinity.java
deleted file mode 100644
index e0d499f..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinity.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * 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.cache.affinity;
-
-import org.apache.ignite.cache.*;
-import org.apache.ignite.cluster.*;
-import org.jetbrains.annotations.*;
-
-import java.util.*;
-
-/**
- * Provides affinity information to detect which node is primary and which 
nodes are
- * backups for a partitioned cache. You can get an instance of this interface 
by calling
- * {@code GridCache.affinity()} method.
- * <p>
- * Mapping of a key to a node is a three-step operation. First step will get 
an affinity key for given key
- * using {@link GridCacheAffinityKeyMapper}. If mapper is not specified, the 
original key will be used. Second step
- * will map affinity key to partition using {@link 
GridCacheAffinityFunction#partition(Object)} method. Third step
- * will map obtained partition to nodes for current grid topology version.
- * <p>
- * Interface provides various {@code 'mapKeysToNodes(..)'} methods which 
provide node affinity mapping for
- * given keys. All {@code 'mapKeysToNodes(..)'} methods are not transactional 
and will not enlist
- * keys into ongoing transaction.
- */
-public interface GridCacheAffinity<K> {
-    /**
-     * Gets number of partitions in cache according to configured affinity 
function.
-     *
-     * @return Number of cache partitions.
-     * @see GridCacheAffinityFunction
-     * @see CacheConfiguration#getAffinity()
-     * @see CacheConfiguration#setAffinity(GridCacheAffinityFunction)
-     */
-    public int partitions();
-
-    /**
-     * Gets partition id for the given key.
-     *
-     * @param key Key to get partition id for.
-     * @return Partition id.
-     * @see GridCacheAffinityFunction
-     * @see CacheConfiguration#getAffinity()
-     * @see CacheConfiguration#setAffinity(GridCacheAffinityFunction)
-     */
-    public int partition(K key);
-
-    /**
-     * Returns {@code true} if given node is the primary node for given key.
-     * To check if local node is primary for given key, pass
-     * {@link org.apache.ignite.Ignite#localNode()} as first parameter.
-     *
-     * @param n Node to check.
-     * @param key Key to check.
-     * @return {@code True} if local node is the primary node for given key.
-     */
-    public boolean isPrimary(ClusterNode n, K key);
-
-    /**
-     * Returns {@code true} if local node is one of the backup nodes for given 
key.
-     * To check if local node is primary for given key, pass {@link 
org.apache.ignite.Ignite#localNode()}
-     * as first parameter.
-     *
-     * @param n Node to check.
-     * @param key Key to check.
-     * @return {@code True} if local node is one of the backup nodes for given 
key.
-     */
-    public boolean isBackup(ClusterNode n, K key);
-
-    /**
-     * Returns {@code true} if local node is primary or one of the backup nodes
-     * for given key. To check if local node is primary or backup for given 
key, pass
-     * {@link org.apache.ignite.Ignite#localNode()} as first parameter.
-     * <p>
-     * This method is essentially equivalent to calling
-     * <i>"{@link #isPrimary(org.apache.ignite.cluster.ClusterNode, Object)} 
|| {@link #isBackup(org.apache.ignite.cluster.ClusterNode, Object)})"</i>,
-     * however it is more efficient as it makes both checks at once.
-     *
-     * @param n Node to check.
-     * @param key Key to check.
-     * @return {@code True} if local node is primary or backup for given key.
-     */
-    public boolean isPrimaryOrBackup(ClusterNode n, K key);
-
-    /**
-     * Gets partition ids for which nodes of the given projection has primary
-     * ownership.
-     * <p>
-     * Note that since {@link org.apache.ignite.cluster.ClusterNode} 
implements {@link org.apache.ignite.cluster.ClusterGroup},
-     * to find out primary partitions for a single node just pass
-     * a single node into this method.
-     * <p>
-     * This method may return an empty array if none of nodes in the projection
-     * have nearOnly disabled.
-     *
-     * @param n Grid node.
-     * @return Partition ids for which given projection has primary ownership.
-     * @see GridCacheAffinityFunction
-     * @see CacheConfiguration#getAffinity()
-     * @see CacheConfiguration#setAffinity(GridCacheAffinityFunction)
-     */
-    public int[] primaryPartitions(ClusterNode n);
-
-    /**
-     * Gets partition ids for which nodes of the given projection has backup
-     * ownership. Note that you can find a back up at a certain level, e.g.
-     * {@code first} backup or {@code third} backup by specifying the
-     * {@code 'levels} parameter. If no {@code 'level'} is specified then
-     * all backup partitions are returned.
-     * <p>
-     * Note that since {@link org.apache.ignite.cluster.ClusterNode} 
implements {@link org.apache.ignite.cluster.ClusterGroup},
-     * to find out backup partitions for a single node, just pass that single
-     * node into this method.
-     * <p>
-     * This method may return an empty array if none of nodes in the projection
-     * have nearOnly disabled.
-     *
-     * @param n Grid node.
-     * @return Partition ids for which given projection has backup ownership.
-     * @see GridCacheAffinityFunction
-     * @see CacheConfiguration#getAffinity()
-     * @see CacheConfiguration#setAffinity(GridCacheAffinityFunction)
-     */
-    public int[] backupPartitions(ClusterNode n);
-
-    /**
-     * Gets partition ids for which nodes of the given projection has ownership
-     * (either primary or backup).
-     * <p>
-     * Note that since {@link org.apache.ignite.cluster.ClusterNode} 
implements {@link org.apache.ignite.cluster.ClusterGroup},
-     * to find out all partitions for a single node, just pass that single
-     * node into this method.
-     * <p>
-     * This method may return an empty array if none of nodes in the projection
-     * have nearOnly disabled.
-     *
-     * @param n Grid node.
-     * @return Partition ids for which given projection has ownership.
-     * @see GridCacheAffinityFunction
-     * @see CacheConfiguration#getAffinity()
-     * @see CacheConfiguration#setAffinity(GridCacheAffinityFunction)
-     */
-    public int[] allPartitions(ClusterNode n);
-
-    /**
-     * Maps passed in key to a key which will be used for node affinity. The 
affinity
-     * key may be different from actual key if some field in the actual key was
-     * designated for affinity mapping via {@link GridCacheAffinityKeyMapped} 
annotation
-     * or if a custom {@link GridCacheAffinityKeyMapper} was configured.
-     *
-     * @param key Key to map.
-     * @return Key to be used for node-to-affinity mapping (may be the same
-     *      key as passed in).
-     */
-    public Object affinityKey(K key);
-
-    /**
-     * This method provides ability to detect which keys are mapped to which 
nodes.
-     * Use it to determine which nodes are storing which keys prior to sending
-     * jobs that access these keys.
-     * <p>
-     * This method works as following:
-     * <ul>
-     * <li>For local caches it returns only local node mapped to all keys.</li>
-     * <li>
-     *      For fully replicated caches {@link GridCacheAffinityFunction} is
-     *      used to determine which keys are mapped to which nodes.
-     * </li>
-     * <li>For partitioned caches, the returned map represents node-to-key 
affinity.</li>
-     * </ul>
-     *
-     * @param keys Keys to map to nodes.
-     * @return Map of nodes to keys or empty map if there are no alive nodes 
for this cache.
-     */
-    public Map<ClusterNode, Collection<K>> mapKeysToNodes(@Nullable 
Collection<? extends K> keys);
-
-    /**
-     * This method provides ability to detect to which primary node the given 
key
-     * is mapped. Use it to determine which nodes are storing which keys prior 
to sending
-     * jobs that access these keys.
-     * <p>
-     * This method works as following:
-     * <ul>
-     * <li>For local caches it returns only local node ID.</li>
-     * <li>
-     *      For fully replicated caches first node ID returned by {@link 
GridCacheAffinityFunction}
-     *      is returned.
-     * </li>
-     * <li>For partitioned caches, primary node for the given key is 
returned.</li>
-     * </ul>
-     *
-     * @param key Keys to map to a node.
-     * @return Primary node for the key or {@code null} if there are no alive 
nodes for this cache.
-     */
-    @Nullable public ClusterNode mapKeyToNode(K key);
-
-    /**
-     * Gets primary and backup nodes for the key. Note that primary node is 
always
-     * first in the returned collection.
-     * <p>
-     * If there are only cache nodes in the projection with
-     * {@link CacheConfiguration#getDistributionMode()} property set to {@code 
NEAR_ONLY}, then this
-     * method will return an empty collection.
-     *
-     * @param key Key to get affinity nodes for.
-     * @return Collection of primary and backup nodes for the key with primary 
node
-     *      always first, or an empty collection if this projection contains 
only nodes with
-     *      {@link CacheConfiguration#getDistributionMode()} property set to 
{@code NEAR_ONLY}.
-     */
-    public Collection<ClusterNode> mapKeyToPrimaryAndBackups(K key);
-
-    /**
-     * Gets primary node for the given partition.
-     *
-     * @param part Partition id.
-     * @return Primary node for the given partition.
-     * @see GridCacheAffinityFunction
-     * @see CacheConfiguration#getAffinity()
-     * @see CacheConfiguration#setAffinity(GridCacheAffinityFunction)
-     */
-    public ClusterNode mapPartitionToNode(int part);
-
-    /**
-     * Gets primary nodes for the given partitions.
-     *
-     * @param parts Partition ids.
-     * @return Mapping of given partitions to their primary nodes.
-     * @see GridCacheAffinityFunction
-     * @see CacheConfiguration#getAffinity()
-     * @see CacheConfiguration#setAffinity(GridCacheAffinityFunction)
-     */
-    public Map<Integer, ClusterNode> mapPartitionsToNodes(Collection<Integer> 
parts);
-
-    /**
-     * Gets primary and backup nodes for partition. Note that primary node is 
always
-     * first in the returned collection.
-     * <p>
-     * If there are only cache nodes in the projection with
-     * {@link CacheConfiguration#getDistributionMode()} property set to {@code 
NEAR_ONLY}, then this
-     * method will return an empty collection.
-     *
-     * @param part Partition to get affinity nodes for.
-     * @return Collection of primary and backup nodes for partition with 
primary node
-     *      always first, or an empty collection if this projection contains 
only nodes with
-     *      {@link CacheConfiguration#getDistributionMode()} property set to 
{@code NEAR_ONLY}.
-     */
-    public Collection<ClusterNode> mapPartitionToPrimaryAndBackups(int part);
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityFunction.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityFunction.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityFunction.java
deleted file mode 100644
index b57ea89..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityFunction.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.cache.affinity;
-
-import org.apache.ignite.cache.*;
-import org.apache.ignite.cluster.*;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * Cache key affinity which maps keys to nodes. This interface is utilized for
- * both, replicated and partitioned caches. Cache affinity can be configured
- * for individual caches via {@link CacheConfiguration#getAffinity()} method.
- * <p>
- * Whenever a key is given to cache, it is first passed to a pluggable
- * {@link GridCacheAffinityKeyMapper} which may potentially map this key to an 
alternate
- * key which should be used for affinity. The key returned from
- * {@link GridCacheAffinityKeyMapper#affinityKey(Object)} method is then 
passed to
- * {@link #partition(Object) partition(Object)} method to find out the 
partition for the key.
- * On each topology change, partition-to-node mapping is calculated using
- * {@link #assignPartitions(GridCacheAffinityFunctionContext)} method, which 
assigns a collection
- * of nodes to each partition.
- * This collection of nodes is used for node affinity. In {@link 
org.apache.ignite.cache.CacheMode#REPLICATED REPLICATED}
- * cache mode the key will be cached on all returned nodes; generally, all 
caching nodes
- * participate in caching every key in replicated mode. In {@link 
org.apache.ignite.cache.CacheMode#PARTITIONED PARTITIONED}
- * mode, only primary and backup nodes are returned with primary node always 
in the
- * first position. So if there is {@code 1} backup node, then the returned 
collection will
- * have {@code 2} nodes in it - {@code primary} node in first position, and 
{@code backup}
- * node in second.
- * <p>
- * For more information about cache affinity and examples refer to {@link 
GridCacheAffinityKeyMapper} and
- * {@link GridCacheAffinityKeyMapped @GridCacheAffinityKeyMapped} 
documentation.
- * @see GridCacheAffinityKeyMapped
- * @see GridCacheAffinityKeyMapper
- */
-public interface GridCacheAffinityFunction extends Serializable {
-    /**
-     * Resets cache affinity to its initial state. This method will be called 
by
-     * the system any time the affinity has been sent to remote node where
-     * it has to be reinitialized. If your implementation of affinity function
-     * has no initialization logic, leave this method empty.
-     */
-    public void reset();
-
-    /**
-     * Gets total number of partitions available. All caches should always 
provide
-     * correct partition count which should be the same on all participating 
nodes.
-     * Note that partitions should always be numbered from {@code 0} 
inclusively to
-     * {@code N} exclusively without any gaps.
-     *
-     * @return Total partition count.
-     */
-    public int partitions();
-
-    /**
-     * Gets partition number for a given key starting from {@code 0}. 
Partitioned caches
-     * should make sure that keys are about evenly distributed across all 
partitions
-     * from {@code 0} to {@link #partitions() partition count} for best 
performance.
-     * <p>
-     * Note that for fully replicated caches it is possible to segment key 
sets among different
-     * grid node groups. In that case each node group should return a unique 
partition
-     * number. However, unlike partitioned cache, mappings of keys to nodes in
-     * replicated caches are constant and a node cannot migrate from one 
partition
-     * to another.
-     *
-     * @param key Key to get partition for.
-     * @return Partition number for a given key.
-     */
-    public int partition(Object key);
-
-    /**
-     * Gets affinity nodes for a partition. In case of replicated cache, all 
returned
-     * nodes are updated in the same manner. In case of partitioned cache, the 
returned
-     * list should contain only the primary and back up nodes with primary 
node being
-     * always first.
-     * <p>
-     * Note that partitioned affinity must obey the following contract: given 
that node
-     * <code>N</code> is primary for some key <code>K</code>, if any other 
node(s) leave
-     * grid and no node joins grid, node <code>N</code> will remain primary 
for key <code>K</code>.
-     *
-     * @param affCtx Affinity function context. Will provide all required 
information to calculate
-     *      new partition assignments.
-     * @return Unmodifiable list indexed by partition number. Each element of 
array is a collection in which
-     *      first node is a primary node and other nodes are backup nodes.
-     */
-    public List<List<ClusterNode>> 
assignPartitions(GridCacheAffinityFunctionContext affCtx);
-
-    /**
-     * Removes node from affinity. This method is called when it is safe to 
remove left node from
-     * affinity mapping.
-     *
-     * @param nodeId ID of node to remove.
-     */
-    public void removeNode(UUID nodeId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityFunctionContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityFunctionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityFunctionContext.java
deleted file mode 100644
index f742d69..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityFunctionContext.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.cache.affinity;
-
-import org.apache.ignite.cluster.*;
-import org.apache.ignite.events.*;
-import org.jetbrains.annotations.*;
-
-import java.util.*;
-
-/**
- * Affinity function context. This context is passed to {@link 
GridCacheAffinityFunction} for
- * partition reassignment on every topology change event.
- */
-public interface GridCacheAffinityFunctionContext {
-    /**
-     * Gets affinity assignment for given partition on previous topology 
version. First node in returned list is
-     * a primary node, other nodes are backups.
-     *
-     * @param part Partition to get previous assignment for.
-     * @return List of nodes assigned to given partition on previous topology 
version or {@code null}
-     *      if this information is not available.
-     */
-    @Nullable public List<ClusterNode> previousAssignment(int part);
-
-    /**
-     * Gets number of backups for new assignment.
-     *
-     * @return Number of backups for new assignment.
-     */
-    public int backups();
-
-    /**
-     * Gets current topology snapshot. Snapshot will contain only nodes on 
which particular cache is configured.
-     * List of passed nodes is guaranteed to be sorted in a same order on all 
nodes on which partition assignment
-     * is performed.
-     *
-     * @return Cache topology snapshot.
-     */
-    public List<ClusterNode> currentTopologySnapshot();
-
-    /**
-     * Gets current topology version number.
-     *
-     * @return Current topology version number.
-     */
-    public long currentTopologyVersion();
-
-    /**
-     * Gets discovery event caused topology change.
-     *
-     * @return Discovery event caused latest topology change or {@code null} 
if this information is
-     *      not available.
-     */
-    @Nullable public IgniteDiscoveryEvent discoveryEvent();
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityKey.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityKey.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityKey.java
deleted file mode 100644
index 21b8dfb..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityKey.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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.cache.affinity;
-
-import org.apache.ignite.internal.processors.cache.*;
-import org.apache.ignite.internal.util.typedef.internal.*;
-import org.apache.ignite.internal.util.tostring.*;
-
-import java.io.*;
-
-/**
- * Optional wrapper for cache keys to provide support
- * for custom affinity mapping. The value returned by
- * {@link #affinityKey(Object)} method will be used for key-to-node
- * affinity.
- * <p>
- * Note that the {@link #equals(Object)} and {@link #hashCode()} methods
- * delegate directly to the wrapped cache key provided by {@link #key()}
- * method.
- * <p>
- * This class is optional and does not have to be used. It only provides
- * extra convenience whenever custom affinity mapping is required. Here is
- * an example of how {@code Person} objects can be collocated with
- * {@code Company} objects they belong to:
- * <pre name="code" class="java">
- * Object personKey = new GridCacheAffinityKey(myPersonId, myCompanyId);
- *
- * // Both, the company and the person objects will be cached on the same node.
- * cache.put(myCompanyId, new Company(..));
- * cache.put(personKey, new Person(..));
- * </pre>
- * <p>
- * For more information and examples of cache affinity refer to
- * {@link GridCacheAffinityKeyMapper} and {@link GridCacheAffinityKeyMapped 
@GridCacheAffinityKeyMapped}
- * documentation.
- * @see GridCacheAffinityKeyMapped
- * @see GridCacheAffinityKeyMapper
- * @see GridCacheAffinityFunction
- */
-public class GridCacheAffinityKey<K> implements Externalizable {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /** Key. */
-    @GridToStringInclude
-    private K key;
-
-    /** Affinity key. */
-    @GridToStringInclude
-    private Object affKey;
-
-    /**
-     * Empty constructor.
-     */
-    public GridCacheAffinityKey() {
-        // No-op.
-    }
-
-    /**
-     * Initializes key wrapper for a given key. If affinity key
-     * is not initialized, then this key will be used for affinity.
-     *
-     * @param key Key.
-     */
-    public GridCacheAffinityKey(K key) {
-        A.notNull(key, "key");
-
-        this.key = key;
-    }
-
-    /**
-     * Initializes key together with its affinity key counter-part.
-     *
-     * @param key Key.
-     * @param affKey Affinity key.
-     */
-    public GridCacheAffinityKey(K key, Object affKey) {
-        A.notNull(key, "key");
-
-        this.key = key;
-        this.affKey = affKey;
-    }
-
-    /**
-     * Gets wrapped key.
-     *
-     * @return Wrapped key.
-     */
-    public K key() {
-        return key;
-    }
-
-    /**
-     * Sets wrapped key.
-     *
-     * @param key Wrapped key.
-     */
-    public void key(K key) {
-        this.key = key;
-    }
-
-    /**
-     * Gets affinity key to use for affinity mapping. If affinity key is not 
provided,
-     * then {@code key} value will be returned.
-     * <p>
-     * This method is annotated with {@link GridCacheAffinityKeyMapped} and 
will be picked up
-     * by {@link GridCacheDefaultAffinityKeyMapper} automatically.
-     *
-     * @return Affinity key to use for affinity mapping.
-     */
-    @GridCacheAffinityKeyMapped
-    @SuppressWarnings({"unchecked"})
-    public <T> T affinityKey() {
-        A.notNull(key, "key");
-
-        return (T)(affKey == null ? key : affKey);
-    }
-
-    /**
-     * Sets affinity key to use for affinity mapping. If affinity key is not 
provided,
-     * then {@code key} value will be returned.
-     *
-     * @param affKey Affinity key to use for affinity mapping.
-     */
-    public void affinityKey(Object affKey) {
-        this.affKey = affKey;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeExternal(ObjectOutput out) throws IOException {
-        out.writeObject(key);
-        out.writeObject(affKey);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
-        key = (K)in.readObject();
-        affKey = in.readObject();
-    }
-
-    /**
-     * Hash code implementation which delegates to the underlying {@link 
#key()}. Note, however,
-     * that different subclasses of {@code GridCacheAffinityKey} will produce 
different hash codes.
-     * <p>
-     * Users should override this method if different behavior is desired.
-     *
-     * @return Hash code.
-     */
-    @Override public int hashCode() {
-        A.notNull(key, "key");
-
-        return 31 * key.hashCode() + getClass().getName().hashCode();
-    }
-
-    /**
-     * Equality check which delegates to the underlying key equality. Note, 
however, that
-     * different subclasses of {@code GridCacheAffinityKey} will never be 
equal.
-     * <p>
-     * Users should override this method if different behavior is desired.
-     *
-     * @param obj Object to check for equality.
-     * @return {@code True} if objects are equal.
-     */
-    @Override public boolean equals(Object obj) {
-        A.notNull(key, "key");
-
-        return obj != null && getClass() == obj.getClass() && 
key.equals(((GridCacheAffinityKey)obj).key);
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(GridCacheAffinityKey.class, this);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cafee25f/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityKeyMapped.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityKeyMapped.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityKeyMapped.java
deleted file mode 100644
index 3cbac33..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/affinity/GridCacheAffinityKeyMapped.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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.cache.affinity;
-
-import java.lang.annotation.*;
-import java.util.concurrent.*;
-
-/**
- * Optional annotation to specify custom key-to-node affinity. Affinity key is 
a key
- * which will be used to determine a node on which given cache key will be 
stored. This
- * annotation allows to mark a field or a method in the cache key object that 
will be
- * used as an affinity key (instead of the entire cache key object that is 
used for
- * affinity by default). Note that a class can have only one field or method 
annotated
- * with {@code @GridCacheAffinityKeyMapped} annotation.
- * <p>
- * One of the major use cases for this annotation is the routing of grid 
computations
- * to the nodes where the data for this computation is cached, the concept
- * otherwise known as {@code Collocation Of Computations And Data}.
- * <p>
- * <h1 class="header">Mapping Cache Keys</h1>
- * The default implementation of {@link GridCacheAffinityKeyMapper}, which 
will be used
- * if no explicit affinity mapper is specified in cache configuration, will 
first look
- * for any field or method annotated with {@code @GridCacheAffinityKeyMapped} 
annotation.
- * If such field or method is not found, then the cache key itself will be 
used for
- * key-to-node affinity (this means that all objects with the same cache key 
will always
- * be routed to the same node). If such field or method is found, then the 
value of this
- * field or method will be used for key-to-node affinity. This allows to 
specify alternate
- * affinity key, other than the cache key itself, whenever needed.
- * <p>
- * For example, if a {@code Person} object is always accessed together with a 
{@code Company} object
- * for which this person is an employee, then for better performance and 
scalability it makes sense to
- * collocate {@code Person} objects together with their {@code Company} object 
when storing them in
- * cache. To achieve that, cache key used to cache {@code Person} objects 
should have a field or method
- * annotated with {@code @GridCacheAffinityKeyMapped} annotation, which will 
provide the value of
- * the company key for which that person works, like so:
- * <pre name="code" class="java">
- * public class PersonKey {
- *     // Person ID used to identify a person.
- *     private String personId;
- *
- *     // Company ID which will be used for affinity.
- *     &#64;GridCacheAffinityKeyMapped
- *     private String companyId;
- *     ...
- * }
- * ...
- * // Instantiate person keys.
- * Object personKey1 = new PersonKey("myPersonId1", "myCompanyId");
- * Object personKey2 = new PersonKey("myPersonId2", "myCompanyId");
- *
- * // Both, the company and the person objects will be cached on the same node.
- * cache.put("myCompanyId", new Company(..));
- * cache.put(personKey1, new Person(..));
- * cache.put(personKey2, new Person(..));
- * </pre>
- * <p>
- * <h2 class="header">GridCacheAffinityKey</h2>
- * For convenience, you can also optionally use {@link GridCacheAffinityKey} 
class. Here is how a
- * {@code PersonKey} defined above would look using {@link 
GridCacheAffinityKey}:
- * <pre name="code" class="java">
- * Object personKey1 = new GridCacheAffinityKey("myPersonId1", "myCompanyId");
- * Object personKey2 = new GridCacheAffinityKey("myPersonId2", "myCompanyId");
- *
- * // Both, the company and the person objects will be cached on the same node.
- * cache.put(myCompanyId, new Company(..));
- * cache.put(personKey1, new Person(..));
- * cache.put(personKey2, new Person(..));
- * </pre>
- * <p>
- * <h1 class="header">Collocating Computations And Data</h1>
- * It is also possible to route computations to the nodes where the data is 
cached. This concept
- * is otherwise known as {@code Collocation Of Computations And Data}. In this 
case,
- * {@code @GridCacheAffinityKeyMapped} annotation allows to specify a routing 
affinity key for a
- * {@link org.apache.ignite.compute.ComputeJob} or any other grid computation, 
such as {@link Runnable}, {@link Callable}, or
- * {@link org.apache.ignite.lang.IgniteClosure}. It should be attached to a 
method or field that provides affinity key
- * for the computation. Only one annotation per class is allowed. Whenever 
such annotation is detected,
- * then {@link org.apache.ignite.spi.loadbalancing.LoadBalancingSpi} will be 
bypassed, and computation will be routed to the grid node
- * where the specified affinity key is cached. You can also use optional 
{@link org.apache.ignite.cache.GridCacheName @GridCacheName}
- * annotation whenever non-default cache name needs to be specified.
- * <p>
- * Here is how this annotation can be used to route a job to a node where 
Person object
- * is cached with ID "1234":
- * <pre name="code" class="java">
- * G.grid().run(new Runnable() {
- *     // This annotation is optional. If omitted, then default
- *     // no-name cache will be used.
- *     &#64;GridCacheName
- *     private String cacheName = "myCache";
- *
- *     // This annotation specifies that computation should be routed
- *     // precisely to the node where key '1234' is cached.
- *     &#64;GridCacheAffinityKeyMapped
- *     private String personKey = "1234";
- *
- *     &#64;Override public void run() {
- *         // Some computation logic here.
- *         ...
- *     }
- * };
- * </pre>
- * The same can be achieved by annotating method instead of field as follows:
- * <pre name="code" class="java">
- * G.grid().run(new Runnable() {
- *     &#64;Override public void run() {
- *         // Some computation logic here.
- *         ...
- *     }
- *
- *     // This annotation is optional. If omitted, then default
- *     // no-name cache will be used.
- *     &#64;GridCacheName
- *     public String cacheName() {
- *         return "myCache";
- *     }
- *
- *     // This annotation specifies that computation should be routed
- *     // precisely to the node where key '1234' is cached.
- *     &#64;GridCacheAffinityKeyMapped
- *     public String personKey() {
- *         return "1234";
- *     }
- * };
- * </pre>
- * <p>
- * For more information about cache affinity also see {@link 
GridCacheAffinityKeyMapper} and
- * {@link GridCacheAffinityFunction} documentation.
- * Affinity for a key can be found from any node, regardless of whether it has 
cache started
- * or not. If cache is not started, affinity function will be fetched from the 
remote node
- * which does have the cache running.
- *
- * @see org.apache.ignite.cache.GridCacheName
- * @see GridCacheAffinityFunction
- * @see GridCacheAffinityKeyMapper
- * @see GridCacheAffinityKey
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.FIELD, ElementType.METHOD})
-public @interface GridCacheAffinityKeyMapped {
-    // No-op.
-}

Reply via email to