3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 // You can alternatively use *this file* under the terms of the the MIT
20 // license included in this package.
26 //#include <fs_cache.h>
28 #include "BlockCache.h"
34 \brief Represents a cached disk block.
36 A block can either be formatted, i.e. a node in the S+Tree, or
37 unformatted containing raw data. When formatted, it can be converted to
38 a Node via the ToNode() method.
59 Block::GetCache() const
66 Block::GetBlockSize() const
68 return fCache
->GetBlockSize();
76 fCache
->GetBlock(this);
84 fCache
->PutBlock(this);
89 Block::GetNumber() const
96 Block::GetData() const
103 Block::SetKind(uint32 kind
)
105 fFlags
= (fFlags
& ~(uint32
)KIND_MASK
) | (kind
& KIND_MASK
);
110 Block::SetChecked(bool checked
)
115 fFlags
&= ~(uint32
)CHECKED
;
124 node
= static_cast<Node
*>(this);
130 Block::ToInternalNode()
132 InternalNode
*internalNode
= NULL
;
133 if (Node
*node
= ToNode()) {
134 if (node
->IsInternal())
135 internalNode
= static_cast<InternalNode
*>(node
);
144 LeafNode
*leafNode
= NULL
;
145 if (Node
*node
= ToNode()) {
147 leafNode
= static_cast<LeafNode
*>(node
);
154 Block::IsFormatted() const
156 return (GetKind() == KIND_FORMATTED
);
161 Block::IsLeaf() const
163 if (Node
*node
= const_cast<Block
*>(this)->ToNode())
164 return node
->IsLeaf();
170 Block::IsInternal() const
172 if (Node
*node
= const_cast<Block
*>(this)->ToNode())
173 return node
->IsInternal();
179 Block::_SetTo(BlockCache
*cache
, uint64 number
)
183 status_t error
= (cache
? B_OK
: B_BAD_VALUE
);
188 fData
= fCache
->_GetBlock(fNumber
);
200 fCache
->_ReleaseBlock(fNumber
, fData
);
205 fFlags
= KIND_UNKNOWN
;
220 return (--fRefCount
== 0);
226 \brief Represents a formatted cached disk block.
228 A Node can be converted to an InternalNode or LeafNode, depending on
229 its kind. Leaf nodes are located at level 1 only.
240 Node::GetLevel() const
242 return le2h(GetHeader()->blk_level
);
246 /*! \brief Returns the number of child "items" the node contains/refers to.
248 If the node is a leaf node, this number is indeed the number of the
249 items it contains. For internal node it is the number of keys, as oposed
250 to the number of child nodes, which is CountItems() + 1.
252 \return The number of child "items" the node contains/refers to.
255 Node::CountItems() const
257 return le2h(GetHeader()->blk_nr_item
);
262 Node::GetFreeSpace() const
264 return le2h(GetHeader()->blk_free_space
);
271 return (GetLevel() == 1);
276 Node::IsInternal() const
278 return (GetLevel() > 1);
285 // check the minimal size of the node against its declared free space
286 if (GetFreeSpace() + sizeof(block_head
) > GetBlockSize()) {
287 FATAL(("WARNING: bad node %Ld: it declares more free space than "
288 "possibly being available (%u vs %lu)!\n", GetNumber(),
289 GetFreeSpace(), GetBlockSize() - sizeof(block_head
)));
297 Node::GetHeader() const
299 return (block_head
*)fData
;
305 \brief Represents an internal tree node.
307 Internal tree node refer to its child nodes via DiskChilds.
312 InternalNode::GetKeys() const
314 return (const Key
*)((uint8
*)fData
+ sizeof(block_head
));
319 InternalNode::KeyAt(int32 index
) const
322 if (index
>= 0 && index
< CountItems())
323 k
= GetKeys() + index
;
329 InternalNode::GetChilds() const
331 return (DiskChild
*)(GetKeys() + CountItems());
336 InternalNode::ChildAt(int32 index
) const
338 const DiskChild
*child
= NULL
;
339 if (index
>= 0 && index
<= CountItems())
340 child
= GetChilds() + index
;
346 InternalNode::Check() const
348 // check the minimal size of the node against its declared free space
349 // Note: This test is stricter than the that of the base class, so we
350 // don't need to invoke it.
351 uint32 size
= (const uint8
*)(GetChilds() + (CountItems() + 1))
352 - (const uint8
*)GetData();
353 if (size
+ GetFreeSpace() > GetBlockSize()) {
354 FATAL(("WARNING: bad internal node %Ld: it declares more free space "
355 "than possibly being available (size: %lu, block size: %lu, "
356 "free space: %u)!\n", GetNumber(), size
, GetBlockSize(),
366 \brief Represents an tree leaf node.
368 Leaf nodes contain items.
373 LeafNode::GetItemHeaders() const
375 return (ItemHeader
*)((uint8
*)fData
+ sizeof(block_head
));
380 LeafNode::ItemHeaderAt(int32 index
) const
382 const ItemHeader
*header
= NULL
;
383 if (index
>= 0 && index
< CountItems())
384 header
= GetItemHeaders() + index
;
390 LeafNode::GetLeftKey(VKey
*k
) const
392 status_t error
= (k
? B_OK
: B_BAD_VALUE
);
394 if (const ItemHeader
*header
= ItemHeaderAt(0))
404 LeafNode::GetRightKey(VKey
*k
) const
406 status_t error
= (k
? B_OK
: B_BAD_VALUE
);
408 if (const ItemHeader
*header
= ItemHeaderAt(CountItems() - 1))
418 LeafNode::Check() const
420 // check the minimal size of the node against its declared free space
421 // Note: This test is stricter than the that of the base class, so we
422 // don't need to invoke it.
423 uint32 size
= GetItemSpaceOffset();
424 if (size
+ GetFreeSpace() > GetBlockSize()) {
425 FATAL(("WARNING: bad leaf node %Ld: it declares more free space "
426 "than possibly being available (min size: %lu, block size: "
427 "%lu, free space: %u)!\n", GetNumber(), size
, GetBlockSize(),
434 // GetItemSpaceOffset
436 LeafNode::GetItemSpaceOffset() const
438 return sizeof(ItemHeader
) * CountItems() + sizeof(block_head
);
444 \brief A structure referring to a child node of an internal node.