Index: hbase-server/src/test/java/org/apache/hadoop/hbase/schema/TestFixedLengthRowKey.java
===================================================================
--- hbase-server/src/test/java/org/apache/hadoop/hbase/schema/TestFixedLengthRowKey.java (revision 0)
+++ hbase-server/src/test/java/org/apache/hadoop/hbase/schema/TestFixedLengthRowKey.java (revision 0)
@@ -0,0 +1,86 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import org.apache.hadoop.hbase.SmallTests;
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.junit.experimental.categories.Category;
+
+@Category(SmallTests.class)
+public class TestFixedLengthRowKey {
+
+ private int hashVal = 4;
+ private int intVal = 5;
+ private long longVal = 6;
+ private byte byteVal = '7';
+ private byte[] bytesVal = {'1', '2', '3', '4', '6', '7'}; // arbitrary set of bytes
+
+ @Test
+ public void testCreate() throws Exception {
+
+ RowKeySchema schema = new RowKeySchema.Builder()
+ .add(RowKeySchema.MD5_HASH)
+ .add(RowKeySchema.INT)
+ .add(RowKeySchema.LONG)
+ .add(RowKeySchema.BYTE)
+ .add(new RowKeyBytesElement(bytesVal.length))
+ .build();
+
+ FixedLengthRowKey rowkey = schema.createFixedLengthRowKey();
+ rowkey.setInt(0, hashVal); // this will hash the int because the schema definition says so.
+ rowkey.setInt(1, intVal);
+ rowkey.setLong(2, longVal);
+ rowkey.setByte(3, byteVal);
+ rowkey.setBytes(4, bytesVal);
+
+ byte bytes[] = rowkey.getBytes();
+ Assert.assertEquals("key length", schema.getRowKeyLength(), bytes.length);
+
+ Assert.assertEquals("e0", rowkey.getBytes(0).length, RowKeySchema.MD5_HASH.getLength());
+ Assert.assertEquals("e1", rowkey.getInt(1), intVal);
+ Assert.assertEquals("e2", rowkey.getLong(2), longVal);
+ Assert.assertEquals("e3", rowkey.getByte(3), byteVal);
+ Assert.assertEquals("e4", rowkey.getBytes(4).length, bytesVal.length);
+ }
+
+ @Test
+ public void testNegativeCreate() {
+
+ RowKeySchema schema = new RowKeySchema.Builder()
+ .add(RowKeySchema.MD5_HASH)
+ .add(RowKeySchema.INT)
+ .add(RowKeySchema.LONG)
+ .build();
+
+ boolean passed = true;
+ try {
+ FixedLengthRowKey rowkey = schema.createFixedLengthRowKey();
+ rowkey.setLong(1, longVal); // trying to set 'long' on an element that is sized for an int.
+ } catch (Exception e) {
+ // we are expecting a sizing exception because we are
+ // setting a long onto an element sized for an int.
+ passed = false;
+ }
+ if (passed) {
+ Assert.fail("Test did not fail!");
+ }
+ }
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/FixedLengthRowKey.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/FixedLengthRowKey.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/FixedLengthRowKey.java (revision 0)
@@ -0,0 +1,257 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.MurmurHash;
+
+/**
+ * A stateful utility class for creating and reading rowkeys for HBase tables, particularly composite keys.
+ * FixedLengthRowKey creates fixed length keys without the need for delimeters in between key elements
+ * (i.e., parts of the rowkey), which is a best practice in HBase.
+ * FixedLengthRowKey instances are instantiated from an associated RowKeySchema, which defines the row key
+ * elements and their lengths.
+ *
+ * RowKeySchema schema = new RowKeySchema.Builder()
+ * .add(RowKeySchema.MD5_HASH)
+ * .add(RowKeySchema.INT)
+ * .add(RowKeySchema.LONG)
+ * .add(RowKeySchema.BYTE)
+ * .add(new RowKeyBytesElement(bytesVal.length))
+ * .build();
+ *
+ * FixedLengthRowKey rowkey = schema.createFixedLengthRowKey();
+ * rowkey.setInt(0, hashVal); // this will hash the int because the schema definition says so.
+ * rowkey.setInt(1, intVal);
+ * rowkey.setLong(2, longVal);
+ * rowkey.setByte(3, byteVal);
+ * rowkey.setBytes(4, bytesVal);
+ *
+ * In the example above, the rowkey consists of 5 key elements: an MD5 hash, followed by an int, followed by a long,
+ * followed by a byte, followed by an arbitrary number of fixed bytes supplied by the user.
+ * The FixedLengthRowKey instance is used to set the values of the key elements (setInt, setLong), and then obtaining
+ * the constructed byte=array to be used as the rowkey in the table.
+ *
+ * FixedLengthRowKey instances should NOT be considered thread-safe, particularly for MD5 hashing.
+ *
+ * FixedLengthRowKey instances can be re-used by calling reset() and will conform to the RowKeySchema specified on creation.
+ * This can be used when reading a number of rows from HBase in sequence, for example:
+ *
+ *
+ * for ( ) {
+ * byte[] row = result.getRow();
+ * rowkey.setBytes(row);
+ * int i = rowkey.getInt(1);
+ * }
+ *
+ *
+ * @see org.apache.hadoop.hbase.schema.RowKeySchema
+ *
+ */
+public class FixedLengthRowKey {
+
+ private static final String MD5 = "MD5";
+ private byte bytes[] = null;
+ private MessageDigest digest = null;
+ private MurmurHash murmur = null;
+ private RowKeySchema schema = null;
+ private RowKeyDataConverter converter = null;
+
+ /**
+ *
+ * @param schema RowKeySchema instance that describes the format of the rowkey
+ */
+ public FixedLengthRowKey(RowKeySchema schema) {
+ this.schema = schema;
+ this.converter = schema.getDataConverter();
+ bytes = new byte[schema.getRowKeyLength()];
+ }
+
+ /**
+ * This method is used to set the entire backing byte array. Use this, for example,
+ * when a RowKey instance is used to read/process elements of a rowkey obtained from a table.
+ *
+ * The byte array must be consistent with the RowKeySchema that created this RowKey instance.
+ *
+ * @param bytes
+ */
+ public void setBytes(byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ /**
+ * Returns a byte at the specified key element position.
+ *
+ * @param elementPosition zero-based index of key element
+ * @return byte
+ */
+ public byte getByte(int elementPosition) {
+ return bytes[schema.getRowKeyStartPosition(elementPosition)];
+ }
+
+ /**
+ * Returns an int at the specified key element position.
+ *
+ * @param elementPosition zero-based index of key element
+ * @return int
+ */
+ public int getInt(int elementPosition) {
+ return converter.toInt(getBytes(elementPosition));
+ }
+
+ /**
+ * Returns a long at the specified key element position.
+ *
+ * @param elementPosition zero-based index of key element
+ * @return long
+ */
+ public long getLong(int elementPosition) {
+ return converter.toLong(getBytes(elementPosition));
+ }
+
+ /**
+ *
+ * Returns the byte array at the specified key element position.
+ *
+ * @param elementPosition zero-based index of key element
+ * @return byte array
+ */
+ public byte[] getBytes(int elementPosition) {
+ int elementLength = schema.getElementLength(elementPosition);
+ byte[] b = new byte[elementLength];
+ System.arraycopy(bytes, schema.getRowKeyStartPosition(elementPosition), b, 0, elementLength);
+ return b;
+ }
+
+ /**
+ * Addds a byte to the rowkey at the specified key element position.
+ *
+ * @param elementPosition zero-based index of key element
+ * @param b byte
+ */
+ public void setByte(int elementPosition, byte b) {
+ byte tb[] = new byte[1];
+ tb[0] = b;
+ setBytes(elementPosition, tb);
+ }
+
+ /**
+ * Adds an int to the rowkey at the specified key element position
+ *
+ * @param elementPosition zero-based index of key element
+ * @param i (int)
+ */
+ public void setInt(int elementPosition, int i) {
+ setBytes(elementPosition, converter.toBytes(i));
+ }
+
+ /**
+ * Adds a long to the rowkey at the specified key element position
+ *
+ * @param elementPosition zero-based index of key element
+ * @param l (long)
+ */
+ public void setLong(int elementPosition, long l) {
+ setBytes(elementPosition, converter.toBytes(l));
+ }
+
+ /**
+ * Adds a bytearray to the rowkey at the specified key element position
+ *
+ * @param elementPosition zero-based index of key element
+ * @param b (bytes)
+ */
+ public void setBytes(int elementPosition, byte[] b) {
+ RowKeyElement element = schema.getElement(elementPosition);
+ if (!(element instanceof RowKeyHashElement)) {
+ int elementLength = schema.getElementLength(elementPosition);
+ if (elementLength != b.length) {
+ throw new RuntimeException("KeyElement wrong size! keyElement:" + elementPosition + " expected " +
+ elementLength + " was " + b.length);
+ }
+ System.arraycopy(b, 0, bytes, schema.getRowKeyStartPosition(elementPosition), b.length);
+ } else if (element instanceof RowKeyMD5Element) {
+ setMD5Hash(elementPosition, b);
+ } else if (element instanceof RowKeyMurmurElement) {
+ setMurmurHash(elementPosition, b);
+ }
+ }
+
+ /**
+ * Adds an array of bytes, which will be MD5 hashed, to the rowkey at the specified key element position
+ *
+ * @param elementPosition zero-based index of key element
+ * @param b (bytes that will be hashed)
+ */
+ protected void setMurmurHash(int elementPosition, byte[] b) {
+ if (murmur == null) {
+ murmur = new MurmurHash();
+ }
+ int n = murmur.hash(b);
+ byte mb[] = Bytes.toBytes(n);
+ int elementLength = schema.getElementLength(elementPosition);
+ if (elementLength != mb.length) {
+ throw new RuntimeException("KeyElement wrong size! keyElement:" + elementPosition + " expected " +
+ elementLength + " was " + mb.length);
+ }
+ System.arraycopy(mb, 0, bytes, schema.getRowKeyStartPosition(elementPosition), mb.length);
+ }
+
+ /**
+ * Adds an array of bytes, which will be MD5 hashed, to the rowkey at the specified key element position
+ *
+ * @param elementPosition zero-based index of key element
+ * @param b (bytes that will be hashed)
+ */
+ protected void setMD5Hash(int elementPosition, byte[] b) {
+ if (digest == null) {
+ try {
+ digest = MessageDigest.getInstance(MD5);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ byte[] dig = digest.digest(b);
+ int elementLength = schema.getElementLength(elementPosition);
+ if (elementLength != dig.length) {
+ throw new RuntimeException("KeyElement wrong size! keyElement:" + elementPosition + " expected " +
+ elementLength + " was " + dig.length);
+ }
+ System.arraycopy(dig, 0, bytes, schema.getRowKeyStartPosition(elementPosition), dig.length);
+ }
+
+ /**
+ *
+ * @return byte array backing the RowKey. These are the bytes that can be used as the rowkey in your HBase table.
+ */
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ /**
+ * Resets and empties the backing byte array to the same length originally specified by the RowKeySchema
+ * when the RowKey was constructed
+ */
+ public void reset() {
+ bytes = new byte[schema.getRowKeyLength()];
+ }
+
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyByteElement.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyByteElement.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyByteElement.java (revision 0)
@@ -0,0 +1,33 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * RowKeySchema element that indicates that the value is a byte.
+ *
+ */
+public class RowKeyByteElement extends RowKeyElement {
+
+ @Override
+ public int getLength() {
+ return Bytes.SIZEOF_BYTE;
+ }
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyBytesDataConverter.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyBytesDataConverter.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyBytesDataConverter.java (revision 0)
@@ -0,0 +1,53 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * RowKeyBytesDataConverter is a strategy pattern for datatype conversion that is used
+ * within FixedLengthRowKey that uses the HBase Bytes utility.
+ *
+ * Note: the HBase Bytes utility does not properly handle the
+ * sort order of numbers, specifically the case of negative to positive (e.g., -1, 0, 1).
+ * The order will be, for example [0, 1, 2, 3, -3, -2, -1] instead of [-3, -2, -1, 0, 1, 2, 3].
+ * This is not a concern if your data is either all-negative or all-positive, but it is a detail
+ * to be aware of.
+ *
+ * @see org.apache.hbase.util.Bytes
+ */
+public class RowKeyBytesDataConverter extends RowKeyDataConverter {
+
+ public long toLong(byte[] b) {
+ return Bytes.toLong(b);
+ }
+
+ public byte[] toBytes(long l) {
+ return Bytes.toBytes(l);
+ }
+
+ public byte[] toBytes(int i) {
+ return Bytes.toBytes(i);
+ }
+
+ public int toInt(byte[] b) {
+ return Bytes.toInt(b);
+ }
+
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyBytesElement.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyBytesElement.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyBytesElement.java (revision 0)
@@ -0,0 +1,39 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+/**
+ *
+ * RowKeySchema element that indicates that the value is an byte-array of configured length,
+ * with the contents being defined by the caller.
+ *
+ */
+public class RowKeyBytesElement extends RowKeyElement {
+
+ private int bytes = 0;
+
+ public RowKeyBytesElement(int bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public int getLength() {
+ return bytes;
+ }
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyDataConverter.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyDataConverter.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyDataConverter.java (revision 0)
@@ -0,0 +1,38 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * RowKeyDataConverter is a strategy pattern for datatype conversion that is used
+ * within FixedLengthRowKey.
+ *
+ */
+public abstract class RowKeyDataConverter {
+
+ public abstract long toLong(byte[] b);
+
+ public abstract byte[] toBytes(long l);
+
+ public abstract byte[] toBytes(int i);
+
+ public abstract int toInt(byte[] b);
+
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyElement.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyElement.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyElement.java (revision 0)
@@ -0,0 +1,29 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+/**
+ * Base class for RowKeySchema elements
+ *
+ */
+public abstract class RowKeyElement {
+
+ public abstract int getLength();
+
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyHashElement.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyHashElement.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyHashElement.java (revision 0)
@@ -0,0 +1,28 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+/**
+ * Abstract RowKeySchema element indicating that values are to be hashed.
+ *
+ */
+public abstract class RowKeyHashElement extends RowKeyElement {
+
+
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyIntElement.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyIntElement.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyIntElement.java (revision 0)
@@ -0,0 +1,33 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * RowKeySchema element that indicates that the value is a int.
+ *
+ */
+public class RowKeyIntElement extends RowKeyElement {
+
+ @Override
+ public int getLength() {
+ return Bytes.SIZEOF_INT;
+ }
+}
\ No newline at end of file
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyLongElement.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyLongElement.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyLongElement.java (revision 0)
@@ -0,0 +1,33 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * RowKeySchema element that indicates that the value is a long.
+ *
+ */
+public class RowKeyLongElement extends RowKeyElement {
+
+ @Override
+ public int getLength() {
+ return Bytes.SIZEOF_LONG;
+ }
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyMD5Element.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyMD5Element.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyMD5Element.java (revision 0)
@@ -0,0 +1,31 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+/**
+ * RowKeySchema element that indicates that the value should be MD5 hashed.
+ *
+ */
+public class RowKeyMD5Element extends RowKeyHashElement {
+
+ @Override
+ public int getLength() {
+ return 16;
+ }
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyMurmurElement.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyMurmurElement.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeyMurmurElement.java (revision 0)
@@ -0,0 +1,33 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * RowKeySchema element that indicates that the value should be Murmur hashed.
+ *
+ */
+public class RowKeyMurmurElement extends RowKeyHashElement {
+
+ @Override
+ public int getLength() {
+ return Bytes.SIZEOF_INT;
+ }
+}
Index: hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeySchema.java
===================================================================
--- hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeySchema.java (revision 0)
+++ hbase-server/src/main/java/org/apache/hadoop/hbase/schema/RowKeySchema.java (revision 0)
@@ -0,0 +1,168 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.schema;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class used to define the schema of a RowKey.
+ * An instance of RowKeySchema is created by defining an array of integers representing the
+ * lengths of the key elements (i.e., parts) of the rowkey.
+ *
+ *
+ * RowKeySchema schema = new RowKeySchema.Builder()
+ * .add(RowKeySchema.MD5_HASH)
+ * .add(RowKeySchema.INT)
+ * .add(RowKeySchema.LONG)
+ * .add(RowKeySchema.BYTE)
+ * .add(new RowKeyBytesElement(bytesVal.length))
+ * .build();
+ *
+ * FixedLengthRowKey rowkey = schema.createFixedLengthRowKey();
+ *
+ *
+ * In the example above, the rowkey consists of 5 key elements: an MD5 hash, followed by an int,
+ * followed by a long, followed by a byte, followed by an arbitrary number of fixed bytes supplied
+ * by the user.
+ *
+ * RowKeySchema instances can specify a DataConverter strategy pattern via the Builder.
+ * The default implementation is RowKeyBytesDataConverter, however the user can supply their own
+ * RowKeyDataConverter implementation.
+ *
+ * @see org.apache.hbase.schema.FixedLengthRowKey
+ * @see org.apache.hbase.schema.RowKeyDataConverter
+ * @see org.apache.hbase.schema.RowKeyBytesDataConverter
+ */
+public class RowKeySchema {
+
+ public static final RowKeyByteElement BYTE = new RowKeyByteElement();
+ public static final RowKeyIntElement INT = new RowKeyIntElement();
+ public static final RowKeyLongElement LONG = new RowKeyLongElement();
+ public static final RowKeyMD5Element MD5_HASH = new RowKeyMD5Element();
+ public static final RowKeyMurmurElement MURMUR_HASH = new RowKeyMurmurElement();
+
+ private List elements = new ArrayList();
+
+ private int rowKeyLength = 0;
+ private int[] startPositions = null;
+
+ private RowKeyDataConverter converter = null;
+
+ protected RowKeySchema(Builder builder) {
+ converter = builder.getDataConverter();
+ elements.addAll(builder.getElements());
+ startPositions = new int[elements.size()];
+
+ for (int i = 0; i < elements.size(); i++) {
+ startPositions[i] = rowKeyLength;
+ rowKeyLength += elements.get(i).getLength();
+ }
+ }
+
+ /**
+ *
+ * @param keyElement zero-based index of a key element in this schema.
+ * @return length of byte array of the key element specified.
+ */
+ public RowKeyElement getElement(int keyElement) {
+ return elements.get(keyElement);
+ }
+
+ /**
+ *
+ * @param keyElement zero-based index of a key element in this schema.
+ * @return length of byte array of the key element specified.
+ */
+ public int getElementLength(int keyElement) {
+ return elements.get(keyElement).getLength();
+ }
+
+ /**
+ *
+ * @return number of key elements (components) in this schema.
+ */
+ public int getNumberOfElements() {
+ return elements.size();
+ }
+
+ /**
+ *
+ * @return total length of the rowkey based on this schema
+ */
+ public int getRowKeyLength() {
+ return rowKeyLength;
+ }
+
+ /**
+ *
+ * @return FixedLengthRowKey instance that conforms to this schema
+ */
+ public FixedLengthRowKey createFixedLengthRowKey() {
+ return new FixedLengthRowKey(this);
+ }
+
+ /**
+ *
+ * @param keyElement zero-based index of the specified key element in this schema
+ * @return start position in the backing byte-array for this key element.
+ */
+ public int getRowKeyStartPosition(int keyElement) {
+ return startPositions[keyElement];
+ }
+
+ /**
+ *
+ * @return RowKeyDataConverter
+ */
+ public RowKeyDataConverter getDataConverter() {
+ return converter;
+ }
+
+ /**
+ * Builder pattern for creating RowKeySchema instances
+ *
+ */
+ public static class Builder {
+
+ private List elements = new ArrayList();
+ private RowKeyDataConverter converter = new RowKeyBytesDataConverter();
+
+ public List getElements() {
+ return elements;
+ }
+
+ public Builder add(RowKeyElement element) {
+ elements.add(element);
+ return this;
+ }
+
+ public void set(RowKeyDataConverter converter) {
+ this.converter = converter;
+ }
+
+ public RowKeyDataConverter getDataConverter() {
+ return this.converter;
+ }
+
+ public RowKeySchema build() {
+ return new RowKeySchema(this);
+ }
+ }
+}