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.managed;
21  
22  
23  import java.io.IOException;
24  
25  import net.sf.ehcache.Element;
26  
27  import org.apache.directory.mavibot.btree.Page;
28  import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
29  
30  
31  /**
32   * A Value holder. As we may not store all the values in memory (except for an in-memory
33   * BTree), we will use a SoftReference to keep a reference to a Value, and if it's null,
34   * then we will load the Value from the underlying physical support, using the offset. 
35   * 
36   * @param <E> The type for the stored element (either a value or a page)
37   * @param <K> The type of the BTree key
38   * @param <V> The type of the BTree value
39   *
40   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
41   */
42  public class PageHolder<K, V>
43  {
44      /** The BTree */
45      private BTree<K, V> btree;
46  
47      /** The offset of the first {@link PageIO} storing the page on disk */
48      private long offset;
49  
50      /** The offset of the last {@link PageIO} storing the page on disk */
51      private long lastOffset;
52  
53  
54      /**
55       * Create a new holder storing an offset and a SoftReference containing the element.
56       * 
57       * @param offset The offset in disk for this value
58       * @param element The element to store into a SoftReference
59       */
60      public PageHolder( BTree<K, V> btree, Page<K, V> element, long offset, long lastOffset )
61      {
62          this.btree = btree;
63          this.offset = offset;
64          this.lastOffset = lastOffset;
65  
66          if ( element instanceof Page<?, ?> )
67          {
68              ( ( AbstractPage<K, V> ) element ).setOffset( offset );
69              ( ( AbstractPage<K, V> ) element ).setLastOffset( lastOffset );
70          }
71  
72          btree.getCache().put( new Element( offset, element ) );
73      }
74  
75  
76      /**
77       * {@inheritDoc}
78       * @throws IOException 
79       * @throws EndOfFileExceededException 
80       */
81      public Page<K, V> getValue( BTree<K, V> btree ) throws EndOfFileExceededException, IOException
82      {
83          Element element = btree.getCache().get( offset );
84  
85          if ( element == null )
86          {
87              // We haven't found the element in the cache, reload it
88              // We have to fetch the element from disk, using the offset now
89              Page<K, V> page = fetchElement( btree );
90  
91              btree.getCache().put( new Element( offset, page ) );
92  
93              return page;
94          }
95  
96          Page<K, V> page = (org.apache.directory.mavibot.btree.Page<K, V> ) element.getObjectValue();
97  
98          if ( page == null )
99          {
100             // We have to fetch the element from disk, using the offset now
101             page = fetchElement( btree );
102 
103             if ( page instanceof Page<?, ?> )
104             {
105                 ( ( AbstractPage<K, V> ) page ).setOffset( offset );
106                 ( ( AbstractPage<K, V> ) page ).setLastOffset( lastOffset );
107             }
108 
109             btree.getCache().put( new Element( offset, page ) );
110         }
111 
112         return page;
113     }
114 
115 
116     /**
117      * Retrieve the value from the disk, using the BTree and offset
118      * @return The deserialized element (
119      * @throws IOException 
120      * @throws EndOfFileExceededException 
121      */
122     private Page<K, V> fetchElement( BTree<K, V> btree ) throws EndOfFileExceededException, IOException
123     {
124         Page<K, V> element = btree.getRecordManager().deserialize( btree, offset );
125 
126         return element;
127     }
128 
129 
130     /**
131      * @return The offset of the first {@link PageIO} storing the data on disk
132      */
133     /* No qualifier */long getOffset()
134     {
135         return offset;
136     }
137 
138 
139     /**
140      * @return The offset of the last {@link PageIO} storing the data on disk
141      */
142     /* No qualifier */long getLastOffset()
143     {
144         return lastOffset;
145     }
146 
147 
148     /**
149      * @see Object#toString()
150      */
151     public String toString()
152     {
153         StringBuilder sb = new StringBuilder();
154 
155         try
156         {
157             Page<K, V> page = getValue( btree );
158 
159             if ( page != null )
160             {
161                 sb.append( btree.getName() ).append( "[" ).append( offset ).append( ", " ).append( lastOffset )
162                     .append( "]:" ).append( page );
163             }
164             else
165             {
166                 sb.append( btree.getName() ).append( "[" ).append( offset ).append( ", " ).append( lastOffset )
167                     .append( "]" );
168             }
169         }
170         catch ( IOException ioe )
171         {
172             // Nothing we can do...
173         }
174 
175         return sb.toString();
176     }
177 }