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 extern "C" { 19 #ifndef _IMPEXP_KERNEL 20 # define _IMPEXP_KERNEL 21 #endif 22 23 #include <fsproto.h> 24 #include "lock.h" 25 #include "cache.h" 26 } 27 28 #include "kernel_cpp.h" 29 #include "UdfDebug.h" 30 31 #include "UdfStructures.h" 32 #include "Volume.h" 33 34 namespace Udf { 35 36 class CachedBlock { 37 public: 38 CachedBlock(Volume *volume); 39 CachedBlock(Volume *volume, off_t block, bool empty = false); 40 CachedBlock(CachedBlock *cached); 41 ~CachedBlock(); 42 43 inline void Keep(); 44 inline void Unset(); 45 inline uint8 *SetTo(off_t block, bool empty = false); 46 inline uint8 *SetTo(long_address address, bool empty = false); 47 template <class Accessor, class Descriptor> 48 inline uint8* SetTo(Accessor &accessor, Descriptor &descriptor, 49 bool empty = false); 50 51 uint8 *Block() const { return fBlock; } 52 off_t BlockNumber() const { return fBlockNumber; } 53 uint32 BlockSize() const { return fVolume->BlockSize(); } 54 uint32 BlockShift() const { return fVolume->BlockShift(); } 55 56 private: 57 CachedBlock(const CachedBlock &); // unimplemented 58 CachedBlock &operator=(const CachedBlock &); // unimplemented 59 60 protected: 61 Volume *fVolume; 62 off_t fBlockNumber; 63 uint8 *fBlock; 64 }; 65 66 inline 67 CachedBlock::CachedBlock(Volume *volume) 68 : 69 fVolume(volume), 70 fBlock(NULL) 71 { 72 } 73 74 inline 75 CachedBlock::CachedBlock(Volume *volume, off_t block, bool empty = false) 76 : 77 fVolume(volume), 78 fBlock(NULL) 79 { 80 SetTo(block, empty); 81 } 82 83 inline 84 CachedBlock::CachedBlock(CachedBlock *cached) 85 : fVolume(cached->fVolume) 86 , fBlockNumber(cached->BlockNumber()) 87 , fBlock(cached->fBlock) 88 { 89 cached->Keep(); 90 } 91 92 inline 93 CachedBlock::~CachedBlock() 94 { 95 Unset(); 96 } 97 98 inline void 99 CachedBlock::Keep() 100 { 101 fBlock = NULL; 102 } 103 104 inline void 105 CachedBlock::Unset() 106 { 107 DEBUG_INIT("CachedBlock"); 108 if (fBlock) { 109 PRINT(("releasing block #%Ld\n", BlockNumber())); 110 release_block(fVolume->Device(), fBlockNumber); 111 } else { 112 PRINT(("no block to release\n")); 113 } 114 } 115 116 inline uint8 * 117 CachedBlock::SetTo(off_t block, bool empty = false) 118 { 119 DEBUG_INIT_ETC("CachedBlock", ("block: %Ld, empty: %s", 120 block, (empty ? "true" : "false"))); 121 Unset(); 122 fBlockNumber = block; 123 PRINT(("getting block #%Ld\n", block)); 124 return fBlock = empty ? (uint8 *)get_empty_block(fVolume->Device(), block, BlockSize()) 125 : (uint8 *)get_block(fVolume->Device(), block, BlockSize()); 126 } 127 128 inline uint8 * 129 CachedBlock::SetTo(long_address address, bool empty = false) 130 { 131 off_t block; 132 if (fVolume->MapBlock(address, &block) == B_OK) 133 return SetTo(block, empty); 134 else 135 return NULL; 136 } 137 138 template <class Accessor, class Descriptor> 139 inline uint8* 140 CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor, bool empty = false) 141 { 142 // Make a long_address out of the descriptor and call it a day 143 long_address address; 144 address.set_to(accessor.GetBlock(descriptor), 145 accessor.GetPartition(descriptor)); 146 return SetTo(address, empty); 147 } 148 149 }; // namespace Udf 150 151 #endif // _UDF_CACHED_BLOCK_H 152 153