/** * 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.tableindexed; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import org.apache.hadoop.hbase.HBaseConfiguration; 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 secondary index. */ public class IndexSpecification implements Writable { // Columns that are indexed (part of the indexRowKey) private byte[][] indexedColumns; // 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 String indexId; /** Construct an "simple" index spec for a single column. * @param indexId * @param indexedColumn */ public IndexSpecification(String indexId, byte[] indexedColumn) { this(indexId, new byte[][] { indexedColumn }, null, new SimpleIndexKeyGenerator(indexedColumn)); } /** * Construct an index spec by specifying everything. * * @param indexId * @param indexedColumns * @param additionalColumns * @param keyGenerator */ public IndexSpecification(String indexId, byte[][] indexedColumns, byte[][] additionalColumns, IndexKeyGenerator keyGenerator) { this.indexId = indexId; this.indexedColumns = indexedColumns; this.keyGenerator = keyGenerator; this.additionalColumns = (additionalColumns == null)? new byte[0][0] : additionalColumns; this.makeAllColumns(); } public IndexSpecification() { // For writable } 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); } } /** * 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 String 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)); } @SuppressWarnings("deprecation") private static final HBaseConfiguration CONF = new HBaseConfiguration(); /** {@inheritDoc} */ public void readFields(DataInput in) throws IOException { indexId = in.readUTF(); int numIndexedCols = in.readInt(); indexedColumns = new byte[numIndexedCols][]; for (int i = 0; i < numIndexedCols; i++) { indexedColumns[i] = Bytes.readByteArray(in); } 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 { out.writeUTF(indexId); out.writeInt(indexedColumns.length); for (byte[] col : indexedColumns) { Bytes.writeByteArray(out, col); } 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} */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ID => "); sb.append(indexId); return sb.toString(); } }