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(¬ification);
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