/* * Copyright 2015 Edward Capriolo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.teknek.nibiru.router; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; import io.teknek.nibiru.Destination; import io.teknek.nibiru.Keyspace; import io.teknek.nibiru.ServerId; import io.teknek.nibiru.Token; import io.teknek.nibiru.cluster.ClusterMembership; public class TokenRouter implements Router { public static final String TOKEN_MAP_KEY = "token_map"; public static final String REPLICATION_FACTOR = "replication_factor"; @SuppressWarnings("unchecked") private TreeMap<String,String> getTokenMap(Keyspace requestKeyspace){ Map<String,String> s = (Map<String, String>) requestKeyspace .getKeyspaceMetaData().getProperties().get(TOKEN_MAP_KEY); return new TreeMap<String,String>(s); } private int getReplicationFactor(Keyspace requestKeyspace){ Integer replicationFactor = (Integer) requestKeyspace .getKeyspaceMetaData().getProperties().get(REPLICATION_FACTOR); int rf = 1; if (replicationFactor != null){ rf = replicationFactor; } return rf; } @Override public List<Destination> routesTo(ServerId local, Keyspace requestKeyspace, ClusterMembership clusterMembership, Token token) { TreeMap<String, String> tokenMap = getTokenMap(requestKeyspace); int rf = getReplicationFactor(requestKeyspace); if (rf > tokenMap.size()) { throw new IllegalArgumentException("Replication factor > than token map size"); } List<Destination> destinations = new ArrayList<Destination>(); Map.Entry<String,String> ceilingEntry = tokenMap.ceilingEntry(token.getToken()); if (ceilingEntry == null){ ceilingEntry = tokenMap.firstEntry(); } destinations.add(new Destination(ceilingEntry.getValue())); for (int i = 1; i < rf; i++) { ceilingEntry = tokenMap.higherEntry(ceilingEntry.getKey()); if (ceilingEntry == null) { ceilingEntry = tokenMap.firstEntry(); } destinations.add(new Destination(ceilingEntry.getValue())); } return destinations; } }