Search in sources :

Example 1 with DrillbitEndpoint

use of org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint in project drill by apache.

the class MongoGroupScan method getOperatorAffinity.

@Override
public List<EndpointAffinity> getOperatorAffinity() {
    watch.reset();
    watch.start();
    Map<String, DrillbitEndpoint> endpointMap = Maps.newHashMap();
    for (DrillbitEndpoint endpoint : storagePlugin.getContext().getBits()) {
        endpointMap.put(endpoint.getAddress(), endpoint);
        logger.debug("Endpoint address: {}", endpoint.getAddress());
    }
    Map<DrillbitEndpoint, EndpointAffinity> affinityMap = Maps.newHashMap();
    // multiple replicas for each chunk.
    for (Set<ServerAddress> addressList : chunksMapping.values()) {
        // meets affinity.
        for (ServerAddress address : addressList) {
            DrillbitEndpoint ep = endpointMap.get(address.getHost());
            if (ep != null) {
                EndpointAffinity affinity = affinityMap.get(ep);
                if (affinity == null) {
                    affinityMap.put(ep, new EndpointAffinity(ep, 1));
                } else {
                    affinity.addAffinity(1);
                }
                break;
            }
        }
    }
    logger.debug("Took {} µs to get operator affinity", watch.elapsed(TimeUnit.NANOSECONDS) / 1000);
    logger.debug("Affined drillbits : " + affinityMap.values());
    return Lists.newArrayList(affinityMap.values());
}
Also used : DrillbitEndpoint(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint) ServerAddress(com.mongodb.ServerAddress) EndpointAffinity(org.apache.drill.exec.physical.EndpointAffinity)

Example 2 with DrillbitEndpoint

use of org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint in project drill by apache.

the class DrillClient method parseAndVerifyEndpoints.

/**
   * Populates the endpointlist with drillbits information provided in the connection string by client.
   * For direct connection we can have connection string with drillbit property as below:
   * <dl>
   *   <dt>drillbit=ip</dt>
   *   <dd>use the ip specified as the Foreman ip with default port in config file</dd>
   *   <dt>drillbit=ip:port</dt>
   *   <dd>use the ip and port specified as the Foreman ip and port</dd>
   *   <dt>drillbit=ip1:port1,ip2:port2,...</dt>
   *   <dd>randomly select the ip and port pair from the specified list as the Foreman ip and port.</dd>
   * </dl>
   *
   * @param drillbits string with drillbit value provided in connection string
   * @param defaultUserPort string with default userport of drillbit specified in config file
   * @return list of drillbit endpoints parsed from connection string
   * @throws InvalidConnectionInfoException if the connection string has invalid or no drillbit information
   */
static List<DrillbitEndpoint> parseAndVerifyEndpoints(String drillbits, String defaultUserPort) throws InvalidConnectionInfoException {
    // If no drillbits is provided then throw exception
    drillbits = drillbits.trim();
    if (drillbits.isEmpty()) {
        throw new InvalidConnectionInfoException("No drillbit information specified in the connection string");
    }
    final List<DrillbitEndpoint> endpointList = new ArrayList<>();
    final String[] connectInfo = drillbits.split(",");
    // Fetch ip address and port information for each drillbit and populate the list
    for (String drillbit : connectInfo) {
        // Trim all the empty spaces and check if the entry is empty string.
        // Ignore the empty ones.
        drillbit = drillbit.trim();
        if (!drillbit.isEmpty()) {
            // Verify if we have only ":" or only ":port" pattern
            if (drillbit.charAt(0) == ':') {
                // Invalid drillbit information
                throw new InvalidConnectionInfoException("Malformed connection string with drillbit hostname or " + "hostaddress missing for an entry: " + drillbit);
            }
            // We are now sure that each ip:port entry will have both the values atleast once.
            // Split each drillbit connection string to get ip address and port value
            final String[] drillbitInfo = drillbit.split(":");
            // Check if we have more than one port
            if (drillbitInfo.length > 2) {
                throw new InvalidConnectionInfoException("Malformed connection string with more than one port in a " + "drillbit entry: " + drillbit);
            }
            // At this point we are sure that drillbitInfo has atleast hostname or host address
            // trim all the empty spaces which might be present in front of hostname or
            // host address information
            final String ipAddress = drillbitInfo[0].trim();
            String port = defaultUserPort;
            if (drillbitInfo.length == 2) {
                // We have a port value also given by user. trim all the empty spaces between : and port value before
                // validating the correctness of value.
                port = drillbitInfo[1].trim();
            }
            try {
                final DrillbitEndpoint endpoint = DrillbitEndpoint.newBuilder().setAddress(ipAddress).setUserPort(Integer.parseInt(port)).build();
                endpointList.add(endpoint);
            } catch (NumberFormatException e) {
                throw new InvalidConnectionInfoException("Malformed port value in entry: " + ipAddress + ":" + port + " " + "passed in connection string");
            }
        }
    }
    if (endpointList.size() == 0) {
        throw new InvalidConnectionInfoException("No valid drillbit information specified in the connection string");
    }
    return endpointList;
}
Also used : DrillbitEndpoint(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint) ArrayList(java.util.ArrayList)

