xref: /AOO41X/main/store/source/stortree.hxx (revision 1a5fa39be4c30003d60dac254349a6f82563f140)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _STORE_STORTREE_HXX
25 #define _STORE_STORTREE_HXX "$Revision: 1.6.8.2 $"
26 
27 #include "sal/types.h"
28 
29 #include "store/types.h"
30 
31 #include "storbase.hxx"
32 
33 namespace store
34 {
35 
36 class OStorePageBIOS;
37 
38 /*========================================================================
39  *
40  * OStoreBTreeEntry.
41  *
42  *======================================================================*/
43 struct OStoreBTreeEntry
44 {
45     typedef OStorePageKey  K;
46     typedef OStorePageLink L;
47 
48     /** Representation.
49     */
50     K          m_aKey;
51     L          m_aLink;
52     sal_uInt32 m_nAttrib;
53 
54     /** Construction.
55     */
OStoreBTreeEntrystore::OStoreBTreeEntry56     explicit OStoreBTreeEntry (
57         K const &  rKey    = K(),
58         L const &  rLink   = L(),
59         sal_uInt32 nAttrib = 0)
60         : m_aKey    (rKey),
61           m_aLink   (rLink),
62           m_nAttrib (store::htonl(nAttrib))
63     {}
64 
OStoreBTreeEntrystore::OStoreBTreeEntry65     OStoreBTreeEntry (const OStoreBTreeEntry & rhs)
66         : m_aKey    (rhs.m_aKey),
67           m_aLink   (rhs.m_aLink),
68           m_nAttrib (rhs.m_nAttrib)
69     {}
70 
operator =store::OStoreBTreeEntry71     OStoreBTreeEntry& operator= (const OStoreBTreeEntry & rhs)
72     {
73         m_aKey    = rhs.m_aKey;
74         m_aLink   = rhs.m_aLink;
75         m_nAttrib = rhs.m_nAttrib;
76         return *this;
77     }
78 
79     /** Comparison.
80     */
81     enum CompareResult
82     {
83         COMPARE_LESS    = -1,
84         COMPARE_EQUAL   =  0,
85         COMPARE_GREATER =  1
86     };
87 
comparestore::OStoreBTreeEntry88     CompareResult compare (const OStoreBTreeEntry& rOther) const
89     {
90         if (m_aKey < rOther.m_aKey)
91             return COMPARE_LESS;
92         else if (m_aKey == rOther.m_aKey)
93             return COMPARE_EQUAL;
94         else
95             return COMPARE_GREATER;
96     }
97 };
98 
99 /*========================================================================
100  *
101  * OStoreBTreeNodeData.
102  *
103  *======================================================================*/
104 #define STORE_MAGIC_BTREENODE sal_uInt32(0x58190322)
105 
106 struct OStoreBTreeNodeData : public store::OStorePageData
107 {
108     typedef OStorePageData      base;
109     typedef OStoreBTreeNodeData self;
110 
111     typedef OStorePageGuard     G;
112     typedef OStoreBTreeEntry    T;
113 
114     /** Representation.
115      */
116     G m_aGuard;
117     T m_pData[1];
118 
119     /** type.
120      */
121     static const sal_uInt32 theTypeId = STORE_MAGIC_BTREENODE;
122 
123     /** theSize.
124      */
125     static const size_t     theSize     = sizeof(G);
126     static const sal_uInt16 thePageSize = base::theSize + self::theSize;
127     STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= self::thePageSize);
128 
129     /** capacity.
130     */
capacitystore::OStoreBTreeNodeData131     sal_uInt16 capacity (void) const
132     {
133         return (store::ntohs(base::m_aDescr.m_nSize) - self::thePageSize);
134     }
135 
136     /** capacityCount (must be even).
137     */
capacityCountstore::OStoreBTreeNodeData138     sal_uInt16 capacityCount (void) const
139     {
140         return sal_uInt16(capacity() / sizeof(T));
141     }
142 
143     /** usage.
144     */
usagestore::OStoreBTreeNodeData145     sal_uInt16 usage (void) const
146     {
147         return (store::ntohs(base::m_aDescr.m_nUsed) - self::thePageSize);
148     }
149 
150     /** usageCount.
151     */
usageCountstore::OStoreBTreeNodeData152     sal_uInt16 usageCount (void) const
153     {
154         return sal_uInt16(usage() / sizeof(T));
155     }
usageCountstore::OStoreBTreeNodeData156     void usageCount (sal_uInt16 nCount)
157     {
158         size_t const nBytes = self::thePageSize + nCount * sizeof(T);
159         base::m_aDescr.m_nUsed = store::htons(sal::static_int_cast< sal_uInt16 >(nBytes));
160     }
161 
162     /** Construction.
163     */
164     explicit OStoreBTreeNodeData (sal_uInt16 nPageSize = self::thePageSize);
165 
166     /** guard (external representation).
167     */
guardstore::OStoreBTreeNodeData168     void guard()
169     {
170         sal_uInt32 nCRC32 = 0;
171         nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
172         nCRC32 = rtl_crc32 (nCRC32, m_pData, capacity());
173         m_aGuard.m_nCRC32 = store::htonl(nCRC32);
174     }
175 
176     /** verify (external representation).
177     */
verifystore::OStoreBTreeNodeData178     storeError verify() const
179     {
180         sal_uInt32 nCRC32 = 0;
181         nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
182         nCRC32 = rtl_crc32 (nCRC32, m_pData, capacity());
183         if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
184             return store_E_InvalidChecksum;
185         else
186             return store_E_None;
187     }
188 
189     /** depth.
190     */
depthstore::OStoreBTreeNodeData191     sal_uInt32 depth (void) const
192     {
193         return store::ntohl(self::m_aGuard.m_nMagic);
194     }
depthstore::OStoreBTreeNodeData195     void depth (sal_uInt32 nDepth)
196     {
197         self::m_aGuard.m_nMagic = store::htonl(nDepth);
198     }
199 
200     /** queryMerge.
201     */
queryMergestore::OStoreBTreeNodeData202     sal_Bool queryMerge (const self &rPageR) const
203     {
204         return ((usageCount() + rPageR.usageCount()) <= capacityCount());
205     }
206 
207     /** querySplit.
208     */
querySplitstore::OStoreBTreeNodeData209     sal_Bool querySplit (void) const
210     {
211         return (!(usageCount() < capacityCount()));
212     }
213 
214     /** Operation.
215     */
216     sal_uInt16 find   (const T& t) const;
217     void       insert (sal_uInt16 i, const T& t);
218     void       remove (sal_uInt16 i);
219 
220 #if 0  /* NYI */
221     /** merge (with right page).
222      */
223     void merge (const self& rPageR);
224 #endif
225 
226     /** split (left half copied from right half of left page).
227     */
228     void split (const self& rPageL);
229 
230     /** truncate (to n elements).
231     */
232     void truncate (sal_uInt16 n);
233 };
234 
235 /*========================================================================
236  *
237  * OStoreBTreeNodeObject.
238  *
239  *======================================================================*/
240 class OStoreBTreeNodeObject : public store::OStorePageObject
241 {
242     typedef OStorePageObject      base;
243     typedef OStoreBTreeNodeObject self;
244     typedef OStoreBTreeNodeData   page;
245 
246     typedef OStoreBTreeEntry      T;
247 
248 public:
249     /** Construction.
250     */
OStoreBTreeNodeObject(PageHolder const & rxPage=PageHolder ())251     explicit OStoreBTreeNodeObject (PageHolder const & rxPage = PageHolder())
252         : OStorePageObject (rxPage)
253     {}
254 
255     /** External representation.
256     */
257     virtual storeError guard  (sal_uInt32 nAddr);
258     virtual storeError verify (sal_uInt32 nAddr) const;
259 
260     /** split.
261      *
262      *  @param rxPageL [inout] left child to be split
263      */
264     storeError split (
265         sal_uInt16                 nIndexL,
266         PageHolderObject< page > & rxPageL,
267         OStorePageBIOS &           rBIOS);
268 
269     /** remove (down to leaf node, recursive).
270     */
271     storeError remove (
272         sal_uInt16         nIndexL,
273         OStoreBTreeEntry & rEntryL,
274         OStorePageBIOS &   rBIOS);
275 };
276 
277 /*========================================================================
278  *
279  * OStoreBTreeRootObject.
280  *
281  *======================================================================*/
282 class OStoreBTreeRootObject : public store::OStoreBTreeNodeObject
283 {
284     typedef OStoreBTreeNodeObject base;
285     typedef OStoreBTreeNodeData   page;
286 
287     typedef OStoreBTreeEntry      T;
288 
289 public:
290     /** Construction.
291      */
OStoreBTreeRootObject(PageHolder const & rxPage=PageHolder ())292     explicit OStoreBTreeRootObject (PageHolder const & rxPage = PageHolder())
293         : OStoreBTreeNodeObject (rxPage)
294     {}
295 
296     storeError loadOrCreate (
297         sal_uInt32       nAddr,
298         OStorePageBIOS & rBIOS);
299 
300     /** find_lookup (w/o split()).
301      *  Precond: root node page loaded.
302      */
303     storeError find_lookup (
304         OStoreBTreeNodeObject & rNode,  // [out]
305         sal_uInt16 &            rIndex, // [out]
306         OStorePageKey const &   rKey,
307         OStorePageBIOS &        rBIOS);
308 
309     /** find_insert (possibly with split()).
310      *  Precond: root node page loaded.
311      */
312     storeError find_insert (
313         OStoreBTreeNodeObject & rNode,
314         sal_uInt16 &            rIndex,
315         OStorePageKey const &   rKey,
316         OStorePageBIOS &        rBIOS);
317 
318 private:
319     /** testInvariant.
320      *  Precond: root node page loaded.
321      */
322     bool testInvariant (char const * message);
323 
324     /** change (Root).
325      *
326      *  @param rxPageL [out] prev. root (needs split)
327      */
328     storeError change (
329         PageHolderObject< page > & rxPageL,
330         OStorePageBIOS &           rBIOS);
331 };
332 
333 /*========================================================================
334  *
335  * The End.
336  *
337  *======================================================================*/
338 
339 } // namespace store
340 
341 #endif /* !_STORE_STORTREE_HXX */
342