public void handleStreamEvent(StreamEvent event) {
      if (event.eventType == StreamEvent.Type.STREAM_PREPARED) {
        SessionInfo session = ((StreamEvent.SessionPreparedEvent) event).session;
        sessionsByHost.put(session.peer, session);
      } else if (event.eventType == StreamEvent.Type.FILE_PROGRESS) {
        ProgressInfo progressInfo = ((StreamEvent.ProgressEvent) event).progress;

        // update progress
        Set<ProgressInfo> progresses = progressByHost.get(progressInfo.peer);
        if (progresses == null) {
          progresses = Sets.newSetFromMap(new ConcurrentHashMap<ProgressInfo, Boolean>());
          progressByHost.put(progressInfo.peer, progresses);
        }
        if (progresses.contains(progressInfo)) progresses.remove(progressInfo);
        progresses.add(progressInfo);

        StringBuilder sb = new StringBuilder();
        sb.append("\rprogress: ");

        long totalProgress = 0;
        long totalSize = 0;
        for (Map.Entry<InetAddress, Set<ProgressInfo>> entry : progressByHost.entrySet()) {
          SessionInfo session = sessionsByHost.get(entry.getKey());

          long size = session.getTotalSizeToSend();
          long current = 0;
          int completed = 0;
          for (ProgressInfo progress : entry.getValue()) {
            if (progress.currentBytes == progress.totalBytes) completed++;
            current += progress.currentBytes;
          }
          totalProgress += current;
          totalSize += size;
          sb.append("[").append(entry.getKey());
          sb.append(" ").append(completed).append("/").append(session.getTotalFilesToSend());
          sb.append(" (").append(size == 0 ? 100L : current * 100L / size).append("%)] ");
        }
        long time = System.nanoTime();
        long deltaTime = Math.max(1L, TimeUnit.NANOSECONDS.toMillis(time - lastTime));
        lastTime = time;
        long deltaProgress = totalProgress - lastProgress;
        lastProgress = totalProgress;

        sb.append("[total: ")
            .append(totalSize == 0 ? 100L : totalProgress * 100L / totalSize)
            .append("% - ");
        sb.append(mbPerSec(deltaProgress, deltaTime)).append("MB/s");
        sb.append(" (avg: ")
            .append(mbPerSec(totalProgress, TimeUnit.NANOSECONDS.toMillis(time - start)))
            .append("MB/s)]");

        System.out.print(sb.toString());
      }
    }
    @Override
    public void init(String keyspace) {
      Iterator<InetAddress> hostiter = hosts.iterator();
      while (hostiter.hasNext()) {
        try {
          // Query endpoint to ranges map and schemas from thrift
          InetAddress host = hostiter.next();
          Cassandra.Client client =
              createThriftClient(
                  host.getHostAddress(), rpcPort, this.user, this.passwd, this.transportFactory);

          setPartitioner(client.describe_partitioner());
          Token.TokenFactory tkFactory = getPartitioner().getTokenFactory();

          for (TokenRange tr : client.describe_ring(keyspace)) {
            Range<Token> range =
                new Range<>(
                    tkFactory.fromString(tr.start_token),
                    tkFactory.fromString(tr.end_token),
                    getPartitioner());
            for (String ep : tr.endpoints) {
              addRangeForEndpoint(range, InetAddress.getByName(ep));
            }
          }

          String query =
              String.format(
                  "SELECT * FROM %s.%s WHERE keyspace_name = '%s'",
                  Keyspace.SYSTEM_KS, SystemKeyspace.SCHEMA_COLUMNFAMILIES_CF, keyspace);
          CqlResult result =
              client.execute_cql3_query(
                  ByteBufferUtil.bytes(query), Compression.NONE, ConsistencyLevel.ONE);
          for (CqlRow row : result.rows) {
            CFMetaData metadata = CFMetaData.fromThriftCqlRow(row);
            knownCfs.put(metadata.cfName, metadata);
          }
          break;
        } catch (Exception e) {
          if (!hostiter.hasNext())
            throw new RuntimeException("Could not retrieve endpoint ranges: ", e);
        }
      }
    }
    public void init(String keyspace) {
      outputHandler.output(
          String.format(
              "Starting client (and waiting %d seconds for gossip) ...",
              StorageService.RING_DELAY / 1000));
      try {
        // Init gossip
        StorageService.instance.initClient();

        Set<InetAddress> hosts = Gossiper.instance.getLiveMembers();
        hosts.remove(FBUtilities.getLocalAddress());
        if (hosts.isEmpty())
          throw new IllegalStateException(
              "Cannot load any sstable, no live member found in the cluster");

        // Query endpoint to ranges map and schemas from thrift
        String host = hosts.iterator().next().toString().substring(1);
        int port = DatabaseDescriptor.getRpcPort();

        Cassandra.Client client = createThriftClient(host, port);
        List<TokenRange> tokenRanges = client.describe_ring(keyspace);
        List<KsDef> ksDefs = client.describe_keyspaces();

        Token.TokenFactory tkFactory = StorageService.getPartitioner().getTokenFactory();

        try {
          for (TokenRange tr : tokenRanges) {
            Range range =
                new Range(tkFactory.fromString(tr.start_token), tkFactory.fromString(tr.end_token));
            for (String ep : tr.endpoints) {
              addRangeForEndpoint(range, InetAddress.getByName(ep));
            }
          }
        } catch (UnknownHostException e) {
          throw new RuntimeException("Got an unknow host from describe_ring()", e);
        }

        for (KsDef ksDef : ksDefs) {
          Set<String> cfs = new HashSet<String>();
          for (CfDef cfDef : ksDef.cf_defs) cfs.add(cfDef.name);
          knownCfs.put(ksDef.name, cfs);
        }
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
 public boolean validateColumnFamily(String keyspace, String cfName) {
   Set<String> cfs = knownCfs.get(keyspace);
   return cfs != null && cfs.contains(cfName);
 }