Revision 887c7aa6 doc/design-2.3.rst

b/doc/design-2.3.rst
205 205
a restart or crash of the master daemon.
206 206

  
207 207
Priorities also need to be considered inside the locking library to
208
ensure opcodes with higher priorities get locks first, but the design
209
changes for this will be discussed in a separate section.
208
ensure opcodes with higher priorities get locks first. See
209
:ref:`locking priorities <locking-priorities>` for more details.
210 210

  
211 211
Worker pool
212 212
+++++++++++
......
243 243
With these changes, the job queue will be able to implement per-job
244 244
priorities.
245 245

  
246
.. _locking-priorities:
247

  
248
Locking
249
+++++++
250

  
251
In order to support priorities in Ganeti's own lock classes,
252
``locking.SharedLock`` and ``locking.LockSet``, the internal structure
253
of the former class needs to be changed. The last major change in this
254
area was done for Ganeti 2.1 and can be found in the respective
255
:doc:`design document <design-2.1>`.
256

  
257
The plain list (``[]``) used as a queue is replaced by a heap queue,
258
similar to the `worker pool`_. The heap or priority queue does automatic
259
sorting, thereby automatically taking care of priorities. For each
260
priority there's a plain list with pending acquires, like the single
261
queue of pending acquires before this change.
262

  
263
When the lock is released, the code locates the list of pending acquires
264
for the highest priority waiting. The first condition (index 0) is
265
notified. Once all waiting threads received the notification, the
266
condition is removed from the list. If the list of conditions is empty
267
it's removed from the heap queue.
268

  
269
Like before, shared acquires are grouped and skip ahead of exclusive
270
acquires if there's already an existing shared acquire for a priority.
271
To accomplish this, a separate dictionary of shared acquires per
272
priority is maintained.
273

  
274
To simplify the code and reduce memory consumption, the concept of the
275
"active" and "inactive" condition for shared acquires is abolished. The
276
lock can't predict what priorities the next acquires will use and even
277
keeping a cache can become computationally expensive for arguable
278
benefit (the underlying POSIX pipe, see ``pipe(2)``, needs to be
279
re-created for each notification anyway).
280

  
281
The following diagram shows a possible state of the internal queue from
282
a high-level view. Conditions are shown as (waiting) threads. Assuming
283
no modifications are made to the queue (e.g. more acquires or timeouts),
284
the lock would be acquired by the threads in this order (concurrent
285
acquires in parentheses): ``threadE1``, ``threadE2``, (``threadS1``,
286
``threadS2``, ``threadS3``), (``threadS4``, ``threadS5``), ``threadE3``,
287
``threadS6``, ``threadE4``, ``threadE5``.
288

  
289
::
290

  
291
  [
292
    (0, [exc/threadE1, exc/threadE2, shr/threadS1/threadS2/threadS3]),
293
    (2, [shr/threadS4/threadS5]),
294
    (10, [exc/threadE3]),
295
    (33, [shr/threadS6, exc/threadE4, exc/threadE5]),
296
  ]
297

  
298

  
246 299
IPv6 support
247 300
------------
248 301

  

Also available in: Unified diff