/** * Creates a HashPrefixedEntityId from the specified HBase row key. * * @param hbaseRowKey HBase row key. * @param format Row key hashing specification. * @return a new HashedEntityId with the specified HBase row key. */ static HashPrefixedEntityId fromHBaseRowKey(byte[] hbaseRowKey, RowKeyFormat format) { Preconditions.checkNotNull(format); Preconditions.checkArgument(format.getEncoding() == RowKeyEncoding.HASH_PREFIX); final int hashSize = format.getHashSize(); final byte[] fijiRowKey = Arrays.copyOfRange(hbaseRowKey, hashSize, hbaseRowKey.length); // TODO Paranoid expensive check : rehash the fiji key and compare with the hash? return new HashPrefixedEntityId(fijiRowKey, hbaseRowKey, format); }
/** * Ensure a row key format (version 1) specified in a layout file is sane. * @param format The RowKeyFormat created from the layout file for a table. * @throws InvalidLayoutException If the format is invalid. */ private void isValidRowKeyFormat1(RowKeyFormat format) throws InvalidLayoutException { RowKeyEncoding rowKeyEncoding = format.getEncoding(); if (rowKeyEncoding != RowKeyEncoding.RAW && rowKeyEncoding != RowKeyEncoding.HASH && rowKeyEncoding != RowKeyEncoding.HASH_PREFIX) { throw new InvalidLayoutException("RowKeyFormat only supports encodings" + "of type RAW, HASH and HASH_PREFIX. Use RowKeyFormat2 instead"); } if (rowKeyEncoding == RowKeyEncoding.HASH || rowKeyEncoding == RowKeyEncoding.HASH_PREFIX) { if (format.getHashSize() < 0 || format.getHashSize() > Hasher.HASH_SIZE_BYTES) { throw new InvalidLayoutException("HASH or HASH_PREFIX row key formats require hash size" + "to be between 1 and " + Hasher.HASH_SIZE_BYTES); } } }
/** * Creates a HashPrefixedEntityId from the specified Fiji row key. * * @param fijiRowKey Fiji row key. * @param format Row key hashing specification. * @return a new HashPrefixedEntityId with the specified Fiji row key. */ static HashPrefixedEntityId getEntityId(byte[] fijiRowKey, RowKeyFormat format) { Preconditions.checkNotNull(format); Preconditions.checkArgument(format.getEncoding() == RowKeyEncoding.HASH_PREFIX); final byte[] hash = hashFijiRowKey(format, fijiRowKey); final int hashSize = format.getHashSize(); // Prepend a subset of the hash to the Fiji row key: final byte[] hbaseRowKey = new byte[hashSize + fijiRowKey.length]; System.arraycopy(hash, 0, hbaseRowKey, 0, hashSize); System.arraycopy(fijiRowKey, 0, hbaseRowKey, hashSize, fijiRowKey.length); return new HashPrefixedEntityId(fijiRowKey, hbaseRowKey, format); }
/** * Get the hash size for a given row key format. * * @param rowKeyFormat Format of row keys of type RowKeyFormat or RowKeyFormat2. * @return The size of the hash prefix. */ public static int getHashSize(Object rowKeyFormat) { if (rowKeyFormat instanceof RowKeyFormat) { return ((RowKeyFormat) rowKeyFormat).getHashSize(); } else if (rowKeyFormat instanceof RowKeyFormat2) { RowKeyFormat2 format2 = (RowKeyFormat2) rowKeyFormat; if (null == format2.getSalt()) { throw new RuntimeException("This RowKeyFormat2 instance does not specify salt/hashing."); } else { return format2.getSalt().getHashSize(); } } else { throw new RuntimeException("Unsupported Row Key Format"); } } }
/** * Gets a table's row-key hash resolution (in number of bytes) * for use in evenly spacing HBase row keys. * * @param tableLayout the layout of the table * @return the table's hash resolution. */ public static int getRowKeyResolution(TableLayoutDesc tableLayout) { // Get hashSize from layout. int hashSize = 16; // No assumptions make about the RKF. if (RowKeyFormat.class.equals(tableLayout.getKeysFormat().getClass())) { hashSize = ((RowKeyFormat) tableLayout.getKeysFormat()).getHashSize(); } else if (RowKeyFormat2.class.equals(tableLayout.getKeysFormat().getClass())) { RowKeyFormat2 format = (RowKeyFormat2) tableLayout.getKeysFormat(); if (null == format.getSalt()) { throw new IllegalArgumentException( "This table layout defines an entityId format without hashing enabled."); } hashSize = ((RowKeyFormat2) tableLayout.getKeysFormat()).getSalt().getHashSize(); } return hashSize; }