1 /*
2 * Copyright 2001-2010, Haiku Inc. All rights reserved.
3 * This file may be used under the terms of the MIT License.
4 *
5 * Authors:
6 * Janito V. Ferreira Filho
7 */
8
9
10 #include "HashRevokeManager.h"
11
12 #include <new>
13
14
15 //#define TRACE_EXT2
16 #ifdef TRACE_EXT2
17 # define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
18 #else
19 # define TRACE(x...) ;
20 #endif
21
22
HashRevokeManager(bool has64bits)23 HashRevokeManager::HashRevokeManager(bool has64bits)
24 : RevokeManager(has64bits),
25 fHash(NULL),
26 kInitialHashSize(128)
27 // TODO: Benchmark and find an optimal value
28 {
29 }
30
31
~HashRevokeManager()32 HashRevokeManager::~HashRevokeManager()
33 {
34 if (fHash != NULL) {
35 if (fRevokeCount != 0) {
36 RevokeElement *element = fHash->Clear(true);
37
38 while (element != NULL) {
39 RevokeElement* next = element->next;
40 delete element;
41 element = next;
42 }
43 }
44
45 delete fHash;
46 }
47 }
48
49
50 status_t
Init()51 HashRevokeManager::Init()
52 {
53 fHash = new(std::nothrow) RevokeTable();
54
55 if (fHash == NULL || fHash->Init(kInitialHashSize) != B_OK)
56 return B_NO_MEMORY;
57
58 return B_OK;
59 }
60
61
62 status_t
Insert(uint32 block,uint32 commitID)63 HashRevokeManager::Insert(uint32 block, uint32 commitID)
64 {
65 RevokeElement* element = fHash->Lookup(block);
66
67 if (element != NULL) {
68 TRACE("HashRevokeManager::Insert(): Already has an element\n");
69 if (element->commitID < commitID) {
70 TRACE("HashRevokeManager::Insert(): Deleting previous element\n");
71 bool retValue = fHash->Remove(element);
72
73 if (!retValue)
74 return B_ERROR;
75
76 delete element;
77 } else {
78 return B_OK;
79 // We already have a newer version of the block
80 }
81 }
82
83 return _ForceInsert(block, commitID);
84 }
85
86
87 status_t
Remove(uint32 block)88 HashRevokeManager::Remove(uint32 block)
89 {
90 RevokeElement* element = fHash->Lookup(block);
91
92 if (element == NULL)
93 return B_ERROR; // TODO: Perhaps we should just ignore?
94
95 fHash->Remove(element);
96 // Can't fail as we just did a sucessful Lookup()
97
98 delete element;
99 return B_OK;
100 }
101
102
103 bool
Lookup(uint32 block,uint32 commitID)104 HashRevokeManager::Lookup(uint32 block, uint32 commitID)
105 {
106 RevokeElement* element = fHash->Lookup(block);
107
108 if (element == NULL)
109 return false;
110
111 return element->commitID >= commitID;
112 }
113
114
115 /*static*/ int
Compare(void * _revoked,const void * _block)116 HashRevokeManager::Compare(void* _revoked, const void *_block)
117 {
118 RevokeElement* revoked = (RevokeElement*)_revoked;
119 uint32 block = *(uint32*)_block;
120
121 if (revoked->block == block)
122 return 0;
123
124 return (revoked->block > block) ? 1 : -1;
125 }
126
127
128 /*static*/ uint32
Hash(void * _revoked,const void * _block,uint32 range)129 HashRevokeManager::Hash(void* _revoked, const void* _block, uint32 range)
130 {
131 TRACE("HashRevokeManager::Hash(): revoked: %p, block: %p, range: %"
132 B_PRIu32 "\n", _revoked, _block, range);
133 RevokeElement* revoked = (RevokeElement*)_revoked;
134
135 if (revoked != NULL)
136 return revoked->block % range;
137
138 uint32 block = *(uint32*)_block;
139 return block % range;
140 }
141
142
143 status_t
_ForceInsert(uint32 block,uint32 commitID)144 HashRevokeManager::_ForceInsert(uint32 block, uint32 commitID)
145 {
146 RevokeElement* element = new(std::nothrow) RevokeElement;
147
148 if (element == NULL)
149 return B_NO_MEMORY;
150
151 element->block = block;
152 element->commitID = commitID;
153
154 status_t retValue = fHash->Insert(element);
155
156 if (retValue == B_OK) {
157 fRevokeCount++;
158 TRACE("HashRevokeManager::_ForceInsert(): revoke count: %" B_PRIu32
159 "\n", fRevokeCount);
160 }
161
162 return retValue;
163 }
164
165