/**
* Copyright 2009 The Apache Software Foundation
*
* 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.client.ccindex;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.ObjectWritable;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;
/** Holds the specification for a single CCIT. */
public class IndexSpecification implements Writable {
// Columns that are indexed (part of the indexRowKey)
private ArrayList<byte[]> additionalFamily =new ArrayList<byte[]>();
private byte[] family;
public byte[] getFamily() {
return family;
}
public void setFamily(byte[] family) {
this.family = family;
}
public byte[] getColumn() {
return column;
}
public void setColumn(byte[] column) {
this.column = column;
}
private byte[] column;
private byte[][] indexedColumns;
public void setIndexedColumns(byte[][] indexedColumns) {
this.indexedColumns = indexedColumns;
}
private CCIndexDescriptor CCIndex;
public CCIndexDescriptor getCCIndex() {
return CCIndex;
}
public void setCCIndex(CCIndexDescriptor cCIndex) {
CCIndex = cCIndex;
this.indexedColumns=cCIndex.getIndexedColumns();
}
private byte[] indexedColumn;
public byte[] getIndexedColumn() {
return indexedColumn;
}
public void setIndexedColumn(byte[] indexedColumn) {
this.indexedColumn = indexedColumn;
byte[][]fq=KeyValue.parseColumn(this.indexedColumn);
this.family=fq[0];
this.column=fq[1];
}
// Constructs the
private IndexKeyGenerator keyGenerator;
// Additional columns mapped into the indexed row. These will be available for
// filters when scanning the index.
private byte[][] additionalColumns;
private byte[][] allColumns;
// Id of this index, unique within a table.
private byte[] indexId;
/** Construct an "simple" index spec for a single column.
* @param indexId
* @param indexedColumn
*/
public IndexSpecification(byte[] indexId,byte[] indexedColumn, CCIndexDescriptor CCIndex) {
this(indexId,indexedColumn , null,
new SimpleIndexKeyGenerator(), CCIndex);
}
public IndexSpecification(byte[] indexId,byte[] indexedColumn,byte[][] additionalColumns, CCIndexDescriptor CCIndex) {
this(indexId,indexedColumn ,additionalColumns,
new SimpleIndexKeyGenerator(), CCIndex);
}
/**
* Construct an index spec by specifying everything.
*
* @param indexId
* @param indexedColumns
* @param additionalColumns
* @param keyGenerator
*/
public IndexSpecification(byte[] indexId,byte[] indexedColumn,
byte[][] additionalColumns, IndexKeyGenerator keyGenerator , CCIndexDescriptor CCIndex) {
this.indexId = indexId;
this.indexedColumn=indexedColumn;
byte[][]fq=KeyValue.parseColumn(this.indexedColumn);
this.family=fq[0];
this.column=fq[1];
this.CCIndex=CCIndex;
this.indexedColumns=CCIndex.getIndexedColumns();
this.keyGenerator = keyGenerator;
this.additionalColumns = (additionalColumns == null)? new byte[0][0] :
additionalColumns;
this.makeAllColumns();
}
public IndexSpecification() {
// For writable
}
public ArrayList<byte[]> getAdditionalFamily() {
return additionalFamily;
}
public void setAdditionalFamily(ArrayList<byte[]> additionalFamily) {
this.additionalFamily = additionalFamily;
}
private void makeAllColumns() {
this.allColumns = new byte[indexedColumns.length
+ (additionalColumns == null ? 0 : additionalColumns.length)][];
System.arraycopy(indexedColumns, 0, allColumns, 0, indexedColumns.length);
if (additionalColumns != null) {
System.arraycopy(additionalColumns, 0, allColumns, indexedColumns.length,
additionalColumns.length);
for(byte[] family:additionalColumns)
{
byte[][] fq=KeyValue.parseColumn(family);
this.additionalFamily.add(fq[0]);
}
}
}
/**
* Get the indexedColumns.
*
* @return Return the indexedColumns.
*/
public byte[][] getIndexedColumns() {
return indexedColumns;
}
/**
* Get the keyGenerator.
*
* @return Return the keyGenerator.
*/
public IndexKeyGenerator getKeyGenerator() {
return keyGenerator;
}
/**
* Get the additionalColumns.
*
* @return Return the additionalColumns.
*/
public byte[][] getAdditionalColumns() {
return additionalColumns;
}
/**
* Get the indexId.
*
* @return Return the indexId.
*/
public byte[] getIndexId() {
return indexId;
}
public byte[][] getAllColumns() {
return allColumns;
}
public boolean containsColumn(byte[] column) {
for (byte[] col : allColumns) {
if (Bytes.equals(column, col)) {
return true;
}
}
return false;
}
public byte[] getIndexedTableName(byte[] baseTableName) {
return Bytes.add(baseTableName, Bytes.toBytes("_" + indexId));
}
private static final HBaseConfiguration CONF = new HBaseConfiguration();
/** {@inheritDoc} */
public static void printBytes(byte[]s)
{
// String out="";
// for(byte b:s)
// {
// out+=","+b;
//
//
// }
// System.out.println(out);
}
public void readFields(DataInput in) throws IOException {
indexId = Bytes.readByteArray(in);
indexedColumn = Bytes.readByteArray(in);
byte[][]fq=KeyValue.parseColumn(this.indexedColumn);
this.family=fq[0];
this.column=fq[1];
//System.out.println("read:");
//this.printBytes(indexedColumn);
//System.out.println(new String(indexedColumn));
int numAdditionalCols = in.readInt();
additionalColumns = new byte[numAdditionalCols][];
for (int i = 0; i < numAdditionalCols; i++) {
additionalColumns[i] = Bytes.readByteArray(in);
}
makeAllColumns();
keyGenerator = (IndexKeyGenerator) ObjectWritable.readObject(in, CONF);
// FIXME this is to read the deprecated comparator, in existing data
ObjectWritable.readObject(in, CONF);
}
/** {@inheritDoc} */
public void write(DataOutput out) throws IOException {
Bytes.writeByteArray(out, this.indexId);
Bytes.writeByteArray(out, this.indexedColumn);
//System.out.println("write:");
//System.out.println(indexedColumn);
//System.out.println(new String(indexedColumn));
if (additionalColumns != null) {
out.writeInt(additionalColumns.length);
for (byte[] col : additionalColumns) {
Bytes.writeByteArray(out, col);
}
} else {
out.writeInt(0);
}
ObjectWritable
.writeObject(out, keyGenerator, IndexKeyGenerator.class, CONF);
// FIXME need to maintain this for exisitng data
ObjectWritable.writeObject(out, null, WritableComparable.class,
CONF);
}
/** {@inheritDoc} */
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ID => ");
sb.append(indexId);
return sb.toString();
}
public boolean equals(Object arg0)
{
if(arg0 instanceof IndexSpecification)
{
IndexSpecification index=(IndexSpecification)arg0;
if(index.CCIndex==null)
{
if(index.indexId.equals(this.indexId))
return true;
}
if(index.indexId.equals(this.indexId)&&this.CCIndex.getBaseTableDescriptor().getName().equals(index.CCIndex.getBaseTableDescriptor().getName()))
return true;
}
return false;
}
public byte[] getCCITName() {
return Bytes.add(this.CCIndex.getBaseTableDescriptor().getName(),Bytes.toBytes("-"),this.indexId);
// TODO Auto-generated method stub
}
public static byte[] getCCTNameBase(byte[] baseName) {
return Bytes.add(baseName,Bytes.toBytes("-"),Bytes.toBytes(CCIndexConstants.CCT_TAIL));
// TODO Auto-generated method stub
}
public byte[] getCCTName() {
return Bytes.add(this.getCCITName(),Bytes.toBytes("-"),Bytes.toBytes(CCIndexConstants.CCT_TAIL));
// TODO Auto-generated method stub
}
}