Example 3 with DrillbitEndpoint

use of org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint in project drill by apache.

the class DrillClient method connect.

public synchronized void connect(String connect, Properties props) throws RpcException {
    if (connected) {
        return;
    }
    properties = DrillProperties.createFromProperties(props);
    final List<DrillbitEndpoint> endpoints = new ArrayList<>();
    if (isDirectConnection) {
        // Populate the endpoints list with all the drillbit information provided in the connection string
        endpoints.addAll(parseAndVerifyEndpoints(properties.getProperty(DrillProperties.DRILLBIT_CONNECTION), config.getString(ExecConstants.INITIAL_USER_PORT)));
    } else {
        if (ownsZkConnection) {
            try {
                this.clusterCoordinator = new ZKClusterCoordinator(this.config, connect);
                this.clusterCoordinator.start(10000);
            } catch (Exception e) {
                throw new RpcException("Failure setting up ZK for client.", e);
            }
        }
        endpoints.addAll(clusterCoordinator.getAvailableEndpoints());
        // Make sure we have at least one endpoint in the list
        checkState(!endpoints.isEmpty(), "No active Drillbit endpoint found from ZooKeeper. Check connection parameters?");
    }
    // shuffle the collection then get the first endpoint
    Collections.shuffle(endpoints);
    eventLoopGroup = createEventLoop(config.getInt(ExecConstants.CLIENT_RPC_THREADS), "Client-");
    executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new NamedThreadFactory("drill-client-executor-")) {

        @Override
        protected void afterExecute(final Runnable r, final Throwable t) {
            if (t != null) {
                logger.error("{}.run() leaked an exception.", r.getClass().getName(), t);
            }
            super.afterExecute(r, t);
        }
    };
    final String connectTriesConf = properties.getProperty(DrillProperties.TRIES, "5");
    int connectTriesVal;
    try {
        connectTriesVal = Math.min(endpoints.size(), Integer.parseInt(connectTriesConf));
    } catch (NumberFormatException e) {
        throw new InvalidConnectionInfoException("Invalid tries value: " + connectTriesConf + " specified in " + "connection string");
    }
    // If the value provided in the connection string is <=0 then override with 1 since we want to try connecting
    // at least once
    connectTriesVal = Math.max(1, connectTriesVal);
    int triedEndpointIndex = 0;
    DrillbitEndpoint endpoint;
    while (triedEndpointIndex < connectTriesVal) {
        client = new UserClient(clientName, config, supportComplexTypes, allocator, eventLoopGroup, executor);
        endpoint = endpoints.get(triedEndpointIndex);
        logger.debug("Connecting to server {}:{}", endpoint.getAddress(), endpoint.getUserPort());
        if (!properties.containsKey(DrillProperties.SERVICE_HOST)) {
            properties.setProperty(DrillProperties.SERVICE_HOST, endpoint.getAddress());
        }
        try {
            connect(endpoint);
            connected = true;
            logger.info("Successfully connected to server {}:{}", endpoint.getAddress(), endpoint.getUserPort());
            break;
        } catch (NonTransientRpcException ex) {
            logger.error("Connection to {}:{} failed with error {}. Not retrying anymore", endpoint.getAddress(), endpoint.getUserPort(), ex.getMessage());
            throw ex;
        } catch (RpcException ex) {
            ++triedEndpointIndex;
            logger.error("Attempt {}: Failed to connect to server {}:{}", triedEndpointIndex, endpoint.getAddress(), endpoint.getUserPort());
            // Throw exception when we have exhausted all the tries without having a successful connection
            if (triedEndpointIndex == connectTriesVal) {
                throw ex;
            }
            // Close the connection here to avoid calling close twice in case when all tries are exhausted.
            // Since DrillClient.close is also calling client.close
            client.close();
        }
    }
}
Also used : UserClient(org.apache.drill.exec.rpc.user.UserClient) NamedThreadFactory(org.apache.drill.exec.rpc.NamedThreadFactory) ArrayList(java.util.ArrayList) NonTransientRpcException(org.apache.drill.exec.rpc.NonTransientRpcException) ZKClusterCoordinator(org.apache.drill.exec.coord.zk.ZKClusterCoordinator) UserException(org.apache.drill.common.exceptions.UserException) RpcException(org.apache.drill.exec.rpc.RpcException) ChannelClosedException(org.apache.drill.exec.rpc.ChannelClosedException) OutOfMemoryException(org.apache.drill.exec.exception.OutOfMemoryException) NonTransientRpcException(org.apache.drill.exec.rpc.NonTransientRpcException) IOException(java.io.IOException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) DrillbitEndpoint(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint) DrillbitEndpoint(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint) RpcException(org.apache.drill.exec.rpc.RpcException) NonTransientRpcException(org.apache.drill.exec.rpc.NonTransientRpcException) SynchronousQueue(java.util.concurrent.SynchronousQueue) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor)

Example 4 with DrillbitEndpoint

use of org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint in project drill by apache.

the class TestMongoChunkAssignment method testMongoGroupScanAssignmentMix.

