org.cloudgraph.hbase.scan.CompleteRowKeyAssembler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cloudgraph-hbase Show documentation
Show all versions of cloudgraph-hbase Show documentation
CloudGraph(tm) is a suite of Service Data Object (SDO) 2.1 services designed for relational and big-table style "cloud" databases, such as HBase and others.
/**
* CloudGraph Community Edition (CE) License
*
* This is a community release of CloudGraph, a dual-license suite of
* Service Data Object (SDO) 2.1 services designed for relational and
* big-table style "cloud" databases, such as HBase and others.
* This particular copy of the software is released under the
* version 2 of the GNU General Public License. CloudGraph was developed by
* TerraMeta Software, Inc.
*
* Copyright (c) 2013, TerraMeta Software, Inc. All rights reserved.
*
* General License information can be found below.
*
* This distribution may include materials developed by third
* parties. For license and attribution notices for these
* materials, please refer to the documentation that accompanies
* this distribution (see the "Licenses for Third-Party Components"
* appendix) or view the online documentation at
* .
*/
package org.cloudgraph.hbase.scan;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.util.Hash;
import org.cloudgraph.config.CloudGraphConfig;
import org.cloudgraph.config.DataGraphConfig;
import org.cloudgraph.config.KeyFieldConfig;
import org.cloudgraph.config.PreDefinedKeyFieldConfig;
import org.cloudgraph.config.TableConfig;
import org.cloudgraph.config.UserDefinedRowKeyFieldConfig;
import org.cloudgraph.hbase.key.Hashing;
import org.cloudgraph.hbase.key.KeySupport;
import org.cloudgraph.hbase.key.Padding;
import org.plasma.query.model.Where;
import org.plasma.sdo.DataFlavor;
import org.plasma.sdo.PlasmaType;
/**
* Assembles a row key where each
* field within the composite row key is constructed
* based a set of given query predicates.
*
* @see org.cloudgraph.config.DataGraphConfig
* @see org.cloudgraph.config.TableConfig
* @see org.cloudgraph.config.UserDefinedField
* @see org.cloudgraph.config.PredefinedField
* @see org.cloudgraph.config.PreDefinedFieldName
* @author Scott Cinnamond
* @since 0.5.5
*/
public class CompleteRowKeyAssembler
implements RowKeyScanAssembler, CompleteRowKey
{
private static Log log = LogFactory.getLog(CompleteRowKeyAssembler.class);
protected int bufsize = 4000;
protected ByteBuffer startKey = ByteBuffer.allocate(bufsize);
protected PlasmaType rootType;
protected DataGraphConfig graph;
protected TableConfig table;
protected KeySupport keySupport = new KeySupport();
protected Charset charset;
protected ScanLiterals scanLiterals;
protected int startRowFieldCount;
protected String rootUUID;
protected Hashing hashing;
protected Padding padding;
@SuppressWarnings("unused")
private CompleteRowKeyAssembler() {}
/**
* Constructor
* @param rootType the root type
*/
public CompleteRowKeyAssembler(PlasmaType rootType)
{
this.rootType = rootType;
QName rootTypeQname = this.rootType.getQualifiedName();
this.graph = CloudGraphConfig.getInstance().getDataGraph(
rootTypeQname);
this.table = CloudGraphConfig.getInstance().getTable(rootTypeQname);
Hash hash = this.keySupport.getHashAlgorithm(this.table);
this.charset = CloudGraphConfig.getInstance().getCharset();
this.hashing = new Hashing(hash, this.charset);
this.padding = new Padding(this.charset);
}
/**
* Constructor which enables the use of data object UUID as
* a pre-defined row key field. Only applicable for graph
* predicate "slice" queries.
* @param rootType the root type
* @param rootUUID the root UUID.
*/
public CompleteRowKeyAssembler(PlasmaType rootType, String rootUUID)
{
this(rootType);
this.rootUUID = rootUUID;
}
/**
* Assemble row key scan information based only on any
* pre-defined row-key fields such as the
* data graph root type or URI.
* @see org.cloudgraph.config.PredefinedField
* @see org.cloudgraph.config.PreDefinedFieldName
*/
@Override
public void assemble() {
this.startKey = ByteBuffer.allocate(bufsize);
assemblePredefinedFields();
}
/**
* Assemble row key scan information based on the given
* scan literals as well as pre-defined row-key fields such as the
* data graph root type or URI.
* @param literalList the scan literals
* @see org.cloudgraph.config.PredefinedField
* @see org.cloudgraph.config.PreDefinedFieldName
*/
@Override
public void assemble(ScanLiterals literals) {
this.scanLiterals = literals;
this.startKey = ByteBuffer.allocate(bufsize);
assembleLiterals();
}
/**
* Assemble row key scan information based on one or more
* given query predicates.
* @param where the row predicate hierarchy
* @param contextType the context type which may be the root type or another
* type linked by one or more relations to the root
*/
@Override
public void assemble(Where where, PlasmaType contextType) {
this.startKey = ByteBuffer.allocate(bufsize);
if (log.isDebugEnabled())
log.debug("begin traverse");
ScanLiteralAssembler literalAssembler =
new ScanLiteralAssembler(this.rootType);
where.accept(literalAssembler); // traverse
this.scanLiterals = literalAssembler.getPartialKeyScanResult();
if (log.isDebugEnabled())
log.debug("end traverse");
assembleLiterals();
}
private void assemblePredefinedFields()
{
List resultFields = new ArrayList();
for (PreDefinedKeyFieldConfig field : this.graph.getPreDefinedRowKeyFields()) {
switch (field.getName()) {
case URI:
case TYPE:
resultFields.add(field);
break;
case UUID:
break; // not applicable
default:
}
}
int fieldCount = resultFields.size();
for (int i = 0; i < fieldCount; i++) {
PreDefinedKeyFieldConfig preDefinedField = resultFields.get(i);
if (startRowFieldCount > 0) {
this.startKey.put(graph.getRowKeyFieldDelimiterBytes());
}
byte[] startValue = this.keySupport.getPredefinedFieldValueStartBytes(this.rootType,
hashing, preDefinedField);
byte[] paddedStartValue = null;
if (preDefinedField.isHash()) {
paddedStartValue = this.padding.pad(startValue, preDefinedField.getMaxLength(),
DataFlavor.integral);
}
else {
paddedStartValue = this.padding.pad(startValue, preDefinedField.getMaxLength(),
preDefinedField.getDataFlavor());
}
this.startKey.put(paddedStartValue);
}
}
private void assembleLiterals()
{
for (KeyFieldConfig fieldConfig : this.graph.getRowKeyFields()) {
if (fieldConfig instanceof PreDefinedKeyFieldConfig) {
PreDefinedKeyFieldConfig predefinedConfig = (PreDefinedKeyFieldConfig)fieldConfig;
byte[] tokenValue = null;
switch (predefinedConfig.getName()) {
case UUID:
if (this.rootUUID != null) {
tokenValue = this.rootUUID.getBytes(this.charset);
break;
}
else
continue;
default:
tokenValue = predefinedConfig.getKeyBytes(this.rootType);
break;
}
//FIXME: if predefined field is last, need stop bytes
byte[] paddedTokenValue = null;
if (fieldConfig.isHash()) {
tokenValue = hashing.toStringBytes(tokenValue);
paddedTokenValue = this.padding.pad(tokenValue, predefinedConfig.getMaxLength(),
DataFlavor.integral);
}
else {
paddedTokenValue = this.padding.pad(tokenValue, predefinedConfig.getMaxLength(),
predefinedConfig.getDataFlavor());
}
if (startRowFieldCount > 0)
this.startKey.put(graph.getRowKeyFieldDelimiterBytes());
this.startKey.put(paddedTokenValue);
this.startRowFieldCount++;
}
else if (fieldConfig instanceof UserDefinedRowKeyFieldConfig) {
UserDefinedRowKeyFieldConfig userFieldConfig = (UserDefinedRowKeyFieldConfig)fieldConfig;
List scanLiterals = this.scanLiterals.getLiterals(userFieldConfig);
if (scanLiterals == null)
continue;
for (ScanLiteral scanLiteral : scanLiterals) {
byte[] startBytes = scanLiteral.getStartBytes();
if (startBytes.length > 0) {
if (this.startRowFieldCount > 0) {
this.startKey.put(graph.getRowKeyFieldDelimiterBytes());
}
this.startKey.put(startBytes);
this.startRowFieldCount++;
}
}
}
}
}
/**
* Returns the row key as a byte array.
* @return the row key
* @throws IllegalStateException if the row key is not yet assembled
*/
@Override
public byte[] getKey() {
if (this.startKey == null)
throw new IllegalStateException("row keys not assembled - first call assemble(...)");
// ByteBuffer.array() returns unsized array so don't sent that back to clients
// to misuse.
// Use native arraycopy() method as it uses native memcopy to create result array
// and because
// ByteBuffer.get(byte[] dst,int offset, int length) is not native
byte [] result = new byte[this.startKey.position()];
System.arraycopy(this.startKey.array(), this.startKey.arrayOffset(), result, 0, this.startKey.position());
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy