xref: /aoo41x/main/store/source/stortree.cxx (revision 73d9b18a)
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