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 = 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 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 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 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 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 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 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 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