@Test
public void testMongoGroupScanAssignmentMix() throws UnknownHostException, ExecutionSetupException {
    final List<DrillbitEndpoint> endpoints = Lists.newArrayList();
    final DrillbitEndpoint DB_A = DrillbitEndpoint.newBuilder().setAddress(HOST_A).setControlPort(1234).build();
    endpoints.add(DB_A);
    endpoints.add(DB_A);
    final DrillbitEndpoint DB_B = DrillbitEndpoint.newBuilder().setAddress(HOST_B).setControlPort(1234).build();
    endpoints.add(DB_B);
    final DrillbitEndpoint DB_D = DrillbitEndpoint.newBuilder().setAddress(HOST_D).setControlPort(1234).build();
    endpoints.add(DB_D);
    final DrillbitEndpoint DB_X = DrillbitEndpoint.newBuilder().setAddress(HOST_X).setControlPort(1234).build();
    endpoints.add(DB_X);
    mongoGroupScan.applyAssignments(endpoints);
    // assignments for chunks on host A, assign on drill bit A
    assertEquals(1, mongoGroupScan.getSpecificScan(0).getChunkScanSpecList().size());
    // assignments for chunks on host A, assign on drill bit A
    assertEquals(1, mongoGroupScan.getSpecificScan(1).getChunkScanSpecList().size());
    // assignments for chunks on host B, assign on drill bit B
    assertEquals(1, mongoGroupScan.getSpecificScan(2).getChunkScanSpecList().size());
    // assignments for chunks on host D, assign on drill bit D
    assertEquals(1, mongoGroupScan.getSpecificScan(3).getChunkScanSpecList().size());
    // assignments for chunks on host C, assign on drill bit X
    assertEquals(2, mongoGroupScan.getSpecificScan(4).getChunkScanSpecList().size());
}
Also used : DrillbitEndpoint(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint) Test(org.junit.Test)

Example 5 with DrillbitEndpoint

use of org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint in project drill by apache.

the class TestMongoChunkAssignment method testMongoGroupScanAssignmentAllAffinity.

@Test
public void testMongoGroupScanAssignmentAllAffinity() throws UnknownHostException, ExecutionSetupException {
    final List<DrillbitEndpoint> endpoints = Lists.newArrayList();
    final DrillbitEndpoint DB_A = DrillbitEndpoint.newBuilder().setAddress(HOST_A).setControlPort(1234).build();
    endpoints.add(DB_A);
    final DrillbitEndpoint DB_B = DrillbitEndpoint.newBuilder().setAddress(HOST_B).setControlPort(1234).build();
    endpoints.add(DB_B);
    final DrillbitEndpoint DB_C = DrillbitEndpoint.newBuilder().setAddress(HOST_C).setControlPort(1234).build();
    endpoints.add(DB_C);
    final DrillbitEndpoint DB_D = DrillbitEndpoint.newBuilder().setAddress(HOST_D).setControlPort(1234).build();
    endpoints.add(DB_D);
    mongoGroupScan.applyAssignments(endpoints);
    // assignments for chunks on host A, assign on drill bit A
    assertEquals(2, mongoGroupScan.getSpecificScan(0).getChunkScanSpecList().size());
    // assignments for chunks on host B, assign on drill bit B
    assertEquals(1, mongoGroupScan.getSpecificScan(1).getChunkScanSpecList().size());
    // assignments for chunks on host C, assign on drill bit C
    assertEquals(2, mongoGroupScan.getSpecificScan(2).getChunkScanSpecList().size());
    // assignments for chunks on host D, assign on drill bit D
    assertEquals(1, mongoGroupScan.getSpecificScan(3).getChunkScanSpecList().size());
}
Also used : DrillbitEndpoint(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint) Test(org.junit.Test)

Aggregations

DrillbitEndpoint (org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint)77 Test (org.junit.Test)23 EndpointAffinity (org.apache.drill.exec.physical.EndpointAffinity)14 IOException (java.io.IOException)9 Stopwatch (com.google.common.base.Stopwatch)7 ArrayList (java.util.ArrayList)7 PlanFragment (org.apache.drill.exec.proto.BitControl.PlanFragment)7 ServerName (org.apache.hadoop.hbase.ServerName)7 HRegionInfo (org.apache.hadoop.hbase.HRegionInfo)6 Entry (java.util.Map.Entry)5 DrillConfig (org.apache.drill.common.config.DrillConfig)5 FragmentHandle (org.apache.drill.exec.proto.ExecProtos.FragmentHandle)5 DrillbitContext (org.apache.drill.exec.server.DrillbitContext)5 HBaseGroupScan (org.apache.drill.exec.store.hbase.HBaseGroupScan)5 HBaseScanSpec (org.apache.drill.exec.store.hbase.HBaseScanSpec)5 QueryWorkUnit (org.apache.drill.exec.work.QueryWorkUnit)5 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)4 HashMap (java.util.HashMap)4 AtomicLong (java.util.concurrent.atomic.AtomicLong)4 NonStrictExpectations (mockit.NonStrictExpectations)4