package org.apache.cassandra.service; import org.apache.cassandra.db.ReadResponse; import org.apache.cassandra.utils.Pair; import java.net.InetAddress; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReferenceArray; /** * Read operation timeout exception based on RpcTimeoutInMillis property in storage configuration * * Created by sergey.trevgoda on 15.09.14. */ public class ReadTimeoutException extends TimeoutException { private final List<InetAddress> successReadNodes; private final List<InetAddress> failReadNodes; private ReadTimeoutException(String message, List<InetAddress> successReadNodes, List<InetAddress> failReadNodes) { super(message); this.successReadNodes = successReadNodes; this.failReadNodes = failReadNodes; } /** * Quorum response timeout case (maybe some nodes are slow) * @param endPointList - the list of replicas nodes based on key * @param responses - the list of received responses * (initially fill with nulls, endPointList.size length - then populated with values from nodes) * @return - exception with detailed info */ public static ReadTimeoutException quorumTimeout(List<InetAddress> endPointList, AtomicReferenceArray<Pair<InetAddress, ReadResponse>> responses) { int endPointListSize = endPointList.size(); List<InetAddress> successReadNodes = new ArrayList<InetAddress>(endPointListSize); List<InetAddress> failReadNodes = new ArrayList<InetAddress>(endPointListSize); for (int i = 0; i < responses.length(); i++) { Pair<InetAddress, ReadResponse> pair = responses.get(i); if (pair != null) { // we have response within given timeout successReadNodes.add(pair.left); } } for (InetAddress endPoint : endPointList) { if (!successReadNodes.contains(endPoint)) { failReadNodes.add(endPoint); } } String detailedMessage = String.format("Quorum read timed out: success nodes: [%s], failed nodes : [%s]", getNodesList(successReadNodes), getNodesList(failReadNodes)); return new ReadTimeoutException(detailedMessage, successReadNodes, failReadNodes); } public List<InetAddress> getSuccessReadNodes() { return successReadNodes; } public List<InetAddress> getFailReadNodes() { return failReadNodes; } private static String getNodesList(List<InetAddress> nodes) { if (nodes == null || nodes.isEmpty()) { return ""; } StringBuilder str = new StringBuilder(); for (InetAddress node : nodes) { str.append(node.getHostAddress()).append(", "); } int length = str.length(); if (length > 0) { str.setLength(length - 2); } return str.toString(); } }