xref: /haiku/src/add-ons/kernel/file_systems/bfs/CachedBlock.h (revision bd6068614473f87449dfa2eaa67fad1527c61e11)
1 /*
2  * Copyright 2001-2017, 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 
24 class CachedBlock {
25 public:
26 								CachedBlock(Volume* volume);
27 								CachedBlock(Volume* volume, off_t block);
28 								CachedBlock(Volume* volume, block_run run);
29 								CachedBlock(CachedBlock* cached);
30 								~CachedBlock();
31 
32 	inline	void				Keep();
33 	inline	void				Unset();
34 
35 	inline const uint8*			SetTo(off_t block, off_t base, size_t length);
36 	inline const uint8*			SetTo(off_t block);
37 	inline const uint8*			SetTo(block_run run);
38 	inline uint8*				SetToWritable(Transaction& transaction,
39 									off_t block, off_t base, size_t length,
40 									bool empty = false);
41 	inline uint8*				SetToWritable(Transaction& transaction,
42 									off_t block, bool empty = false);
43 	inline uint8*				SetToWritable(Transaction& transaction,
44 									block_run run, bool empty = false);
45 	inline status_t				MakeWritable(Transaction& transaction);
46 
47 			const uint8*		Block() const { return fBlock; }
48 			off_t				BlockNumber() const { return fBlockNumber; }
49 			uint32				BlockSize() const
50 									{ return fVolume->BlockSize(); }
51 			uint32				BlockShift() const
52 									{ return fVolume->BlockShift(); }
53 
54 private:
55 	CachedBlock(const CachedBlock& other);
56 	CachedBlock& operator=(const CachedBlock& other);
57 		// no implementation
58 
59 protected:
60 			Volume*				fVolume;
61 			off_t				fBlockNumber;
62 			uint8*				fBlock;
63 };
64 
65 
66 // inlines
67 
68 
69 inline
70 CachedBlock::CachedBlock(Volume* volume)
71 	:
72 	fVolume(volume),
73 	fBlockNumber(0),
74 	fBlock(NULL)
75 {
76 }
77 
78 
79 inline
80 CachedBlock::CachedBlock(Volume* volume, off_t block)
81 	:
82 	fVolume(volume),
83 	fBlockNumber(0),
84 	fBlock(NULL)
85 {
86 	SetTo(block);
87 }
88 
89 
90 inline
91 CachedBlock::CachedBlock(Volume* volume, block_run run)
92 	:
93 	fVolume(volume),
94 	fBlockNumber(0),
95 	fBlock(NULL)
96 {
97 	SetTo(volume->ToBlock(run));
98 }
99 
100 
101 inline
102 CachedBlock::CachedBlock(CachedBlock* cached)
103 	:
104 	fVolume(cached->fVolume),
105 	fBlockNumber(cached->BlockNumber()),
106 	fBlock(cached->fBlock)
107 {
108 	cached->Keep();
109 }
110 
111 
112 inline
113 CachedBlock::~CachedBlock()
114 {
115 	Unset();
116 }
117 
118 
119 inline void
120 CachedBlock::Keep()
121 {
122 	fBlock = NULL;
123 }
124 
125 
126 inline void
127 CachedBlock::Unset()
128 {
129 	if (fBlock != NULL) {
130 		block_cache_put(fVolume->BlockCache(), fBlockNumber);
131 		fBlock = NULL;
132 	}
133 }
134 
135 
136 inline const uint8*
137 CachedBlock::SetTo(off_t block, off_t base, size_t length)
138 {
139 	Unset();
140 	fBlockNumber = block;
141 	return fBlock = (uint8*)block_cache_get_etc(fVolume->BlockCache(),
142 		block, base, length);
143 }
144 
145 
146 inline const uint8*
147 CachedBlock::SetTo(off_t block)
148 {
149 	return SetTo(block, block, 1);
150 }
151 
152 
153 inline const uint8*
154 CachedBlock::SetTo(block_run run)
155 {
156 	return SetTo(fVolume->ToBlock(run));
157 }
158 
159 
160 inline uint8*
161 CachedBlock::SetToWritable(Transaction& transaction, off_t block, off_t base,
162 	size_t length, bool empty)
163 {
164 	Unset();
165 	fBlockNumber = block;
166 
167 	if (empty) {
168 		fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(),
169 			block, transaction.ID());
170 	} else {
171 		fBlock = (uint8*)block_cache_get_writable_etc(fVolume->BlockCache(),
172 			block, base, length, transaction.ID());
173 	}
174 
175 	return fBlock;
176 }
177 
178 
179 inline uint8*
180 CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty)
181 {
182 	return SetToWritable(transaction, block, block, 1, empty);
183 }
184 
185 
186 inline uint8*
187 CachedBlock::SetToWritable(Transaction& transaction, block_run run, bool empty)
188 {
189 	return SetToWritable(transaction, fVolume->ToBlock(run), empty);
190 }
191 
192 
193 inline status_t
194 CachedBlock::MakeWritable(Transaction& transaction)
195 {
196 	if (fBlock == NULL)
197 		return B_NO_INIT;
198 
199 	return block_cache_make_writable(fVolume->BlockCache(), fBlockNumber,
200 		transaction.ID());
201 }
202 
203 
204 #endif	// CACHED_BLOCK_H
205