1 /* 2 * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com 3 * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net 4 * Copyright 2002, 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 OpenBFS, 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 class CachedBlock { 24 public: 25 CachedBlock(Volume *volume); 26 CachedBlock(Volume *volume, off_t block); 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 uint8 *SetTo(off_t block); 39 inline uint8 *SetTo(off_t block, off_t base, size_t length); 40 inline uint8 *SetTo(long_address address); 41 template <class Accessor, class Descriptor> 42 inline uint8* SetTo(Accessor &accessor, 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(Volume *volume, off_t block) 63 : 64 fBlock(NULL), 65 fBlockNumber(0), 66 fVolume(volume) 67 { 68 SetTo(block); 69 } 70 71 72 inline 73 CachedBlock::CachedBlock(CachedBlock *cached) 74 : 75 fBlock(cached->fBlock), 76 fBlockNumber(cached->BlockNumber()), 77 fVolume(cached->fVolume) 78 { 79 cached->Keep(); 80 } 81 82 83 inline 84 CachedBlock::~CachedBlock() 85 { 86 Unset(); 87 } 88 89 90 inline void 91 CachedBlock::Keep() 92 { 93 fBlock = NULL; 94 } 95 96 97 inline void 98 CachedBlock::Unset() 99 { 100 if (fBlock) { 101 block_cache_put(fVolume->BlockCache(), fBlockNumber); 102 fBlock = NULL; 103 } 104 } 105 106 107 inline uint8* 108 CachedBlock::SetTo(off_t block) 109 { 110 return SetTo(block, block, 1); 111 } 112 113 114 inline uint8* 115 CachedBlock::SetTo(off_t block, off_t base, size_t length) 116 { 117 Unset(); 118 fBlockNumber = block; 119 return fBlock = (uint8 *)block_cache_get_etc(fVolume->BlockCache(), 120 block, base, length); 121 } 122 123 124 inline uint8 * 125 CachedBlock::SetTo(long_address address) 126 { 127 off_t block; 128 if (fVolume->MapBlock(address, &block) == B_OK) 129 return SetTo(block, block, 1); 130 else 131 return NULL; 132 } 133 134 135 template <class Accessor, class Descriptor> 136 inline uint8* 137 CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor) 138 { 139 // Make a long_address out of the descriptor and call it a day 140 long_address address; 141 address.set_to(accessor.GetBlock(descriptor), 142 accessor.GetPartition(descriptor)); 143 return SetTo(address); 144 } 145 146 #endif // _UDF_CACHED_BLOCK_H 147