1// NodeHandleMap.cpp 2 3#include "NodeHandleMap.h" 4 5#include "AutoLocker.h" 6#include "GlobalBlockerPool.h" 7 8 9// constructor 10NodeHandleMap::NodeHandleMap(const char* name) 11 : Locker(name), 12 fNextNodeHandleCookie(0) 13{ 14} 15 16// destructor 17NodeHandleMap::~NodeHandleMap() 18{ 19} 20 21// Init 22status_t 23NodeHandleMap::Init() 24{ 25 // check semaphore 26 if (Sem() < 0) 27 return Sem(); 28 29 return B_OK; 30} 31 32// AddNodeHandle 33status_t 34NodeHandleMap::AddNodeHandle(NodeHandle* handle) 35{ 36 if (!handle) 37 return B_BAD_VALUE; 38 39 AutoLocker<Locker> _(this); 40 41 handle->SetCookie(_NextNodeHandleCookie()); 42 43 status_t error = Put(handle->GetCookie(), handle); 44 if (error == B_OK) 45 handle->AcquireReference(); 46 47 return error; 48} 49 50// RemoveNodeHandle 51bool 52NodeHandleMap::RemoveNodeHandle(NodeHandle* handle) 53{ 54 if (!handle) 55 return false; 56 57 AutoLocker<Locker> _(this); 58 59 if (Get(handle->GetCookie()) != handle) 60 return false; 61 62 Remove(handle->GetCookie()); 63 handle->ReleaseReference(); 64 return true; 65} 66 67// LockNodeHandle 68// 69// VolumeManager must NOT be locked. 70status_t 71NodeHandleMap::LockNodeHandle(int32 cookie, NodeHandle** _handle) 72{ 73 if (!_handle) 74 return B_BAD_VALUE; 75 76 NodeHandle* handle; 77 { 78 AutoLocker<Locker> _(this); 79 80 // get the node handle 81 handle = Get(cookie); 82 if (!handle) 83 return B_ENTRY_NOT_FOUND; 84 handle->AcquireReference(); 85 86 // first attempt: we just try to lock the node handle, which will fail, 87 // if someone else has the lock at the momemt 88 if (handle->Lock()) { 89 *_handle = handle; 90 return B_OK; 91 } 92 } 93 94 // someone else is locking, get a blocker and wait for the lock 95 BlockerPool* blockerPool = GlobalBlockerPool::GetDefault(); 96 Blocker blocker = blockerPool->GetBlocker(); 97 BlockerPutter blockerPutter(*blockerPool, blocker); 98 LockerCandidate lockerCandidate(blocker); 99 { 100 AutoLocker<Locker> _(this); 101 102 if (handle->Lock()) { 103 *_handle = handle; 104 return B_OK; 105 } 106 handle->QueueLockerCandidate(&lockerCandidate); 107 } 108 109 // wait for the lock 110 status_t error = lockerCandidate.Block(); 111 if (error != B_OK) { 112 handle->ReleaseReference(); 113 return error; 114 } 115 116 *_handle = handle; 117 return B_OK; 118} 119 120// UnlockNodeHandle 121// 122// VolumeManager may or may not be locked. 123void 124NodeHandleMap::UnlockNodeHandle(NodeHandle* nodeHandle) 125{ 126 if (!nodeHandle) 127 return; 128 129 if (nodeHandle->IsLocked()) { 130 AutoLocker<Locker> _(this); 131 132 nodeHandle->Unlock(); 133 nodeHandle->ReleaseReference(); 134 } 135} 136 137// _NextNodeHandleCookie 138int32 139NodeHandleMap::_NextNodeHandleCookie() 140{ 141 int32 cookie; 142 143 do { 144 if (fNextNodeHandleCookie < 0) 145 fNextNodeHandleCookie = 0; 146 cookie = fNextNodeHandleCookie++; 147 } while (ContainsKey(cookie)); 148 149 return cookie; 150} 151 152