public static void waitForSchemaVersionsToCoalesce(
      String encapsulatingOperationDescription, CQLKeyValueService kvs) {
    PreparedStatement peerInfoQuery =
        kvs.getPreparedStatement(
            CassandraConstants.NO_TABLE,
            "select peer, schema_version from system.peers;",
            kvs.session);
    peerInfoQuery.setConsistencyLevel(ConsistencyLevel.ALL);

    Multimap<UUID, InetAddress> peerInfo = ArrayListMultimap.create();
    long start = System.currentTimeMillis();
    long sleepTime = 100;
    do {
      peerInfo.clear();
      for (Row row : kvs.session.execute(peerInfoQuery.bind()).all()) {
        peerInfo.put(row.getUUID("schema_version"), row.getInet("peer"));
      }

      if (peerInfo.keySet().size() <= 1) { // full schema agreement
        return;
      }
      sleepTime = Math.min(sleepTime * 2, 5000);
    } while (System.currentTimeMillis()
        < start + CassandraConstants.SECONDS_WAIT_FOR_VERSIONS * 1000);

    StringBuilder sb = new StringBuilder();
    sb.append(
        String.format(
            "Cassandra cluster cannot come to agreement on schema versions, during operation: %s.",
            encapsulatingOperationDescription));

    for (Entry<UUID, Collection<InetAddress>> versionToPeer : peerInfo.asMap().entrySet()) {
      sb.append(String.format("\nAt schema version %s:", versionToPeer.getKey()));
      for (InetAddress peer : versionToPeer.getValue()) {
        sb.append(String.format("\n\tNode: %s", peer));
      }
    }
    sb.append(
        "\nFind the nodes above that diverge from the majority schema "
            + "(or have schema 'UNKNOWN', which likely means they are down/unresponsive) "
            + "and examine their logs to determine the issue. Fixing the underlying issue and restarting Cassandra "
            + "should resolve the problem. You can quick-check this with 'nodetool describecluster'.");
    throw new IllegalStateException(sb.toString());
  }
  static void setSettingsForTable(String tableName, byte[] rawMetadata, CQLKeyValueService kvs) {
    int explicitCompressionBlockSizeKB = 0;
    boolean negativeLookups = false;
    double falsePositiveChance =
        CassandraConstants.DEFAULT_LEVELED_COMPACTION_BLOOM_FILTER_FP_CHANCE;
    boolean appendHeavyAndReadLight = false;

    if (rawMetadata != null && rawMetadata.length != 0) {
      TableMetadata tableMetadata = TableMetadata.BYTES_HYDRATOR.hydrateFromBytes(rawMetadata);
      explicitCompressionBlockSizeKB = tableMetadata.getExplicitCompressionBlockSizeKB();
      negativeLookups = tableMetadata.hasNegativeLookups();
      appendHeavyAndReadLight = tableMetadata.isAppendHeavyAndReadLight();
    }

    if (negativeLookups) {
      falsePositiveChance = CassandraConstants.NEGATIVE_LOOKUPS_BLOOM_FILTER_FP_CHANCE;
    } else if (appendHeavyAndReadLight) {
      falsePositiveChance =
          CassandraConstants.DEFAULT_SIZE_TIERED_COMPACTION_BLOOM_FILTER_FP_CHANCE;
    }

    int chunkLength = AtlasDbConstants.MINIMUM_COMPRESSION_BLOCK_SIZE_KB;
    if (explicitCompressionBlockSizeKB != 0) {
      chunkLength = explicitCompressionBlockSizeKB;
    }

    StringBuilder sb = new StringBuilder();
    sb.append(
        "ALTER TABLE "
            + kvs.getFullTableName(tableName)
            + " WITH "
            + "bloom_filter_fp_chance = "
            + falsePositiveChance
            + " ");

    sb.append("AND caching = '{\"keys\":\"ALL\", \"rows_per_partition\":\"ALL\"}' ");

    if (appendHeavyAndReadLight) {
      sb.append(
          "AND compaction = { 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy'} ");
    } else {
      sb.append(
          "AND compaction = {'sstable_size_in_mb': '80', 'class': 'org.apache.cassandra.db.compaction.LeveledCompactionStrategy'} ");
    }
    sb.append(
        "AND compression = {'chunk_length_kb': '"
            + chunkLength
            + "', "
            + "'sstable_compression': '"
            + CassandraConstants.DEFAULT_COMPRESSION_TYPE
            + "'}");

    BoundStatement alterTableStatement =
        kvs.getPreparedStatement(tableName, sb.toString(), kvs.longRunningQuerySession)
            .setConsistencyLevel(ConsistencyLevel.ALL)
            .bind();
    try {
      kvs.longRunningQuerySession.execute(alterTableStatement);
    } catch (Throwable t) {
      throw Throwables.throwUncheckedException(t);
    }
  }
  static void createTableWithSettings(
      String tableName, byte[] rawMetadata, CQLKeyValueService kvs) {
    StringBuilder queryBuilder = new StringBuilder();

    int explicitCompressionBlockSizeKB = 0;
    boolean negativeLookups = false;
    double falsePositiveChance =
        CassandraConstants.DEFAULT_LEVELED_COMPACTION_BLOOM_FILTER_FP_CHANCE;
    boolean appendHeavyAndReadLight = false;

    if (rawMetadata != null && rawMetadata.length != 0) {
      TableMetadata tableMetadata = TableMetadata.BYTES_HYDRATOR.hydrateFromBytes(rawMetadata);
      explicitCompressionBlockSizeKB = tableMetadata.getExplicitCompressionBlockSizeKB();
      negativeLookups = tableMetadata.hasNegativeLookups();
      appendHeavyAndReadLight = tableMetadata.isAppendHeavyAndReadLight();
    }

    if (negativeLookups) {
      falsePositiveChance = CassandraConstants.NEGATIVE_LOOKUPS_BLOOM_FILTER_FP_CHANCE;
    } else if (appendHeavyAndReadLight) {
      falsePositiveChance =
          CassandraConstants.DEFAULT_SIZE_TIERED_COMPACTION_BLOOM_FILTER_FP_CHANCE;
    }

    int chunkLength = AtlasDbConstants.MINIMUM_COMPRESSION_BLOCK_SIZE_KB;
    if (explicitCompressionBlockSizeKB != 0) {
      chunkLength = explicitCompressionBlockSizeKB;
    }

    queryBuilder.append(
        "CREATE TABLE "
            + kvs.getFullTableName(tableName)
            + " ( " // full table name (ks.cf)
            + CassandraConstants.ROW_NAME
            + " blob, "
            + CassandraConstants.COL_NAME_COL
            + " blob, "
            + CassandraConstants.TS_COL
            + " bigint, "
            + CassandraConstants.VALUE_COL
            + " blob, "
            + "PRIMARY KEY ("
            + CassandraConstants.ROW_NAME
            + ", "
            + CassandraConstants.COL_NAME_COL
            + ", "
            + CassandraConstants.TS_COL
            + ")) "
            + "WITH COMPACT STORAGE ");
    queryBuilder.append("AND " + "bloom_filter_fp_chance = " + falsePositiveChance + " ");
    queryBuilder.append("AND caching = '{\"keys\":\"ALL\", \"rows_per_partition\":\"ALL\"}' ");
    if (appendHeavyAndReadLight) {
      queryBuilder.append(
          "AND compaction = { 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy'} ");
    } else {
      queryBuilder.append(
          "AND compaction = {'sstable_size_in_mb': '80', 'class': 'org.apache.cassandra.db.compaction.LeveledCompactionStrategy'} ");
    }
    queryBuilder.append(
        "AND compression = {'chunk_length_kb': '"
            + chunkLength
            + "', "
            + "'sstable_compression': '"
            + CassandraConstants.DEFAULT_COMPRESSION_TYPE
            + "'}");
    queryBuilder.append(
        "AND CLUSTERING ORDER BY ("
            + CassandraConstants.COL_NAME_COL
            + " ASC, "
            + CassandraConstants.TS_COL
            + " ASC) ");

    BoundStatement createTableStatement =
        kvs.getPreparedStatement(tableName, queryBuilder.toString(), kvs.longRunningQuerySession)
            .setConsistencyLevel(ConsistencyLevel.ALL)
            .bind();
    try {
      ResultSet resultSet = kvs.longRunningQuerySession.execute(createTableStatement);
      CQLKeyValueServices.logTracedQuery(
          queryBuilder.toString(), resultSet, kvs.session, kvs.cqlStatementCache.NORMAL_QUERY);
    } catch (Throwable t) {
      throw Throwables.throwUncheckedException(t);
    }
  }