1 /* 2 * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. 3 * This file may be used under the terms of the MIT License. 4 */ 5 #ifndef CACHED_BLOCK_H 6 #define CACHED_BLOCK_H 7 8 9 //! Interface for the block cache 10 11 12 #include "system_dependencies.h" 13 14 #include "Volume.h" 15 #include "Journal.h" 16 #include "Debug.h" 17 18 19 // The CachedBlock class is completely implemented as inlines. 20 // It should be used when cache single blocks to make sure they 21 // will be properly released after use (and it's also very 22 // convenient to use them). 23 24 class CachedBlock { 25 public: 26 CachedBlock(Volume* volume); 27 CachedBlock(Volume* volume, off_t block); 28 CachedBlock(Volume* volume, block_run run); 29 CachedBlock(CachedBlock* cached); 30 ~CachedBlock(); 31 32 inline void Keep(); 33 inline void Unset(); 34 35 inline const uint8* SetTo(off_t block, off_t base, size_t length); 36 inline const uint8* SetTo(off_t block); 37 inline const uint8* SetTo(block_run run); 38 inline uint8* SetToWritable(Transaction& transaction, 39 off_t block, off_t base, size_t length, 40 bool empty = false); 41 inline uint8* SetToWritable(Transaction& transaction, 42 off_t block, bool empty = false); 43 inline uint8* SetToWritable(Transaction& transaction, 44 block_run run, bool empty = false); 45 inline status_t MakeWritable(Transaction& transaction); 46 47 const uint8* Block() const { return fBlock; } 48 off_t BlockNumber() const { return fBlockNumber; } 49 uint32 BlockSize() const 50 { return fVolume->BlockSize(); } 51 uint32 BlockShift() const 52 { return fVolume->BlockShift(); } 53 54 private: 55 CachedBlock(const CachedBlock& other); 56 CachedBlock& operator=(const CachedBlock& other); 57 // no implementation 58 59 protected: 60 Volume* fVolume; 61 off_t fBlockNumber; 62 uint8* fBlock; 63 }; 64 65 66 // inlines 67 68 69 inline 70 CachedBlock::CachedBlock(Volume* volume) 71 : 72 fVolume(volume), 73 fBlockNumber(0), 74 fBlock(NULL) 75 { 76 } 77 78 79 inline 80 CachedBlock::CachedBlock(Volume* volume, off_t block) 81 : 82 fVolume(volume), 83 fBlockNumber(0), 84 fBlock(NULL) 85 { 86 SetTo(block); 87 } 88 89 90 inline 91 CachedBlock::CachedBlock(Volume* volume, block_run run) 92 : 93 fVolume(volume), 94 fBlockNumber(0), 95 fBlock(NULL) 96 { 97 SetTo(volume->ToBlock(run)); 98 } 99 100 101 inline 102 CachedBlock::CachedBlock(CachedBlock* cached) 103 : 104 fVolume(cached->fVolume), 105 fBlockNumber(cached->BlockNumber()), 106 fBlock(cached->fBlock) 107 { 108 cached->Keep(); 109 } 110 111 112 inline 113 CachedBlock::~CachedBlock() 114 { 115 Unset(); 116 } 117 118 119 inline void 120 CachedBlock::Keep() 121 { 122 fBlock = NULL; 123 } 124 125 126 inline void 127 CachedBlock::Unset() 128 { 129 if (fBlock != NULL) { 130 block_cache_put(fVolume->BlockCache(), fBlockNumber); 131 fBlock = NULL; 132 } 133 } 134 135 136 inline const uint8* 137 CachedBlock::SetTo(off_t block, off_t base, size_t length) 138 { 139 Unset(); 140 fBlockNumber = block; 141 return fBlock = (uint8*)block_cache_get_etc(fVolume->BlockCache(), 142 block, base, length); 143 } 144 145 146 inline const uint8* 147 CachedBlock::SetTo(off_t block) 148 { 149 return SetTo(block, block, 1); 150 } 151 152 153 inline const uint8* 154 CachedBlock::SetTo(block_run run) 155 { 156 return SetTo(fVolume->ToBlock(run)); 157 } 158 159 160 inline uint8* 161 CachedBlock::SetToWritable(Transaction& transaction, off_t block, off_t base, 162 size_t length, bool empty) 163 { 164 Unset(); 165 fBlockNumber = block; 166 167 if (empty) { 168 fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(), 169 block, transaction.ID()); 170 } else { 171 fBlock = (uint8*)block_cache_get_writable_etc(fVolume->BlockCache(), 172 block, base, length, transaction.ID()); 173 } 174 175 return fBlock; 176 } 177 178 179 inline uint8* 180 CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty) 181 { 182 return SetToWritable(transaction, block, block, 1, empty); 183 } 184 185 186 inline uint8* 187 CachedBlock::SetToWritable(Transaction& transaction, block_run run, bool empty) 188 { 189 return SetToWritable(transaction, fVolume->ToBlock(run), empty); 190 } 191 192 193 inline status_t 194 CachedBlock::MakeWritable(Transaction& transaction) 195 { 196 if (fBlock == NULL) 197 return B_NO_INIT; 198 199 return block_cache_make_writable(fVolume->BlockCache(), fBlockNumber, 200 transaction.ID()); 201 } 202 203 204 #endif // CACHED_BLOCK_H 205