com.linkedin.pinot.controller.api.restlet.resources.ServerTableSizeReader.java Source code

Java tutorial

Introduction

Here is the source code for com.linkedin.pinot.controller.api.restlet.resources.ServerTableSizeReader.java

Source

/**
 * Copyright (C) 2014-2015 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.controller.api.restlet.resources;

import com.google.common.base.Throwables;
import com.google.common.collect.BiMap;
import com.linkedin.pinot.common.http.MultiGetRequest;
import com.linkedin.pinot.common.restlet.resources.SegmentSizeInfo;
import com.linkedin.pinot.common.restlet.resources.TableSizeInfo;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.ConnectionPoolTimeoutException;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.methods.GetMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Get the size information details from the server. Only the servers returning success are returned by the method
 * For servers returning errors (http error or otherwise), no entry is created in the return map
 */
public class ServerTableSizeReader {
    private static final Logger LOGGER = LoggerFactory.getLogger(ServerTableSizeReader.class);

    private final Executor executor;
    private final HttpConnectionManager connectionManager;

    public ServerTableSizeReader(Executor executor, HttpConnectionManager connectionManager) {
        this.executor = executor;
        this.connectionManager = connectionManager;
    }

    public Map<String, List<SegmentSizeInfo>> getSizeDetailsFromServers(BiMap<String, String> serverEndPoints,
            String table, int timeoutMsec) {

        List<String> serverUrls = new ArrayList<>(serverEndPoints.size());
        BiMap<String, String> endpointsToServers = serverEndPoints.inverse();
        for (String endpoint : endpointsToServers.keySet()) {
            String tableSizeUri = "http://" + endpoint + "/table/" + table + "/size";
            serverUrls.add(tableSizeUri);
        }

        MultiGetRequest mget = new MultiGetRequest(executor, connectionManager);
        LOGGER.info("Reading segment sizes from servers for table: {}, timeoutMsec: {}", table, timeoutMsec);
        CompletionService<GetMethod> completionService = mget.execute(serverUrls, timeoutMsec);

        Map<String, List<SegmentSizeInfo>> serverSegmentSizes = new HashMap<>(serverEndPoints.size());

        for (int i = 0; i < serverUrls.size(); i++) {
            try {
                GetMethod getMethod = completionService.take().get();
                URI uri = getMethod.getURI();
                String instance = endpointsToServers.get(uri.getHost() + ":" + uri.getPort());
                if (getMethod.getStatusCode() >= 300) {
                    LOGGER.error("Server: {} returned error: {}", instance, getMethod.getStatusCode());
                    continue;
                }
                TableSizeInfo tableSizeInfo = new ObjectMapper().readValue(getMethod.getResponseBodyAsString(),
                        TableSizeInfo.class);
                serverSegmentSizes.put(instance, tableSizeInfo.segments);
            } catch (InterruptedException e) {
                LOGGER.warn("Interrupted exception while reading segment size for table: {}", table, e);
            } catch (ExecutionException e) {
                if (Throwables.getRootCause(e) instanceof SocketTimeoutException) {
                    LOGGER.warn("Server request to read table size was timed out for table: {}", table, e);
                } else if (Throwables.getRootCause(e) instanceof ConnectTimeoutException) {
                    LOGGER.warn("Server request to read table size timed out waiting for connection. table: {}",
                            table, e);
                } else if (Throwables.getRootCause(e) instanceof ConnectionPoolTimeoutException) {
                    LOGGER.warn(
                            "Server request to read table size timed out on getting a connection from pool, table: {}",
                            table, e);
                } else {
                    LOGGER.warn("Execution exception while reading segment sizes for table: {}", table, e);
                }
            } catch (Exception e) {
                LOGGER.warn("Error while reading segment sizes for table: {}", table);
            }
        }
        LOGGER.info("Finished reading segment sizes for table: {}", table);
        return serverSegmentSizes;
    }
}