3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / kernel / file_systems / reiserfs / Block.cpp
blob3d98e07283dd3170dd4878aa38fe474966dc9b60
1 // Block.cpp
2 //
3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
4 //
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.
9 //
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.
14 //
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.
22 #include "Block.h"
24 #include <stdlib.h>
26 //#include <fs_cache.h>
28 #include "BlockCache.h"
29 #include "Item.h"
30 #include "Key.h"
32 /*!
33 \class Block
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.
41 // constructor
42 Block::Block()
43 : fCache(NULL),
44 fNumber(0),
45 fData(NULL),
46 fFlags(KIND_UNKNOWN),
47 fRefCount(0)
51 // destructor
52 Block::~Block()
54 _Unset();
57 // GetCache
58 BlockCache *
59 Block::GetCache() const
61 return fCache;
64 // GetBlockSize
65 uint32
66 Block::GetBlockSize() const
68 return fCache->GetBlockSize();
71 // Get
72 void
73 Block::Get()
75 if (fCache)
76 fCache->GetBlock(this);
79 // Put
80 void
81 Block::Put()
83 if (fCache)
84 fCache->PutBlock(this);
87 // GetNumber
88 uint64
89 Block::GetNumber() const
91 return fNumber;
94 // GetData
95 void *
96 Block::GetData() const
98 return fData;
101 // SetKind
102 void
103 Block::SetKind(uint32 kind)
105 fFlags = (fFlags & ~(uint32)KIND_MASK) | (kind & KIND_MASK);
108 // SetChecked
109 void
110 Block::SetChecked(bool checked)
112 if (checked)
113 fFlags |= CHECKED;
114 else
115 fFlags &= ~(uint32)CHECKED;
118 // ToNode
119 Node *
120 Block::ToNode()
122 Node *node = NULL;
123 if (IsFormatted())
124 node = static_cast<Node*>(this);
125 return node;
128 // ToInternalNode
129 InternalNode *
130 Block::ToInternalNode()
132 InternalNode *internalNode = NULL;
133 if (Node *node = ToNode()) {
134 if (node->IsInternal())
135 internalNode = static_cast<InternalNode*>(node);
137 return internalNode;
140 // ToLeafNode
141 LeafNode *
142 Block::ToLeafNode()
144 LeafNode *leafNode = NULL;
145 if (Node *node = ToNode()) {
146 if (node->IsLeaf())
147 leafNode = static_cast<LeafNode*>(node);
149 return leafNode;
152 // IsFormatted
153 bool
154 Block::IsFormatted() const
156 return (GetKind() == KIND_FORMATTED);
159 // IsLeaf
160 bool
161 Block::IsLeaf() const
163 if (Node *node = const_cast<Block*>(this)->ToNode())
164 return node->IsLeaf();
165 return false;
168 // IsInternal
169 bool
170 Block::IsInternal() const
172 if (Node *node = const_cast<Block*>(this)->ToNode())
173 return node->IsInternal();
174 return false;
177 // _SetTo
178 status_t
179 Block::_SetTo(BlockCache *cache, uint64 number)
181 // unset
182 _Unset();
183 status_t error = (cache ? B_OK : B_BAD_VALUE);
184 // set to new values
185 fCache = cache;
186 fNumber = number;
187 if (error == B_OK) {
188 fData = fCache->_GetBlock(fNumber);
189 if (!fData)
190 error = B_BAD_VALUE;
192 return error;
195 // _Unset
196 void
197 Block::_Unset()
199 if (fCache && fData)
200 fCache->_ReleaseBlock(fNumber, fData);
201 fData = NULL;
202 fCache = NULL;
203 fNumber = 0;
204 fData = NULL;
205 fFlags = KIND_UNKNOWN;
206 fRefCount = 0;
209 // _Get
210 void
211 Block::_Get()
213 fRefCount++;
216 // _Put
217 bool
218 Block::_Put()
220 return (--fRefCount == 0);
225 \class Node
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.
232 // dummy constructor
233 Node::Node()
234 : Block()
238 // GetLevel
239 uint16
240 Node::GetLevel() const
242 return le2h(GetHeader()->blk_level);
245 // CountItems
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.
254 uint16
255 Node::CountItems() const
257 return le2h(GetHeader()->blk_nr_item);
260 // FreeSpace
261 uint16
262 Node::GetFreeSpace() const
264 return le2h(GetHeader()->blk_free_space);
267 // IsLeaf
268 bool
269 Node::IsLeaf() const
271 return (GetLevel() == 1);
274 // IsInternal
275 bool
276 Node::IsInternal() const
278 return (GetLevel() > 1);
281 // Check
282 status_t
283 Node::Check() const
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)));
290 return B_BAD_DATA;
292 return B_OK;
295 // GetHeader
296 block_head *
297 Node::GetHeader() const
299 return (block_head*)fData;
304 \class InternalNode
305 \brief Represents an internal tree node.
307 Internal tree node refer to its child nodes via DiskChilds.
310 // GetKeys
311 const Key *
312 InternalNode::GetKeys() const
314 return (const Key*)((uint8*)fData + sizeof(block_head));
317 // KeyAt
318 const Key *
319 InternalNode::KeyAt(int32 index) const
321 const Key *k = NULL;
322 if (index >= 0 && index < CountItems())
323 k = GetKeys() + index;
324 return k;
327 // GetChilds
328 const DiskChild *
329 InternalNode::GetChilds() const
331 return (DiskChild*)(GetKeys() + CountItems());
334 // ChildAt
335 const DiskChild *
336 InternalNode::ChildAt(int32 index) const
338 const DiskChild *child = NULL;
339 if (index >= 0 && index <= CountItems())
340 child = GetChilds() + index;
341 return child;
344 // Check
345 status_t
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(),
357 GetFreeSpace()));
358 return B_BAD_DATA;
360 return B_OK;
365 \class LeafNode
366 \brief Represents an tree leaf node.
368 Leaf nodes contain items.
371 // GetItemHeaders
372 const ItemHeader *
373 LeafNode::GetItemHeaders() const
375 return (ItemHeader*)((uint8*)fData + sizeof(block_head));
378 // ItemHeaderAt
379 const ItemHeader *
380 LeafNode::ItemHeaderAt(int32 index) const
382 const ItemHeader *header = NULL;
383 if (index >= 0 && index < CountItems())
384 header = GetItemHeaders() + index;
385 return header;
388 // GetLeftKey
389 status_t
390 LeafNode::GetLeftKey(VKey *k) const
392 status_t error = (k ? B_OK : B_BAD_VALUE);
393 if (error == B_OK) {
394 if (const ItemHeader *header = ItemHeaderAt(0))
395 header->GetKey(k);
396 else
397 error = B_ERROR;
399 return error;
402 // GetRightKey
403 status_t
404 LeafNode::GetRightKey(VKey *k) const
406 status_t error = (k ? B_OK : B_BAD_VALUE);
407 if (error == B_OK) {
408 if (const ItemHeader *header = ItemHeaderAt(CountItems() - 1))
409 header->GetKey(k);
410 else
411 error = B_ERROR;
413 return error;
416 // Check
417 status_t
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(),
428 GetFreeSpace()));
429 return B_BAD_DATA;
431 return B_OK;
434 // GetItemSpaceOffset
435 uint32
436 LeafNode::GetItemSpaceOffset() const
438 return sizeof(ItemHeader) * CountItems() + sizeof(block_head);
443 \class DiskChild
444 \brief A structure referring to a child node of an internal node.