xref: /haiku/src/add-ons/kernel/file_systems/udf/CachedBlock.h (revision 8195a5a835117ab2da405e0d477153570b75d921)
1 //----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //
5 //  Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
6 //  Based on the CachedBlock class from OpenBFS,
7 //  Copyright (c) 2002 Axel Dörfler, axeld@pinc-software.de
8 //---------------------------------------------------------------------
9 #ifndef _UDF_CACHED_BLOCK_H
10 #define _UDF_CACHED_BLOCK_H
11 
12 /*! \file CachedBlock.h
13 
14 	Based on the CachedBlock class from OpenBFS, written by
15 	Axel Dörfler, axeld@pinc-software.de
16 */
17 
18 #ifdef COMPILE_FOR_R5
19 extern "C" {
20 #endif
21 	#include "fsproto.h"
22 #ifdef COMPILE_FOR_R5
23 }
24 #endif
25 
26 extern "C" {
27 	#ifndef _IMPEXP_KERNEL
28 	#	define _IMPEXP_KERNEL
29 	#endif
30 
31 	#include "lock.h"
32 	#include "cache.h"
33 }
34 
35 #include "kernel_cpp.h"
36 #include "UdfDebug.h"
37 
38 #include "UdfStructures.h"
39 #include "Volume.h"
40 
41 namespace Udf {
42 
43 class CachedBlock {
44 	public:
45 		CachedBlock(Volume *volume);
46 		CachedBlock(Volume *volume, off_t block, bool empty = false);
47 		CachedBlock(CachedBlock *cached);
48 		~CachedBlock();
49 
50 		inline void Keep();
51 		inline void Unset();
52 		inline uint8 *SetTo(off_t block, bool empty = false);
53 		inline uint8 *SetTo(long_address address, bool empty = false);
54 		template <class Accessor, class Descriptor>
55 			inline uint8* SetTo(Accessor &accessor, Descriptor &descriptor,
56 			bool empty = false);
57 
58 		uint8 *Block() const { return fBlock; }
59 		off_t BlockNumber() const { return fBlockNumber; }
60 		uint32 BlockSize() const { return fVolume->BlockSize(); }
61 		uint32 BlockShift() const { return fVolume->BlockShift(); }
62 
63 	private:
64 		CachedBlock(const CachedBlock &);				// unimplemented
65 		CachedBlock &operator=(const CachedBlock &);	// unimplemented
66 
67 	protected:
68 		Volume	*fVolume;
69 		off_t	fBlockNumber;
70 		uint8	*fBlock;
71 };
72 
73 inline
74 CachedBlock::CachedBlock(Volume *volume)
75 	:
76 	fVolume(volume),
77 	fBlock(NULL)
78 {
79 }
80 
81 inline
82 CachedBlock::CachedBlock(Volume *volume, off_t block, bool empty = false)
83 	:
84 	fVolume(volume),
85 	fBlock(NULL)
86 {
87 	SetTo(block, empty);
88 }
89 
90 inline
91 CachedBlock::CachedBlock(CachedBlock *cached)
92 	: fVolume(cached->fVolume)
93 	, fBlockNumber(cached->BlockNumber())
94 	, fBlock(cached->fBlock)
95 {
96 	cached->Keep();
97 }
98 
99 inline
100 CachedBlock::~CachedBlock()
101 {
102 	Unset();
103 }
104 
105 inline void
106 CachedBlock::Keep()
107 {
108 	fBlock = NULL;
109 }
110 
111 inline void
112 CachedBlock::Unset()
113 {
114 	DEBUG_INIT("CachedBlock");
115 	if (fBlock) {
116 		PRINT(("releasing block #%Ld\n", BlockNumber()));
117 		release_block(fVolume->Device(), fBlockNumber);
118 	} else {
119 		PRINT(("no block to release\n"));
120 	}
121 }
122 
123 inline uint8 *
124 CachedBlock::SetTo(off_t block, bool empty = false)
125 {
126 	DEBUG_INIT_ETC("CachedBlock", ("block: %Ld, empty: %s",
127 	               block, (empty ? "true" : "false")));
128 	Unset();
129 	fBlockNumber = block;
130 	PRINT(("getting block #%Ld\n", block));
131 	return fBlock = empty ? (uint8 *)get_empty_block(fVolume->Device(), block, BlockSize())
132 						  : (uint8 *)get_block(fVolume->Device(), block, BlockSize());
133 }
134 
135 inline uint8 *
136 CachedBlock::SetTo(long_address address, bool empty = false)
137 {
138 	off_t block;
139 	if (fVolume->MapBlock(address, &block) == B_OK)
140 		return SetTo(block, empty);
141 	else
142 		return NULL;
143 }
144 
145 template <class Accessor, class Descriptor>
146 inline uint8*
147 CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor, bool empty = false)
148 {
149 	// Make a long_address out of the descriptor and call it a day
150 	long_address address;
151 	address.set_to(accessor.GetBlock(descriptor),
152                              accessor.GetPartition(descriptor));
153     return SetTo(address, empty);
154 }
155 
156 };	// namespace Udf
157 
158 #endif	// _UDF_CACHED_BLOCK_H
159 
160