xref: /haiku/src/add-ons/kernel/file_systems/ext2/HashRevokeManager.cpp (revision 04a0e9c7b68cbe3a43d38e2bca8e860fd80936fb)
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 
23 HashRevokeManager::HashRevokeManager()
24 	:
25 	fHash(NULL),
26 	kInitialHashSize(128)
27 		// TODO: Benchmark and find an optimal value
28 {
29 }
30 
31 
32 HashRevokeManager::~HashRevokeManager()
33 {
34 	if (fHash != NULL) {
35 		if (fRevokeCount != 0) {
36 			RevokeElement *element =
37 				(RevokeElement*)hash_remove_first(fHash, NULL);
38 
39 			while (element != NULL) {
40 				delete element;
41 				element = (RevokeElement*)hash_remove_first(fHash, NULL);
42 			}
43 		}
44 
45 		hash_uninit(fHash);
46 	}
47 }
48 
49 
50 status_t
51 HashRevokeManager::Init()
52 {
53 	RevokeElement dummyElement;
54 
55 	fHash = hash_init(kInitialHashSize, offset_of_member(dummyElement, next),
56 		&HashRevokeManager::Compare,
57 		&HashRevokeManager::Hash);
58 
59 	if (fHash == NULL)
60 		return B_NO_MEMORY;
61 
62 	return B_OK;
63 }
64 
65 
66 status_t
67 HashRevokeManager::Insert(uint32 block, uint32 commitID)
68 {
69 	RevokeElement* element = (RevokeElement*)hash_lookup(fHash, &block);
70 
71 	if (element != NULL) {
72 		TRACE("HashRevokeManager::Insert(): Already has an element\n");
73 		if (element->commitID < commitID) {
74 			TRACE("HashRevokeManager::Insert(): Deleting previous element\n");
75 			status_t retValue = hash_remove(fHash, element);
76 
77 			if (retValue != B_OK)
78 				return retValue;
79 
80 			delete element;
81 		}
82 		else {
83 			return B_OK;
84 				// We already have a newer version of the block
85 		}
86 	}
87 
88 	return _ForceInsert(block, commitID);
89 }
90 
91 
92 status_t
93 HashRevokeManager::Remove(uint32 block)
94 {
95 	RevokeElement* element = (RevokeElement*)hash_lookup(fHash, &block);
96 
97 	if (element == NULL)
98 		return B_ERROR; // TODO: Perhaps we should just ignore?
99 
100 	status_t retValue = hash_remove(fHash, element);
101 
102 	if (retValue == B_OK)
103 		delete element;
104 
105 	return retValue;
106 }
107 
108 
109 bool
110 HashRevokeManager::Lookup(uint32 block, uint32 commitID)
111 {
112 	RevokeElement* element = (RevokeElement*)hash_lookup(fHash, &block);
113 
114 	if (element == NULL)
115 		return false;
116 
117 	return element->commitID >= commitID;
118 }
119 
120 
121 /*static*/ int
122 HashRevokeManager::Compare(void* _revoked, const void *_block)
123 {
124 	RevokeElement* revoked = (RevokeElement*)_revoked;
125 	uint32 block = *(uint32*)_block;
126 
127 	if (revoked->block == block)
128 		return 0;
129 
130 	return (revoked->block > block) ? 1 : -1;
131 }
132 
133 
134 /*static*/ uint32
135 HashRevokeManager::Hash(void* _revoked, const void* _block, uint32 range)
136 {
137 	TRACE("HashRevokeManager::Hash(): revoked: %p, block: %p, range: %"
138 		B_PRIu32 "\n", _revoked, _block, range);
139 	RevokeElement* revoked = (RevokeElement*)_revoked;
140 
141 	if (revoked != NULL)
142 		return revoked->block % range;
143 
144 	uint32 block = *(uint32*)_block;
145 	return block % range;
146 }
147 
148 
149 status_t
150 HashRevokeManager::_ForceInsert(uint32 block, uint32 commitID)
151 {
152 	RevokeElement* element = new(std::nothrow) RevokeElement;
153 
154 	if (element == NULL)
155 		return B_NO_MEMORY;
156 
157 	element->block = block;
158 	element->commitID = commitID;
159 
160 	status_t retValue = hash_insert_grow(fHash, element);
161 
162 	if (retValue == B_OK) {
163 		fRevokeCount++;
164 		TRACE("HashRevokeManager::_ForceInsert(): revoke count: %" B_PRIu32
165 			"\n", fRevokeCount);
166 	}
167 
168 	return retValue;
169 }
170 
171