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 #ifndef _IMPEXP_KERNEL 12 # define _IMPEXP_KERNEL 13 #endif 14 15 #include "Volume.h" 16 #include "Chain.h" 17 #include "Utility.h" 18 19 20 struct run_array; 21 class LogEntry; 22 typedef DoublyLinkedList<LogEntry> LogEntryList; 23 24 25 // Locking policy in BFS: if you need both, the volume lock and the 26 // journal lock, you must lock the volume first - or else you will 27 // end up in a deadlock. 28 // That is, if you start a transaction, and will need to lock the 29 // volume while the transaction is in progress (for the unsafe 30 // get_vnode() call, for example), you must lock the volume before 31 // starting the transaction. 32 33 class Journal { 34 public: 35 Journal(Volume *); 36 ~Journal(); 37 38 status_t InitCheck(); 39 40 status_t Lock(Transaction *owner); 41 void Unlock(Transaction *owner, bool success); 42 43 status_t ReplayLog(); 44 45 Transaction *CurrentTransaction() const { return fOwner; } 46 47 status_t FlushLogAndBlocks(); 48 Volume *GetVolume() const { return fVolume; } 49 int32 TransactionID() const { return fTransactionID; } 50 51 inline uint32 FreeLogBlocks() const; 52 53 private: 54 bool _HasSubTransaction() { return fHasSubtransaction; } 55 uint32 _TransactionSize() const; 56 status_t _WriteTransactionToLog(); 57 status_t _CheckRunArray(const run_array *array); 58 status_t _ReplayRunArray(int32 *start); 59 status_t _TransactionDone(bool success); 60 static void _TransactionNotify(int32 transactionID, int32 event, 61 void *_logEntry); 62 63 Volume *fVolume; 64 RecursiveLock fLock; 65 Transaction *fOwner; 66 uint32 fLogSize, fMaxTransactionSize, fUsed; 67 int32 fUnwrittenTransactions; 68 SimpleLock fEntriesLock; 69 LogEntryList fEntries; 70 bigtime_t fTimestamp; 71 int32 fTransactionID; 72 bool fHasSubtransaction; 73 }; 74 75 76 inline uint32 77 Journal::FreeLogBlocks() const 78 { 79 return fVolume->LogStart() <= fVolume->LogEnd() 80 ? fLogSize - fVolume->LogEnd() + fVolume->LogStart() 81 : fVolume->LogStart() - fVolume->LogEnd(); 82 } 83 84 85 // For now, that's only a dumb class that does more or less nothing 86 // else than writing the blocks directly to the real location. 87 // It doesn't yet use logging. 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) 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 void 121 Done() 122 { 123 if (fJournal != NULL) 124 fJournal->Unlock(this, true); 125 fJournal = NULL; 126 } 127 128 bool 129 HasParent() 130 { 131 if (fJournal != NULL) 132 return fJournal->CurrentTransaction() == this; 133 134 return false; 135 } 136 137 status_t 138 WriteBlocks(off_t blockNumber, const uint8 *buffer, 139 size_t numBlocks = 1) 140 { 141 if (fJournal == NULL) 142 return B_NO_INIT; 143 144 void *cache = GetVolume()->BlockCache(); 145 size_t blockSize = GetVolume()->BlockSize(); 146 147 for (size_t i = 0; i < numBlocks; i++) { 148 void *block = block_cache_get_empty(cache, blockNumber + i, 149 ID()); 150 if (block == NULL) 151 return B_ERROR; 152 153 memcpy(block, buffer, blockSize); 154 buffer += blockSize; 155 156 block_cache_put(cache, blockNumber + i); 157 } 158 159 return B_OK; 160 } 161 162 Volume *GetVolume() 163 { return fJournal != NULL ? fJournal->GetVolume() : NULL; } 164 int32 ID() const 165 { return fJournal->TransactionID(); } 166 167 private: 168 Transaction(const Transaction &); 169 Transaction &operator=(const Transaction &); 170 // no implementation 171 172 Journal *fJournal; 173 }; 174 175 #endif /* JOURNAL_H */ 176