1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <sal/config.h>
26 #include <sal/types.h>
28 #include <store/types.h>
30 #include "storbase.hxx"
37 struct OStoreBTreeEntry
39 typedef OStorePageKey K
;
40 typedef OStorePageLink L
;
46 explicit OStoreBTreeEntry (
48 L
const & rLink
= L())
51 m_nAttrib (store::htonl(0))
61 CompareResult
compare (const OStoreBTreeEntry
& rOther
) const
63 if (m_aKey
< rOther
.m_aKey
)
65 else if (m_aKey
== rOther
.m_aKey
)
68 return COMPARE_GREATER
;
72 #define STORE_MAGIC_BTREENODE sal_uInt32(0x58190322)
74 struct OStoreBTreeNodeData
: public store::PageData
76 typedef PageData base
;
77 typedef OStoreBTreeNodeData self
;
79 typedef OStorePageGuard G
;
80 typedef OStoreBTreeEntry T
;
85 static const sal_uInt32 theTypeId
= STORE_MAGIC_BTREENODE
;
87 static const size_t theSize
= sizeof(G
);
88 static const sal_uInt16 thePageSize
= base::theSize
+ self::theSize
;
89 static_assert(STORE_MINIMUM_PAGESIZE
>= self::thePageSize
, "got to be at least equal in size");
91 sal_uInt16
capacity() const
93 return static_cast<sal_uInt16
>(store::ntohs(base::m_aDescr
.m_nSize
) - self::thePageSize
);
96 /** capacityCount (must be even).
98 sal_uInt16
capacityCount() const
100 return sal_uInt16(capacity() / sizeof(T
));
103 sal_uInt16
usage() const
105 return static_cast<sal_uInt16
>(store::ntohs(base::m_aDescr
.m_nUsed
) - self::thePageSize
);
108 sal_uInt16
usageCount() const
110 return sal_uInt16(usage() / sizeof(T
));
112 void usageCount (sal_uInt16 nCount
)
114 size_t const nBytes
= self::thePageSize
+ nCount
* sizeof(T
);
115 base::m_aDescr
.m_nUsed
= store::htons(sal::static_int_cast
< sal_uInt16
>(nBytes
));
118 explicit OStoreBTreeNodeData (sal_uInt16 nPageSize
);
122 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
123 nCRC32
= rtl_crc32 (nCRC32
, m_pData
, capacity());
124 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
127 storeError
verify() const
129 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
130 nCRC32
= rtl_crc32 (nCRC32
, m_pData
, capacity());
131 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
132 return store_E_InvalidChecksum
;
137 sal_uInt32
depth() const
139 return store::ntohl(self::m_aGuard
.m_nMagic
);
141 void depth (sal_uInt32 nDepth
)
143 self::m_aGuard
.m_nMagic
= store::htonl(nDepth
);
146 bool querySplit() const
148 return usageCount() >= capacityCount();
151 sal_uInt16
find (const T
& t
) const;
152 void insert (sal_uInt16 i
, const T
& t
);
153 void remove (sal_uInt16 i
);
155 /** split (left half copied from right half of left page).
157 void split (const self
& rPageL
);
159 /** truncate (to n elements).
161 void truncate (sal_uInt16 n
);
164 class OStoreBTreeNodeObject
: public store::OStorePageObject
166 typedef OStorePageObject base
;
167 typedef OStoreBTreeNodeObject self
;
168 typedef OStoreBTreeNodeData page
;
170 typedef OStoreBTreeEntry T
;
173 explicit OStoreBTreeNodeObject (std::shared_ptr
<PageData
> const & rxPage
= std::shared_ptr
<PageData
>())
174 : OStorePageObject (rxPage
)
177 virtual storeError
guard (sal_uInt32 nAddr
) override
;
178 virtual storeError
verify (sal_uInt32 nAddr
) const override
;
182 * @param rxPageL [inout] left child to be split
186 PageHolderObject
< page
> & rxPageL
,
187 OStorePageBIOS
& rBIOS
);
189 /** remove (down to leaf node, recursive).
193 OStoreBTreeEntry
& rEntryL
,
194 OStorePageBIOS
& rBIOS
);
197 class OStoreBTreeRootObject
: public store::OStoreBTreeNodeObject
199 typedef OStoreBTreeNodeObject base
;
200 typedef OStoreBTreeNodeData page
;
202 typedef OStoreBTreeEntry T
;
205 explicit OStoreBTreeRootObject (std::shared_ptr
<PageData
> const & rxPage
= std::shared_ptr
<PageData
>())
206 : OStoreBTreeNodeObject (rxPage
)
209 storeError
loadOrCreate (
211 OStorePageBIOS
& rBIOS
);
213 /** find_lookup (w/o split()).
214 * Precond: root node page loaded.
216 storeError
find_lookup (
217 OStoreBTreeNodeObject
& rNode
, // [out]
218 sal_uInt16
& rIndex
, // [out]
219 OStorePageKey
const & rKey
,
220 OStorePageBIOS
& rBIOS
) const;
222 /** find_insert (possibly with split()).
223 * Precond: root node page loaded.
225 storeError
find_insert (
226 OStoreBTreeNodeObject
& rNode
,
228 OStorePageKey
const & rKey
,
229 OStorePageBIOS
& rBIOS
);
233 * Precond: root node page loaded.
235 void testInvariant (char const * message
) const;
239 * @param rxPageL [out] prev. root (needs split)
242 PageHolderObject
< page
> & rxPageL
,
243 OStorePageBIOS
& rBIOS
);
248 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */