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
19extern "C" {
20#endif
21	#include "fsproto.h"
22#ifdef COMPILE_FOR_R5
23}
24#endif
25
26extern "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
41namespace Udf {
42
43class 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
73inline
74CachedBlock::CachedBlock(Volume *volume)
75	:
76	fVolume(volume),
77	fBlock(NULL)
78{
79}
80
81inline
82CachedBlock::CachedBlock(Volume *volume, off_t block, bool empty = false)
83	:
84	fVolume(volume),
85	fBlock(NULL)
86{
87	SetTo(block, empty);
88}
89
90inline
91CachedBlock::CachedBlock(CachedBlock *cached)
92	: fVolume(cached->fVolume)
93	, fBlockNumber(cached->BlockNumber())
94	, fBlock(cached->fBlock)
95{
96	cached->Keep();
97}
98
99inline
100CachedBlock::~CachedBlock()
101{
102	Unset();
103}
104
105inline void
106CachedBlock::Keep()
107{
108	fBlock = NULL;
109}
110
111inline void
112CachedBlock::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
123inline uint8 *
124CachedBlock::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
135inline uint8 *
136CachedBlock::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
145template <class Accessor, class Descriptor>
146inline uint8*
147CachedBlock::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