/**
* Copyright 2013 Oak Ridge National Laboratory
* Author: James Horey <horeyjl@ornl.gov>
*
* Licensed 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 gov.ornl.keva.table;
/**
* Java libs.
**/
import java.util.Arrays;
import java.nio.ByteBuffer;
/**
* Hashing functions.
**/
import net.jpountz.xxhash.XXHash32;
import net.jpountz.xxhash.XXHashFactory;
/**
* Table keys uniquely identify a set of table values in the memtable and
* sstables. Internally, table keys use an array of bytes to store the
* actual key. In addition, table keys are data type aware (they store an
* optional string identifying the data).
*
* @author James Horey
*/
public class TableKey implements Comparable<TableKey> {
private byte[] data; // Actual key.
private int hashCode;
/**
* Fast hash capabilities.
*/
private static final XXHashFactory factory = XXHashFactory.fastestInstance();
private static final XXHash32 hash = factory.hash32();
public TableKey() {
this(null);
}
/**
* Create a key from the byte array with the optional data type.
*
* @param key Data used for the key
*/
public TableKey(byte[] key) {
data = key;
}
/**
* The value is the actual data for the key.
*
* @param data Data used for the key
*/
public void setValue(byte[] key) {
// Get the hash code of the key.
hashCode = hash.hash(key, 0, key.length, 7829);
data = key;
}
/**
* Get the data value.
*
* @return Data used for the key
*/
public byte[] getValue() {
return data;
}
/**
* Compare the two table keys using string-based order.
*
* @param key Table key to compare
* @return Positive value if this key is greater, otherwise
* a negative value.
*/
@Override public int compareTo(TableKey key) {
if(this == key) {
return 0;
}
byte[] keyData = key.getValue();
int n = Math.min(data.length, keyData.length);
for (int i = 0, j = 0; i < n; i++, j++) {
byte v1 = data[i];
byte v2 = keyData[j];
if (v1 == v2)
continue;
if ((v1 != v1) && (v2 != v2)) // For float and double
continue;
if (v1 < v2)
return -1;
return +1;
}
return data.length - keyData.length;
}
/**
* Test if the object is an equivalent key.
* Both type and values must match.
*
* @param obj Table key to compare
* @return True if the keys are equivalent. False otherwise.
*/
@Override public boolean equals(Object obj) {
if(this == obj) {
return true;
}
TableKey ok = (TableKey)obj;
return Arrays.equals(data, ok.getValue());
}
/**
* Generate a hash value for the key.
* Base the new hash code on the type and value.
*
* @return Hash value
*/
@Override public int hashCode() {
return hashCode;
}
/**
* Estimate the size of this table key.
*
* @return Number of bytes
*/
public long size() {
return
(Integer.SIZE / 8) +
data.length;
}
/**
* Serialize the key.
*
* @return Serialized key
*/
public byte[] serialize() {
// ByteBuffer buf;
// buf = ByteBuffer.allocate(data.length);
// buf.put(data);
// // Reset the data to the initial position.
// return buf.array();
return data;
}
/**
* Create a new table key from the serialized byte buffer.
*
* @param buf Serialized byte buffer
* @return New table key
*/
public static TableKey fromBytes(ByteBuffer buf) {
TableKey key;
if(buf.isDirect()) {
return new TableKey(buf.array());
}
else {
byte[] value = new byte[buf.capacity()];
buf.get(value);
return new TableKey(value);
}
}
/**
* Return the string representation of this key data.
*
* @return String representation of the key
*/
public String toString() {
return new String(data);
}
/**
* Create a new table key from the string.
*
* @param string Table key data value
* @return New table key
*/
public static TableKey fromString(String string) {
return new TableKey(string.getBytes());
}
}