xref: /haiku/src/tests/system/kernel/file_corruption/fs/Transaction.h (revision 9bc87c767b30fc60aef22c7d3f11edd74d4f89ac)
1 /*
2  * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef TRANSACTION_H
6 #define TRANSACTION_H
7 
8 
9 #include <fs_cache.h>
10 
11 #include <util/DoublyLinkedList.h>
12 #include <util/OpenHashTable.h>
13 
14 #include "CheckSum.h"
15 #include "driver/checksum_device.h"
16 #include "Node.h"
17 
18 
19 class PostCommitNotification;
20 class Volume;
21 
22 
23 enum {
24 	TRANSACTION_DELETE_NODE				= 0x01,
25 	TRANSACTION_NODE_ALREADY_LOCKED		= 0x02,
26 	TRANSACTION_KEEP_NODE_LOCKED		= 0x04,
27 	TRANSACTION_REMOVE_NODE_ON_ERROR	= 0x08,
28 	TRANSACTION_UNREMOVE_NODE_ON_ERROR	= 0x10
29 };
30 
31 
32 class Transaction {
33 public:
34 	explicit					Transaction(Volume* volume);
35 								~Transaction();
36 
ID()37 			int32				ID() const	{ return fID; }
38 
39 			status_t			Start();
40 			status_t			StartAndAddNode(Node* node, uint32 flags = 0);
41 			status_t			Commit(
42 									const PostCommitNotification* notification1
43 										= NULL,
44 									const PostCommitNotification* notification2
45 										= NULL,
46 									const PostCommitNotification* notification3
47 										= NULL);
48 	inline	status_t			Commit(
49 									const PostCommitNotification& notification);
50 			void				Abort();
51 
IsActive()52 	inline	bool				IsActive() const	{ return fID >= 0; }
53 
54 			status_t			AddNode(Node* node, uint32 flags = 0);
55 			status_t			AddNodes(Node* node1, Node* node2,
56 									Node* node3 = NULL);
57 			bool				RemoveNode(Node* node);
58 			void				UpdateNodeFlags(Node* node, uint32 flags);
59 
60 			void				KeepNode(Node* node);
61 
IsNodeLocked(Node * node)62 			bool				IsNodeLocked(Node* node) const
63 									{ return _GetNodeInfo(node) != NULL; }
64 
65 			status_t			RegisterBlock(uint64 blockIndex);
66 			void				PutBlock(uint64 blockIndex, const void* data);
67 
68 private:
69 			struct NodeInfo : DoublyLinkedListLinkImpl<NodeInfo> {
70 				Node*			node;
71 				checksumfs_node	oldNodeData;
72 				uint32			flags;
73 			};
74 
75 			typedef DoublyLinkedList<NodeInfo> NodeInfoList;
76 
77 			struct BlockInfo {
78 				checksum_device_ioctl_check_sum	indexAndCheckSum;
79 				BlockInfo*						hashNext;
80 				const void*						data;
81 				int32							refCount;
82 				bool							dirty;
83 			};
84 
85 			struct BlockInfoHashDefinition {
86 				typedef uint64		KeyType;
87 				typedef	BlockInfo	ValueType;
88 
HashKeyBlockInfoHashDefinition89 				size_t HashKey(uint64 key) const
90 				{
91 					return (size_t)key;
92 				}
93 
HashBlockInfoHashDefinition94 				size_t Hash(const BlockInfo* value) const
95 				{
96 					return HashKey(value->indexAndCheckSum.blockIndex);
97 				}
98 
CompareBlockInfoHashDefinition99 				bool Compare(uint64 key, const BlockInfo* value) const
100 				{
101 					return value->indexAndCheckSum.blockIndex == key;
102 				}
103 
GetLinkBlockInfoHashDefinition104 				BlockInfo*& GetLink(BlockInfo* value) const
105 				{
106 					return value->hashNext;
107 				}
108 			};
109 
110 			typedef BOpenHashTable<BlockInfoHashDefinition> BlockInfoTable;
111 
112 private:
113 			NodeInfo*			_GetNodeInfo(Node* node) const;
114 			void				_DeleteNodeInfosAndUnlock(bool failed);
115 			void				_DeleteNodeInfoAndUnlock(NodeInfo* info,
116 									bool failed);
117 
118 			status_t			_UpdateBlockCheckSums();
119 			status_t			_RevertBlockCheckSums();
120 
121 private:
122 			Volume*				fVolume;
123 			SHA256*				fSHA256;
124 			checksum_device_ioctl_check_sum* fCheckSum;
125 			int32				fID;
126 			NodeInfoList		fNodeInfos;
127 			BlockInfoTable		fBlockInfos;
128 			uint64				fOldFreeBlockCount;
129 };
130 
131 
132 status_t
Commit(const PostCommitNotification & notification)133 Transaction::Commit(const PostCommitNotification& notification)
134 {
135 	return Commit(&notification);
136 }
137 
138 
139 // #pragma mark -
140 
141 
142 class PostCommitNotification {
143 public:
144 	virtual						~PostCommitNotification();
145 
146 	virtual	void				NotifyPostCommit() const = 0;
147 };
148 
149 
150 #endif	// TRANSACTION_H
151