Revision 32935f7a
b/src/Ganeti/Locking/Waiting.hs | ||
---|---|---|
118 | 118 |
-- the owners to be notified. The type is chosen to be suitable as fold |
119 | 119 |
-- operation. |
120 | 120 |
-- |
121 |
-- This function calls the later defined updateLocksWaiting, as they are |
|
121 |
-- This function calls the later defined updateLocksWaiting', as they are
|
|
122 | 122 |
-- mutually recursive. |
123 | 123 |
tryFulfillRequest :: (Lock a, Ord b, Ord c) |
124 | 124 |
=> (LockWaiting a b c, S.Set b) |
125 | 125 |
-> (c, b, [L.LockRequest a]) |
126 | 126 |
-> (LockWaiting a b c, S.Set b) |
127 | 127 |
tryFulfillRequest (waiting, toNotify) (prio, owner, req) = |
128 |
let (waiting', (_, newNotify)) = updateLocksWaiting prio owner req waiting |
|
128 |
let (waiting', (_, newNotify)) = updateLocksWaiting' prio owner req waiting
|
|
129 | 129 |
in (waiting', toNotify `S.union` newNotify) |
130 | 130 |
|
131 | 131 |
-- | Internal function to recursively follow the consequences of a change. |
... | ... | |
156 | 156 |
-- | Update the locks on an onwer according to the given request, if possible. |
157 | 157 |
-- Additionally (if the request succeeds) fulfill any pending requests that |
158 | 158 |
-- became possible through this request. Return the new state of the waiting |
159 |
-- structure, the result of the operation, and a list of nodes to be notified
|
|
160 |
-- that their locks are available now. The result is, as for lock allocation,
|
|
161 |
-- the set of owners the request is blocked on. Again, the type is chosen to be
|
|
162 |
-- suitable for use in atomicModifyIORef.
|
|
163 |
updateLocks :: (Lock a, Ord b, Ord c) |
|
164 |
=> b |
|
165 |
-> [L.LockRequest a] |
|
166 |
-> LockWaiting a b c |
|
167 |
-> (LockWaiting a b c, (Result (S.Set b), S.Set b)) |
|
168 |
updateLocks owner reqs state = |
|
159 |
-- structure, the result of the operation, and a list of owner whose requests
|
|
160 |
-- have been fulfilled. The result is, as for lock allocation, the set of owners
|
|
161 |
-- the request is blocked on. Again, the type is chosen to be suitable for use
|
|
162 |
-- in atomicModifyIORef. |
|
163 |
updateLocks' :: (Lock a, Ord b, Ord c)
|
|
164 |
=> b
|
|
165 |
-> [L.LockRequest a]
|
|
166 |
-> LockWaiting a b c
|
|
167 |
-> (LockWaiting a b c, (Result (S.Set b), S.Set b))
|
|
168 |
updateLocks' owner reqs state =
|
|
169 | 169 |
let (allocation', result) = L.updateLocks owner reqs (lwAllocation state) |
170 | 170 |
state' = state { lwAllocation = allocation' } |
171 | 171 |
(notify, state'') = revisitRequests S.empty (S.singleton owner) state' |
... | ... | |
184 | 184 |
-- | Update locks as soon as possible. If the request cannot be fulfilled |
185 | 185 |
-- immediately add the request to the waiting queue. The first argument is |
186 | 186 |
-- the priority at which the owner is waiting, the remaining are as for |
187 |
-- updateLocks, and so is the output. |
|
188 |
updateLocksWaiting :: (Lock a, Ord b, Ord c) |
|
189 |
=> c |
|
190 |
-> b |
|
191 |
-> [L.LockRequest a] |
|
192 |
-> LockWaiting a b c |
|
193 |
-> (LockWaiting a b c, (Result (S.Set b), S.Set b)) |
|
194 |
updateLocksWaiting prio owner reqs state = |
|
195 |
let (state', (result, notify)) = updateLocks owner reqs state |
|
187 |
-- updateLocks', and so is the output.
|
|
188 |
updateLocksWaiting' :: (Lock a, Ord b, Ord c)
|
|
189 |
=> c
|
|
190 |
-> b
|
|
191 |
-> [L.LockRequest a]
|
|
192 |
-> LockWaiting a b c
|
|
193 |
-> (LockWaiting a b c, (Result (S.Set b), S.Set b))
|
|
194 |
updateLocksWaiting' prio owner reqs state =
|
|
195 |
let (state', (result, notify)) = updateLocks' owner reqs state
|
|
196 | 196 |
state'' = case result of |
197 | 197 |
Bad _ -> state' -- bad requests cannot be queued |
198 | 198 |
Ok empty | S.null empty -> state' |
... | ... | |
210 | 210 |
} |
211 | 211 |
in (state'', (result, notify)) |
212 | 212 |
|
213 |
-- | Update the locks on an onwer according to the given request, if possible. |
|
214 |
-- Additionally (if the request succeeds) fulfill any pending requests that |
|
215 |
-- became possible through this request. Return the new state of the waiting |
|
216 |
-- structure, the result of the operation, and a list of owners to be notified. |
|
217 |
-- The result is, as for lock allocation, the set of owners the request is |
|
218 |
-- blocked on. Again, the type is chosen to be suitable for use in |
|
219 |
-- atomicModifyIORef. |
|
220 |
updateLocks :: (Lock a, Ord b, Ord c) |
|
221 |
=> b |
|
222 |
-> [L.LockRequest a] |
|
223 |
-> LockWaiting a b c |
|
224 |
-> (LockWaiting a b c, (Result (S.Set b), S.Set b)) |
|
225 |
updateLocks owner req state = |
|
226 |
second (second $ S.delete owner) $ updateLocks' owner req state |
|
227 |
|
|
228 |
-- | Update locks as soon as possible. If the request cannot be fulfilled |
|
229 |
-- immediately add the request to the waiting queue. The first argument is |
|
230 |
-- the priority at which the owner is waiting, the remaining are as for |
|
231 |
-- updateLocks, and so is the output. |
|
232 |
updateLocksWaiting :: (Lock a, Ord b, Ord c) |
|
233 |
=> c |
|
234 |
-> b |
|
235 |
-> [L.LockRequest a] |
|
236 |
-> LockWaiting a b c |
|
237 |
-> (LockWaiting a b c, (Result (S.Set b), S.Set b)) |
|
238 |
updateLocksWaiting prio owner req state = |
|
239 |
second (second $ S.delete owner) $ updateLocksWaiting' prio owner req state |
|
240 |
|
|
213 | 241 |
-- | Compute the state of a waiting after an owner gives up |
214 | 242 |
-- on his pending request. |
215 | 243 |
removePendingRequest :: (Lock a, Ord b, Ord c) |
Also available in: Unified diff