/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.linkedin.pinot.routing; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.codehaus.jackson.map.ObjectMapper; import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.linkedin.pinot.common.response.ServerInstance; import com.linkedin.pinot.common.utils.CommonConstants; import com.linkedin.pinot.common.utils.EqualityUtils; import com.linkedin.pinot.transport.common.SegmentId; import com.linkedin.pinot.transport.common.SegmentIdSet; /** * Data structure to hold a whole mapping from ServerInstances to all the queryable segments. * * */ public class ServerToSegmentSetMap { private static final ObjectMapper mapper = new ObjectMapper(); private static final Logger logger = LoggerFactory.getLogger(ServerToSegmentSetMap.class); private Map<String, Set<String>> _serverToSegmentSetMap; private Map<ServerInstance, SegmentIdSet> _routingTable; public static final String NAME_PORT_DELIMITER = "_"; public ServerToSegmentSetMap(Map<String, Set<String>> serverToSegmentSetMap) { _serverToSegmentSetMap = serverToSegmentSetMap; _routingTable = new HashMap<ServerInstance, SegmentIdSet>(); for (Entry<String, Set<String>> entry : _serverToSegmentSetMap.entrySet()) { String namePortStr = entry.getKey().split(CommonConstants.Helix.PREFIX_OF_SERVER_INSTANCE)[1]; String hostName = namePortStr.split(NAME_PORT_DELIMITER)[0]; int port; try { port = Integer.parseInt(namePortStr.split(NAME_PORT_DELIMITER)[1]); } catch (Exception e) { port = CommonConstants.Helix.DEFAULT_SERVER_NETTY_PORT; } ServerInstance serverInstance = new ServerInstance(hostName, port); SegmentIdSet segmentIdSet = new SegmentIdSet(); for (String segmentId : entry.getValue()) { segmentIdSet.addSegment(new SegmentId(segmentId)); } _routingTable.put(serverInstance, segmentIdSet); } } public Set<String> getServerSet() { return _serverToSegmentSetMap.keySet(); } public Set<String> getSegmentSet(String server) { return _serverToSegmentSetMap.get(server); } public Map<ServerInstance, SegmentIdSet> getRouting() { return _routingTable; } @Override public String toString() { try { JSONObject ret = new JSONObject(); for (ServerInstance i : _routingTable.keySet()) { JSONArray serverInstanceSegmentList = new JSONArray(); List<String> sortedSegmentIds = new ArrayList<>(); for (SegmentId segmentId : _routingTable.get(i).getSegments()) { sortedSegmentIds.add(segmentId.getSegmentId()); } Collections.sort(sortedSegmentIds); for (String sortedSegmentId : sortedSegmentIds) { serverInstanceSegmentList.put(sortedSegmentId); } ret.put(i.toString(), serverInstanceSegmentList); } return ret.toString(); } catch (Exception e) { logger.error("error toString()", e); return "routing table : [ " + _routingTable + " ] "; } } @Override public boolean equals(Object o) { if (EqualityUtils.isSameReference(this, o)) { return true; } if (EqualityUtils.isNullOrNotSameClass(this, o)) { return false; } ServerToSegmentSetMap other = (ServerToSegmentSetMap) o; return EqualityUtils.isEqual(_serverToSegmentSetMap, other._serverToSegmentSetMap) && EqualityUtils.isEqual(_routingTable, other._routingTable); } @Override public int hashCode() { int result = EqualityUtils.hashCodeOf(_serverToSegmentSetMap); result = EqualityUtils.hashCodeOf(result, _routingTable); return result; } }