1*73d9b18aSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*73d9b18aSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*73d9b18aSAndrew Rist * or more contributor license agreements. See the NOTICE file
5*73d9b18aSAndrew Rist * distributed with this work for additional information
6*73d9b18aSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*73d9b18aSAndrew Rist * to you under the Apache License, Version 2.0 (the
8*73d9b18aSAndrew Rist * "License"); you may not use this file except in compliance
9*73d9b18aSAndrew Rist * with the License. You may obtain a copy of the License at
10*73d9b18aSAndrew Rist *
11*73d9b18aSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*73d9b18aSAndrew Rist *
13*73d9b18aSAndrew Rist * Unless required by applicable law or agreed to in writing,
14*73d9b18aSAndrew Rist * software distributed under the License is distributed on an
15*73d9b18aSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*73d9b18aSAndrew Rist * KIND, either express or implied. See the License for the
17*73d9b18aSAndrew Rist * specific language governing permissions and limitations
18*73d9b18aSAndrew Rist * under the License.
19*73d9b18aSAndrew Rist *
20*73d9b18aSAndrew Rist *************************************************************/
21*73d9b18aSAndrew Rist
22*73d9b18aSAndrew 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 {
66cdf0e10cSrcweir register sal_Int32 l = 0;
67cdf0e10cSrcweir register sal_Int32 r = usageCount() - 1;
68cdf0e10cSrcweir
69cdf0e10cSrcweir while (l < r)
70cdf0e10cSrcweir {
71cdf0e10cSrcweir register 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