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 19class PostCommitNotification; 20class Volume; 21 22 23enum { 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 32class Transaction { 33public: 34 explicit Transaction(Volume* volume); 35 ~Transaction(); 36 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 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 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 68private: 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 89 size_t HashKey(uint64 key) const 90 { 91 return (size_t)key; 92 } 93 94 size_t Hash(const BlockInfo* value) const 95 { 96 return HashKey(value->indexAndCheckSum.blockIndex); 97 } 98 99 bool Compare(uint64 key, const BlockInfo* value) const 100 { 101 return value->indexAndCheckSum.blockIndex == key; 102 } 103 104 BlockInfo*& GetLink(BlockInfo* value) const 105 { 106 return value->hashNext; 107 } 108 }; 109 110 typedef BOpenHashTable<BlockInfoHashDefinition> BlockInfoTable; 111 112private: 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 121private: 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 132status_t 133Transaction::Commit(const PostCommitNotification& notification) 134{ 135 return Commit(¬ification); 136} 137 138 139// #pragma mark - 140 141 142class PostCommitNotification { 143public: 144 virtual ~PostCommitNotification(); 145 146 virtual void NotifyPostCommit() const = 0; 147}; 148 149 150#endif // TRANSACTION_H 151