2 * Copyright 2001-2012, Axel Dörfler, axeld@pinc-software.de.
3 * This file may be used under the terms of the MIT License.
9 #include "system_dependencies.h"
18 typedef DoublyLinkedList
<LogEntry
> LogEntryList
;
23 Journal(Volume
* volume
);
28 status_t
Lock(Transaction
* owner
,
29 bool separateSubTransactions
);
30 status_t
Unlock(Transaction
* owner
, bool success
);
34 Transaction
* CurrentTransaction() const { return fOwner
; }
35 size_t CurrentTransactionSize() const;
36 bool CurrentTransactionTooLarge() const;
38 status_t
FlushLogAndBlocks();
39 Volume
* GetVolume() const { return fVolume
; }
40 int32
TransactionID() const { return fTransactionID
; }
42 inline uint32
FreeLogBlocks() const;
44 #ifdef BFS_DEBUGGER_COMMANDS
49 bool _HasSubTransaction() const
50 { return fHasSubtransaction
; }
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
);
59 static void _TransactionWritten(int32 transactionID
,
60 int32 event
, void* _logEntry
);
61 static void _TransactionIdle(int32 transactionID
, int32 event
,
63 static status_t
_FlushLog(void* _journal
);
70 uint32 fMaxTransactionSize
;
72 int32 fUnwrittenTransactions
;
74 LogEntryList fEntries
;
77 bool fHasSubtransaction
;
78 bool fSeparateSubTransactions
;
83 Journal::FreeLogBlocks() const
85 return fVolume
->LogStart() <= fVolume
->LogEnd()
86 ? fLogSize
- fVolume
->LogEnd() + fVolume
->LogStart()
87 : fVolume
->LogStart() - fVolume
->LogEnd();
91 class TransactionListener
92 : public DoublyLinkedListLinkImpl
<TransactionListener
> {
94 TransactionListener();
95 virtual ~TransactionListener();
97 virtual void TransactionDone(bool success
) = 0;
98 virtual void RemovedFromTransaction() = 0;
101 typedef DoublyLinkedList
<TransactionListener
> TransactionListeners
;
106 Transaction(Volume
* volume
, off_t refBlock
)
111 Start(volume
, refBlock
);
114 Transaction(Volume
* volume
, block_run refRun
)
119 Start(volume
, volume
->ToBlock(refRun
));
131 if (fJournal
!= NULL
)
132 fJournal
->Unlock(this, false);
135 status_t
Start(Volume
* volume
, off_t refBlock
);
136 bool IsStarted() const { return fJournal
!= NULL
; }
140 status_t status
= B_OK
;
141 if (fJournal
!= NULL
) {
142 status
= fJournal
->Unlock(this, true);
149 bool HasParent() const
151 return fParent
!= NULL
;
154 bool IsTooLarge() const
156 return fJournal
->CurrentTransactionTooLarge();
159 status_t
WriteBlocks(off_t blockNumber
, const uint8
* buffer
,
160 size_t numBlocks
= 1)
162 if (fJournal
== NULL
)
165 void* cache
= GetVolume()->BlockCache();
166 size_t blockSize
= GetVolume()->BlockSize();
168 for (size_t i
= 0; i
< numBlocks
; i
++) {
169 void* block
= block_cache_get_empty(cache
, blockNumber
+ i
,
174 memcpy(block
, buffer
, blockSize
);
177 block_cache_put(cache
, blockNumber
+ i
);
183 Volume
* GetVolume() const
184 { return fJournal
!= NULL
? fJournal
->GetVolume() : NULL
; }
186 { return fJournal
->TransactionID(); }
188 void AddListener(TransactionListener
* listener
);
189 void RemoveListener(TransactionListener
* listener
);
191 void NotifyListeners(bool success
);
192 void MoveListenersTo(Transaction
* transaction
);
194 void SetParent(Transaction
* parent
)
195 { fParent
= parent
; }
196 Transaction
* Parent() const
200 Transaction(const Transaction
& other
);
201 Transaction
& operator=(const Transaction
& other
);
205 TransactionListeners fListeners
;
206 Transaction
* fParent
;
210 #ifdef BFS_DEBUGGER_COMMANDS
211 int dump_journal(int argc
, char** argv
);