xref: /haiku/src/add-ons/kernel/file_systems/bfs/CachedBlock.h (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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 
24 class CachedBlock {
25 public:
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);
34 	inline status_t				SetTo(block_run run);
35 	inline status_t				SetToWritable(Transaction& transaction,
36 									off_t block, bool empty = false);
37 	inline status_t				SetToWritable(Transaction& transaction,
38 									block_run run, bool empty = false);
39 	inline status_t				MakeWritable(Transaction& transaction);
40 
41 			const uint8*		Block() const { return fBlock; }
42 			uint8*				WritableBlock() const { return fBlock; }
43 			off_t				BlockNumber() const { return fBlockNumber; }
44 			uint32				BlockSize() const
45 									{ return fVolume->BlockSize(); }
46 			uint32				BlockShift() const
47 									{ return fVolume->BlockShift(); }
48 
49 private:
50 	CachedBlock(const CachedBlock& other);
51 	CachedBlock& operator=(const CachedBlock& other);
52 		// no implementation
53 
54 protected:
55 			Volume*				fVolume;
56 			off_t				fBlockNumber;
57 			uint8*				fBlock;
58 };
59 
60 
61 // inlines
62 
63 
64 inline
65 CachedBlock::CachedBlock(Volume* volume)
66 	:
67 	fVolume(volume),
68 	fBlockNumber(0),
69 	fBlock(NULL)
70 {
71 }
72 
73 
74 inline
75 CachedBlock::CachedBlock(CachedBlock* cached)
76 	:
77 	fVolume(cached->fVolume),
78 	fBlockNumber(cached->BlockNumber()),
79 	fBlock(cached->fBlock)
80 {
81 	cached->Keep();
82 }
83 
84 
85 inline
86 CachedBlock::~CachedBlock()
87 {
88 	Unset();
89 }
90 
91 
92 inline void
93 CachedBlock::Keep()
94 {
95 	fBlock = NULL;
96 }
97 
98 
99 inline void
100 CachedBlock::Unset()
101 {
102 	if (fBlock != NULL) {
103 		block_cache_put(fVolume->BlockCache(), fBlockNumber);
104 		fBlock = NULL;
105 	}
106 }
107 
108 
109 inline status_t
110 CachedBlock::SetTo(off_t block)
111 {
112 	Unset();
113 	fBlockNumber = block;
114 	return block_cache_get_etc(fVolume->BlockCache(), block, (const void**)&fBlock);
115 }
116 
117 
118 inline status_t
119 CachedBlock::SetTo(block_run run)
120 {
121 	return SetTo(fVolume->ToBlock(run));
122 }
123 
124 
125 inline status_t
126 CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty)
127 {
128 	Unset();
129 	fBlockNumber = block;
130 
131 	if (empty) {
132 		fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(),
133 			block, transaction.ID());
134 		return fBlock != NULL ? B_OK : B_NO_MEMORY;
135 	}
136 
137 	return block_cache_get_writable_etc(fVolume->BlockCache(),
138 		block, transaction.ID(), (void**)&fBlock);
139 }
140 
141 
142 inline status_t
143 CachedBlock::SetToWritable(Transaction& transaction, block_run run, bool empty)
144 {
145 	return SetToWritable(transaction, fVolume->ToBlock(run), empty);
146 }
147 
148 
149 inline status_t
150 CachedBlock::MakeWritable(Transaction& transaction)
151 {
152 	if (fBlock == NULL)
153 		return B_NO_INIT;
154 
155 	return block_cache_make_writable(fVolume->BlockCache(), fBlockNumber,
156 		transaction.ID());
157 }
158 
159 
160 #endif	// CACHED_BLOCK_H
161