1 /* 2 * Copyright 2001-2008, 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 typedef SinglyLinkedList<Inode> InodeList; 20 21 22 class Journal { 23 public: 24 Journal(Volume* volume); 25 ~Journal(); 26 27 status_t InitCheck(); 28 29 status_t Lock(Transaction* owner, 30 bool separateSubTransactions); 31 void Unlock(Transaction* owner, bool success); 32 33 status_t ReplayLog(); 34 35 Transaction* CurrentTransaction() const { return fOwner; } 36 37 status_t FlushLogAndBlocks(); 38 Volume* GetVolume() const { return fVolume; } 39 int32 TransactionID() const { return fTransactionID; } 40 41 inline uint32 FreeLogBlocks() const; 42 43 #ifdef BFS_DEBUGGER_COMMANDS 44 void Dump(); 45 #endif 46 47 private: 48 bool _HasSubTransaction() { return fHasSubtransaction; } 49 status_t _FlushLog(bool canWait, bool flushBlocks); 50 uint32 _TransactionSize() const; 51 status_t _WriteTransactionToLog(); 52 status_t _CheckRunArray(const run_array* array); 53 status_t _ReplayRunArray(int32* start); 54 status_t _TransactionDone(bool success); 55 56 static void _TransactionWritten(int32 transactionID, 57 int32 event, void* _logEntry); 58 static void _TransactionIdle(int32 transactionID, int32 event, 59 void* _journal); 60 61 Volume* fVolume; 62 recursive_lock fLock; 63 Transaction* fOwner; 64 uint32 fLogSize; 65 uint32 fMaxTransactionSize; 66 uint32 fUsed; 67 int32 fUnwrittenTransactions; 68 mutex fEntriesLock; 69 LogEntryList fEntries; 70 bigtime_t fTimestamp; 71 int32 fTransactionID; 72 bool fHasSubtransaction; 73 bool fSeparateSubTransactions; 74 }; 75 76 77 inline uint32 78 Journal::FreeLogBlocks() const 79 { 80 return fVolume->LogStart() <= fVolume->LogEnd() 81 ? fLogSize - fVolume->LogEnd() + fVolume->LogStart() 82 : fVolume->LogStart() - fVolume->LogEnd(); 83 } 84 85 86 // For now, that's only a dumb class that does more or less nothing 87 // else than writing the blocks directly to the real location. 88 // It doesn't yet use logging. 89 90 class Transaction { 91 public: 92 Transaction(Volume* volume, off_t refBlock) 93 : 94 fJournal(NULL) 95 { 96 Start(volume, refBlock); 97 } 98 99 Transaction(Volume* volume, block_run refRun) 100 : 101 fJournal(NULL) 102 { 103 Start(volume, volume->ToBlock(refRun)); 104 } 105 106 Transaction() 107 : 108 fJournal(NULL) 109 { 110 } 111 112 ~Transaction() 113 { 114 if (fJournal != NULL) { 115 fJournal->Unlock(this, false); 116 _UnlockInodes(); 117 } 118 } 119 120 status_t Start(Volume* volume, off_t refBlock); 121 bool IsStarted() const { return fJournal != NULL; } 122 123 void Done() 124 { 125 if (fJournal != NULL) { 126 _UnlockInodes(); 127 fJournal->Unlock(this, true); 128 } 129 fJournal = NULL; 130 } 131 132 bool HasParent() 133 { 134 if (fJournal != NULL) 135 return fJournal->CurrentTransaction() == this; 136 137 return false; 138 } 139 140 status_t WriteBlocks(off_t blockNumber, const uint8* buffer, 141 size_t numBlocks = 1) 142 { 143 if (fJournal == NULL) 144 return B_NO_INIT; 145 146 void* cache = GetVolume()->BlockCache(); 147 size_t blockSize = GetVolume()->BlockSize(); 148 149 for (size_t i = 0; i < numBlocks; i++) { 150 void* block = block_cache_get_empty(cache, blockNumber + i, 151 ID()); 152 if (block == NULL) 153 return B_ERROR; 154 155 memcpy(block, buffer, blockSize); 156 buffer += blockSize; 157 158 block_cache_put(cache, blockNumber + i); 159 } 160 161 return B_OK; 162 } 163 164 Volume *GetVolume() 165 { return fJournal != NULL ? fJournal->GetVolume() : NULL; } 166 int32 ID() const 167 { return fJournal->TransactionID(); } 168 169 void AddInode(Inode* inode); 170 171 private: 172 Transaction(const Transaction& other); 173 Transaction& operator=(const Transaction& other); 174 // no implementation 175 176 void _UnlockInodes(); 177 178 Journal* fJournal; 179 InodeList fLockedInodes; 180 }; 181 182 #ifdef BFS_DEBUGGER_COMMANDS 183 int dump_journal(int argc, char** argv); 184 #endif 185 186 #endif // JOURNAL_H 187