/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.bigdata.btree; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Properties; import java.util.UUID; import com.bigdata.btree.raba.codec.IRabaCoder; import com.bigdata.htree.HTree; import com.bigdata.io.LongPacker; import com.bigdata.journal.IIndexManager; import com.bigdata.service.IBigdataFederation; /** * HTree specific implementation. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> */ public class HTreeIndexMetadata extends IndexMetadata { private static final long serialVersionUID = -1L; /** * {@link HTree} specific options. */ public interface Options extends IndexMetadata.Options { /** * The name of a class derived from {@link HTree} that will be used to * re-load the index. */ String HTREE_CLASS_NAME = HTree.class.getName()+".className"; /** * The name of an optional property whose value specifies the number of * address bits for an {@link HTree} (default * {@value #DEFAULT_HTREE_ADDRESS_BITS}). * <p> * The #of children for a directory is <code>2^addressBits</code>. For * example, a value of <code>10</code> means a <code>10</code> bit * address space in the directory. Such a directory would provide direct * addressing for <code>1024</code> child references. Given an overhead * of <code>8</code> bytes per child address, that would result in an * expected page size of 8k before compression. * * @see #DEFAULT_HTREE_ADDRESS_BITS */ String HTREE_ADDRESS_BITS = HTree.class.getPackage().getName() + ".addressBits"; String DEFAULT_HTREE_ADDRESS_BITS = "10"; /** * The name of an optional property whose value specifies the fixed by * length of the keys in the {@link HTree} -or- ZERO (0) if the key * length is unconstrained, in which case variable length keys may be * used (default {@value #DEFAULT_HTREE_KEY_LEN}). This may be used in * combination with an appropriate {@link IRabaCoder} to optimize to * search and encoding of int32 or int64 keys. * * @see #DEFAULT_HTREE_KEY_LEN */ String HTREE_KEY_LEN = HTree.class.getPackage().getName() + ".keyLen"; String DEFAULT_HTREE_KEY_LEN = "0"; } /** * @see Options#HTREE_CLASS_NAME */ private String htreeClassName; /** * @see Options#HTREE_ADDRESS_BITS */ private int addressBits; /** * @see Options#HTREE_KEY_LEN */ private int keyLen; /** * The name of a class derived from {@link HTree} that will be used to * re-load the index. * * @see Options#HTREE_CLASS_NAME */ public final String getHTreeClassName() { return htreeClassName; } public void setHTreeClassName(final String className) { if (className == null) throw new IllegalArgumentException(); this.htreeClassName = className; } public int getAddressBits() { return addressBits; } public void setAddressBits(final int addressBits) { this.addressBits = addressBits; } public int getKeyLen() { return keyLen; } public void setKeyLen(final int keyLen) { this.keyLen = keyLen; } /** * <strong>De-serialization constructor only</strong> - DO NOT use this ctor * for creating a new instance! It will result in a thrown exception, * typically from {@link #firstCheckpoint()}. */ public HTreeIndexMetadata() { super(); } /** * Constructor used to configure a new <em>unnamed</em> {@link HTree}. The * index UUID is set to the given value and all other fields are defaulted * as explained at {@link #HTreeIndexMetadata(Properties, String, UUID)}. * Those defaults may be overridden using the various setter methods, but * some values can not be safely overridden after the index is in use. * * @param indexUUID * The indexUUID. * * @throws IllegalArgumentException * if the indexUUID is <code>null</code>. */ public HTreeIndexMetadata(final UUID indexUUID) { this(null/* name */, indexUUID); } /** * Constructor used to configure a new <em>named</em> {@link BTree}. The * index UUID is set to the given value and all other fields are defaulted * as explained at {@link #IndexMetadata(Properties, String, UUID)}. Those * defaults may be overridden using the various setter methods, but some * values can not be safely overridden after the index is in use. * * @param name * The index name. When this is a scale-out index, the same * <i>name</i> is specified for each index resource. However they * will be registered on the journal under different names * depending on the index partition to which they belong. * * @param indexUUID * The indexUUID. The same index UUID MUST be used for all * component indices in a scale-out index. * * @throws IllegalArgumentException * if the indexUUID is <code>null</code>. */ public HTreeIndexMetadata(final String name, final UUID indexUUID) { this(null/* name */, System.getProperties(), name, indexUUID); } /** * Constructor used to configure a new <em>named</em> B+Tree. The index UUID * is set to the given value and all other fields are defaulted as explained * at {@link #getProperty(Properties, String, String, String)}. Those * defaults may be overridden using the various setter methods. * * @param indexManager * Optional. When given and when the {@link IIndexManager} is a * scale-out {@link IBigdataFederation}, this object will be used * to interpret the {@link Options#INITIAL_DATA_SERVICE} * property. * @param properties * Properties object used to overridden the default values for * this {@link IndexMetadata} instance. * @param namespace * The index name. When this is a scale-out index, the same * <i>name</i> is specified for each index resource. However they * will be registered on the journal under different names * depending on the index partition to which they belong. * @param indexUUID * component indices in a scale-out index. * The indexUUID. The same index UUID MUST be used for all * @param indexType * Type-safe enumeration specifying the type of the persistence * class data structure (historically, this was always a B+Tree). * * @throws IllegalArgumentException * if <i>properties</i> is <code>null</code>. * @throws IllegalArgumentException * if <i>indexUUID</i> is <code>null</code>. */ public HTreeIndexMetadata(final IIndexManager indexManager, final Properties properties, final String namespace, final UUID indexUUID) { super(indexManager, properties, namespace, indexUUID, IndexTypeEnum.HTree); /* * Intern'd to reduce duplication on the heap. */ this.htreeClassName = getProperty(indexManager, properties, namespace, Options.HTREE_CLASS_NAME, HTree.class.getName()).intern(); this.addressBits = Integer.parseInt(getProperty(indexManager, properties, namespace, Options.HTREE_ADDRESS_BITS, Options.DEFAULT_HTREE_ADDRESS_BITS)); this.keyLen = Integer .parseInt(getProperty(indexManager, properties, namespace, Options.HTREE_KEY_LEN, Options.DEFAULT_HTREE_KEY_LEN)); } @Override protected void toString(final StringBuilder sb) { super.toString(sb); // htree sb.append(", htreeClassName=" + htreeClassName); sb.append(", addressBits=" + addressBits); sb.append(", keyLen=" + keyLen); } /** * The initial version. */ private static transient final int VERSION0 = 0x0; /** * The version that will be serialized by this class. */ private static transient final int CURRENT_VERSION = VERSION0; @Override public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); final int version = LongPacker.unpackInt(in); keyLen = LongPacker.unpackInt(in); addressBits = LongPacker.unpackInt(in); htreeClassName = in.readUTF(); } @Override public void writeExternal(final ObjectOutput out) throws IOException { super.writeExternal(out); final int version = CURRENT_VERSION; LongPacker.packLong(out, version); LongPacker.packLong(out, keyLen); LongPacker.packLong(out, addressBits); out.writeUTF(htreeClassName); } @Override public HTreeIndexMetadata clone() { return (HTreeIndexMetadata) super.clone(); } }