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