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