code: @Override
      public Iterator<Host> newQueryPlan(String loggedKeyspace, Statement statement) {
  
          // We clone liveHosts because we want a version of the list that
          // cannot change concurrently of the query plan iterator (this
          // would be racy). We use clone() as it don't involve a copy of the
          // underlying array (and thus we rely on liveHosts being a CopyOnWriteArrayList).
          @SuppressWarnings("unchecked")
          final List<Host> hosts = (List<Host>) liveHosts.clone();
          final int startIdx = index.getAndIncrement();
  
          // Overflow protection; not theoretically thread safe but should be good enough
          if (startIdx > Integer.MAX_VALUE - 10000) {
              index.set(0);
          }
  
          return new AbstractIterator<Host>() {
  
              private int idx = startIdx;
              private int remaining = hosts.size();
  
              @Override
              protected Host computeNext() {
                  if (remaining <= 0) {
                      return endOfData();
                  }
  
                  remaining--;
                  int c = idx++ % hosts.size();
                  if (c < 0) {
                      c += hosts.size();
                  }
                  return hosts.get(c);
              }
          };
      }
docs: Returns the hosts to use for a new query.
  <p/>
  The returned plan will try each known host of the cluster. Upon each
  call to this method, the {@code i}th host of the plans returned will cycle
  over all the hosts of the cluster in a round-robin fashion.
  
  @param loggedKeyspace the keyspace currently logged in on for this
  query.
  @param statement      the query for which to build the plan.
  @return a new query plan, i.e. an iterator indicating which host to
  try first for querying, which one to use as failover, etc...