private int compareTypeBytes(Cell key, Cell right) { if (key.getFamilyLength() + key.getQualifierLength() == 0 && key.getTypeByte() == Type.Minimum.getCode()) { // left is "bigger", i.e. it appears later in the sorted order return 1; } if (right.getFamilyLength() + right.getQualifierLength() == 0 && right.getTypeByte() == Type.Minimum.getCode()) { return -1; } return 0; }
@Override public void write(Cell cell) throws IOException { if (encryptor == null) { super.write(cell); return; } byte[] iv = nextIv(); encryptor.setIv(iv); encryptor.reset(); // TODO: Check if this is a cell for an encrypted CF. If not, we can // write a 0 here to signal an unwrapped cell and just dump the KV bytes // afterward StreamUtils.writeRawVInt32(out, iv.length); out.write(iv); // TODO: Add support for WAL compression ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream cout = encryptor.createEncryptionStream(baos); int tlen = cell.getTagsLength(); // Write the KeyValue infrastructure as VInts. StreamUtils.writeRawVInt32(cout, KeyValueUtil.keyLength(cell)); StreamUtils.writeRawVInt32(cout, cell.getValueLength()); // To support tags StreamUtils.writeRawVInt32(cout, tlen); // Write row, qualifier, and family StreamUtils.writeRawVInt32(cout, cell.getRowLength()); cout.write(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()); StreamUtils.writeRawVInt32(cout, cell.getFamilyLength()); cout.write(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); StreamUtils.writeRawVInt32(cout, cell.getQualifierLength()); cout.write(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); // Write the rest ie. ts, type, value and tags parts StreamUtils.writeLong(cout, cell.getTimestamp()); cout.write(cell.getTypeByte()); cout.write(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); if (tlen > 0) { cout.write(cell.getTagsArray(), cell.getTagsOffset(), tlen); } cout.close(); StreamUtils.writeRawVInt32(out, baos.size()); baos.writeTo(out); // Increment IV given the final payload length incrementIv(baos.size()); }
@Override public void write(Cell cell) throws IOException { checkFlushed(); // Row write(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()); // Column family write(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); // Qualifier write(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); // Version this.out.write(Bytes.toBytes(cell.getTimestamp())); // Type this.out.write(cell.getTypeByte()); // Value write(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); // Tags write(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength()); // MvccVersion this.out.write(Bytes.toBytes(cell.getMvccVersion())); }
@Override public int seekToKeyInBlock(Cell seekCell, boolean seekBefore) { int rowCommonPrefix = 0; int familyCommonPrefix = 0; int qualCommonPrefix = 0; previous.invalidate(); do { int comp; keyOnlyKV.setKey(current.keyBuffer, 0, current.keyLength); if (current.lastCommonPrefix != 0) { // The KV format has row key length also in the byte array. The // common prefix // includes it. So we need to subtract to find out the common prefix // in the // row part alone rowCommonPrefix = Math.min(rowCommonPrefix, current.lastCommonPrefix - 2); } if (current.lastCommonPrefix <= 2) { rowCommonPrefix = 0; } rowCommonPrefix += findCommonPrefixInRowPart(seekCell, keyOnlyKV, rowCommonPrefix); comp = compareCommonRowPrefix(seekCell, keyOnlyKV, rowCommonPrefix); if (comp == 0) { comp = compareTypeBytes(seekCell, keyOnlyKV); if (comp == 0) { // Subtract the fixed row key length and the family key fixed length familyCommonPrefix = Math.max( 0, Math.min( familyCommonPrefix, current.lastCommonPrefix - (3 + keyOnlyKV.getRowLength()))); familyCommonPrefix += findCommonPrefixInFamilyPart(seekCell, keyOnlyKV, familyCommonPrefix); comp = compareCommonFamilyPrefix(seekCell, keyOnlyKV, familyCommonPrefix); if (comp == 0) { // subtract the rowkey fixed length and the family key fixed // length qualCommonPrefix = Math.max( 0, Math.min( qualCommonPrefix, current.lastCommonPrefix - (3 + keyOnlyKV.getRowLength() + keyOnlyKV.getFamilyLength()))); qualCommonPrefix += findCommonPrefixInQualifierPart(seekCell, keyOnlyKV, qualCommonPrefix); comp = compareCommonQualifierPrefix(seekCell, keyOnlyKV, qualCommonPrefix); if (comp == 0) { comp = CellComparator.compareTimestamps(seekCell, keyOnlyKV); if (comp == 0) { // Compare types. Let the delete types sort ahead of puts; // i.e. types // of higher numbers sort before those of lesser numbers. // Maximum // (255) // appears ahead of everything, and minimum (0) appears // after // everything. comp = (0xff & keyOnlyKV.getTypeByte()) - (0xff & seekCell.getTypeByte()); } } } } } if (comp == 0) { // exact match if (seekBefore) { if (!previous.isValid()) { // The caller (seekBefore) has to ensure that we are not at the // first key in the block. throw new IllegalStateException( "Cannot seekBefore if " + "positioned at the first key in the block: key=" + Bytes.toStringBinary(seekCell.getRowArray())); } moveToPrevious(); return 1; } return 0; } if (comp < 0) { // already too large, check previous if (previous.isValid()) { moveToPrevious(); } else { return HConstants.INDEX_KEY_MAGIC; // using optimized index key } return 1; } // move to next, if more data is available if (currentBuffer.hasRemaining()) { previous.copyFromNext(current); decodeNext(); current.setKey(current.keyBuffer, current.memstoreTS); } else { break; } } while (true); // we hit the end of the block, not an exact match return 1; }