I am using the C++ bindings to have redundancy in my application. Alongside the main C++ node, I am running a vanilla Java node via ignite.sh
as a backup on another node. I would like appoint this vanilla Java node to always stay a backup node and never a primary node as long as there is a C++ node running. Also, I need the C++ nodes to always stay as primary nodes. A little data loss is acceptable with the PRIMARY_SYNC
synchronization.
My research led me to AffinityFunction.BackupFilter
property to filter C++ nodes as primary. It seems that there is also some functions to give attributes to nodes. So I guess I can set a specific attribute on C++ nodes and filter them to always stay as primary nodes.
However, C++ bindings apparently neither provide a way to set backup filter nor allow setting attributes on the launched node. I have noticed some modules get plugged through ignite-dir/libs
but there is no tutorial about that approach to add AffinityFunction
. How can I achieve what I need? I need to plug a custom affinity function while using C++ as the main and a way to distinguish the C++ nodes.
Ignite adds the files in ignite_dir/libs
into classpath. According to the documentation, environment variables can be read via ClusterNode.attribute()
method. So I have put the following java code to libs/
folder:
import java.util.List;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.lang.IgniteBiPredicate;
import org.apache.ignite.cache.affinity.*;
public class RendezvousAffinityFunction extends org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction {
@Override
public List<List<ClusterNode>> assignPartitions(AffinityFunctionContext affCtx) {
System.out.println("Assigning partitions...");
List<List<ClusterNode>> partitions = super.assignPartitions(affCtx);
for (List<ClusterNode> nodes : partitions) {
for (int i = 0; i < nodes.size(); ++i) {
ClusterNode node = nodes.get(i);
boolean is_primary_instance = ((Object)node.attribute("IGNITE_PRIMARY_NODE") != null);
if (is_primary_instance && i != 0) {
// move to the top of the node list
nodes.remove(i);
nodes.add(0, node);
System.out.println("Putting node " + i + " to the head of the node list.");
}
}
}
return partitions;
}
}
Apparently, this method is called on topology change. The method override checks the environment variable IGNITE_PRIMARY_NODE
, if it exists, it puts the node at the beginning of the ClusterNode
list which is then used as the primary node by Ignite. This override will prefer the nodes with IGNITE_PRIMARY_NODE
environment variable set as the primary nodes.