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 = 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 50status_t 51HashRevokeManager::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 66status_t 67HashRevokeManager::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 92status_t 93HashRevokeManager::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 109bool 110HashRevokeManager::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 122HashRevokeManager::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 135HashRevokeManager::Hash(void* _revoked, const void* _block, uint32 range) 136{ 137 TRACE("HashRevokeManager::Hash(): revoked: %p, block: %p, range: %lu\n", 138 _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 149status_t 150HashRevokeManager::_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: %lu\n", 165 fRevokeCount); 166 } 167 168 return retValue; 169} 170 171