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(bool has64bits) 24 : RevokeManager(has64bits), 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