private UserType getSessionType(Session session, CassandraType type) {
   return session
       .getCluster()
       .getMetadata()
       .getKeyspace(session.getLoggedKeyspace())
       .getUserType(type.getName());
 }
  CqlRecordWriter(Configuration conf) {
    this.conf = conf;
    this.queueSize =
        conf.getInt(ColumnFamilyOutputFormat.QUEUE_SIZE, 32 * FBUtilities.getAvailableProcessors());
    batchThreshold = conf.getLong(ColumnFamilyOutputFormat.BATCH_THRESHOLD, 32);
    this.clients = new HashMap<>();

    try {
      String keyspace = ConfigHelper.getOutputKeyspace(conf);
      try (Session client =
          CqlConfigHelper.getOutputCluster(ConfigHelper.getOutputInitialAddress(conf), conf)
              .connect(keyspace)) {
        ringCache = new NativeRingCache(conf);
        if (client != null) {
          TableMetadata tableMetadata =
              client
                  .getCluster()
                  .getMetadata()
                  .getKeyspace(client.getLoggedKeyspace())
                  .getTable(ConfigHelper.getOutputColumnFamily(conf));
          clusterColumns = tableMetadata.getClusteringColumns();
          partitionKeyColumns = tableMetadata.getPartitionKey();

          String cqlQuery = CqlConfigHelper.getOutputCql(conf).trim();
          if (cqlQuery.toLowerCase().startsWith("insert"))
            throw new UnsupportedOperationException(
                "INSERT with CqlRecordWriter is not supported, please use UPDATE/DELETE statement");
          cql = appendKeyWhereClauses(cqlQuery);
        } else {
          throw new IllegalArgumentException("Invalid configuration specified " + conf);
        }
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  public void logState() {
    Session s = sessions[0];
    Cluster cluster = s.getCluster();
    LoadBalancingPolicy lbPolicy =
        cluster.getConfiguration().getPolicies().getLoadBalancingPolicy();

    int count = 0;
    String keyspace = null;
    for (final Session session : sessions) {
      SessionManager sessionM = (SessionManager) session;
      Session.State sessionState = session.getState();

      String newKeyspace = session.getLoggedKeyspace();
      if (keyspace == null || !keyspace.equals(newKeyspace)) {
        count = 0;
        keyspace = newKeyspace;
      }

      int sessionKey = count++;
      logger.info("Host States for Session {}#{}:", keyspace, sessionKey);
      Collection<Host> hosts = sessionState.getConnectedHosts();
      for (final Host host : hosts) {
        HostConnectionPool pool = sessionM.pools.get(host);
        HostDistance distance = lbPolicy.distance(host);
        // Whether or not the host will reconnect while in a suspected state.
        boolean isReconnectingFromSuspected =
            host.getInitialReconnectionAttemptFuture() != null
                && !host.getInitialReconnectionAttemptFuture().isDone();
        // Whether or not the host will reconnect while in a down state.
        boolean isReconnectingFromDown =
            host.getReconnectionAttemptFuture() != null
                && !host.getReconnectionAttemptFuture().isDone();

        if (pool != null) {
          String msg =
              String.format(
                  "\t[%s:%s:%s] version=%s, state=%s, dist=%s, inFlight=%d, openConnections=%d, "
                      + "trashedConnections=%d, reconnectFromSuspected=%s, reconnectFromDown=%s. pool=%s, poolClosed=%s",
                  host.getDatacenter(),
                  host.getRack(),
                  host.getAddress(),
                  host.getCassandraVersion(),
                  host.state,
                  distance,
                  sessionState.getInFlightQueries(host),
                  sessionState.getOpenConnections(host),
                  pool.trash.size(),
                  isReconnectingFromSuspected,
                  isReconnectingFromDown,
                  pool.hashCode(),
                  pool.isClosed());

          logger.info(msg);

          for (Connection connection : pool.connections) {
            long now = System.currentTimeMillis();
            Connection.State state = connection.state.get();
            if (connection.isClosed()
                || connection.isDefunct()
                || state == Connection.State.TRASHED
                || state == Connection.State.GONE
                || connection.maxIdleTime > 0 && connection.maxIdleTime < now) {
              logger.warn(
                  "\t\t{} defunct?={}, state={}, maxIdleTime={}",
                  connection,
                  connection.isDefunct(),
                  state,
                  new Date(connection.maxIdleTime));
            } else {
              logger.info(
                  "\t\t{} defunct?={}, state={}, maxIdleTime={}",
                  connection,
                  connection.isDefunct(),
                  state,
                  new Date(connection.maxIdleTime));
            }
          }
          for (Connection connection : pool.trash) {
            Connection.State state = connection.state.get();
            if (connection.isClosed()
                || connection.isDefunct()
                || state == Connection.State.OPEN
                || state == Connection.State.GONE) {
              logger.warn(
                  "\t\t{} defunct?={}, state={}, maxIdleTime={} [trash]",
                  connection,
                  connection.isDefunct(),
                  state,
                  new Date(connection.maxIdleTime));
            } else {
              logger.info(
                  "\t\t{} defunct?={}, state={}, maxIdleTime={} [trash]",
                  connection,
                  connection.isDefunct(),
                  state,
                  new Date(connection.maxIdleTime));
            }
          }
        } else {
          logger.error("Pool is null for {}.", host);
        }

        // Register by host / session metrics if not already registered.
        // Replace periods with underscores (better graphite metric names) in host, also remove
        // backslashes.
        // If the host is no longer part of the session, it will return 0.
        String prefix =
            "Session."
                + sessionKey
                + "."
                + host.getAddress().toString().replaceAll("\\.", "_").replaceAll("/", "")
                + ".";
        String inFlightKey = prefix + "inFlight";
        String openConnectionsKey = prefix + "openConnections";
        if (!metricRegistry.getMetrics().containsKey(inFlightKey)) {
          metricRegistry.register(
              inFlightKey,
              new CachedGauge<Integer>(1, TimeUnit.SECONDS) {

                @Override
                protected Integer loadValue() {
                  Session.State sessionState = session.getState();
                  if (sessionState.getConnectedHosts().contains(host)) {
                    return sessionState.getInFlightQueries(host);
                  } else {
                    return 0;
                  }
                }
              });
        }
        if (!metricRegistry.getMetrics().containsKey(openConnectionsKey)) {
          metricRegistry.register(
              openConnectionsKey,
              new CachedGauge<Integer>(1, TimeUnit.SECONDS) {

                @Override
                protected Integer loadValue() {
                  Session.State sessionState = session.getState();
                  if (sessionState.getConnectedHosts().contains(host)) {
                    return sessionState.getOpenConnections(host);
                  } else {
                    return 0;
                  }
                }
              });
        }
      }
    }

    ControlConnection connection = cluster.manager.controlConnection;
    if (connection.isOpen()) {
      logger.info("Control connection is open to {}.", connection.connectedHost());
    } else {
      logger.warn("Control connection is closed.");
    }

    List<Host> queryPlan = Lists.newArrayList(lbPolicy.newQueryPlan(null, new SimpleStatement("")));
    if (queryPlan.size() == 0) {
      logger.warn("Query Plan is empty!");
    } else {
      logger.info("Query Plan: {}", queryPlan);
    }
  }