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