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