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  
31  
32  /**
33   * A holder to store the Values
34   *
35   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
36   * @param <V> The value type
37   */
38  /* No qualifier */class InMemoryValueHolder<V> extends AbstractValueHolder<V>
39  {
40      /**
41       * Creates a new instance of a ValueHolder, containing the serialized values.
42       *
43       * @param parentBtree the parent BTree
44       * @param valueSerializer The Value's serializer
45       * @param raw The raw data containing the values
46       * @param nbValues the number of stored values
47       * @param raw the byte[] containing either the serialized array of values or the sub-btree offset
48       */
49      InMemoryValueHolder( BTree<?, V> parentBtree, int nbValues )
50      {
51          valueSerializer = parentBtree.getValueSerializer();
52  
53          if ( nbValues <= 1 )
54          {
55              valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), nbValues );
56          }
57      }
58  
59  
60      /**
61       * Creates a new instance of a ValueHolder, containing Values. This constructor is called
62       * when we need to create a new ValueHolder with deserialized values.
63       *
64       * @param parentBtree The parent BTree
65       * @param values The Values stored in the ValueHolder
66       */
67      InMemoryValueHolder( BTree<?, V> parentBtree, V... values )
68      {
69          valueSerializer = parentBtree.getValueSerializer();
70  
71          if ( ( values != null ) && ( values.length > 0 ) )
72          {
73              int nbValues = values.length;
74  
75              if ( nbValues == 1 )
76              {
77                  // Store the value
78                  valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), nbValues );
79                  valueArray[0] = values[0];
80                  nbArrayElems = nbValues;
81              }
82              else
83              {
84                  // Use a sub btree, now that we have reached the threshold
85                  createSubTree();
86  
87                  // Now inject all the values into it
88                  for ( V value : values )
89                  {
90                      try
91                      {
92                          valueBtree.insert( value, value );
93                      }
94                      catch ( IOException e )
95                      {
96                          e.printStackTrace();
97                      }
98                  }
99              }
100         }
101     }
102 
103 
104     /**
105      * {@inheritDoc}
106      */
107     public int size()
108     {
109         if ( valueBtree != null )
110         {
111             return ( int ) valueBtree.getNbElems();
112         }
113         else
114         {
115             return nbArrayElems;
116         }
117     }
118 
119 
120     /**
121      * Create a new Sub-BTree to store the values.
122      */
123     protected void createSubTree()
124     {
125         InMemoryBTreeConfiguration<V, V> configuration = new InMemoryBTreeConfiguration<V, V>();
126         configuration.setAllowDuplicates( false );
127         configuration.setName( UUID.randomUUID().toString() );
128         configuration.setKeySerializer( valueSerializer );
129         configuration.setValueSerializer( valueSerializer );
130 
131         valueBtree = BTreeFactory.createInMemoryBTree( configuration );
132     }
133 
134 
135     /**
136      * Set the subBtree in the ValueHolder
137      */
138     /* No qualifier*/void setSubBtree( BTree<V, V> subBtree )
139     {
140         valueBtree = subBtree;
141         valueArray = null;
142     }
143 
144 
145     /**
146      * {@inheritDoc}
147      */
148     public V remove( V value )
149     {
150         V removedValue = null;
151 
152         if ( valueArray != null )
153         {
154             removedValue = removeFromArray( value );
155         }
156         else
157         {
158             removedValue = removeFromBtree( value );
159         }
160 
161         return removedValue;
162     }
163 
164 
165     /**
166      * Remove the value from a sub btree
167      */
168     private V removeFromBtree( V removedValue )
169     {
170         V returnedValue = null;
171 
172         try
173         {
174             Tuple<V, V> removedTuple = valueBtree.delete( removedValue );
175 
176             if ( removedTuple != null )
177             {
178                 returnedValue = removedTuple.getKey();
179             }
180         }
181         catch ( IOException e )
182         {
183             throw new BTreeOperationException( e );
184         }
185 
186         if ( valueBtree.getNbElems() == 1 )
187         {
188             try
189             {
190                 valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), 1 );
191                 valueArray[0] = valueBtree.browse().next().getKey();
192                 nbArrayElems = 1;
193                 valueBtree.close();
194                 valueBtree = null;
195             }
196             catch ( EndOfFileExceededException e )
197             {
198                 throw new BTreeOperationException( e );
199             }
200             catch ( IOException e )
201             {
202                 throw new BTreeOperationException( e );
203             }
204         }
205 
206         return returnedValue;
207     }
208 
209 
210     /**
211      * Remove a value from an array
212      */
213     private V removeFromArray( V value )
214     {
215         // First check that the value is not already present in the ValueHolder
216         Comparator<V> comparator = valueSerializer.getComparator();
217 
218         int result = comparator.compare( valueArray[0], value );
219 
220         if ( result != 0 )
221         {
222             // The value does not exists : nothing to do
223             return null;
224         }
225         else
226         {
227             V returnedValue = valueArray[0];
228             nbArrayElems = 0;
229 
230             return returnedValue;
231         }
232     }
233 
234 
235     /**
236      * {@inheritDoc}
237      */
238     public boolean contains( V checkedValue )
239     {
240         if ( valueBtree != null )
241         {
242             try
243             {
244                 return valueBtree.hasKey( checkedValue );
245             }
246             catch ( IOException e )
247             {
248                 // TODO Auto-generated catch block
249                 e.printStackTrace();
250                 return false;
251             }
252         }
253         else
254         {
255             Comparator<V> comparator = valueSerializer.getComparator();
256 
257             int result = comparator.compare( checkedValue, valueArray[0] );
258 
259             return result == 0;
260         }
261     }
262 
263 
264     /**
265      * @see Object#toString()
266      */
267     public String toString()
268     {
269         StringBuilder sb = new StringBuilder();
270 
271         sb.append( "ValueHolder[" ).append( valueSerializer.getClass().getSimpleName() );
272 
273         if ( valueBtree != null )
274         {
275             sb.append( ", SubBTree" );
276         }
277         else
278         {
279             sb.append( ", {" );
280 
281             if ( size() != 0 )
282             {
283                 sb.append( valueArray[0] );
284             }
285 
286             sb.append( "}" );
287         }
288 
289         sb.append( "]" );
290 
291         return sb.toString();
292     }
293 }