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