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 fParent(NULL) 95 { 96 Start(volume, refBlock); 97 } 98 99 Transaction(Volume* volume, block_run refRun) 100 : 101 fJournal(NULL), 102 fParent(NULL) 103 { 104 Start(volume, volume->ToBlock(refRun)); 105 } 106 107 Transaction() 108 : 109 fJournal(NULL), 110 fParent(NULL) 111 { 112 } 113 114 ~Transaction() 115 { 116 if (fJournal != NULL) 117 fJournal->Unlock(this, false); 118 } 119 120 status_t Start(Volume* volume, off_t refBlock); 121 bool IsStarted() const { return fJournal != NULL; } 122 123 status_t Done() 124 { 125 status_t status = B_OK; 126 if (fJournal != NULL) { 127 status = fJournal->Unlock(this, true); 128 if (status == B_OK) 129 fJournal = NULL; 130 } 131 return status; 132 } 133 134 bool HasParent() const 135 { 136 return fParent != NULL; 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 void SetParent(Transaction* parent) 186 { fParent = parent; } 187 Transaction* Parent() const 188 { return fParent; } 189 190 private: 191 Transaction(const Transaction& other); 192 Transaction& operator=(const Transaction& other); 193 // no implementation 194 195 Journal* fJournal; 196 InodeList fLockedInodes; 197 Transaction* fParent; 198 }; 199 200 #ifdef BFS_DEBUGGER_COMMANDS 201 int dump_journal(int argc, char** argv); 202 #endif 203 204 #endif // JOURNAL_H 205