1// Item.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
18//
19// You can alternatively use *this file* under the terms of the the MIT
20// license included in this package.
21
22#include "Item.h"
23#include "Block.h"
24
25/*!
26	\class ItemHeader
27	\brief Represents the on-disk structure for an item header.
28
29	An ItemHeader is located in a leaf nodes and provides information about
30	a respective item. Aside from the location and the size of the item
31	it also contains the leftmost key of the item (used for searching)
32	and the format version of that key.
33*/
34
35/*!
36	\class Item
37	\brief Provides access to the on-disk item structure.
38
39	Item is the base class for DirItem, IndirectItem and StatItem.
40	It does little more than to hold a pointer to the leaf node it resides
41	on and to its ItemHeader. The Item locks the node in the block cache
42	as longs as it exists. An Item can be savely casted into one of the
43	derived types.
44*/
45
46// constructor
47Item::Item()
48	: fNode(NULL),
49	  fHeader(NULL)
50{
51}
52
53// constructor
54Item::Item(const Item &item)
55	: fNode(NULL),
56	  fHeader(NULL)
57{
58	SetTo(item.GetNode(), item.GetHeader());
59}
60
61// constructor
62Item::Item(LeafNode *node, const ItemHeader *header)
63	: fNode(NULL),
64	  fHeader(NULL)
65{
66	SetTo(node, header);
67}
68
69// destructor
70Item::~Item()
71{
72	Unset();
73}
74
75// SetTo
76status_t
77Item::SetTo(LeafNode *node, const ItemHeader *header)
78{
79	Unset();
80	status_t error = (node && header ? B_OK : B_BAD_VALUE);
81	if (error == B_OK) {
82		fNode = node;
83		fHeader = const_cast<ItemHeader*>(header);
84		fNode->Get();
85		// check the item
86		error = Check();
87		if (error != B_OK)
88			Unset();
89	}
90	return error;
91}
92
93// SetTo
94status_t
95Item::SetTo(LeafNode *node, int32 index)
96{
97	Unset();
98	status_t error = (node ? B_OK : B_BAD_VALUE);
99	if (error == B_OK)
100		error = SetTo(node, node->ItemHeaderAt(index));
101	return error;
102}
103
104// Unset
105void
106Item::Unset()
107{
108	if (fNode) {
109		fNode->Put();
110		fNode = NULL;
111	}
112	fHeader = NULL;
113}
114
115// GetNode
116LeafNode *
117Item::GetNode() const
118{
119	return fNode;
120}
121
122// GetHeader
123ItemHeader *
124Item::GetHeader() const
125{
126	return fHeader;
127}
128
129// GetIndex
130int32
131Item::GetIndex() const
132{
133	return (fHeader - fNode->GetItemHeaders());
134}
135
136// GetData
137void *
138Item::GetData() const
139{
140	return (uint8*)fNode->GetData() + fHeader->GetLocation();
141}
142
143// GetLen
144uint16
145Item::GetLen() const
146{
147	return fHeader->GetLen();
148}
149
150// GetType
151uint16
152Item::GetType() const
153{
154	return fHeader->GetType();
155}
156
157// GetDirID
158uint32
159Item::GetDirID() const
160{
161	return fHeader->GetDirID();
162}
163
164// GetObjectID
165uint32
166Item::GetObjectID() const
167{
168	return fHeader->GetObjectID();
169}
170
171// GetOffset
172uint64
173Item::GetOffset() const
174{
175	return fHeader->GetOffset();
176}
177
178// GetKey
179const Key *
180Item::GetKey() const
181{
182	return fHeader->GetKey();
183}
184
185// GetKey
186VKey *
187Item::GetKey(VKey *k) const
188{
189	return fHeader->GetKey(k);
190}
191
192// GetEntryCount
193uint16
194Item::GetEntryCount() const
195{
196	return fHeader->GetEntryCount();
197}
198
199// Check
200status_t
201Item::Check() const
202{
203	// check location of the item
204	uint32 blockSize = fNode->GetBlockSize();
205	uint32 itemSpaceOffset = fNode->GetItemSpaceOffset();
206	uint32 location = fHeader->GetLocation();
207	if (location < itemSpaceOffset
208		|| location + fHeader->GetLen() > blockSize) {
209		FATAL(("WARNING: bad item %" B_PRId32
210			" on node %" B_PRIu64 ": it can not be located "
211			"where it claims to be: (location: %" B_PRIu32 ", len: %u, "
212			"item space offset: %" B_PRIu32 ", "
213			"block size: %" B_PRIu32 ")!\n", GetIndex(),
214			fNode->GetNumber(), location, fHeader->GetLen(),
215			itemSpaceOffset, blockSize));
216		return B_BAD_DATA;
217	}
218	return B_OK;
219}
220
221// =
222Item &
223Item::operator=(const Item &item)
224{
225	SetTo(item.GetNode(), item.GetHeader());
226	return *this;
227}
228
229