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.memory;
21  
22  
23  import java.io.IOException;
24  import java.lang.ref.SoftReference;
25  import java.util.UUID;
26  
27  
28  /**
29   * A holder for values of duplicate keys. The values are either present in memory
30   * or loaded on the fly from disk when needed.
31   * 
32   * @param <K> The type of the BTree key
33   * @param <V> The type of the BTree value
34   *
35   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
36   */
37  public class MultipleMemoryHolder<K, V> implements ElementHolder<V, K, V>
38  {
39      /** The BTree */
40      private BTree<K, V> btree;
41  
42      /** the offset of the value container btree. This value is set only when the parent BTree is in managed mode */
43      private long valContainerOffset = -1;
44  
45      /** The reference to the Value instance, or null if it's not present. This will be null when the parent BTree is in managed mode */
46      private BTree<V, V> valueContainer;
47  
48      /** This value is set only when the parent BTree is in managed mode */
49      private SoftReference<BTree<V, V>> reference;
50  
51      /** the single value of the key when only one value exists for the key */
52      private V singleValue;
53  
54  
55      /**
56       * Create a new holder storing an offset and a SoftReference containing the value.
57       * 
58       * @param offset The offset in disk for this value
59       * @param value The value to store into a SoftReference
60       */
61      public MultipleMemoryHolder( BTree<K, V> btree, V value )
62      {
63          this.btree = btree;
64          this.singleValue = value;
65      }
66  
67  
68      /**
69       * 
70       * Creates a new instance of DuplicateKeyMemoryHolder.
71       * 
72       * Note: the valueContainer should have a valid offset, in other words
73       *       the valueContainer should always be the one that is already
74       *       managed by RecordManager
75       * 
76       * @param btree the parent BTree
77       * @param valueContainer the BTree holding the values of a duplicate key
78       *        present in the parent tree
79       */
80      MultipleMemoryHolder( BTree<K, V> btree, BTree<V, V> valueContainer )
81      {
82          this.btree = btree;
83          this.valueContainer = valueContainer;
84      }
85  
86  
87      /**
88       * {@inheritDoc}
89       */
90      @Override
91      public V getValue( BTree<K, V> btree )
92      {
93          if ( valueContainer != null )
94          {
95              // wrong cast to please compiler
96              return ( V ) valueContainer;
97          }
98          else
99          {
100             return singleValue;
101         }
102     }
103 
104 
105     void switchToSingleValMode()
106     {
107         if ( ( valueContainer == null ) || ( reference == null ) )
108         {
109             return;
110         }
111 
112         try
113         {
114             //delete the btree using offset
115             singleValue = valueContainer.rootPage.getLeftMostKey();
116             valueContainer = null;
117         }
118         catch ( IOException e )
119         {
120             throw new RuntimeException( e );
121         }
122     }
123 
124 
125     BTree<V, V> createAndSwitchToSubTree()
126     {
127         if ( reference != null )
128         {
129             throw new IllegalStateException( "Subtree was already created with offset " + valContainerOffset );
130         }
131 
132         try
133         {
134             BTree<V, V> valueContainer = new BTree<V, V>( UUID.randomUUID().toString(), btree.getValueSerializer(),
135                 btree.getValueSerializer() );
136 
137             this.valueContainer = valueContainer;
138 
139             valueContainer.insert( singleValue, null, 0 );
140         }
141         catch ( IOException e )
142         {
143             throw new RuntimeException( e );
144         }
145 
146         return valueContainer;
147     }
148 
149 
150     /**
151      * Tells if there is only one value in this element holder
152      * 
153      * @return true if single value is present, false if multiple values are present
154      */
155     public boolean isSingleValue()
156     {
157         return ( valueContainer == null );
158     }
159 
160 
161     /**
162      * @see Object#toString()
163      */
164     public String toString()
165     {
166         StringBuilder sb = new StringBuilder();
167 
168         sb.append( "'" );
169 
170         V value = getValue( btree );
171 
172         sb.append( value );
173 
174         sb.append( "'" );
175 
176         return sb.toString();
177     }
178 }