public List<InetAddress> getEndpoints(TokenRange range) {
   Set<Host> hostSet = rangeMap.get(range);
   List<InetAddress> addresses = new ArrayList<>(hostSet.size());
   for (Host host : hostSet) {
     addresses.add(host.getAddress());
   }
   return addresses;
 }
Beispiel #2
0
    /*
     * When the set of live nodes change, the loadbalancer will change his
     * mind on host distances. It might change it on the node that came/left
     * but also on other nodes (for instance, if a node dies, another
     * previously ignored node may be now considered).
     *
     * This method ensures that all hosts for which a pool should exist
     * have one, and hosts that shouldn't don't.
     */
    private void updateCreatedPools() {
      for (Host h : cluster.getMetadata().allHosts()) {
        HostDistance dist = loadBalancingPolicy().distance(h);
        HostConnectionPool pool = pools.get(h);

        if (pool == null) {
          if (dist != HostDistance.IGNORED && h.getMonitor().isUp()) addOrRenewPool(h);
        } else if (dist != pool.hostDistance) {
          if (dist == HostDistance.IGNORED) {
            removePool(h);
          } else {
            pool.hostDistance = dist;
          }
        }
      }
    }
Beispiel #3
0
    public void onDown(Host host) {
      loadBalancer.onDown(host);
      HostConnectionPool pool = pools.remove(host);

      // This should not be necessary but it's harmless
      if (pool != null) pool.shutdown();

      // If we've remove a host, the loadBalancer is allowed to change his mind on host distances.
      for (Host h : cluster.getMetadata().allHosts()) {
        if (!h.getMonitor().isUp()) continue;

        HostDistance dist = loadBalancer.distance(h);
        if (dist != HostDistance.IGNORED) {
          HostConnectionPool p = pools.get(h);
          if (p == null) addHost(host);
          else p.hostDistance = dist;
        }
      }
    }
Beispiel #4
0
 private HostConnectionPool addHost(Host host) {
   try {
     HostDistance distance = loadBalancer.distance(host);
     if (distance == HostDistance.IGNORED) {
       return pools.get(host);
     } else {
       logger.debug("Adding {} to list of queried hosts", host);
       return pools.put(host, new HostConnectionPool(host, distance, this));
     }
   } catch (AuthenticationException e) {
     logger.error("Error creating pool to {} ({})", host, e.getMessage());
     host.getMonitor()
         .signalConnectionFailure(new ConnectionException(e.getHost(), e.getMessage()));
     return pools.get(host);
   } catch (ConnectionException e) {
     logger.debug("Error creating pool to {} ({})", host, e.getMessage());
     host.getMonitor().signalConnectionFailure(e);
     return pools.get(host);
   }
 }
  public Connection borrowConnection(long timeout, TimeUnit unit)
      throws ConnectionException, TimeoutException {
    if (isShutdown.get())
      // Note: throwing a ConnectionException is probably fine in practice as it will trigger the
      // creation of a new host.
      // That being said, maybe having a specific exception could be cleaner.
      throw new ConnectionException(host.getAddress(), "Pool is shutdown");

    if (connections.isEmpty()) {
      for (int i = 0; i < options().getCoreConnectionsPerHost(hostDistance); i++) {
        // We don't respect MAX_SIMULTANEOUS_CREATION here because it's  only to
        // protect against creating connection in excess of core too quickly
        scheduledForCreation.incrementAndGet();
        manager.executor().submit(newConnectionTask);
      }
      Connection c = waitForConnection(timeout, unit);
      c.setKeyspace(manager.poolsState.keyspace);
      return c;
    }

    int minInFlight = Integer.MAX_VALUE;
    Connection leastBusy = null;
    for (Connection connection : connections) {
      int inFlight = connection.inFlight.get();
      if (inFlight < minInFlight) {
        minInFlight = inFlight;
        leastBusy = connection;
      }
    }

    if (minInFlight >= options().getMaxSimultaneousRequestsPerConnectionThreshold(hostDistance)
        && connections.size() < options().getMaxConnectionsPerHost(hostDistance))
      maybeSpawnNewConnection();

    while (true) {
      int inFlight = leastBusy.inFlight.get();

      if (inFlight >= Connection.MAX_STREAM_PER_CONNECTION) {
        leastBusy = waitForConnection(timeout, unit);
        break;
      }

      if (leastBusy.inFlight.compareAndSet(inFlight, inFlight + 1)) break;
    }
    leastBusy.setKeyspace(manager.poolsState.keyspace);
    return leastBusy;
  }
  public void returnConnection(Connection connection) {
    int inFlight = connection.inFlight.decrementAndGet();

    if (connection.isDefunct()) {
      if (host.getMonitor().signalConnectionFailure(connection.lastException())) shutdown();
      else replace(connection);
    } else {

      if (trash.contains(connection) && inFlight == 0) {
        if (trash.remove(connection)) close(connection);
        return;
      }

      if (connections.size() > options().getCoreConnectionsPerHost(hostDistance)
          && inFlight <= options().getMinSimultaneousRequestsPerConnectionThreshold(hostDistance)) {
        trashConnection(connection);
      } else {
        signalAvailableConnection();
      }
    }
  }
  private boolean addConnectionIfUnderMaximum() {

    // First, make sure we don't cross the allowed limit of open connections
    for (; ; ) {
      int opened = open.get();
      if (opened >= options().getMaxConnectionsPerHost(hostDistance)) return false;

      if (open.compareAndSet(opened, opened + 1)) break;
    }

    if (isShutdown()) {
      open.decrementAndGet();
      return false;
    }

    // Now really open the connection
    try {
      connections.add(manager.connectionFactory().open(host));
      signalAvailableConnection();
      return true;
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      // Skip the open but ignore otherwise
      open.decrementAndGet();
      return false;
    } catch (ConnectionException e) {
      open.decrementAndGet();
      logger.debug("Connection error to {} while creating additional connection", host);
      if (host.getMonitor().signalConnectionFailure(e)) shutdown();
      return false;
    } catch (AuthenticationException e) {
      // This shouldn't really happen in theory
      open.decrementAndGet();
      logger.error(
          "Authentication error while creating additional connection (error is: {})",
          e.getMessage());
      shutdown();
      return false;
    }
  }
  private Connection waitForConnection(long timeout, TimeUnit unit)
      throws ConnectionException, TimeoutException {
    long start = System.nanoTime();
    long remaining = timeout;
    do {
      try {
        awaitAvailableConnection(remaining, unit);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        // If we're interrupted fine, check if there is a connection available but stop waiting
        // otherwise
        timeout = 0; // this will make us stop the loop if we don't get a connection right away
      }

      if (isShutdown()) throw new ConnectionException(host.getAddress(), "Pool is shutdown");

      int minInFlight = Integer.MAX_VALUE;
      Connection leastBusy = null;
      for (Connection connection : connections) {
        int inFlight = connection.inFlight.get();
        if (inFlight < minInFlight) {
          minInFlight = inFlight;
          leastBusy = connection;
        }
      }

      while (true) {
        int inFlight = leastBusy.inFlight.get();

        if (inFlight >= Connection.MAX_STREAM_PER_CONNECTION) break;

        if (leastBusy.inFlight.compareAndSet(inFlight, inFlight + 1)) return leastBusy;
      }

      remaining = timeout - Cluster.timeSince(start, unit);
    } while (remaining > 0);

    throw new TimeoutException();
  }