xref: /haiku/src/add-ons/kernel/file_systems/bfs/Journal.h (revision f75a7bf508f3156d63a14f8fd77c5e0ca4d08c42)
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 			void			Unlock(Transaction* owner, bool success);
31 
32 			status_t		ReplayLog();
33 
34 			Transaction*	CurrentTransaction() const { return fOwner; }
35 
36 			status_t		FlushLogAndBlocks();
37 			Volume*			GetVolume() const { return fVolume; }
38 			int32			TransactionID() const { return fTransactionID; }
39 
40 	inline	uint32			FreeLogBlocks() const;
41 
42 #ifdef BFS_DEBUGGER_COMMANDS
43 			void			Dump();
44 #endif
45 
46 private:
47 			bool			_HasSubTransaction() { return fHasSubtransaction; }
48 			status_t		_FlushLog(bool canWait, bool flushBlocks);
49 			uint32			_TransactionSize() const;
50 			status_t		_WriteTransactionToLog();
51 			status_t		_CheckRunArray(const run_array* array);
52 			status_t		_ReplayRunArray(int32* start);
53 			status_t		_TransactionDone(bool success);
54 
55 	static	void			_TransactionWritten(int32 transactionID,
56 								int32 event, void* _logEntry);
57 	static	void			_TransactionIdle(int32 transactionID, int32 event,
58 								void* _journal);
59 
60 			Volume*			fVolume;
61 			recursive_lock	fLock;
62 			Transaction*	fOwner;
63 			uint32			fLogSize;
64 			uint32			fMaxTransactionSize;
65 			uint32			fUsed;
66 			int32			fUnwrittenTransactions;
67 			mutex			fEntriesLock;
68 			LogEntryList	fEntries;
69 			bigtime_t		fTimestamp;
70 			int32			fTransactionID;
71 			bool			fHasSubtransaction;
72 };
73 
74 
75 inline uint32
76 Journal::FreeLogBlocks() const
77 {
78 	return fVolume->LogStart() <= fVolume->LogEnd()
79 		? fLogSize - fVolume->LogEnd() + fVolume->LogStart()
80 		: fVolume->LogStart() - fVolume->LogEnd();
81 }
82 
83 
84 // For now, that's only a dumb class that does more or less nothing
85 // else than writing the blocks directly to the real location.
86 // It doesn't yet use logging.
87 
88 class Transaction {
89 public:
90 	Transaction(Volume* volume, off_t refBlock)
91 		:
92 		fJournal(NULL)
93 	{
94 		Start(volume, refBlock);
95 	}
96 
97 	Transaction(Volume* volume, block_run refRun)
98 		:
99 		fJournal(NULL)
100 	{
101 		Start(volume, volume->ToBlock(refRun));
102 	}
103 
104 	Transaction()
105 		:
106 		fJournal(NULL)
107 	{
108 	}
109 
110 	~Transaction()
111 	{
112 		if (fJournal != NULL) {
113 			fJournal->Unlock(this, false);
114 			_UnlockInodes();
115 		}
116 	}
117 
118 	status_t Start(Volume* volume, off_t refBlock);
119 	bool IsStarted() const { return fJournal != NULL; }
120 
121 	void Done()
122 	{
123 		if (fJournal != NULL) {
124 			_UnlockInodes();
125 			fJournal->Unlock(this, true);
126 		}
127 		fJournal = NULL;
128 	}
129 
130 	bool HasParent()
131 	{
132 		if (fJournal != NULL)
133 			return fJournal->CurrentTransaction() == this;
134 
135 		return false;
136 	}
137 
138 	status_t 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 	void AddInode(Inode* inode);
168 
169 private:
170 	Transaction(const Transaction& other);
171 	Transaction& operator=(const Transaction& other);
172 		// no implementation
173 
174 	void _UnlockInodes();
175 
176 	Journal*	fJournal;
177 	InodeList	fLockedInodes;
178 };
179 
180 #ifdef BFS_DEBUGGER_COMMANDS
181 int dump_journal(int argc, char** argv);
182 #endif
183 
184 #endif	// JOURNAL_H
185