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
23HashRevokeManager::HashRevokeManager()
24	:
25	fHash(NULL),
26	kInitialHashSize(128)
27		// TODO: Benchmark and find an optimal value
28{
29}
30
31
32HashRevokeManager::~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
50status_t
51HashRevokeManager::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
62status_t
63HashRevokeManager::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
87status_t
88HashRevokeManager::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
103bool
104HashRevokeManager::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
116HashRevokeManager::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
129HashRevokeManager::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
143status_t
144HashRevokeManager::_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