1 /* 2 * Copyright 2001-2009, Axel Dörfler, axeld@pinc-software.de. 3 * This file may be used under the terms of the MIT License. 4 */ 5 #ifndef JOURNAL_H 6 #define JOURNAL_H 7 8 9 #include "system_dependencies.h" 10 11 #include "Volume.h" 12 #include "Utility.h" 13 14 15 struct run_array; 16 class Inode; 17 class LogEntry; 18 typedef DoublyLinkedList<LogEntry> LogEntryList; 19 20 21 class Journal { 22 public: 23 Journal(Volume* volume); 24 ~Journal(); 25 26 status_t InitCheck(); 27 28 status_t Lock(Transaction* owner, 29 bool separateSubTransactions); 30 status_t Unlock(Transaction* owner, bool success); 31 32 status_t ReplayLog(); 33 34 Transaction* CurrentTransaction() const { return fOwner; } 35 size_t CurrentTransactionSize() const; 36 bool CurrentTransactionTooLarge() const; 37 38 status_t FlushLogAndBlocks(); 39 Volume* GetVolume() const { return fVolume; } 40 int32 TransactionID() const { return fTransactionID; } 41 42 inline uint32 FreeLogBlocks() const; 43 44 #ifdef BFS_DEBUGGER_COMMANDS 45 void Dump(); 46 #endif 47 48 private: 49 bool _HasSubTransaction() const 50 { return fHasSubtransaction; } 51 52 status_t _FlushLog(bool canWait, bool flushBlocks); 53 uint32 _TransactionSize() const; 54 status_t _WriteTransactionToLog(); 55 status_t _CheckRunArray(const run_array* array); 56 status_t _ReplayRunArray(int32* start); 57 status_t _TransactionDone(bool success); 58 59 static void _TransactionWritten(int32 transactionID, 60 int32 event, void* _logEntry); 61 static void _TransactionIdle(int32 transactionID, int32 event, 62 void* _journal); 63 64 Volume* fVolume; 65 recursive_lock fLock; 66 Transaction* fOwner; 67 uint32 fLogSize; 68 uint32 fMaxTransactionSize; 69 uint32 fUsed; 70 int32 fUnwrittenTransactions; 71 mutex fEntriesLock; 72 LogEntryList fEntries; 73 bigtime_t fTimestamp; 74 int32 fTransactionID; 75 bool fHasSubtransaction; 76 bool fSeparateSubTransactions; 77 }; 78 79 80 inline uint32 81 Journal::FreeLogBlocks() const 82 { 83 return fVolume->LogStart() <= fVolume->LogEnd() 84 ? fLogSize - fVolume->LogEnd() + fVolume->LogStart() 85 : fVolume->LogStart() - fVolume->LogEnd(); 86 } 87 88 89 class Transaction { 90 public: 91 Transaction(Volume* volume, off_t refBlock) 92 : 93 fJournal(NULL) 94 { 95 Start(volume, refBlock); 96 } 97 98 Transaction(Volume* volume, block_run refRun) 99 : 100 fJournal(NULL) 101 { 102 Start(volume, volume->ToBlock(refRun)); 103 } 104 105 Transaction() 106 : 107 fJournal(NULL) 108 { 109 } 110 111 ~Transaction() 112 { 113 if (fJournal != NULL) 114 fJournal->Unlock(this, false); 115 } 116 117 status_t Start(Volume* volume, off_t refBlock); 118 bool IsStarted() const { return fJournal != NULL; } 119 120 status_t Done() 121 { 122 status_t status = B_OK; 123 if (fJournal != NULL) { 124 status = fJournal->Unlock(this, true); 125 if (status == B_OK) 126 fJournal = NULL; 127 } 128 return status; 129 } 130 131 bool HasParent() const 132 { 133 if (fJournal != NULL) 134 return fJournal->CurrentTransaction() == this; 135 136 return false; 137 } 138 139 bool IsTooLarge() const 140 { 141 return fJournal->CurrentTransactionTooLarge(); 142 } 143 144 status_t WriteBlocks(off_t blockNumber, const uint8* buffer, 145 size_t numBlocks = 1) 146 { 147 if (fJournal == NULL) 148 return B_NO_INIT; 149 150 void* cache = GetVolume()->BlockCache(); 151 size_t blockSize = GetVolume()->BlockSize(); 152 153 for (size_t i = 0; i < numBlocks; i++) { 154 void* block = block_cache_get_empty(cache, blockNumber + i, 155 ID()); 156 if (block == NULL) 157 return B_ERROR; 158 159 memcpy(block, buffer, blockSize); 160 buffer += blockSize; 161 162 block_cache_put(cache, blockNumber + i); 163 } 164 165 return B_OK; 166 } 167 168 void Split() 169 { 170 cache_start_sub_transaction(fJournal->GetVolume()->BlockCache(), 171 fJournal->TransactionID()); 172 } 173 174 Volume* GetVolume() const 175 { return fJournal != NULL ? fJournal->GetVolume() : NULL; } 176 int32 ID() const 177 { return fJournal->TransactionID(); } 178 179 void AddInode(Inode* inode); 180 void RemoveInode(Inode* inode); 181 182 void UnlockInodes(bool success); 183 void MoveInodesTo(Transaction* transaction); 184 185 private: 186 Transaction(const Transaction& other); 187 Transaction& operator=(const Transaction& other); 188 // no implementation 189 190 Journal* fJournal; 191 InodeList fLockedInodes; 192 }; 193 194 #ifdef BFS_DEBUGGER_COMMANDS 195 int dump_journal(int argc, char** argv); 196 #endif 197 198 #endif // JOURNAL_H 199