001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.fusesource.hawtdb.api; 018 019 import org.fusesource.hawtbuf.codec.Codec; 020 import org.fusesource.hawtdb.internal.index.BTreeIndex; 021 import org.fusesource.hawtbuf.codec.ObjectCodec; 022 023 import java.util.Comparator; 024 025 /** 026 * This object is used to create variable magnitude b+tree indexes. 027 * 028 * A b+tree can be used for set or map-based indexing. Leaf 029 * nodes are linked together for faster iteration of the values. 030 * 031 * <br> 032 * The variable magnitude attribute means that the b+tree attempts 033 * to store as many values and pointers on one page as is possible. 034 * 035 * <br> 036 * It will act as a simple-prefix b+tree if a prefixer is configured. 037 * 038 * <br> 039 * In a simple-prefix b+tree, instead of promoting actual keys to branch pages, when 040 * leaves are split, a shortest-possible separator is generated at the pivot. 041 * That separator is what is promoted to the parent branch (and continuing up 042 * the list). As a result, actual keys and pointers can only be found at the 043 * leaf level. This also affords the index the ability to ignore costly merging 044 * and redistribution of pages when deletions occur. Deletions only affect leaf 045 * pages in this implementation, and so it is entirely possible for a leaf page 046 * to be completely empty after all of its keys have been removed. 047 * 048 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 049 */ 050 public class BTreeIndexFactory<Key, Value> implements IndexFactory<Key, Value> { 051 052 private Codec<Key> keyCodec = new ObjectCodec<Key>(); 053 private Codec<Value> valueCodec = new ObjectCodec<Value>(); 054 private boolean deferredEncoding=true; 055 private Prefixer<Key> prefixer; 056 private Comparator comparator = null; 057 058 /** 059 * Creates a new BTree index on the Paged object. 060 */ 061 public SortedIndex<Key, Value> create(Paged paged) { 062 BTreeIndex<Key, Value> index = createInstance(paged, paged.alloc()); 063 index.create(); 064 return index; 065 } 066 067 @Override 068 public String toString() { 069 return "{ deferredEncoding: "+deferredEncoding+" }"; 070 } 071 072 /** 073 * Loads an existing BTree index from the paged object. 074 */ 075 public SortedIndex<Key, Value> open(Paged paged, int indexNumber) { 076 return createInstance(paged, indexNumber); 077 } 078 079 /** 080 * Loads an existing BTree index from the paged object. 081 */ 082 public SortedIndex<Key, Value> open(Paged paged) { 083 return createInstance(paged, 0); 084 } 085 086 private BTreeIndex<Key, Value> createInstance(Paged paged, int page) { 087 return new BTreeIndex<Key, Value>(paged, page, this); 088 } 089 090 /** 091 * Defaults to an {@link org.fusesource.hawtbuf.codec.ObjectCodec} if not explicitly set. 092 * 093 * @return the marshaller used for keys. 094 */ 095 public Codec<Key> getKeyCodec() { 096 return keyCodec; 097 } 098 099 /** 100 * Allows you to configure custom marshalling logic to encode the index keys. 101 * 102 * @param codec the marshaller used for keys. 103 */ 104 public void setKeyCodec(Codec<Key> codec) { 105 this.keyCodec = codec; 106 } 107 108 /** 109 * Defaults to an {@link org.fusesource.hawtbuf.codec.ObjectCodec} if not explicitly set. 110 * 111 * @return the marshaller used for values. 112 */ 113 public Codec<Value> getValueCodec() { 114 return valueCodec; 115 } 116 117 /** 118 * Allows you to configure custom marshalling logic to encode the index values. 119 * 120 * @param codec the marshaller used for values 121 */ 122 public void setValueCodec(Codec<Value> codec) { 123 this.valueCodec = codec; 124 } 125 126 /** 127 * 128 * @return true if deferred encoding enabled 129 */ 130 public boolean isDeferredEncoding() { 131 return deferredEncoding; 132 } 133 134 /** 135 * <p> 136 * When deferred encoding is enabled, the index avoids encoding keys and values 137 * for as long as possible so take advantage of collapsing multiple updates of the 138 * same key/value into a single update operation and single encoding operation. 139 * </p><p> 140 * Using this feature requires the keys and values to be immutable objects since 141 * unexpected errors would occur if they are changed after they have been handed 142 * to to the index for storage. 143 * </p> 144 * @param enable should deferred encoding be enabled. 145 */ 146 public void setDeferredEncoding(boolean enable) { 147 this.deferredEncoding = enable; 148 } 149 150 public Prefixer<Key> getPrefixer() { 151 return prefixer; 152 } 153 154 public void setPrefixer(Prefixer<Key> prefixer) { 155 this.prefixer = prefixer; 156 } 157 158 /** 159 * Gets the custom configured Comparator used to sort the keys 160 * in the index. Defaults to null. 161 * 162 * @return 163 */ 164 public Comparator getComparator() { 165 return comparator; 166 } 167 168 /** 169 * Configures a custom Comparator used to sort the keys 170 * in the index. If not set, the keys must implement the 171 * {@link Comparable} interface. 172 * 173 * @param comparator 174 */ 175 public void setComparator(Comparator comparator) { 176 this.comparator = comparator; 177 } 178 }