@Override
  public void update(Key k, Value v) {
    // SIGNAL from SingleTransposeIterator
    if (k.getTimestamp() % 2 != 0) return;

    String rStr;
    {
      ByteSequence rowData = k.getRowData();
      rStr = new String(rowData.toArray(), rowData.offset(), rowData.length());
    }
    int pos = rStr.indexOf(edgeSep);
    if (pos == -1) return; // this is a degree row, not an edge row.

    //    log.debug("edge row "+rStr+" : now "+setNodesReached.toString());

    String toNode = rStr.substring(pos + 1);
    setNodesReached.add(toNode);

    //    if (copyDeg) {
    //      Integer cnt = setNodesReachedCount.get(toNode);
    //      cnt = cnt == null ? new Integer(1) : new Integer(cnt+1);
    //      setNodesReachedCount.put(toNode, cnt);
    //    }

  }
 private static String normalizeEndRow(Range range) {
   Key endKey = range.getEndKey();
   if (endKey == null) return null;
   String endRow = new String(endKey.getRowData().getBackingArray());
   if (!range.isEndKeyInclusive()) return prevRow(endRow);
   else return endRow;
 }
 private static String normalizeStartRow(Range range) {
   Key startKey = range.getStartKey();
   if (startKey == null) return null;
   String startRow = new String(startKey.getRowData().getBackingArray());
   if (!range.isStartKeyInclusive()) return startRow + '\0';
   else return startRow;
 }
 private static float getProgressForRange(final Range range, final Key currentKey) {
   if (currentKey == null) {
     return 0f;
   }
   if ((range.getStartKey() != null) && (range.getEndKey() != null)) {
     if (!range.getStartKey().equals(range.getEndKey(), PartialKey.ROW)) {
       // just look at the row progress
       return getProgressForRange(
           range.getStartKey().getRowData(),
           range.getEndKey().getRowData(),
           currentKey.getRowData());
     } else if (!range.getStartKey().equals(range.getEndKey(), PartialKey.ROW_COLFAM)) {
       // just look at the column family progress
       return getProgressForRange(
           range.getStartKey().getColumnFamilyData(),
           range.getEndKey().getColumnFamilyData(),
           currentKey.getColumnFamilyData());
     } else if (!range.getStartKey().equals(range.getEndKey(), PartialKey.ROW_COLFAM_COLQUAL)) {
       // just look at the column qualifier progress
       return getProgressForRange(
           range.getStartKey().getColumnQualifierData(),
           range.getEndKey().getColumnQualifierData(),
           currentKey.getColumnQualifierData());
     }
   }
   // if we can't figure it out, then claim no progress
   return 0f;
 }
  /** Write entries to a table. */
  public static void writeEntries(
      Connector connector, Map<Key, Value> map, String table, boolean createIfNotExist) {
    if (createIfNotExist && !connector.tableOperations().exists(table))
      try {
        connector.tableOperations().create(table);
      } catch (AccumuloException | AccumuloSecurityException e) {
        log.error("trouble creating " + table, e);
        throw new RuntimeException(e);
      } catch (TableExistsException e) {
        log.error("crazy", e);
        throw new RuntimeException(e);
      }

    BatchWriterConfig bwc = new BatchWriterConfig();
    BatchWriter bw;
    try {
      bw = connector.createBatchWriter(table, bwc);
    } catch (TableNotFoundException e) {
      log.error("tried to write to a non-existant table " + table, e);
      throw new RuntimeException(e);
    }

    try {
      for (Map.Entry<Key, Value> entry : map.entrySet()) {
        Key k = entry.getKey();
        ByteSequence rowData = k.getRowData(),
            cfData = k.getColumnFamilyData(),
            cqData = k.getColumnQualifierData();
        Mutation m = new Mutation(rowData.getBackingArray(), rowData.offset(), rowData.length());
        m.put(
            cfData.getBackingArray(),
            cqData.getBackingArray(),
            k.getColumnVisibilityParsed(),
            entry.getValue().get());
        bw.addMutation(m);
      }

    } catch (MutationsRejectedException e) {
      log.error("mutations rejected", e);
      throw new RuntimeException(e);
    } finally {
      try {
        bw.close();
      } catch (MutationsRejectedException e) {
        log.error("mutations rejected while trying to close BatchWriter", e);
      }
    }
  }
  @Override
  protected HashCode hash(HashFunction hashFunction, Key k) {
    Hasher hasher = hashFunction.newHasher();

    if (row) {
      putByteSquence(k.getRowData(), hasher);
    }

    if (family) {
      putByteSquence(k.getColumnFamilyData(), hasher);
    }

    if (qualifier) {
      putByteSquence(k.getColumnQualifierData(), hasher);
    }

    if (visibility) {
      putByteSquence(k.getColumnVisibilityData(), hasher);
    }

    return hasher.hash();
  }
  public static Entry<Key, Value> checkColumn(
      Environment env, IteratorSetting iterConf, Bytes row, Column col) {
    Span span = Span.exact(row, col);

    Scanner scanner;
    try {
      // TODO reuse or share scanner
      scanner = env.getConnector().createScanner(env.getTable(), env.getAuthorizations());
    } catch (TableNotFoundException e) {
      // TODO proper exception handling
      throw new RuntimeException(e);
    }
    scanner.setRange(SpanUtil.toRange(span));
    scanner.addScanIterator(iterConf);

    Iterator<Entry<Key, Value>> iter = scanner.iterator();
    if (iter.hasNext()) {
      Entry<Key, Value> entry = iter.next();

      Key k = entry.getKey();
      Bytes r = Bytes.of(k.getRowData().toArray());
      Bytes cf = Bytes.of(k.getColumnFamilyData().toArray());
      Bytes cq = Bytes.of(k.getColumnQualifierData().toArray());
      Bytes cv = Bytes.of(k.getColumnVisibilityData().toArray());

      if (r.equals(row)
          && cf.equals(col.getFamily())
          && cq.equals(col.getQualifier())
          && cv.equals(col.getVisibility())) {
        return entry;
      } else {
        throw new RuntimeException("unexpected key " + k + " " + row + " " + col);
      }
    }

    return null;
  }
 /**
  * Create a copy of key with all fields except the ones specified cleared.
  *
  * @param key The key to copy
  * @param pk What fields to retain from the key
  * @return A new Key object pointing to new copies of fields specified by pk; other fields are
  *     empty/default.
  */
 public static Key keyCopy(Key key, PartialKey pk) {
   if (key == null || pk == null) return null;
   switch (pk) {
     case ROW:
       return new Key(
           key.getRowData().getBackingArray(),
           EMPTY_BYTES,
           EMPTY_BYTES,
           EMPTY_BYTES,
           Long.MAX_VALUE,
           false,
           true);
     case ROW_COLFAM:
       return new Key(
           key.getRowData().getBackingArray(),
           key.getColumnFamilyData().getBackingArray(),
           EMPTY_BYTES,
           EMPTY_BYTES,
           Long.MAX_VALUE,
           false,
           true);
     case ROW_COLFAM_COLQUAL:
       return new Key(
           key.getRowData().getBackingArray(),
           key.getColumnFamilyData().getBackingArray(),
           key.getColumnQualifierData().getBackingArray(),
           EMPTY_BYTES,
           Long.MAX_VALUE,
           false,
           true);
     case ROW_COLFAM_COLQUAL_COLVIS:
       return new Key(
           key.getRowData().getBackingArray(),
           key.getColumnFamilyData().getBackingArray(),
           key.getColumnQualifierData().getBackingArray(),
           key.getColumnVisibilityData().getBackingArray(),
           Long.MAX_VALUE,
           false,
           true);
     case ROW_COLFAM_COLQUAL_COLVIS_TIME:
       return new Key(
           key.getRowData().getBackingArray(),
           key.getColumnFamilyData().getBackingArray(),
           key.getColumnQualifierData().getBackingArray(),
           key.getColumnVisibilityData().getBackingArray(),
           key.getTimestamp(),
           false,
           true);
     case ROW_COLFAM_COLQUAL_COLVIS_TIME_DEL:
       return new Key(
           key.getRowData().getBackingArray(),
           key.getColumnFamilyData().getBackingArray(),
           key.getColumnQualifierData().getBackingArray(),
           key.getColumnVisibilityData().getBackingArray(),
           key.getTimestamp(),
           key.isDeleted(),
           true);
     default:
       throw new AssertionError("unknown pk: " + pk);
   }
 }