xref: /trunk/main/store/source/stortree.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
173d9b18aSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
373d9b18aSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
473d9b18aSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
573d9b18aSAndrew Rist  * distributed with this work for additional information
673d9b18aSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
773d9b18aSAndrew Rist  * to you under the Apache License, Version 2.0 (the
873d9b18aSAndrew Rist  * "License"); you may not use this file except in compliance
973d9b18aSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
1173d9b18aSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
1373d9b18aSAndrew Rist  * Unless required by applicable law or agreed to in writing,
1473d9b18aSAndrew Rist  * software distributed under the License is distributed on an
1573d9b18aSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1673d9b18aSAndrew Rist  * KIND, either express or implied.  See the License for the
1773d9b18aSAndrew Rist  * specific language governing permissions and limitations
1873d9b18aSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
2073d9b18aSAndrew Rist  *************************************************************/
2173d9b18aSAndrew Rist 
2273d9b18aSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_store.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "stortree.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "sal/types.h"
30cdf0e10cSrcweir #include "osl/diagnose.h"
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include "store/types.h"
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include "storbase.hxx"
35cdf0e10cSrcweir #include "storbios.hxx"
36cdf0e10cSrcweir 
37cdf0e10cSrcweir using namespace store;
38cdf0e10cSrcweir 
39cdf0e10cSrcweir /*========================================================================
40cdf0e10cSrcweir  *
41cdf0e10cSrcweir  * OStoreBTreeNodeData implementation.
42cdf0e10cSrcweir  *
43cdf0e10cSrcweir  *======================================================================*/
44cdf0e10cSrcweir /*
45cdf0e10cSrcweir  * OStoreBTreeNodeData.
46cdf0e10cSrcweir  */
OStoreBTreeNodeData(sal_uInt16 nPageSize)47cdf0e10cSrcweir OStoreBTreeNodeData::OStoreBTreeNodeData (sal_uInt16 nPageSize)
48cdf0e10cSrcweir     : OStorePageData (nPageSize)
49cdf0e10cSrcweir {
50cdf0e10cSrcweir     base::m_aGuard.m_nMagic = store::htonl(self::theTypeId);
51cdf0e10cSrcweir     base::m_aDescr.m_nUsed  = store::htons(self::thePageSize); // usageCount(0)
52cdf0e10cSrcweir     self::m_aGuard.m_nMagic = store::htonl(0); // depth(0)
53cdf0e10cSrcweir 
54cdf0e10cSrcweir     sal_uInt16 const n = capacityCount();
55cdf0e10cSrcweir     T const          t;
56cdf0e10cSrcweir 
57cdf0e10cSrcweir     for (sal_uInt16 i = 1; i < n; i++)
58cdf0e10cSrcweir         m_pData[i] = t;
59cdf0e10cSrcweir }
60cdf0e10cSrcweir 
61cdf0e10cSrcweir /*
62cdf0e10cSrcweir  * find.
63cdf0e10cSrcweir  */
find(const T & t) const64cdf0e10cSrcweir sal_uInt16 OStoreBTreeNodeData::find (const T& t) const
65cdf0e10cSrcweir {
66*c1e8cc3aSDon Lewis     sal_Int32 l = 0;
67*c1e8cc3aSDon Lewis     sal_Int32 r = usageCount() - 1;
68cdf0e10cSrcweir 
69cdf0e10cSrcweir     while (l < r)
70cdf0e10cSrcweir     {
71*c1e8cc3aSDon Lewis         sal_Int32 const m = ((l + r) >> 1);
72cdf0e10cSrcweir 
73cdf0e10cSrcweir         if (t.m_aKey == m_pData[m].m_aKey)
74cdf0e10cSrcweir             return ((sal_uInt16)(m));
75cdf0e10cSrcweir         if (t.m_aKey < m_pData[m].m_aKey)
76cdf0e10cSrcweir             r = m - 1;
77cdf0e10cSrcweir         else
78cdf0e10cSrcweir             l = m + 1;
79cdf0e10cSrcweir     }
80cdf0e10cSrcweir 
81cdf0e10cSrcweir     sal_uInt16 const k = ((sal_uInt16)(r));
82cdf0e10cSrcweir     if ((k < capacityCount()) && (t.m_aKey < m_pData[k].m_aKey))
83cdf0e10cSrcweir         return(k - 1);
84cdf0e10cSrcweir     else
85cdf0e10cSrcweir         return(k);
86cdf0e10cSrcweir }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir /*
89cdf0e10cSrcweir  * insert.
90cdf0e10cSrcweir  */
insert(sal_uInt16 i,const T & t)91cdf0e10cSrcweir void OStoreBTreeNodeData::insert (sal_uInt16 i, const T& t)
92cdf0e10cSrcweir {
93cdf0e10cSrcweir     sal_uInt16 const n = usageCount();
94cdf0e10cSrcweir     sal_uInt16 const m = capacityCount();
95cdf0e10cSrcweir     if ((n < m) && (i < m))
96cdf0e10cSrcweir     {
97cdf0e10cSrcweir         // shift right.
98cdf0e10cSrcweir         memmove (&(m_pData[i + 1]), &(m_pData[i]), (n - i) * sizeof(T));
99cdf0e10cSrcweir 
100cdf0e10cSrcweir         // insert.
101cdf0e10cSrcweir         m_pData[i] = t;
102cdf0e10cSrcweir         usageCount (n + 1);
103cdf0e10cSrcweir     }
104cdf0e10cSrcweir }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir /*
107cdf0e10cSrcweir  * remove.
108cdf0e10cSrcweir  */
remove(sal_uInt16 i)109cdf0e10cSrcweir void OStoreBTreeNodeData::remove (sal_uInt16 i)
110cdf0e10cSrcweir {
111cdf0e10cSrcweir     sal_uInt16 const n = usageCount();
112cdf0e10cSrcweir     if (i < n)
113cdf0e10cSrcweir     {
114cdf0e10cSrcweir         // shift left.
115cdf0e10cSrcweir         memmove (&(m_pData[i]), &(m_pData[i + 1]), (n - i - 1) * sizeof(T));
116cdf0e10cSrcweir 
117cdf0e10cSrcweir         // truncate.
118cdf0e10cSrcweir         m_pData[n - 1] = T();
119cdf0e10cSrcweir         usageCount (n - 1);
120cdf0e10cSrcweir     }
121cdf0e10cSrcweir }
122cdf0e10cSrcweir 
123cdf0e10cSrcweir #if 0  /* NYI */
124cdf0e10cSrcweir /*
125cdf0e10cSrcweir  * merge (with right page).
126cdf0e10cSrcweir  */
127cdf0e10cSrcweir void OStoreBTreeNodeData::merge (const self& rPageR)
128cdf0e10cSrcweir {
129cdf0e10cSrcweir     sal_uInt16 const n = usageCount();
130cdf0e10cSrcweir     sal_uInt16 const m = rPageR.usageCount();
131cdf0e10cSrcweir     if ((n + m) <= capacityCount())
132cdf0e10cSrcweir     {
133cdf0e10cSrcweir         memcpy (&(m_pData[n]), &(rPageR.m_pData[0]), m * sizeof(T));
134cdf0e10cSrcweir         usageCount (n + m);
135cdf0e10cSrcweir     }
136cdf0e10cSrcweir }
137cdf0e10cSrcweir #endif
138cdf0e10cSrcweir 
139cdf0e10cSrcweir /*
140cdf0e10cSrcweir  * split (left half copied from right half of left page).
141cdf0e10cSrcweir  */
split(const self & rPageL)142cdf0e10cSrcweir void OStoreBTreeNodeData::split (const self& rPageL)
143cdf0e10cSrcweir {
144cdf0e10cSrcweir     sal_uInt16 const h = capacityCount() / 2;
145cdf0e10cSrcweir     memcpy (&(m_pData[0]), &(rPageL.m_pData[h]), h * sizeof(T));
146cdf0e10cSrcweir     truncate (h);
147cdf0e10cSrcweir }
148cdf0e10cSrcweir 
149cdf0e10cSrcweir /*
150cdf0e10cSrcweir  * truncate.
151cdf0e10cSrcweir  */
truncate(sal_uInt16 n)152cdf0e10cSrcweir void OStoreBTreeNodeData::truncate (sal_uInt16 n)
153cdf0e10cSrcweir {
154cdf0e10cSrcweir     sal_uInt16 const m = capacityCount();
155cdf0e10cSrcweir     T const          t;
156cdf0e10cSrcweir 
157cdf0e10cSrcweir     for (sal_uInt16 i = n; i < m; i++)
158cdf0e10cSrcweir         m_pData[i] = t;
159cdf0e10cSrcweir     usageCount (n);
160cdf0e10cSrcweir }
161cdf0e10cSrcweir 
162cdf0e10cSrcweir /*========================================================================
163cdf0e10cSrcweir  *
164cdf0e10cSrcweir  * OStoreBTreeNodeObject implementation.
165cdf0e10cSrcweir  *
166cdf0e10cSrcweir  *======================================================================*/
167cdf0e10cSrcweir /*
168cdf0e10cSrcweir  * guard.
169cdf0e10cSrcweir  */
guard(sal_uInt32 nAddr)170cdf0e10cSrcweir storeError OStoreBTreeNodeObject::guard (sal_uInt32 nAddr)
171cdf0e10cSrcweir {
172cdf0e10cSrcweir     return PageHolderObject< page >::guard (m_xPage, nAddr);
173cdf0e10cSrcweir }
174cdf0e10cSrcweir 
175cdf0e10cSrcweir /*
176cdf0e10cSrcweir  * verify.
177cdf0e10cSrcweir  */
verify(sal_uInt32 nAddr) const178cdf0e10cSrcweir storeError OStoreBTreeNodeObject::verify (sal_uInt32 nAddr) const
179cdf0e10cSrcweir {
180cdf0e10cSrcweir     return PageHolderObject< page >::verify (m_xPage, nAddr);
181cdf0e10cSrcweir }
182cdf0e10cSrcweir 
183cdf0e10cSrcweir /*
184cdf0e10cSrcweir  * split.
185cdf0e10cSrcweir  */
split(sal_uInt16 nIndexL,PageHolderObject<page> & rxPageL,OStorePageBIOS & rBIOS)186cdf0e10cSrcweir storeError OStoreBTreeNodeObject::split (
187cdf0e10cSrcweir     sal_uInt16                 nIndexL,
188cdf0e10cSrcweir     PageHolderObject< page > & rxPageL,
189cdf0e10cSrcweir     OStorePageBIOS           & rBIOS)
190cdf0e10cSrcweir {
191cdf0e10cSrcweir     PageHolderObject< page > xPage (m_xPage);
192cdf0e10cSrcweir     if (!xPage.is())
193cdf0e10cSrcweir         return store_E_InvalidAccess;
194cdf0e10cSrcweir 
195cdf0e10cSrcweir     // Check left page usage.
196cdf0e10cSrcweir     if (!rxPageL.is())
197cdf0e10cSrcweir         return store_E_InvalidAccess;
198cdf0e10cSrcweir     if (!rxPageL->querySplit())
199cdf0e10cSrcweir         return store_E_None;
200cdf0e10cSrcweir 
201cdf0e10cSrcweir     // Construct right page.
202cdf0e10cSrcweir     PageHolderObject< page > xPageR;
203cdf0e10cSrcweir     if (!xPageR.construct (rBIOS.allocator()))
204cdf0e10cSrcweir         return store_E_OutOfMemory;
205cdf0e10cSrcweir 
206cdf0e10cSrcweir     // Split right page off left page.
207cdf0e10cSrcweir     xPageR->split (*rxPageL);
208cdf0e10cSrcweir     xPageR->depth (rxPageL->depth());
209cdf0e10cSrcweir 
210cdf0e10cSrcweir     // Allocate right page.
211cdf0e10cSrcweir     self aNodeR (xPageR.get());
212cdf0e10cSrcweir     storeError eErrCode = rBIOS.allocate (aNodeR);
213cdf0e10cSrcweir     if (eErrCode != store_E_None)
214cdf0e10cSrcweir         return eErrCode;
215cdf0e10cSrcweir 
216cdf0e10cSrcweir     // Truncate left page.
217cdf0e10cSrcweir     rxPageL->truncate (rxPageL->capacityCount() / 2);
218cdf0e10cSrcweir 
219cdf0e10cSrcweir     // Save left page.
220cdf0e10cSrcweir     self aNodeL (rxPageL.get());
221cdf0e10cSrcweir     eErrCode = rBIOS.saveObjectAt (aNodeL, aNodeL.location());
222cdf0e10cSrcweir     if (eErrCode != store_E_None)
223cdf0e10cSrcweir         return eErrCode;
224cdf0e10cSrcweir 
225cdf0e10cSrcweir     // Insert right page.
226cdf0e10cSrcweir     OStorePageLink aLink (xPageR->location());
227cdf0e10cSrcweir     xPage->insert (nIndexL + 1, T(xPageR->m_pData[0].m_aKey, aLink));
228cdf0e10cSrcweir 
229cdf0e10cSrcweir     // Save this page and leave.
230cdf0e10cSrcweir     return rBIOS.saveObjectAt (*this, location());
231cdf0e10cSrcweir }
232cdf0e10cSrcweir 
233cdf0e10cSrcweir /*
234cdf0e10cSrcweir  * remove (down to leaf node, recursive).
235cdf0e10cSrcweir  */
remove(sal_uInt16 nIndexL,OStoreBTreeEntry & rEntryL,OStorePageBIOS & rBIOS)236cdf0e10cSrcweir storeError OStoreBTreeNodeObject::remove (
237cdf0e10cSrcweir     sal_uInt16         nIndexL,
238cdf0e10cSrcweir     OStoreBTreeEntry & rEntryL,
239cdf0e10cSrcweir     OStorePageBIOS &   rBIOS)
240cdf0e10cSrcweir {
241cdf0e10cSrcweir     PageHolderObject< page > xImpl (m_xPage);
242cdf0e10cSrcweir     page & rPage = (*xImpl);
243cdf0e10cSrcweir 
244cdf0e10cSrcweir     // Check depth.
245cdf0e10cSrcweir     storeError eErrCode = store_E_None;
246cdf0e10cSrcweir     if (rPage.depth())
247cdf0e10cSrcweir     {
248cdf0e10cSrcweir         // Check link entry.
249cdf0e10cSrcweir         T const aEntryL (rPage.m_pData[nIndexL]);
250cdf0e10cSrcweir         if (!(rEntryL.compare (aEntryL) == T::COMPARE_EQUAL))
251cdf0e10cSrcweir             return store_E_InvalidAccess;
252cdf0e10cSrcweir 
253cdf0e10cSrcweir         // Load link node.
254cdf0e10cSrcweir         self aNodeL;
255cdf0e10cSrcweir         eErrCode = rBIOS.loadObjectAt (aNodeL, aEntryL.m_aLink.location());
256cdf0e10cSrcweir         if (eErrCode != store_E_None)
257cdf0e10cSrcweir             return eErrCode;
258cdf0e10cSrcweir 
259cdf0e10cSrcweir         // Recurse: remove from link node.
260cdf0e10cSrcweir         eErrCode = aNodeL.remove (0, rEntryL, rBIOS);
261cdf0e10cSrcweir         if (eErrCode != store_E_None)
262cdf0e10cSrcweir             return eErrCode;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir         // Check resulting link node usage.
265cdf0e10cSrcweir         PageHolderObject< page > xPageL (aNodeL.get());
266cdf0e10cSrcweir         if (xPageL->usageCount() == 0)
267cdf0e10cSrcweir         {
268cdf0e10cSrcweir             // Free empty link node.
269cdf0e10cSrcweir             eErrCode = rBIOS.free (xPageL->location());
270cdf0e10cSrcweir             if (eErrCode != store_E_None)
271cdf0e10cSrcweir                 return eErrCode;
272cdf0e10cSrcweir 
273cdf0e10cSrcweir             // Remove index.
274cdf0e10cSrcweir             rPage.remove (nIndexL);
275cdf0e10cSrcweir             touch();
276cdf0e10cSrcweir         }
277cdf0e10cSrcweir         else
278cdf0e10cSrcweir         {
279cdf0e10cSrcweir #if 0   /* NYI */
280cdf0e10cSrcweir             // Check for right sibling.
281cdf0e10cSrcweir             sal_uInt16 const nIndexR = nIndexL + 1;
282cdf0e10cSrcweir             if (nIndexR < rPage.usageCount())
283cdf0e10cSrcweir             {
284cdf0e10cSrcweir                 // Load right link node.
285cdf0e10cSrcweir                 self aNodeR;
286cdf0e10cSrcweir                 eErrCode = rBIOS.loadObjectAt (aNodeR, rPage.m_pData[nIndexR].m_aLink.location());
287cdf0e10cSrcweir                 if (eErrCode == store_E_None)
288cdf0e10cSrcweir                 {
289cdf0e10cSrcweir                     if (rPageL.queryMerge (rPageR))
290cdf0e10cSrcweir                     {
291cdf0e10cSrcweir                         rPageL.merge (rPageR);
292cdf0e10cSrcweir 
293cdf0e10cSrcweir                         eErrCode = rBIOS.free (rPageR.location());
294cdf0e10cSrcweir                     }
295cdf0e10cSrcweir                 }
296cdf0e10cSrcweir             }
297cdf0e10cSrcweir #endif  /* NYI */
298cdf0e10cSrcweir 
299cdf0e10cSrcweir             // Relink.
300cdf0e10cSrcweir             rPage.m_pData[nIndexL].m_aKey = xPageL->m_pData[0].m_aKey;
301cdf0e10cSrcweir             touch();
302cdf0e10cSrcweir         }
303cdf0e10cSrcweir     }
304cdf0e10cSrcweir     else
305cdf0e10cSrcweir     {
306cdf0e10cSrcweir         // Check leaf entry.
307cdf0e10cSrcweir         if (!(rEntryL.compare (rPage.m_pData[nIndexL]) == T::COMPARE_EQUAL))
308cdf0e10cSrcweir             return store_E_NotExists;
309cdf0e10cSrcweir 
310cdf0e10cSrcweir         // Save leaf entry.
311cdf0e10cSrcweir         rEntryL = rPage.m_pData[nIndexL];
312cdf0e10cSrcweir 
313cdf0e10cSrcweir         // Remove leaf index.
314cdf0e10cSrcweir         rPage.remove (nIndexL);
315cdf0e10cSrcweir         touch();
316cdf0e10cSrcweir     }
317cdf0e10cSrcweir 
318cdf0e10cSrcweir     // Check for modified node.
319cdf0e10cSrcweir     if (dirty())
320cdf0e10cSrcweir     {
321cdf0e10cSrcweir         // Save this page.
322cdf0e10cSrcweir         eErrCode = rBIOS.saveObjectAt (*this, location());
323cdf0e10cSrcweir     }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir     // Done.
326cdf0e10cSrcweir     return eErrCode;
327cdf0e10cSrcweir }
328cdf0e10cSrcweir 
329cdf0e10cSrcweir /*========================================================================
330cdf0e10cSrcweir  *
331cdf0e10cSrcweir  * OStoreBTreeRootObject implementation.
332cdf0e10cSrcweir  *
333cdf0e10cSrcweir  *======================================================================*/
334cdf0e10cSrcweir /*
335cdf0e10cSrcweir  * testInvariant.
336cdf0e10cSrcweir  * Precond: root node page loaded.
337cdf0e10cSrcweir  */
testInvariant(char const * message)338cdf0e10cSrcweir bool OStoreBTreeRootObject::testInvariant (char const * message)
339cdf0e10cSrcweir {
340cdf0e10cSrcweir     OSL_PRECOND(m_xPage.get() != 0, "OStoreBTreeRootObject::testInvariant(): Null pointer");
341cdf0e10cSrcweir     bool result = ((m_xPage->location() - m_xPage->size()) == 0);
342cdf0e10cSrcweir     OSL_POSTCOND(result, message); (void) message;
343cdf0e10cSrcweir     return result;
344cdf0e10cSrcweir }
345cdf0e10cSrcweir 
346cdf0e10cSrcweir /*
347cdf0e10cSrcweir  * loadOrCreate.
348cdf0e10cSrcweir  */
loadOrCreate(sal_uInt32 nAddr,OStorePageBIOS & rBIOS)349cdf0e10cSrcweir storeError OStoreBTreeRootObject::loadOrCreate (
350cdf0e10cSrcweir     sal_uInt32       nAddr,
351cdf0e10cSrcweir     OStorePageBIOS & rBIOS)
352cdf0e10cSrcweir {
353cdf0e10cSrcweir     storeError eErrCode = rBIOS.loadObjectAt (*this, nAddr);
354cdf0e10cSrcweir     if (eErrCode != store_E_NotExists)
355cdf0e10cSrcweir         return eErrCode;
356cdf0e10cSrcweir 
357cdf0e10cSrcweir     eErrCode = construct<page>(rBIOS.allocator());
358cdf0e10cSrcweir     if (eErrCode != store_E_None)
359cdf0e10cSrcweir         return eErrCode;
360cdf0e10cSrcweir 
361cdf0e10cSrcweir     eErrCode = rBIOS.allocate (*this);
362cdf0e10cSrcweir     if (eErrCode != store_E_None)
363cdf0e10cSrcweir         return eErrCode;
364cdf0e10cSrcweir 
365cdf0e10cSrcweir     // Notify caller of the creation.
366cdf0e10cSrcweir     (void) testInvariant("OStoreBTreeRootObject::loadOrCreate(): leave");
367cdf0e10cSrcweir     return store_E_Pending;
368cdf0e10cSrcweir }
369cdf0e10cSrcweir 
370cdf0e10cSrcweir /*
371cdf0e10cSrcweir  * change.
372cdf0e10cSrcweir  */
change(PageHolderObject<page> & rxPageL,OStorePageBIOS & rBIOS)373cdf0e10cSrcweir storeError OStoreBTreeRootObject::change (
374cdf0e10cSrcweir     PageHolderObject< page > & rxPageL,
375cdf0e10cSrcweir     OStorePageBIOS &           rBIOS)
376cdf0e10cSrcweir {
377cdf0e10cSrcweir     PageHolderObject< page > xPage (m_xPage);
378cdf0e10cSrcweir     (void) testInvariant("OStoreBTreeRootObject::change(): enter");
379cdf0e10cSrcweir 
380cdf0e10cSrcweir     // Save root location.
381cdf0e10cSrcweir     sal_uInt32 const nRootAddr = xPage->location();
382cdf0e10cSrcweir 
383cdf0e10cSrcweir     // Construct new root.
384cdf0e10cSrcweir     if (!rxPageL.construct (rBIOS.allocator()))
385cdf0e10cSrcweir         return store_E_OutOfMemory;
386cdf0e10cSrcweir 
387cdf0e10cSrcweir     // Save this as prev root.
388cdf0e10cSrcweir     storeError eErrCode = rBIOS.allocate (*this);
389cdf0e10cSrcweir     if (eErrCode != store_E_None)
390cdf0e10cSrcweir         return store_E_OutOfMemory;
391cdf0e10cSrcweir 
392cdf0e10cSrcweir     // Setup new root.
393cdf0e10cSrcweir     rxPageL->depth (xPage->depth() + 1);
394cdf0e10cSrcweir     rxPageL->m_pData[0] = xPage->m_pData[0];
395cdf0e10cSrcweir     rxPageL->m_pData[0].m_aLink = xPage->location();
396cdf0e10cSrcweir     rxPageL->usageCount(1);
397cdf0e10cSrcweir 
398cdf0e10cSrcweir     // Change root.
399cdf0e10cSrcweir     rxPageL.swap (xPage);
400cdf0e10cSrcweir     {
401cdf0e10cSrcweir         PageHolder tmp (xPage.get());
402cdf0e10cSrcweir         tmp.swap (m_xPage);
403cdf0e10cSrcweir     }
404cdf0e10cSrcweir 
405cdf0e10cSrcweir     // Save this as new root and finish.
406cdf0e10cSrcweir     eErrCode = rBIOS.saveObjectAt (*this, nRootAddr);
407cdf0e10cSrcweir     (void) testInvariant("OStoreBTreeRootObject::change(): leave");
408cdf0e10cSrcweir     return eErrCode;
409cdf0e10cSrcweir }
410cdf0e10cSrcweir 
411cdf0e10cSrcweir /*
412cdf0e10cSrcweir  * find_lookup (w/o split()).
413cdf0e10cSrcweir  * Precond: root node page loaded.
414cdf0e10cSrcweir  */
find_lookup(OStoreBTreeNodeObject & rNode,sal_uInt16 & rIndex,OStorePageKey const & rKey,OStorePageBIOS & rBIOS)415cdf0e10cSrcweir storeError OStoreBTreeRootObject::find_lookup (
416cdf0e10cSrcweir     OStoreBTreeNodeObject & rNode,  // [out]
417cdf0e10cSrcweir     sal_uInt16 &            rIndex, // [out]
418cdf0e10cSrcweir     OStorePageKey const &   rKey,
419cdf0e10cSrcweir     OStorePageBIOS &        rBIOS)
420cdf0e10cSrcweir {
421cdf0e10cSrcweir     // Init node w/ root page.
422cdf0e10cSrcweir     (void) testInvariant("OStoreBTreeRootObject::find_lookup(): enter");
423cdf0e10cSrcweir     {
424cdf0e10cSrcweir         PageHolder tmp (m_xPage);
425cdf0e10cSrcweir         tmp.swap (rNode.get());
426cdf0e10cSrcweir     }
427cdf0e10cSrcweir 
428cdf0e10cSrcweir     // Setup BTree entry.
429cdf0e10cSrcweir     T const entry (rKey);
430cdf0e10cSrcweir 
431cdf0e10cSrcweir     // Check current page.
432cdf0e10cSrcweir     PageHolderObject< page > xPage (rNode.get());
433cdf0e10cSrcweir     for (; xPage->depth() > 0; xPage = rNode.makeHolder< page >())
434cdf0e10cSrcweir     {
435cdf0e10cSrcweir         // Find next page.
436cdf0e10cSrcweir         page const & rPage = (*xPage);
437cdf0e10cSrcweir         sal_uInt16 const i = rPage.find(entry);
438cdf0e10cSrcweir         sal_uInt16 const n = rPage.usageCount();
439cdf0e10cSrcweir         if (!(i < n))
440cdf0e10cSrcweir         {
441cdf0e10cSrcweir             // Path to entry not exists (Must not happen(?)).
442cdf0e10cSrcweir             return store_E_NotExists;
443cdf0e10cSrcweir         }
444cdf0e10cSrcweir 
445cdf0e10cSrcweir         // Check address.
446cdf0e10cSrcweir         sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
447cdf0e10cSrcweir         if (nAddr == STORE_PAGE_NULL)
448cdf0e10cSrcweir         {
449cdf0e10cSrcweir             // Path to entry not exists (Must not happen(?)).
450cdf0e10cSrcweir             return store_E_NotExists;
451cdf0e10cSrcweir         }
452cdf0e10cSrcweir 
453cdf0e10cSrcweir         // Load next page.
454cdf0e10cSrcweir         storeError eErrCode = rBIOS.loadObjectAt (rNode, nAddr);
455cdf0e10cSrcweir         if (eErrCode != store_E_None)
456cdf0e10cSrcweir             return eErrCode;
457cdf0e10cSrcweir     }
458cdf0e10cSrcweir 
459cdf0e10cSrcweir     // Find index.
460cdf0e10cSrcweir     page const & rPage = (*xPage);
461cdf0e10cSrcweir     rIndex = rPage.find(entry);
462cdf0e10cSrcweir     if (!(rIndex < rPage.usageCount()))
463cdf0e10cSrcweir         return store_E_NotExists;
464cdf0e10cSrcweir 
465cdf0e10cSrcweir     // Compare entry.
466cdf0e10cSrcweir     T::CompareResult eResult = entry.compare(rPage.m_pData[rIndex]);
467cdf0e10cSrcweir     OSL_POSTCOND(eResult != T::COMPARE_LESS, "store::BTreeRoot::find_lookup(): sort error");
468cdf0e10cSrcweir     if (eResult == T::COMPARE_LESS)
469cdf0e10cSrcweir         return store_E_Unknown;
470cdf0e10cSrcweir 
471cdf0e10cSrcweir     // Greater or Equal.
472cdf0e10cSrcweir     (void) testInvariant("OStoreBTreeRootObject::find_lookup(): leave");
473cdf0e10cSrcweir     return store_E_None;
474cdf0e10cSrcweir }
475cdf0e10cSrcweir 
476cdf0e10cSrcweir /*
477cdf0e10cSrcweir  * find_insert (possibly with split()).
478cdf0e10cSrcweir  * Precond: root node page loaded.
479cdf0e10cSrcweir  */
find_insert(OStoreBTreeNodeObject & rNode,sal_uInt16 & rIndex,OStorePageKey const & rKey,OStorePageBIOS & rBIOS)480cdf0e10cSrcweir storeError OStoreBTreeRootObject::find_insert (
481cdf0e10cSrcweir     OStoreBTreeNodeObject & rNode,  // [out]
482cdf0e10cSrcweir     sal_uInt16 &            rIndex, // [out]
483cdf0e10cSrcweir     OStorePageKey const &   rKey,
484cdf0e10cSrcweir     OStorePageBIOS &        rBIOS)
485cdf0e10cSrcweir {
486cdf0e10cSrcweir     (void) testInvariant("OStoreBTreeRootObject::find_insert(): enter");
487cdf0e10cSrcweir 
488cdf0e10cSrcweir     // Check for RootNode split.
489cdf0e10cSrcweir     PageHolderObject< page > xRoot (m_xPage);
490cdf0e10cSrcweir     if (xRoot->querySplit())
491cdf0e10cSrcweir     {
492cdf0e10cSrcweir         PageHolderObject< page > xPageL;
493cdf0e10cSrcweir 
494cdf0e10cSrcweir         // Change root.
495cdf0e10cSrcweir         storeError eErrCode = change (xPageL, rBIOS);
496cdf0e10cSrcweir         if (eErrCode != store_E_None)
497cdf0e10cSrcweir             return eErrCode;
498cdf0e10cSrcweir 
499cdf0e10cSrcweir         // Split left page (prev root).
500cdf0e10cSrcweir         eErrCode = split (0, xPageL, rBIOS);
501cdf0e10cSrcweir         if (eErrCode != store_E_None)
502cdf0e10cSrcweir             return eErrCode;
503cdf0e10cSrcweir     }
504cdf0e10cSrcweir 
505cdf0e10cSrcweir     // Init node w/ root page.
506cdf0e10cSrcweir     {
507cdf0e10cSrcweir         PageHolder tmp (m_xPage);
508cdf0e10cSrcweir         tmp.swap (rNode.get());
509cdf0e10cSrcweir     }
510cdf0e10cSrcweir 
511cdf0e10cSrcweir     // Setup BTree entry.
512cdf0e10cSrcweir     T const entry (rKey);
513cdf0e10cSrcweir 
514cdf0e10cSrcweir     // Check current Page.
515cdf0e10cSrcweir     PageHolderObject< page > xPage (rNode.get());
516cdf0e10cSrcweir     for (; xPage->depth() > 0; xPage = rNode.makeHolder< page >())
517cdf0e10cSrcweir     {
518cdf0e10cSrcweir         // Find next page.
519cdf0e10cSrcweir         page const & rPage = (*xPage);
520cdf0e10cSrcweir         sal_uInt16 const i = rPage.find (entry);
521cdf0e10cSrcweir         sal_uInt16 const n = rPage.usageCount();
522cdf0e10cSrcweir         if (!(i < n))
523cdf0e10cSrcweir         {
524cdf0e10cSrcweir             // Path to entry not exists (Must not happen(?)).
525cdf0e10cSrcweir             return store_E_NotExists;
526cdf0e10cSrcweir         }
527cdf0e10cSrcweir 
528cdf0e10cSrcweir         // Check address.
529cdf0e10cSrcweir         sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
530cdf0e10cSrcweir         if (nAddr == STORE_PAGE_NULL)
531cdf0e10cSrcweir         {
532cdf0e10cSrcweir             // Path to entry not exists (Must not happen(?)).
533cdf0e10cSrcweir             return store_E_NotExists;
534cdf0e10cSrcweir         }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir         // Load next page.
537cdf0e10cSrcweir         OStoreBTreeNodeObject aNext;
538cdf0e10cSrcweir         storeError eErrCode = rBIOS.loadObjectAt (aNext, nAddr);
539cdf0e10cSrcweir         if (eErrCode != store_E_None)
540cdf0e10cSrcweir             return eErrCode;
541cdf0e10cSrcweir 
542cdf0e10cSrcweir         // Check for next node split.
543cdf0e10cSrcweir         PageHolderObject< page > xNext (aNext.get());
544cdf0e10cSrcweir         if (xNext->querySplit())
545cdf0e10cSrcweir         {
546cdf0e10cSrcweir             // Split next node.
547cdf0e10cSrcweir             eErrCode = rNode.split (i, xNext, rBIOS);
548cdf0e10cSrcweir             if (eErrCode != store_E_None)
549cdf0e10cSrcweir                 return eErrCode;
550cdf0e10cSrcweir 
551cdf0e10cSrcweir             // Restart.
552cdf0e10cSrcweir             continue;
553cdf0e10cSrcweir         }
554cdf0e10cSrcweir 
555cdf0e10cSrcweir         // Let next page be current.
556cdf0e10cSrcweir         PageHolder tmp (aNext.get());
557cdf0e10cSrcweir         tmp.swap (rNode.get());
558cdf0e10cSrcweir     }
559cdf0e10cSrcweir 
560cdf0e10cSrcweir     // Find index.
561cdf0e10cSrcweir     page const & rPage = (*xPage);
562cdf0e10cSrcweir     rIndex = rPage.find(entry);
563cdf0e10cSrcweir     if (rIndex < rPage.usageCount())
564cdf0e10cSrcweir     {
565cdf0e10cSrcweir         // Compare entry.
566cdf0e10cSrcweir         T::CompareResult result = entry.compare (rPage.m_pData[rIndex]);
567cdf0e10cSrcweir         OSL_POSTCOND(result != T::COMPARE_LESS, "store::BTreeRoot::find_insert(): sort error");
568cdf0e10cSrcweir         if (result == T::COMPARE_LESS)
569cdf0e10cSrcweir             return store_E_Unknown;
570cdf0e10cSrcweir 
571cdf0e10cSrcweir         if (result == T::COMPARE_EQUAL)
572cdf0e10cSrcweir             return store_E_AlreadyExists;
573cdf0e10cSrcweir     }
574cdf0e10cSrcweir 
575cdf0e10cSrcweir     // Greater or not (yet) existing.
576cdf0e10cSrcweir     (void) testInvariant("OStoreBTreeRootObject::find_insert(): leave");
577cdf0e10cSrcweir     return store_E_None;
578cdf0e10cSrcweir }
579