xref: /haiku/src/add-ons/kernel/file_systems/udf/CachedBlock.h (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
1 /*
2  * 	Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com
3  * 	Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net
4  * 	Copyright 2002-2020, Axel Dörfler, axeld@pinc-software.de
5  * 	Distributed under the terms of the MIT License.
6  */
7 #ifndef _UDF_CACHED_BLOCK_H
8 #define _UDF_CACHED_BLOCK_H
9 
10 /*! \file CachedBlock.h
11 
12 	Based on the CachedBlock class from BFS, written by
13 	Axel Dörfler, axeld@pinc-software.de
14 */
15 
16 #include <fs_cache.h>
17 #include <util/kernel_cpp.h>
18 
19 #include "UdfDebug.h"
20 #include "UdfStructures.h"
21 #include "Volume.h"
22 
23 
24 class CachedBlock {
25 public:
26 								CachedBlock(Volume *volume);
27 								CachedBlock(CachedBlock *cached);
28 								~CachedBlock();
29 
30 	uint8						*Block() const { return fBlock; }
31 	off_t						BlockNumber() const { return fBlockNumber; }
32 	uint32						BlockSize() const { return fVolume->BlockSize(); }
33 	uint32						BlockShift() const { return fVolume->BlockShift(); }
34 
35 	inline void					Keep();
36 	inline void					Unset();
37 
38 	inline status_t				SetTo(off_t block);
39 	inline status_t				SetTo(long_address address);
40 	template <class Accessor, class Descriptor>
41 	inline status_t				SetTo(Accessor &accessor,
42 									Descriptor &descriptor);
43 
44 protected:
45 	uint8						*fBlock;
46 	off_t						fBlockNumber;
47 	Volume						*fVolume;
48 };
49 
50 
51 inline
52 CachedBlock::CachedBlock(Volume *volume)
53 	:
54 	fBlock(NULL),
55 	fBlockNumber(0),
56 	fVolume(volume)
57 {
58 }
59 
60 
61 inline
62 CachedBlock::CachedBlock(CachedBlock *cached)
63 	:
64 	fBlock(cached->fBlock),
65 	fBlockNumber(cached->BlockNumber()),
66 	fVolume(cached->fVolume)
67 {
68 	cached->Keep();
69 }
70 
71 
72 inline
73 CachedBlock::~CachedBlock()
74 {
75 	Unset();
76 }
77 
78 
79 inline void
80 CachedBlock::Keep()
81 {
82 	fBlock = NULL;
83 }
84 
85 
86 inline void
87 CachedBlock::Unset()
88 {
89 	if (fBlock != NULL) {
90 		block_cache_put(fVolume->BlockCache(), fBlockNumber);
91 		fBlock = NULL;
92 	}
93 }
94 
95 
96 inline status_t
97 CachedBlock::SetTo(off_t block)
98 {
99 	Unset();
100 	fBlockNumber = block;
101 	return block_cache_get_etc(fVolume->BlockCache(), block,
102 		(const void**)&fBlock);
103 }
104 
105 
106 inline status_t
107 CachedBlock::SetTo(long_address address)
108 {
109 	off_t block;
110 	if (fVolume->MapBlock(address, &block) == B_OK)
111 		return SetTo(block);
112 
113 	return B_BAD_VALUE;
114 }
115 
116 
117 template <class Accessor, class Descriptor>
118 inline status_t
119 CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor)
120 {
121 	// Make a long_address out of the descriptor and call it a day
122 	long_address address;
123 	address.set_to(accessor.GetBlock(descriptor),
124 		accessor.GetPartition(descriptor));
125     return SetTo(address);
126 }
127 
128 
129 #endif	// _UDF_CACHED_BLOCK_H
130