1/*
2 * Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
3 * This file may be used under the terms of the MIT License.
4 */
5#ifndef CACHED_BLOCK_H
6#define CACHED_BLOCK_H
7
8//!	interface for the block cache
9
10
11#include "system_dependencies.h"
12
13#include "Volume.h"
14#include "Journal.h"
15#include "Debug.h"
16
17
18// The CachedBlock class is completely implemented as inlines.
19// It should be used when cache single blocks to make sure they
20// will be properly released after use (and it's also very
21// convenient to use them).
22
23class CachedBlock {
24	public:
25		CachedBlock(Volume* volume);
26		CachedBlock(Volume* volume, off_t block);
27		CachedBlock(Volume* volume, block_run run);
28		CachedBlock(CachedBlock* cached);
29		~CachedBlock();
30
31		inline void Keep();
32		inline void Unset();
33
34		inline const uint8* SetTo(off_t block, off_t base, size_t length);
35		inline const uint8* SetTo(off_t block);
36		inline const uint8* SetTo(block_run run);
37		inline uint8* SetToWritable(Transaction& transaction, off_t block,
38			off_t base, size_t length, bool empty = false);
39		inline uint8* SetToWritable(Transaction& transaction, off_t block,
40			bool empty = false);
41		inline uint8* SetToWritable(Transaction& transaction, block_run run,
42			bool empty = false);
43		inline status_t MakeWritable(Transaction& transaction);
44
45		const uint8* Block() const { return fBlock; }
46		off_t BlockNumber() const { return fBlockNumber; }
47		uint32 BlockSize() const { return fVolume->BlockSize(); }
48		uint32 BlockShift() const { return fVolume->BlockShift(); }
49
50	private:
51		CachedBlock(const CachedBlock& other);
52		CachedBlock& operator=(const CachedBlock& other);
53			// no implementation
54
55	protected:
56		Volume	*fVolume;
57		off_t	fBlockNumber;
58		uint8	*fBlock;
59};
60
61
62// inlines
63
64
65inline
66CachedBlock::CachedBlock(Volume* volume)
67	:
68	fVolume(volume),
69	fBlockNumber(0),
70	fBlock(NULL)
71{
72}
73
74
75inline
76CachedBlock::CachedBlock(Volume* volume, off_t block)
77	:
78	fVolume(volume),
79	fBlockNumber(0),
80	fBlock(NULL)
81{
82	SetTo(block);
83}
84
85
86inline
87CachedBlock::CachedBlock(Volume* volume, block_run run)
88	:
89	fVolume(volume),
90	fBlockNumber(0),
91	fBlock(NULL)
92{
93	SetTo(volume->ToBlock(run));
94}
95
96
97inline
98CachedBlock::CachedBlock(CachedBlock* cached)
99	:
100	fVolume(cached->fVolume),
101	fBlockNumber(cached->BlockNumber()),
102	fBlock(cached->fBlock)
103{
104	cached->Keep();
105}
106
107
108inline
109CachedBlock::~CachedBlock()
110{
111	Unset();
112}
113
114
115inline void
116CachedBlock::Keep()
117{
118	fBlock = NULL;
119}
120
121
122inline void
123CachedBlock::Unset()
124{
125	if (fBlock != NULL) {
126		block_cache_put(fVolume->BlockCache(), fBlockNumber);
127		fBlock = NULL;
128	}
129}
130
131
132inline const uint8*
133CachedBlock::SetTo(off_t block, off_t base, size_t length)
134{
135	Unset();
136	fBlockNumber = block;
137	return fBlock = (uint8*)block_cache_get_etc(fVolume->BlockCache(),
138		block, base, length);
139}
140
141
142inline const uint8*
143CachedBlock::SetTo(off_t block)
144{
145	return SetTo(block, block, 1);
146}
147
148
149inline const uint8*
150CachedBlock::SetTo(block_run run)
151{
152	return SetTo(fVolume->ToBlock(run));
153}
154
155
156inline uint8*
157CachedBlock::SetToWritable(Transaction& transaction, off_t block, off_t base,
158	size_t length, bool empty)
159{
160	Unset();
161	fBlockNumber = block;
162
163	if (empty) {
164		fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(),
165			block, transaction.ID());
166	} else {
167		fBlock = (uint8*)block_cache_get_writable_etc(fVolume->BlockCache(),
168			block, base, length, transaction.ID());
169	}
170
171	return fBlock;
172}
173
174
175inline uint8*
176CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty)
177{
178	return SetToWritable(transaction, block, block, 1, empty);
179}
180
181
182inline uint8*
183CachedBlock::SetToWritable(Transaction& transaction, block_run run, bool empty)
184{
185	return SetToWritable(transaction, fVolume->ToBlock(run), empty);
186}
187
188
189inline status_t
190CachedBlock::MakeWritable(Transaction& transaction)
191{
192	if (fBlock == NULL)
193		return B_NO_INIT;
194
195	return block_cache_make_writable(fVolume->BlockCache(), fBlockNumber,
196		transaction.ID());
197}
198
199#endif	// CACHED_BLOCK_H
200