1 // NodeHandleMap.cpp 2 3 #include "NodeHandleMap.h" 4 5 #include "AutoLocker.h" 6 #include "GlobalBlockerPool.h" 7 8 9 // constructor 10 NodeHandleMap::NodeHandleMap(const char* name) 11 : Locker(name), 12 fNextNodeHandleCookie(0) 13 { 14 } 15 16 // destructor 17 NodeHandleMap::~NodeHandleMap() 18 { 19 } 20 21 // Init 22 status_t 23 NodeHandleMap::Init() 24 { 25 // check semaphore 26 if (Sem() < 0) 27 return Sem(); 28 29 return B_OK; 30 } 31 32 // AddNodeHandle 33 status_t 34 NodeHandleMap::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->AddReference(); 46 47 return error; 48 } 49 50 // RemoveNodeHandle 51 bool 52 NodeHandleMap::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->RemoveReference(); 64 return true; 65 } 66 67 // LockNodeHandle 68 // 69 // VolumeManager must NOT be locked. 70 status_t 71 NodeHandleMap::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->AddReference(); 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->RemoveReference(); 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. 123 void 124 NodeHandleMap::UnlockNodeHandle(NodeHandle* nodeHandle) 125 { 126 if (!nodeHandle) 127 return; 128 129 if (nodeHandle->IsLocked()) { 130 AutoLocker<Locker> _(this); 131 132 nodeHandle->Unlock(); 133 nodeHandle->RemoveReference(); 134 } 135 } 136 137 // _NextNodeHandleCookie 138 int32 139 NodeHandleMap::_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