btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / src / add-ons / kernel / file_systems / bfs / Journal.h
blob6e22ad0a815b177d29eda6ef1b2aa148f4e56906
1 /*
2 * Copyright 2001-2012, 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
9 #include "system_dependencies.h"
11 #include "Volume.h"
12 #include "Utility.h"
15 struct run_array;
16 class Inode;
17 class LogEntry;
18 typedef DoublyLinkedList<LogEntry> LogEntryList;
21 class Journal {
22 public:
23 Journal(Volume* volume);
24 ~Journal();
26 status_t InitCheck();
28 status_t Lock(Transaction* owner,
29 bool separateSubTransactions);
30 status_t Unlock(Transaction* owner, bool success);
32 status_t ReplayLog();
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
45 void Dump();
46 #endif
48 private:
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,
62 void* _journal);
63 static status_t _FlushLog(void* _journal);
65 private:
66 Volume* fVolume;
67 recursive_lock fLock;
68 Transaction* fOwner;
69 uint32 fLogSize;
70 uint32 fMaxTransactionSize;
71 uint32 fUsed;
72 int32 fUnwrittenTransactions;
73 mutex fEntriesLock;
74 LogEntryList fEntries;
75 bigtime_t fTimestamp;
76 int32 fTransactionID;
77 bool fHasSubtransaction;
78 bool fSeparateSubTransactions;
82 inline uint32
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> {
93 public:
94 TransactionListener();
95 virtual ~TransactionListener();
97 virtual void TransactionDone(bool success) = 0;
98 virtual void RemovedFromTransaction() = 0;
101 typedef DoublyLinkedList<TransactionListener> TransactionListeners;
104 class Transaction {
105 public:
106 Transaction(Volume* volume, off_t refBlock)
108 fJournal(NULL),
109 fParent(NULL)
111 Start(volume, refBlock);
114 Transaction(Volume* volume, block_run refRun)
116 fJournal(NULL),
117 fParent(NULL)
119 Start(volume, volume->ToBlock(refRun));
122 Transaction()
124 fJournal(NULL),
125 fParent(NULL)
129 ~Transaction()
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; }
138 status_t Done()
140 status_t status = B_OK;
141 if (fJournal != NULL) {
142 status = fJournal->Unlock(this, true);
143 if (status == B_OK)
144 fJournal = NULL;
146 return status;
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)
163 return B_NO_INIT;
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,
170 ID());
171 if (block == NULL)
172 return B_ERROR;
174 memcpy(block, buffer, blockSize);
175 buffer += blockSize;
177 block_cache_put(cache, blockNumber + i);
180 return B_OK;
183 Volume* GetVolume() const
184 { return fJournal != NULL ? fJournal->GetVolume() : NULL; }
185 int32 ID() const
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
197 { return fParent; }
199 private:
200 Transaction(const Transaction& other);
201 Transaction& operator=(const Transaction& other);
202 // no implementation
204 Journal* fJournal;
205 TransactionListeners fListeners;
206 Transaction* fParent;
210 #ifdef BFS_DEBUGGER_COMMANDS
211 int dump_journal(int argc, char** argv);
212 #endif
215 #endif // JOURNAL_H