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