1 /* 2 * Copyright 2001-2020, 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(CachedBlock* cached); 28 ~CachedBlock(); 29 30 inline void Keep(); 31 inline void Unset(); 32 33 inline status_t SetTo(off_t block); 34 inline status_t SetTo(block_run run); 35 inline status_t SetToWritable(Transaction& transaction, 36 off_t block, bool empty = false); 37 inline status_t SetToWritable(Transaction& transaction, 38 block_run run, bool empty = false); 39 inline status_t MakeWritable(Transaction& transaction); 40 41 const uint8* Block() const { return fBlock; } 42 uint8* WritableBlock() const { return fBlock; } 43 off_t BlockNumber() const { return fBlockNumber; } 44 uint32 BlockSize() const 45 { return fVolume->BlockSize(); } 46 uint32 BlockShift() const 47 { return fVolume->BlockShift(); } 48 49 private: 50 CachedBlock(const CachedBlock& other); 51 CachedBlock& operator=(const CachedBlock& other); 52 // no implementation 53 54 protected: 55 Volume* fVolume; 56 off_t fBlockNumber; 57 uint8* fBlock; 58 }; 59 60 61 // inlines 62 63 64 inline 65 CachedBlock::CachedBlock(Volume* volume) 66 : 67 fVolume(volume), 68 fBlockNumber(0), 69 fBlock(NULL) 70 { 71 } 72 73 74 inline 75 CachedBlock::CachedBlock(CachedBlock* cached) 76 : 77 fVolume(cached->fVolume), 78 fBlockNumber(cached->BlockNumber()), 79 fBlock(cached->fBlock) 80 { 81 cached->Keep(); 82 } 83 84 85 inline 86 CachedBlock::~CachedBlock() 87 { 88 Unset(); 89 } 90 91 92 inline void 93 CachedBlock::Keep() 94 { 95 fBlock = NULL; 96 } 97 98 99 inline void 100 CachedBlock::Unset() 101 { 102 if (fBlock != NULL) { 103 block_cache_put(fVolume->BlockCache(), fBlockNumber); 104 fBlock = NULL; 105 } 106 } 107 108 109 inline status_t 110 CachedBlock::SetTo(off_t block) 111 { 112 Unset(); 113 fBlockNumber = block; 114 return block_cache_get_etc(fVolume->BlockCache(), block, (const void**)&fBlock); 115 } 116 117 118 inline status_t 119 CachedBlock::SetTo(block_run run) 120 { 121 return SetTo(fVolume->ToBlock(run)); 122 } 123 124 125 inline status_t 126 CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty) 127 { 128 Unset(); 129 fBlockNumber = block; 130 131 if (empty) { 132 fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(), 133 block, transaction.ID()); 134 return fBlock != NULL ? B_OK : B_NO_MEMORY; 135 } 136 137 return block_cache_get_writable_etc(fVolume->BlockCache(), 138 block, transaction.ID(), (void**)&fBlock); 139 } 140 141 142 inline status_t 143 CachedBlock::SetToWritable(Transaction& transaction, block_run run, bool empty) 144 { 145 return SetToWritable(transaction, fVolume->ToBlock(run), empty); 146 } 147 148 149 inline status_t 150 CachedBlock::MakeWritable(Transaction& transaction) 151 { 152 if (fBlock == NULL) 153 return B_NO_INIT; 154 155 return block_cache_make_writable(fVolume->BlockCache(), fBlockNumber, 156 transaction.ID()); 157 } 158 159 160 #endif // CACHED_BLOCK_H 161