View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.mavibot.btree;
21  
22  
23  import java.io.IOException;
24  import java.lang.reflect.Array;
25  import java.util.Comparator;
26  import java.util.UUID;
27  
28  import org.apache.directory.mavibot.btree.exception.BTreeOperationException;
29  import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
30  import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
31  
32  
33  /**
34   * A holder to store the Values
35   *
36   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
37   * @param <V> The value type
38   */
39  /* No qualifier */class InMemoryValueHolder<V> extends AbstractValueHolder<V>
40  {
41      /**
42       * Creates a new instance of a ValueHolder, containing the serialized values.
43       *
44       * @param parentBtree the parent BTree
45       * @param valueSerializer The Value's serializer
46       * @param raw The raw data containing the values
47       * @param nbValues the number of stored values
48       * @param raw the byte[] containing either the serialized array of values or the sub-btree offset
49       */
50      InMemoryValueHolder( BTree<?, V> parentBtree, int nbValues )
51      {
52          valueSerializer = parentBtree.getValueSerializer();
53  
54          if ( nbValues <= 1 )
55          {
56              valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), nbValues );
57          }
58      }
59  
60  
61      /**
62       * Creates a new instance of a ValueHolder, containing Values. This constructor is called
63       * when we need to create a new ValueHolder with deserialized values.
64       *
65       * @param parentBtree The parent BTree
66       * @param values The Values stored in the ValueHolder
67       */
68      InMemoryValueHolder( BTree<?, V> parentBtree, V... values )
69      {
70          valueSerializer = parentBtree.getValueSerializer();
71  
72          if ( ( values != null ) && ( values.length > 0 ) )
73          {
74              int nbValues = values.length;
75  
76              if ( nbValues == 1 )
77              {
78                  // Store the value
79                  valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), nbValues );
80                  valueArray[0] = values[0];
81                  nbArrayElems = nbValues;
82              }
83              else
84              {
85                  // Use a sub btree, now that we have reached the threshold
86                  createSubTree();
87  
88                  // Now inject all the values into it
89                  for ( V value : values )
90                  {
91                      try
92                      {
93                          valueBtree.insert( value, value );
94                      }
95                      catch ( IOException e )
96                      {
97                          e.printStackTrace();
98                      }
99                  }
100             }
101         }
102     }
103 
104 
105     /**
106      * {@inheritDoc}
107      */
108     public int size()
109     {
110         if ( valueBtree != null )
111         {
112             return ( int ) valueBtree.getNbElems();
113         }
114         else
115         {
116             return nbArrayElems;
117         }
118     }
119 
120 
121     /**
122      * Create a new Sub-BTree to store the values.
123      */
124     protected void createSubTree()
125     {
126         InMemoryBTreeConfiguration<V, V> configuration = new InMemoryBTreeConfiguration<V, V>();
127         configuration.setAllowDuplicates( false );
128         configuration.setName( UUID.randomUUID().toString() );
129         configuration.setKeySerializer( valueSerializer );
130         configuration.setValueSerializer( valueSerializer );
131 
132         valueBtree = BTreeFactory.createInMemoryBTree( configuration );
133     }
134 
135 
136     /**
137      * Manage a new Sub-BTree
138      */
139     protected void manageSubTree()
140     {
141         // Nothing to do
142     }
143 
144 
145     /**
146      * Set the subBtree in the ValueHolder
147      */
148     /* No qualifier*/void setSubBtree( BTree<V, V> subBtree )
149     {
150         valueBtree = subBtree;
151         valueArray = null;
152     }
153 
154 
155     /**
156      * {@inheritDoc}
157      */
158     public V remove( V value )
159     {
160         V removedValue = null;
161 
162         if ( valueArray != null )
163         {
164             removedValue = removeFromArray( value );
165         }
166         else
167         {
168             removedValue = removeFromBtree( value );
169         }
170 
171         return removedValue;
172     }
173 
174 
175     /**
176      * Remove the value from a sub btree
177      */
178     private V removeFromBtree( V removedValue )
179     {
180         V returnedValue = null;
181 
182         try
183         {
184             Tuple<V, V> removedTuple = valueBtree.delete( removedValue );
185 
186             if ( removedTuple != null )
187             {
188                 returnedValue = removedTuple.getKey();
189             }
190         }
191         catch ( IOException e )
192         {
193             throw new BTreeOperationException( e );
194         }
195 
196         if ( valueBtree.getNbElems() == 1 )
197         {
198             try
199             {
200                 valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), 1 );
201                 valueArray[0] = valueBtree.browse().next().getKey();
202                 nbArrayElems = 1;
203                 valueBtree.close();
204                 valueBtree = null;
205             }
206             catch ( EndOfFileExceededException e )
207             {
208                 throw new BTreeOperationException( e );
209             }
210             catch ( IOException e )
211             {
212                 throw new BTreeOperationException( e );
213             }
214             catch ( KeyNotFoundException knfe )
215             {
216                 throw new BTreeOperationException( knfe );
217             }
218         }
219 
220         return returnedValue;
221     }
222 
223 
224     /**
225      * Remove a value from an array
226      */
227     private V removeFromArray( V value )
228     {
229         // First check that the value is not already present in the ValueHolder
230         Comparator<V> comparator = valueSerializer.getComparator();
231 
232         int result = comparator.compare( valueArray[0], value );
233 
234         if ( result != 0 )
235         {
236             // The value does not exists : nothing to do
237             return null;
238         }
239         else
240         {
241             V returnedValue = valueArray[0];
242             nbArrayElems = 0;
243 
244             return returnedValue;
245         }
246     }
247 
248 
249     /**
250      * {@inheritDoc}
251      */
252     public boolean contains( V checkedValue )
253     {
254         if ( valueBtree != null )
255         {
256             try
257             {
258                 return valueBtree.hasKey( checkedValue );
259             }
260             catch ( IOException e )
261             {
262                 // TODO Auto-generated catch block
263                 e.printStackTrace();
264                 return false;
265             }
266             catch ( KeyNotFoundException knfe )
267             {
268                 // TODO Auto-generated catch block
269                 knfe.printStackTrace();
270                 return false;
271             }
272         }
273         else
274         {
275             Comparator<V> comparator = valueSerializer.getComparator();
276 
277             int result = comparator.compare( checkedValue, valueArray[0] );
278 
279             return result == 0;
280         }
281     }
282 
283 
284     /**
285      * @see Object#toString()
286      */
287     public String toString()
288     {
289         StringBuilder sb = new StringBuilder();
290 
291         sb.append( "ValueHolder[" ).append( valueSerializer.getClass().getSimpleName() );
292 
293         if ( valueBtree != null )
294         {
295             sb.append( ", SubBTree" );
296         }
297         else
298         {
299             sb.append( ", {" );
300 
301             if ( size() != 0 )
302             {
303                 sb.append( valueArray[0] );
304             }
305 
306             sb.append( "}" );
307         }
308 
309         sb.append( "]" );
310 
311         return sb.toString();
312     }
313 }