Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 3dbe3ddf

History | View | Annotate | Download (73.1 kB)

1 162c1c1f Guido Trotter
#!/usr/bin/python
2 162c1c1f Guido Trotter
#
3 162c1c1f Guido Trotter
4 7f93570a Iustin Pop
# Copyright (C) 2006, 2007, 2010 Google Inc.
5 162c1c1f Guido Trotter
#
6 162c1c1f Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 162c1c1f Guido Trotter
# it under the terms of the GNU General Public License as published by
8 162c1c1f Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 162c1c1f Guido Trotter
# (at your option) any later version.
10 162c1c1f Guido Trotter
#
11 162c1c1f Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 162c1c1f Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 162c1c1f Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 162c1c1f Guido Trotter
# General Public License for more details.
15 162c1c1f Guido Trotter
#
16 162c1c1f Guido Trotter
# You should have received a copy of the GNU General Public License
17 162c1c1f Guido Trotter
# along with this program; if not, write to the Free Software
18 162c1c1f Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 162c1c1f Guido Trotter
# 0.0510-1301, USA.
20 162c1c1f Guido Trotter
21 162c1c1f Guido Trotter
22 162c1c1f Guido Trotter
"""Script for unittesting the locking module"""
23 162c1c1f Guido Trotter
24 162c1c1f Guido Trotter
25 162c1c1f Guido Trotter
import os
26 162c1c1f Guido Trotter
import unittest
27 162c1c1f Guido Trotter
import time
28 162c1c1f Guido Trotter
import Queue
29 84e344d4 Michael Hanselmann
import threading
30 19b9ba9a Michael Hanselmann
import random
31 e4e35357 Michael Hanselmann
import gc
32 887c7aa6 Michael Hanselmann
import itertools
33 162c1c1f Guido Trotter
34 24d16f76 Michael Hanselmann
from ganeti import constants
35 162c1c1f Guido Trotter
from ganeti import locking
36 a95fd5d7 Guido Trotter
from ganeti import errors
37 19b9ba9a Michael Hanselmann
from ganeti import utils
38 887c7aa6 Michael Hanselmann
from ganeti import compat
39 24d16f76 Michael Hanselmann
from ganeti import objects
40 24d16f76 Michael Hanselmann
from ganeti import query
41 162c1c1f Guido Trotter
42 25231ec5 Michael Hanselmann
import testutils
43 25231ec5 Michael Hanselmann
44 162c1c1f Guido Trotter
45 42a999d1 Guido Trotter
# This is used to test the ssynchronize decorator.
46 42a999d1 Guido Trotter
# Since it's passed as input to a decorator it must be declared as a global.
47 7f93570a Iustin Pop
_decoratorlock = locking.SharedLock("decorator lock")
48 42a999d1 Guido Trotter
49 4607c978 Iustin Pop
#: List for looping tests
50 4607c978 Iustin Pop
ITERATIONS = range(8)
51 4607c978 Iustin Pop
52 84e344d4 Michael Hanselmann
53 4607c978 Iustin Pop
def _Repeat(fn):
54 4607c978 Iustin Pop
  """Decorator for executing a function many times"""
55 4607c978 Iustin Pop
  def wrapper(*args, **kwargs):
56 4607c978 Iustin Pop
    for i in ITERATIONS:
57 4607c978 Iustin Pop
      fn(*args, **kwargs)
58 4607c978 Iustin Pop
  return wrapper
59 4607c978 Iustin Pop
60 84e344d4 Michael Hanselmann
61 5aab242c Michael Hanselmann
def SafeSleep(duration):
62 5aab242c Michael Hanselmann
  start = time.time()
63 5aab242c Michael Hanselmann
  while True:
64 5aab242c Michael Hanselmann
    delay = start + duration - time.time()
65 5aab242c Michael Hanselmann
    if delay <= 0.0:
66 5aab242c Michael Hanselmann
      break
67 5aab242c Michael Hanselmann
    time.sleep(delay)
68 5aab242c Michael Hanselmann
69 5aab242c Michael Hanselmann
70 4607c978 Iustin Pop
class _ThreadedTestCase(unittest.TestCase):
71 4607c978 Iustin Pop
  """Test class that supports adding/waiting on threads"""
72 4607c978 Iustin Pop
  def setUp(self):
73 4607c978 Iustin Pop
    unittest.TestCase.setUp(self)
74 63f2e724 Guido Trotter
    self.done = Queue.Queue(0)
75 4607c978 Iustin Pop
    self.threads = []
76 4607c978 Iustin Pop
77 4607c978 Iustin Pop
  def _addThread(self, *args, **kwargs):
78 4607c978 Iustin Pop
    """Create and remember a new thread"""
79 84e344d4 Michael Hanselmann
    t = threading.Thread(*args, **kwargs)
80 4607c978 Iustin Pop
    self.threads.append(t)
81 4607c978 Iustin Pop
    t.start()
82 4607c978 Iustin Pop
    return t
83 4607c978 Iustin Pop
84 4607c978 Iustin Pop
  def _waitThreads(self):
85 4607c978 Iustin Pop
    """Wait for all our threads to finish"""
86 4607c978 Iustin Pop
    for t in self.threads:
87 4607c978 Iustin Pop
      t.join(60)
88 4607c978 Iustin Pop
      self.failIf(t.isAlive())
89 4607c978 Iustin Pop
    self.threads = []
90 42a999d1 Guido Trotter
91 4607c978 Iustin Pop
92 c5fe2a67 Guido Trotter
class _ConditionTestCase(_ThreadedTestCase):
93 c5fe2a67 Guido Trotter
  """Common test case for conditions"""
94 48dabc6a Michael Hanselmann
95 c5fe2a67 Guido Trotter
  def setUp(self, cls):
96 48dabc6a Michael Hanselmann
    _ThreadedTestCase.setUp(self)
97 48dabc6a Michael Hanselmann
    self.lock = threading.Lock()
98 c5fe2a67 Guido Trotter
    self.cond = cls(self.lock)
99 48dabc6a Michael Hanselmann
100 c5fe2a67 Guido Trotter
  def _testAcquireRelease(self):
101 158206e0 Manuel Franceschini
    self.assertFalse(self.cond._is_owned())
102 83f2d5f6 Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.wait, None)
103 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.notifyAll)
104 48dabc6a Michael Hanselmann
105 48dabc6a Michael Hanselmann
    self.cond.acquire()
106 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
107 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
108 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
109 48dabc6a Michael Hanselmann
    self.cond.release()
110 48dabc6a Michael Hanselmann
111 158206e0 Manuel Franceschini
    self.assertFalse(self.cond._is_owned())
112 83f2d5f6 Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.wait, None)
113 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.notifyAll)
114 48dabc6a Michael Hanselmann
115 c5fe2a67 Guido Trotter
  def _testNotification(self):
116 48dabc6a Michael Hanselmann
    def _NotifyAll():
117 b8140229 Guido Trotter
      self.done.put("NE")
118 48dabc6a Michael Hanselmann
      self.cond.acquire()
119 b8140229 Guido Trotter
      self.done.put("NA")
120 48dabc6a Michael Hanselmann
      self.cond.notifyAll()
121 b8140229 Guido Trotter
      self.done.put("NN")
122 48dabc6a Michael Hanselmann
      self.cond.release()
123 48dabc6a Michael Hanselmann
124 48dabc6a Michael Hanselmann
    self.cond.acquire()
125 48dabc6a Michael Hanselmann
    self._addThread(target=_NotifyAll)
126 b8140229 Guido Trotter
    self.assertEqual(self.done.get(True, 1), "NE")
127 b8140229 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get_nowait)
128 83f2d5f6 Michael Hanselmann
    self.cond.wait(None)
129 b8140229 Guido Trotter
    self.assertEqual(self.done.get(True, 1), "NA")
130 b8140229 Guido Trotter
    self.assertEqual(self.done.get(True, 1), "NN")
131 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
132 48dabc6a Michael Hanselmann
    self.cond.release()
133 158206e0 Manuel Franceschini
    self.assertFalse(self.cond._is_owned())
134 48dabc6a Michael Hanselmann
135 c5fe2a67 Guido Trotter
136 34cb5617 Guido Trotter
class TestSingleNotifyPipeCondition(_ConditionTestCase):
137 34cb5617 Guido Trotter
  """SingleNotifyPipeCondition tests"""
138 34cb5617 Guido Trotter
139 34cb5617 Guido Trotter
  def setUp(self):
140 34cb5617 Guido Trotter
    _ConditionTestCase.setUp(self, locking.SingleNotifyPipeCondition)
141 34cb5617 Guido Trotter
142 34cb5617 Guido Trotter
  def testAcquireRelease(self):
143 34cb5617 Guido Trotter
    self._testAcquireRelease()
144 34cb5617 Guido Trotter
145 34cb5617 Guido Trotter
  def testNotification(self):
146 34cb5617 Guido Trotter
    self._testNotification()
147 34cb5617 Guido Trotter
148 34cb5617 Guido Trotter
  def testWaitReuse(self):
149 34cb5617 Guido Trotter
    self.cond.acquire()
150 34cb5617 Guido Trotter
    self.cond.wait(0)
151 34cb5617 Guido Trotter
    self.cond.wait(0.1)
152 34cb5617 Guido Trotter
    self.cond.release()
153 34cb5617 Guido Trotter
154 34cb5617 Guido Trotter
  def testNoNotifyReuse(self):
155 34cb5617 Guido Trotter
    self.cond.acquire()
156 34cb5617 Guido Trotter
    self.cond.notifyAll()
157 83f2d5f6 Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.wait, None)
158 34cb5617 Guido Trotter
    self.assertRaises(RuntimeError, self.cond.notifyAll)
159 34cb5617 Guido Trotter
    self.cond.release()
160 34cb5617 Guido Trotter
161 34cb5617 Guido Trotter
162 c5fe2a67 Guido Trotter
class TestPipeCondition(_ConditionTestCase):
163 34cb5617 Guido Trotter
  """PipeCondition tests"""
164 c5fe2a67 Guido Trotter
165 c5fe2a67 Guido Trotter
  def setUp(self):
166 34cb5617 Guido Trotter
    _ConditionTestCase.setUp(self, locking.PipeCondition)
167 c5fe2a67 Guido Trotter
168 c5fe2a67 Guido Trotter
  def testAcquireRelease(self):
169 c5fe2a67 Guido Trotter
    self._testAcquireRelease()
170 c5fe2a67 Guido Trotter
171 c5fe2a67 Guido Trotter
  def testNotification(self):
172 c5fe2a67 Guido Trotter
    self._testNotification()
173 c5fe2a67 Guido Trotter
174 48dabc6a Michael Hanselmann
  def _TestWait(self, fn):
175 c31825f7 Michael Hanselmann
    threads = [
176 c31825f7 Michael Hanselmann
      self._addThread(target=fn),
177 c31825f7 Michael Hanselmann
      self._addThread(target=fn),
178 c31825f7 Michael Hanselmann
      self._addThread(target=fn),
179 c31825f7 Michael Hanselmann
      ]
180 48dabc6a Michael Hanselmann
181 48dabc6a Michael Hanselmann
    # Wait for threads to be waiting
182 c31825f7 Michael Hanselmann
    for _ in threads:
183 c31825f7 Michael Hanselmann
      self.assertEqual(self.done.get(True, 1), "A")
184 48dabc6a Michael Hanselmann
185 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
186 48dabc6a Michael Hanselmann
187 48dabc6a Michael Hanselmann
    self.cond.acquire()
188 c31825f7 Michael Hanselmann
    self.assertEqual(len(self.cond._waiters), 3)
189 c31825f7 Michael Hanselmann
    self.assertEqual(self.cond._waiters, set(threads))
190 c31825f7 Michael Hanselmann
    # This new thread can't acquire the lock, and thus call wait, before we
191 48dabc6a Michael Hanselmann
    # release it
192 48dabc6a Michael Hanselmann
    self._addThread(target=fn)
193 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
194 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
195 48dabc6a Michael Hanselmann
    self.cond.release()
196 48dabc6a Michael Hanselmann
197 48dabc6a Michael Hanselmann
    # We should now get 3 W and 1 A (for the new thread) in whatever order
198 48dabc6a Michael Hanselmann
    w = 0
199 48dabc6a Michael Hanselmann
    a = 0
200 48dabc6a Michael Hanselmann
    for i in range(4):
201 48dabc6a Michael Hanselmann
      got = self.done.get(True, 1)
202 48dabc6a Michael Hanselmann
      if got == "W":
203 48dabc6a Michael Hanselmann
        w += 1
204 48dabc6a Michael Hanselmann
      elif got == "A":
205 48dabc6a Michael Hanselmann
        a += 1
206 48dabc6a Michael Hanselmann
      else:
207 48dabc6a Michael Hanselmann
        self.fail("Got %s on the done queue" % got)
208 48dabc6a Michael Hanselmann
209 48dabc6a Michael Hanselmann
    self.assertEqual(w, 3)
210 48dabc6a Michael Hanselmann
    self.assertEqual(a, 1)
211 48dabc6a Michael Hanselmann
212 48dabc6a Michael Hanselmann
    self.cond.acquire()
213 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
214 48dabc6a Michael Hanselmann
    self.cond.release()
215 48dabc6a Michael Hanselmann
    self._waitThreads()
216 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "W")
217 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
218 48dabc6a Michael Hanselmann
219 48dabc6a Michael Hanselmann
  def testBlockingWait(self):
220 48dabc6a Michael Hanselmann
    def _BlockingWait():
221 48dabc6a Michael Hanselmann
      self.cond.acquire()
222 48dabc6a Michael Hanselmann
      self.done.put("A")
223 83f2d5f6 Michael Hanselmann
      self.cond.wait(None)
224 48dabc6a Michael Hanselmann
      self.cond.release()
225 48dabc6a Michael Hanselmann
      self.done.put("W")
226 48dabc6a Michael Hanselmann
227 48dabc6a Michael Hanselmann
    self._TestWait(_BlockingWait)
228 48dabc6a Michael Hanselmann
229 48dabc6a Michael Hanselmann
  def testLongTimeoutWait(self):
230 48dabc6a Michael Hanselmann
    def _Helper():
231 48dabc6a Michael Hanselmann
      self.cond.acquire()
232 48dabc6a Michael Hanselmann
      self.done.put("A")
233 48dabc6a Michael Hanselmann
      self.cond.wait(15.0)
234 48dabc6a Michael Hanselmann
      self.cond.release()
235 48dabc6a Michael Hanselmann
      self.done.put("W")
236 48dabc6a Michael Hanselmann
237 48dabc6a Michael Hanselmann
    self._TestWait(_Helper)
238 48dabc6a Michael Hanselmann
239 48dabc6a Michael Hanselmann
  def _TimeoutWait(self, timeout, check):
240 48dabc6a Michael Hanselmann
    self.cond.acquire()
241 48dabc6a Michael Hanselmann
    self.cond.wait(timeout)
242 48dabc6a Michael Hanselmann
    self.cond.release()
243 48dabc6a Michael Hanselmann
    self.done.put(check)
244 48dabc6a Michael Hanselmann
245 48dabc6a Michael Hanselmann
  def testShortTimeoutWait(self):
246 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0.1, "T1"))
247 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0.1, "T1"))
248 48dabc6a Michael Hanselmann
    self._waitThreads()
249 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T1")
250 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T1")
251 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
252 48dabc6a Michael Hanselmann
253 48dabc6a Michael Hanselmann
  def testZeroTimeoutWait(self):
254 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
255 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
256 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
257 48dabc6a Michael Hanselmann
    self._waitThreads()
258 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
259 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
260 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
261 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
262 48dabc6a Michael Hanselmann
263 48dabc6a Michael Hanselmann
264 4607c978 Iustin Pop
class TestSharedLock(_ThreadedTestCase):
265 d6646186 Guido Trotter
  """SharedLock tests"""
266 162c1c1f Guido Trotter
267 162c1c1f Guido Trotter
  def setUp(self):
268 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
269 7f93570a Iustin Pop
    self.sl = locking.SharedLock("TestSharedLock")
270 162c1c1f Guido Trotter
271 162c1c1f Guido Trotter
  def testSequenceAndOwnership(self):
272 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned())
273 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
274 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
275 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
276 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned(shared=0))
277 162c1c1f Guido Trotter
    self.sl.release()
278 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned())
279 162c1c1f Guido Trotter
    self.sl.acquire()
280 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
281 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned(shared=1))
282 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
283 162c1c1f Guido Trotter
    self.sl.release()
284 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned())
285 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
286 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
287 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
288 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned(shared=0))
289 162c1c1f Guido Trotter
    self.sl.release()
290 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned())
291 162c1c1f Guido Trotter
292 162c1c1f Guido Trotter
  def testBooleanValue(self):
293 162c1c1f Guido Trotter
    # semaphores are supposed to return a true value on a successful acquire
294 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire(shared=1))
295 162c1c1f Guido Trotter
    self.sl.release()
296 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire())
297 162c1c1f Guido Trotter
    self.sl.release()
298 162c1c1f Guido Trotter
299 162c1c1f Guido Trotter
  def testDoubleLockingStoE(self):
300 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
301 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
302 162c1c1f Guido Trotter
303 162c1c1f Guido Trotter
  def testDoubleLockingEtoS(self):
304 162c1c1f Guido Trotter
    self.sl.acquire()
305 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
306 162c1c1f Guido Trotter
307 162c1c1f Guido Trotter
  def testDoubleLockingStoS(self):
308 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
309 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
310 162c1c1f Guido Trotter
311 162c1c1f Guido Trotter
  def testDoubleLockingEtoE(self):
312 162c1c1f Guido Trotter
    self.sl.acquire()
313 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
314 162c1c1f Guido Trotter
315 162c1c1f Guido Trotter
  # helper functions: called in a separate thread they acquire the lock, send
316 162c1c1f Guido Trotter
  # their identifier on the done queue, then release it.
317 162c1c1f Guido Trotter
  def _doItSharer(self):
318 a95fd5d7 Guido Trotter
    try:
319 a95fd5d7 Guido Trotter
      self.sl.acquire(shared=1)
320 a95fd5d7 Guido Trotter
      self.done.put('SHR')
321 a95fd5d7 Guido Trotter
      self.sl.release()
322 a95fd5d7 Guido Trotter
    except errors.LockError:
323 a95fd5d7 Guido Trotter
      self.done.put('ERR')
324 162c1c1f Guido Trotter
325 162c1c1f Guido Trotter
  def _doItExclusive(self):
326 a95fd5d7 Guido Trotter
    try:
327 a95fd5d7 Guido Trotter
      self.sl.acquire()
328 a95fd5d7 Guido Trotter
      self.done.put('EXC')
329 a95fd5d7 Guido Trotter
      self.sl.release()
330 a95fd5d7 Guido Trotter
    except errors.LockError:
331 a95fd5d7 Guido Trotter
      self.done.put('ERR')
332 a95fd5d7 Guido Trotter
333 a95fd5d7 Guido Trotter
  def _doItDelete(self):
334 a95fd5d7 Guido Trotter
    try:
335 4354ab03 Guido Trotter
      self.sl.delete()
336 a95fd5d7 Guido Trotter
      self.done.put('DEL')
337 a95fd5d7 Guido Trotter
    except errors.LockError:
338 a95fd5d7 Guido Trotter
      self.done.put('ERR')
339 162c1c1f Guido Trotter
340 162c1c1f Guido Trotter
  def testSharersCanCoexist(self):
341 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
342 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
343 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
344 162c1c1f Guido Trotter
    self.sl.release()
345 162c1c1f Guido Trotter
346 4607c978 Iustin Pop
  @_Repeat
347 162c1c1f Guido Trotter
  def testExclusiveBlocksExclusive(self):
348 162c1c1f Guido Trotter
    self.sl.acquire()
349 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
350 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
351 162c1c1f Guido Trotter
    self.sl.release()
352 4607c978 Iustin Pop
    self._waitThreads()
353 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
354 162c1c1f Guido Trotter
355 4607c978 Iustin Pop
  @_Repeat
356 a95fd5d7 Guido Trotter
  def testExclusiveBlocksDelete(self):
357 a95fd5d7 Guido Trotter
    self.sl.acquire()
358 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
359 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
360 a95fd5d7 Guido Trotter
    self.sl.release()
361 4607c978 Iustin Pop
    self._waitThreads()
362 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'DEL')
363 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
364 a95fd5d7 Guido Trotter
365 4607c978 Iustin Pop
  @_Repeat
366 162c1c1f Guido Trotter
  def testExclusiveBlocksSharer(self):
367 162c1c1f Guido Trotter
    self.sl.acquire()
368 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
369 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
370 162c1c1f Guido Trotter
    self.sl.release()
371 4607c978 Iustin Pop
    self._waitThreads()
372 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
373 162c1c1f Guido Trotter
374 4607c978 Iustin Pop
  @_Repeat
375 162c1c1f Guido Trotter
  def testSharerBlocksExclusive(self):
376 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
377 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
378 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
379 162c1c1f Guido Trotter
    self.sl.release()
380 4607c978 Iustin Pop
    self._waitThreads()
381 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
382 162c1c1f Guido Trotter
383 4607c978 Iustin Pop
  @_Repeat
384 a95fd5d7 Guido Trotter
  def testSharerBlocksDelete(self):
385 a95fd5d7 Guido Trotter
    self.sl.acquire(shared=1)
386 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
387 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
388 a95fd5d7 Guido Trotter
    self.sl.release()
389 4607c978 Iustin Pop
    self._waitThreads()
390 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'DEL')
391 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
392 a95fd5d7 Guido Trotter
393 4607c978 Iustin Pop
  @_Repeat
394 162c1c1f Guido Trotter
  def testWaitingExclusiveBlocksSharer(self):
395 e6416152 Iustin Pop
    """SKIPPED testWaitingExclusiveBlockSharer"""
396 e6416152 Iustin Pop
    return
397 e6416152 Iustin Pop
398 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
399 162c1c1f Guido Trotter
    # the lock is acquired in shared mode...
400 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
401 162c1c1f Guido Trotter
    # ...but now an exclusive is waiting...
402 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
403 162c1c1f Guido Trotter
    # ...so the sharer should be blocked as well
404 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
405 162c1c1f Guido Trotter
    self.sl.release()
406 4607c978 Iustin Pop
    self._waitThreads()
407 162c1c1f Guido Trotter
    # The exclusive passed before
408 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
409 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
410 162c1c1f Guido Trotter
411 4607c978 Iustin Pop
  @_Repeat
412 162c1c1f Guido Trotter
  def testWaitingSharerBlocksExclusive(self):
413 a143be68 Iustin Pop
    """SKIPPED testWaitingSharerBlocksExclusive"""
414 a143be68 Iustin Pop
    return
415 a143be68 Iustin Pop
416 162c1c1f Guido Trotter
    self.sl.acquire()
417 162c1c1f Guido Trotter
    # the lock is acquired in exclusive mode...
418 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
419 162c1c1f Guido Trotter
    # ...but now a sharer is waiting...
420 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
421 162c1c1f Guido Trotter
    # ...the exclusive is waiting too...
422 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
423 162c1c1f Guido Trotter
    self.sl.release()
424 4607c978 Iustin Pop
    self._waitThreads()
425 162c1c1f Guido Trotter
    # The sharer passed before
426 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'SHR')
427 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'EXC')
428 162c1c1f Guido Trotter
429 a95fd5d7 Guido Trotter
  def testDelete(self):
430 a95fd5d7 Guido Trotter
    self.sl.delete()
431 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire)
432 84152b96 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
433 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.delete)
434 a95fd5d7 Guido Trotter
435 a66bd91b Michael Hanselmann
  def testDeleteTimeout(self):
436 a66bd91b Michael Hanselmann
    self.sl.delete(timeout=60)
437 a66bd91b Michael Hanselmann
438 84152b96 Guido Trotter
  def testNoDeleteIfSharer(self):
439 84152b96 Guido Trotter
    self.sl.acquire(shared=1)
440 84152b96 Guido Trotter
    self.assertRaises(AssertionError, self.sl.delete)
441 84152b96 Guido Trotter
442 4607c978 Iustin Pop
  @_Repeat
443 a95fd5d7 Guido Trotter
  def testDeletePendingSharersExclusiveDelete(self):
444 a95fd5d7 Guido Trotter
    self.sl.acquire()
445 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
446 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
447 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
448 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
449 a95fd5d7 Guido Trotter
    self.sl.delete()
450 4607c978 Iustin Pop
    self._waitThreads()
451 4607c978 Iustin Pop
    # The threads who were pending return ERR
452 4607c978 Iustin Pop
    for _ in range(4):
453 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'ERR')
454 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
455 a95fd5d7 Guido Trotter
456 4607c978 Iustin Pop
  @_Repeat
457 a95fd5d7 Guido Trotter
  def testDeletePendingDeleteExclusiveSharers(self):
458 a95fd5d7 Guido Trotter
    self.sl.acquire()
459 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
460 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
461 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
462 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
463 a95fd5d7 Guido Trotter
    self.sl.delete()
464 4607c978 Iustin Pop
    self._waitThreads()
465 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
466 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
467 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
468 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
469 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
470 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
471 a95fd5d7 Guido Trotter
472 84e344d4 Michael Hanselmann
  @_Repeat
473 84e344d4 Michael Hanselmann
  def testExclusiveAcquireTimeout(self):
474 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
475 008b92fa Michael Hanselmann
      on_queue = threading.Event()
476 008b92fa Michael Hanselmann
      release_exclusive = threading.Event()
477 008b92fa Michael Hanselmann
478 008b92fa Michael Hanselmann
      def _LockExclusive():
479 008b92fa Michael Hanselmann
        self.sl.acquire(shared=0, test_notify=on_queue.set)
480 008b92fa Michael Hanselmann
        self.done.put("A: start wait")
481 008b92fa Michael Hanselmann
        release_exclusive.wait()
482 008b92fa Michael Hanselmann
        self.done.put("A: end wait")
483 008b92fa Michael Hanselmann
        self.sl.release()
484 008b92fa Michael Hanselmann
485 008b92fa Michael Hanselmann
      # Start thread to hold lock in exclusive mode
486 008b92fa Michael Hanselmann
      self._addThread(target=_LockExclusive)
487 84e344d4 Michael Hanselmann
488 008b92fa Michael Hanselmann
      # Wait for wait to begin
489 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get(timeout=60), "A: start wait")
490 008b92fa Michael Hanselmann
491 008b92fa Michael Hanselmann
      # Wait up to 60s to get lock, but release exclusive lock as soon as we're
492 008b92fa Michael Hanselmann
      # on the queue
493 008b92fa Michael Hanselmann
      self.failUnless(self.sl.acquire(shared=shared, timeout=60,
494 008b92fa Michael Hanselmann
                                      test_notify=release_exclusive.set))
495 2042aa94 Michael Hanselmann
496 84e344d4 Michael Hanselmann
      self.done.put("got 2nd")
497 84e344d4 Michael Hanselmann
      self.sl.release()
498 84e344d4 Michael Hanselmann
499 84e344d4 Michael Hanselmann
      self._waitThreads()
500 84e344d4 Michael Hanselmann
501 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "A: end wait")
502 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "got 2nd")
503 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
504 84e344d4 Michael Hanselmann
505 84e344d4 Michael Hanselmann
  @_Repeat
506 84e344d4 Michael Hanselmann
  def testAcquireExpiringTimeout(self):
507 84e344d4 Michael Hanselmann
    def _AcquireWithTimeout(shared, timeout):
508 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=shared, timeout=timeout):
509 84e344d4 Michael Hanselmann
        self.done.put("timeout")
510 84e344d4 Michael Hanselmann
511 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
512 84e344d4 Michael Hanselmann
      # Lock exclusively
513 84e344d4 Michael Hanselmann
      self.sl.acquire()
514 84e344d4 Michael Hanselmann
515 84e344d4 Michael Hanselmann
      # Start shared acquires with timeout between 0 and 20 ms
516 f1501b3f Michael Hanselmann
      for i in range(11):
517 84e344d4 Michael Hanselmann
        self._addThread(target=_AcquireWithTimeout,
518 84e344d4 Michael Hanselmann
                        args=(shared, i * 2.0 / 1000.0))
519 84e344d4 Michael Hanselmann
520 84e344d4 Michael Hanselmann
      # Wait for threads to finish (makes sure the acquire timeout expires
521 84e344d4 Michael Hanselmann
      # before releasing the lock)
522 84e344d4 Michael Hanselmann
      self._waitThreads()
523 84e344d4 Michael Hanselmann
524 84e344d4 Michael Hanselmann
      # Release lock
525 84e344d4 Michael Hanselmann
      self.sl.release()
526 84e344d4 Michael Hanselmann
527 f1501b3f Michael Hanselmann
      for _ in range(11):
528 84e344d4 Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "timeout")
529 84e344d4 Michael Hanselmann
530 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
531 84e344d4 Michael Hanselmann
532 84e344d4 Michael Hanselmann
  @_Repeat
533 84e344d4 Michael Hanselmann
  def testSharedSkipExclusiveAcquires(self):
534 84e344d4 Michael Hanselmann
    # Tests whether shared acquires jump in front of exclusive acquires in the
535 84e344d4 Michael Hanselmann
    # queue.
536 84e344d4 Michael Hanselmann
537 008b92fa Michael Hanselmann
    def _Acquire(shared, name, notify_ev, wait_ev):
538 008b92fa Michael Hanselmann
      if notify_ev:
539 008b92fa Michael Hanselmann
        notify_fn = notify_ev.set
540 008b92fa Michael Hanselmann
      else:
541 008b92fa Michael Hanselmann
        notify_fn = None
542 84e344d4 Michael Hanselmann
543 008b92fa Michael Hanselmann
      if wait_ev:
544 008b92fa Michael Hanselmann
        wait_ev.wait()
545 008b92fa Michael Hanselmann
546 008b92fa Michael Hanselmann
      if not self.sl.acquire(shared=shared, test_notify=notify_fn):
547 84e344d4 Michael Hanselmann
        return
548 84e344d4 Michael Hanselmann
549 84e344d4 Michael Hanselmann
      self.done.put(name)
550 84e344d4 Michael Hanselmann
      self.sl.release()
551 84e344d4 Michael Hanselmann
552 008b92fa Michael Hanselmann
    # Get exclusive lock while we fill the queue
553 008b92fa Michael Hanselmann
    self.sl.acquire()
554 84e344d4 Michael Hanselmann
555 008b92fa Michael Hanselmann
    shrcnt1 = 5
556 008b92fa Michael Hanselmann
    shrcnt2 = 7
557 008b92fa Michael Hanselmann
    shrcnt3 = 9
558 008b92fa Michael Hanselmann
    shrcnt4 = 2
559 84e344d4 Michael Hanselmann
560 008b92fa Michael Hanselmann
    # Add acquires using threading.Event for synchronization. They'll be
561 008b92fa Michael Hanselmann
    # acquired exactly in the order defined in this list.
562 008b92fa Michael Hanselmann
    acquires = (shrcnt1 * [(1, "shared 1")] +
563 008b92fa Michael Hanselmann
                3 * [(0, "exclusive 1")] +
564 008b92fa Michael Hanselmann
                shrcnt2 * [(1, "shared 2")] +
565 008b92fa Michael Hanselmann
                shrcnt3 * [(1, "shared 3")] +
566 008b92fa Michael Hanselmann
                shrcnt4 * [(1, "shared 4")] +
567 008b92fa Michael Hanselmann
                3 * [(0, "exclusive 2")])
568 84e344d4 Michael Hanselmann
569 008b92fa Michael Hanselmann
    ev_cur = None
570 008b92fa Michael Hanselmann
    ev_prev = None
571 008b92fa Michael Hanselmann
572 008b92fa Michael Hanselmann
    for args in acquires:
573 008b92fa Michael Hanselmann
      ev_cur = threading.Event()
574 008b92fa Michael Hanselmann
      self._addThread(target=_Acquire, args=args + (ev_cur, ev_prev))
575 008b92fa Michael Hanselmann
      ev_prev = ev_cur
576 008b92fa Michael Hanselmann
577 008b92fa Michael Hanselmann
    # Wait for last acquire to start
578 008b92fa Michael Hanselmann
    ev_prev.wait()
579 84e344d4 Michael Hanselmann
580 84e344d4 Michael Hanselmann
    # Expect 6 pending exclusive acquires and 1 for all shared acquires
581 008b92fa Michael Hanselmann
    # together
582 008b92fa Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 7)
583 84e344d4 Michael Hanselmann
584 84e344d4 Michael Hanselmann
    # Release exclusive lock and wait
585 84e344d4 Michael Hanselmann
    self.sl.release()
586 84e344d4 Michael Hanselmann
587 84e344d4 Michael Hanselmann
    self._waitThreads()
588 84e344d4 Michael Hanselmann
589 84e344d4 Michael Hanselmann
    # Check sequence
590 008b92fa Michael Hanselmann
    for _ in range(shrcnt1 + shrcnt2 + shrcnt3 + shrcnt4):
591 84e344d4 Michael Hanselmann
      # Shared locks aren't guaranteed to be notified in order, but they'll be
592 84e344d4 Michael Hanselmann
      # first
593 2042aa94 Michael Hanselmann
      tmp = self.done.get_nowait()
594 008b92fa Michael Hanselmann
      if tmp == "shared 1":
595 008b92fa Michael Hanselmann
        shrcnt1 -= 1
596 008b92fa Michael Hanselmann
      elif tmp == "shared 2":
597 008b92fa Michael Hanselmann
        shrcnt2 -= 1
598 008b92fa Michael Hanselmann
      elif tmp == "shared 3":
599 008b92fa Michael Hanselmann
        shrcnt3 -= 1
600 008b92fa Michael Hanselmann
      elif tmp == "shared 4":
601 008b92fa Michael Hanselmann
        shrcnt4 -= 1
602 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt1, 0)
603 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt2, 0)
604 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt3, 0)
605 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt3, 0)
606 84e344d4 Michael Hanselmann
607 f1501b3f Michael Hanselmann
    for _ in range(3):
608 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive 1")
609 84e344d4 Michael Hanselmann
610 f1501b3f Michael Hanselmann
    for _ in range(3):
611 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive 2")
612 84e344d4 Michael Hanselmann
613 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
614 84e344d4 Michael Hanselmann
615 3dbe3ddf Michael Hanselmann
  def testIllegalDowngrade(self):
616 3dbe3ddf Michael Hanselmann
    # Not yet acquired
617 3dbe3ddf Michael Hanselmann
    self.assertRaises(AssertionError, self.sl.downgrade)
618 3dbe3ddf Michael Hanselmann
619 3dbe3ddf Michael Hanselmann
    # Acquire in shared mode, downgrade should be no-op
620 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl.acquire(shared=1))
621 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl._is_owned(shared=1))
622 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl.downgrade())
623 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl._is_owned(shared=1))
624 3dbe3ddf Michael Hanselmann
    self.sl.release()
625 3dbe3ddf Michael Hanselmann
626 3dbe3ddf Michael Hanselmann
  def testDowngrade(self):
627 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl.acquire())
628 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl._is_owned(shared=0))
629 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl.downgrade())
630 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl._is_owned(shared=1))
631 3dbe3ddf Michael Hanselmann
    self.sl.release()
632 3dbe3ddf Michael Hanselmann
633 3dbe3ddf Michael Hanselmann
  @_Repeat
634 3dbe3ddf Michael Hanselmann
  def testDowngradeJumpsAheadOfExclusive(self):
635 3dbe3ddf Michael Hanselmann
    def _KeepExclusive(ev_got, ev_downgrade, ev_release):
636 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl.acquire())
637 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl._is_owned(shared=0))
638 3dbe3ddf Michael Hanselmann
      ev_got.set()
639 3dbe3ddf Michael Hanselmann
      ev_downgrade.wait()
640 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl._is_owned(shared=0))
641 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl.downgrade())
642 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl._is_owned(shared=1))
643 3dbe3ddf Michael Hanselmann
      ev_release.wait()
644 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl._is_owned(shared=1))
645 3dbe3ddf Michael Hanselmann
      self.sl.release()
646 3dbe3ddf Michael Hanselmann
647 3dbe3ddf Michael Hanselmann
    def _KeepExclusive2(ev_started, ev_release):
648 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl.acquire(test_notify=ev_started.set))
649 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl._is_owned(shared=0))
650 3dbe3ddf Michael Hanselmann
      ev_release.wait()
651 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl._is_owned(shared=0))
652 3dbe3ddf Michael Hanselmann
      self.sl.release()
653 3dbe3ddf Michael Hanselmann
654 3dbe3ddf Michael Hanselmann
    def _KeepShared(ev_started, ev_got, ev_release):
655 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl.acquire(shared=1, test_notify=ev_started.set))
656 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl._is_owned(shared=1))
657 3dbe3ddf Michael Hanselmann
      ev_got.set()
658 3dbe3ddf Michael Hanselmann
      ev_release.wait()
659 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl._is_owned(shared=1))
660 3dbe3ddf Michael Hanselmann
      self.sl.release()
661 3dbe3ddf Michael Hanselmann
662 3dbe3ddf Michael Hanselmann
    # Acquire lock in exclusive mode
663 3dbe3ddf Michael Hanselmann
    ev_got_excl1 = threading.Event()
664 3dbe3ddf Michael Hanselmann
    ev_downgrade_excl1 = threading.Event()
665 3dbe3ddf Michael Hanselmann
    ev_release_excl1 = threading.Event()
666 3dbe3ddf Michael Hanselmann
    th_excl1 = self._addThread(target=_KeepExclusive,
667 3dbe3ddf Michael Hanselmann
                               args=(ev_got_excl1, ev_downgrade_excl1,
668 3dbe3ddf Michael Hanselmann
                                     ev_release_excl1))
669 3dbe3ddf Michael Hanselmann
    ev_got_excl1.wait()
670 3dbe3ddf Michael Hanselmann
671 3dbe3ddf Michael Hanselmann
    # Start a second exclusive acquire
672 3dbe3ddf Michael Hanselmann
    ev_started_excl2 = threading.Event()
673 3dbe3ddf Michael Hanselmann
    ev_release_excl2 = threading.Event()
674 3dbe3ddf Michael Hanselmann
    th_excl2 = self._addThread(target=_KeepExclusive2,
675 3dbe3ddf Michael Hanselmann
                               args=(ev_started_excl2, ev_release_excl2))
676 3dbe3ddf Michael Hanselmann
    ev_started_excl2.wait()
677 3dbe3ddf Michael Hanselmann
678 3dbe3ddf Michael Hanselmann
    # Start shared acquires, will jump ahead of second exclusive acquire when
679 3dbe3ddf Michael Hanselmann
    # first exclusive acquire downgrades
680 3dbe3ddf Michael Hanselmann
    ev_shared = [(threading.Event(), threading.Event()) for _ in range(5)]
681 3dbe3ddf Michael Hanselmann
    ev_release_shared = threading.Event()
682 3dbe3ddf Michael Hanselmann
683 3dbe3ddf Michael Hanselmann
    th_shared = [self._addThread(target=_KeepShared,
684 3dbe3ddf Michael Hanselmann
                                 args=(ev_started, ev_got, ev_release_shared))
685 3dbe3ddf Michael Hanselmann
                 for (ev_started, ev_got) in ev_shared]
686 3dbe3ddf Michael Hanselmann
687 3dbe3ddf Michael Hanselmann
    # Wait for all shared acquires to start
688 3dbe3ddf Michael Hanselmann
    for (ev, _) in ev_shared:
689 3dbe3ddf Michael Hanselmann
      ev.wait()
690 3dbe3ddf Michael Hanselmann
691 3dbe3ddf Michael Hanselmann
    # Check lock information
692 3dbe3ddf Michael Hanselmann
    self.assertEqual(self.sl.GetInfo(set([query.LQ_MODE, query.LQ_OWNER])),
693 3dbe3ddf Michael Hanselmann
                     (self.sl.name, "exclusive", [th_excl1.getName()], None))
694 3dbe3ddf Michael Hanselmann
    (_, _, _, pending) = self.sl.GetInfo(set([query.LQ_PENDING]))
695 3dbe3ddf Michael Hanselmann
    self.assertEqual([(pendmode, sorted(waiting))
696 3dbe3ddf Michael Hanselmann
                      for (pendmode, waiting) in pending],
697 3dbe3ddf Michael Hanselmann
                     [("exclusive", [th_excl2.getName()]),
698 3dbe3ddf Michael Hanselmann
                      ("shared", sorted(th.getName() for th in th_shared))])
699 3dbe3ddf Michael Hanselmann
700 3dbe3ddf Michael Hanselmann
    # Shared acquires won't start until the exclusive lock is downgraded
701 3dbe3ddf Michael Hanselmann
    ev_downgrade_excl1.set()
702 3dbe3ddf Michael Hanselmann
703 3dbe3ddf Michael Hanselmann
    # Wait for all shared acquires to be successful
704 3dbe3ddf Michael Hanselmann
    for (_, ev) in ev_shared:
705 3dbe3ddf Michael Hanselmann
      ev.wait()
706 3dbe3ddf Michael Hanselmann
707 3dbe3ddf Michael Hanselmann
    # Check lock information again
708 3dbe3ddf Michael Hanselmann
    self.assertEqual(self.sl.GetInfo(set([query.LQ_MODE, query.LQ_PENDING])),
709 3dbe3ddf Michael Hanselmann
                     (self.sl.name, "shared", None,
710 3dbe3ddf Michael Hanselmann
                      [("exclusive", [th_excl2.getName()])]))
711 3dbe3ddf Michael Hanselmann
    (_, _, owner, _) = self.sl.GetInfo(set([query.LQ_OWNER]))
712 3dbe3ddf Michael Hanselmann
    self.assertEqual(set(owner), set([th_excl1.getName()] +
713 3dbe3ddf Michael Hanselmann
                                     [th.getName() for th in th_shared]))
714 3dbe3ddf Michael Hanselmann
715 3dbe3ddf Michael Hanselmann
    ev_release_excl1.set()
716 3dbe3ddf Michael Hanselmann
    ev_release_excl2.set()
717 3dbe3ddf Michael Hanselmann
    ev_release_shared.set()
718 3dbe3ddf Michael Hanselmann
719 3dbe3ddf Michael Hanselmann
    self._waitThreads()
720 3dbe3ddf Michael Hanselmann
721 3dbe3ddf Michael Hanselmann
    self.assertEqual(self.sl.GetInfo(set([query.LQ_MODE, query.LQ_OWNER,
722 3dbe3ddf Michael Hanselmann
                                          query.LQ_PENDING])),
723 3dbe3ddf Michael Hanselmann
                     (self.sl.name, None, None, []))
724 3dbe3ddf Michael Hanselmann
725 84e344d4 Michael Hanselmann
  @_Repeat
726 84e344d4 Michael Hanselmann
  def testMixedAcquireTimeout(self):
727 51e3bb92 Michael Hanselmann
    sync = threading.Event()
728 84e344d4 Michael Hanselmann
729 84e344d4 Michael Hanselmann
    def _AcquireShared(ev):
730 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=1, timeout=None):
731 84e344d4 Michael Hanselmann
        return
732 84e344d4 Michael Hanselmann
733 84e344d4 Michael Hanselmann
      self.done.put("shared")
734 84e344d4 Michael Hanselmann
735 84e344d4 Michael Hanselmann
      # Notify main thread
736 84e344d4 Michael Hanselmann
      ev.set()
737 84e344d4 Michael Hanselmann
738 51e3bb92 Michael Hanselmann
      # Wait for notification from main thread
739 51e3bb92 Michael Hanselmann
      sync.wait()
740 84e344d4 Michael Hanselmann
741 84e344d4 Michael Hanselmann
      # Release lock
742 84e344d4 Michael Hanselmann
      self.sl.release()
743 84e344d4 Michael Hanselmann
744 84e344d4 Michael Hanselmann
    acquires = []
745 f1501b3f Michael Hanselmann
    for _ in range(3):
746 84e344d4 Michael Hanselmann
      ev = threading.Event()
747 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireShared, args=(ev, ))
748 84e344d4 Michael Hanselmann
      acquires.append(ev)
749 84e344d4 Michael Hanselmann
750 84e344d4 Michael Hanselmann
    # Wait for all acquires to finish
751 84e344d4 Michael Hanselmann
    for i in acquires:
752 84e344d4 Michael Hanselmann
      i.wait()
753 84e344d4 Michael Hanselmann
754 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
755 84e344d4 Michael Hanselmann
756 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
757 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
758 84e344d4 Michael Hanselmann
759 84e344d4 Michael Hanselmann
    # Acquire exclusive without timeout
760 51e3bb92 Michael Hanselmann
    exclsync = threading.Event()
761 84e344d4 Michael Hanselmann
    exclev = threading.Event()
762 84e344d4 Michael Hanselmann
763 84e344d4 Michael Hanselmann
    def _AcquireExclusive():
764 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=0):
765 84e344d4 Michael Hanselmann
        return
766 84e344d4 Michael Hanselmann
767 84e344d4 Michael Hanselmann
      self.done.put("exclusive")
768 84e344d4 Michael Hanselmann
769 84e344d4 Michael Hanselmann
      # Notify main thread
770 84e344d4 Michael Hanselmann
      exclev.set()
771 84e344d4 Michael Hanselmann
772 51e3bb92 Michael Hanselmann
      # Wait for notification from main thread
773 51e3bb92 Michael Hanselmann
      exclsync.wait()
774 84e344d4 Michael Hanselmann
775 84e344d4 Michael Hanselmann
      self.sl.release()
776 84e344d4 Michael Hanselmann
777 84e344d4 Michael Hanselmann
    self._addThread(target=_AcquireExclusive)
778 84e344d4 Michael Hanselmann
779 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
780 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
781 84e344d4 Michael Hanselmann
782 84e344d4 Michael Hanselmann
    # Make all shared holders release their locks
783 51e3bb92 Michael Hanselmann
    sync.set()
784 84e344d4 Michael Hanselmann
785 84e344d4 Michael Hanselmann
    # Wait for exclusive acquire to succeed
786 84e344d4 Michael Hanselmann
    exclev.wait()
787 84e344d4 Michael Hanselmann
788 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
789 84e344d4 Michael Hanselmann
790 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
791 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
792 84e344d4 Michael Hanselmann
793 84e344d4 Michael Hanselmann
    def _AcquireSharedSimple():
794 84e344d4 Michael Hanselmann
      if self.sl.acquire(shared=1, timeout=None):
795 84e344d4 Michael Hanselmann
        self.done.put("shared2")
796 84e344d4 Michael Hanselmann
        self.sl.release()
797 84e344d4 Michael Hanselmann
798 f1501b3f Michael Hanselmann
    for _ in range(10):
799 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireSharedSimple)
800 84e344d4 Michael Hanselmann
801 84e344d4 Michael Hanselmann
    # Tell exclusive lock to release
802 51e3bb92 Michael Hanselmann
    exclsync.set()
803 84e344d4 Michael Hanselmann
804 84e344d4 Michael Hanselmann
    # Wait for everything to finish
805 84e344d4 Michael Hanselmann
    self._waitThreads()
806 84e344d4 Michael Hanselmann
807 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
808 84e344d4 Michael Hanselmann
809 84e344d4 Michael Hanselmann
    # Check sequence
810 f1501b3f Michael Hanselmann
    for _ in range(3):
811 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared")
812 84e344d4 Michael Hanselmann
813 84e344d4 Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "exclusive")
814 84e344d4 Michael Hanselmann
815 f1501b3f Michael Hanselmann
    for _ in range(10):
816 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared2")
817 84e344d4 Michael Hanselmann
818 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
819 84e344d4 Michael Hanselmann
820 887c7aa6 Michael Hanselmann
  def testPriority(self):
821 887c7aa6 Michael Hanselmann
    # Acquire in exclusive mode
822 887c7aa6 Michael Hanselmann
    self.assert_(self.sl.acquire(shared=0))
823 887c7aa6 Michael Hanselmann
824 887c7aa6 Michael Hanselmann
    # Queue acquires
825 887c7aa6 Michael Hanselmann
    def _Acquire(prev, next, shared, priority, result):
826 887c7aa6 Michael Hanselmann
      prev.wait()
827 887c7aa6 Michael Hanselmann
      self.sl.acquire(shared=shared, priority=priority, test_notify=next.set)
828 887c7aa6 Michael Hanselmann
      try:
829 887c7aa6 Michael Hanselmann
        self.done.put(result)
830 887c7aa6 Michael Hanselmann
      finally:
831 887c7aa6 Michael Hanselmann
        self.sl.release()
832 887c7aa6 Michael Hanselmann
833 887c7aa6 Michael Hanselmann
    counter = itertools.count(0)
834 887c7aa6 Michael Hanselmann
    priorities = range(-20, 30)
835 887c7aa6 Michael Hanselmann
    first = threading.Event()
836 887c7aa6 Michael Hanselmann
    prev = first
837 887c7aa6 Michael Hanselmann
838 887c7aa6 Michael Hanselmann
    # Data structure:
839 887c7aa6 Michael Hanselmann
    # {
840 887c7aa6 Michael Hanselmann
    #   priority:
841 887c7aa6 Michael Hanselmann
    #     [(shared/exclusive, set(acquire names), set(pending threads)),
842 887c7aa6 Michael Hanselmann
    #      (shared/exclusive, ...),
843 887c7aa6 Michael Hanselmann
    #      ...,
844 887c7aa6 Michael Hanselmann
    #     ],
845 887c7aa6 Michael Hanselmann
    # }
846 887c7aa6 Michael Hanselmann
    perprio = {}
847 887c7aa6 Michael Hanselmann
848 887c7aa6 Michael Hanselmann
    # References shared acquire per priority in L{perprio}. Data structure:
849 887c7aa6 Michael Hanselmann
    # {
850 887c7aa6 Michael Hanselmann
    #   priority: (shared=1, set(acquire names), set(pending threads)),
851 887c7aa6 Michael Hanselmann
    # }
852 887c7aa6 Michael Hanselmann
    prioshared = {}
853 887c7aa6 Michael Hanselmann
854 887c7aa6 Michael Hanselmann
    for seed in [4979, 9523, 14902, 32440]:
855 887c7aa6 Michael Hanselmann
      # Use a deterministic random generator
856 887c7aa6 Michael Hanselmann
      rnd = random.Random(seed)
857 887c7aa6 Michael Hanselmann
      for priority in [rnd.choice(priorities) for _ in range(30)]:
858 887c7aa6 Michael Hanselmann
        modes = [0, 1]
859 887c7aa6 Michael Hanselmann
        rnd.shuffle(modes)
860 887c7aa6 Michael Hanselmann
        for shared in modes:
861 887c7aa6 Michael Hanselmann
          # Unique name
862 887c7aa6 Michael Hanselmann
          acqname = "%s/shr=%s/prio=%s" % (counter.next(), shared, priority)
863 887c7aa6 Michael Hanselmann
864 887c7aa6 Michael Hanselmann
          ev = threading.Event()
865 887c7aa6 Michael Hanselmann
          thread = self._addThread(target=_Acquire,
866 887c7aa6 Michael Hanselmann
                                   args=(prev, ev, shared, priority, acqname))
867 887c7aa6 Michael Hanselmann
          prev = ev
868 887c7aa6 Michael Hanselmann
869 887c7aa6 Michael Hanselmann
          # Record expected aqcuire, see above for structure
870 887c7aa6 Michael Hanselmann
          data = (shared, set([acqname]), set([thread]))
871 887c7aa6 Michael Hanselmann
          priolist = perprio.setdefault(priority, [])
872 887c7aa6 Michael Hanselmann
          if shared:
873 887c7aa6 Michael Hanselmann
            priosh = prioshared.get(priority, None)
874 887c7aa6 Michael Hanselmann
            if priosh:
875 887c7aa6 Michael Hanselmann
              # Shared acquires are merged
876 887c7aa6 Michael Hanselmann
              for i, j in zip(priosh[1:], data[1:]):
877 887c7aa6 Michael Hanselmann
                i.update(j)
878 887c7aa6 Michael Hanselmann
              assert data[0] == priosh[0]
879 887c7aa6 Michael Hanselmann
            else:
880 887c7aa6 Michael Hanselmann
              prioshared[priority] = data
881 887c7aa6 Michael Hanselmann
              priolist.append(data)
882 887c7aa6 Michael Hanselmann
          else:
883 887c7aa6 Michael Hanselmann
            priolist.append(data)
884 887c7aa6 Michael Hanselmann
885 887c7aa6 Michael Hanselmann
    # Start all acquires and wait for them
886 887c7aa6 Michael Hanselmann
    first.set()
887 887c7aa6 Michael Hanselmann
    prev.wait()
888 887c7aa6 Michael Hanselmann
889 887c7aa6 Michael Hanselmann
    # Check lock information
890 24d16f76 Michael Hanselmann
    self.assertEqual(self.sl.GetInfo(set()), (self.sl.name, None, None, None))
891 24d16f76 Michael Hanselmann
    self.assertEqual(self.sl.GetInfo(set([query.LQ_MODE, query.LQ_OWNER])),
892 24d16f76 Michael Hanselmann
                     (self.sl.name, "exclusive",
893 24d16f76 Michael Hanselmann
                      [threading.currentThread().getName()], None))
894 24d16f76 Michael Hanselmann
895 24d16f76 Michael Hanselmann
    self._VerifyPrioPending(self.sl.GetInfo(set([query.LQ_PENDING])), perprio)
896 887c7aa6 Michael Hanselmann
897 887c7aa6 Michael Hanselmann
    # Let threads acquire the lock
898 887c7aa6 Michael Hanselmann
    self.sl.release()
899 887c7aa6 Michael Hanselmann
900 887c7aa6 Michael Hanselmann
    # Wait for everything to finish
901 887c7aa6 Michael Hanselmann
    self._waitThreads()
902 887c7aa6 Michael Hanselmann
903 887c7aa6 Michael Hanselmann
    self.assert_(self.sl._check_empty())
904 887c7aa6 Michael Hanselmann
905 887c7aa6 Michael Hanselmann
    # Check acquires by priority
906 887c7aa6 Michael Hanselmann
    for acquires in [perprio[i] for i in sorted(perprio.keys())]:
907 887c7aa6 Michael Hanselmann
      for (_, names, _) in acquires:
908 887c7aa6 Michael Hanselmann
        # For shared acquires, the set will contain 1..n entries. For exclusive
909 887c7aa6 Michael Hanselmann
        # acquires only one.
910 887c7aa6 Michael Hanselmann
        while names:
911 887c7aa6 Michael Hanselmann
          names.remove(self.done.get_nowait())
912 887c7aa6 Michael Hanselmann
      self.assertFalse(compat.any(names for (_, names, _) in acquires))
913 887c7aa6 Michael Hanselmann
914 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
915 887c7aa6 Michael Hanselmann
916 24d16f76 Michael Hanselmann
  def _VerifyPrioPending(self, (name, mode, owner, pending), perprio):
917 24d16f76 Michael Hanselmann
    self.assertEqual(name, self.sl.name)
918 24d16f76 Michael Hanselmann
    self.assert_(mode is None)
919 24d16f76 Michael Hanselmann
    self.assert_(owner is None)
920 24d16f76 Michael Hanselmann
921 24d16f76 Michael Hanselmann
    self.assertEqual([(pendmode, sorted(waiting))
922 24d16f76 Michael Hanselmann
                      for (pendmode, waiting) in pending],
923 24d16f76 Michael Hanselmann
                     [(["exclusive", "shared"][int(bool(shared))],
924 24d16f76 Michael Hanselmann
                       sorted(t.getName() for t in threads))
925 24d16f76 Michael Hanselmann
                      for acquires in [perprio[i]
926 24d16f76 Michael Hanselmann
                                       for i in sorted(perprio.keys())]
927 24d16f76 Michael Hanselmann
                      for (shared, _, threads) in acquires])
928 24d16f76 Michael Hanselmann
929 162c1c1f Guido Trotter
930 1a4e32d0 Guido Trotter
class TestSharedLockInCondition(_ThreadedTestCase):
931 1a4e32d0 Guido Trotter
  """SharedLock as a condition lock tests"""
932 1a4e32d0 Guido Trotter
933 1a4e32d0 Guido Trotter
  def setUp(self):
934 1a4e32d0 Guido Trotter
    _ThreadedTestCase.setUp(self)
935 7f93570a Iustin Pop
    self.sl = locking.SharedLock("TestSharedLockInCondition")
936 7f890059 Guido Trotter
    self.setCondition()
937 7f890059 Guido Trotter
938 7f890059 Guido Trotter
  def setCondition(self):
939 1a4e32d0 Guido Trotter
    self.cond = threading.Condition(self.sl)
940 1a4e32d0 Guido Trotter
941 1a4e32d0 Guido Trotter
  def testKeepMode(self):
942 1a4e32d0 Guido Trotter
    self.cond.acquire(shared=1)
943 1a4e32d0 Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
944 1a4e32d0 Guido Trotter
    self.cond.wait(0)
945 1a4e32d0 Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
946 1a4e32d0 Guido Trotter
    self.cond.release()
947 1a4e32d0 Guido Trotter
    self.cond.acquire(shared=0)
948 1a4e32d0 Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
949 1a4e32d0 Guido Trotter
    self.cond.wait(0)
950 1a4e32d0 Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
951 1a4e32d0 Guido Trotter
    self.cond.release()
952 1a4e32d0 Guido Trotter
953 1a4e32d0 Guido Trotter
954 7f890059 Guido Trotter
class TestSharedLockInPipeCondition(TestSharedLockInCondition):
955 7f890059 Guido Trotter
  """SharedLock as a pipe condition lock tests"""
956 7f890059 Guido Trotter
957 7f890059 Guido Trotter
  def setCondition(self):
958 7f890059 Guido Trotter
    self.cond = locking.PipeCondition(self.sl)
959 7f890059 Guido Trotter
960 7f890059 Guido Trotter
961 4607c978 Iustin Pop
class TestSSynchronizedDecorator(_ThreadedTestCase):
962 42a999d1 Guido Trotter
  """Shared Lock Synchronized decorator test"""
963 42a999d1 Guido Trotter
964 42a999d1 Guido Trotter
  def setUp(self):
965 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
966 42a999d1 Guido Trotter
967 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock)
968 42a999d1 Guido Trotter
  def _doItExclusive(self):
969 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned())
970 42a999d1 Guido Trotter
    self.done.put('EXC')
971 42a999d1 Guido Trotter
972 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock, shared=1)
973 42a999d1 Guido Trotter
  def _doItSharer(self):
974 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned(shared=1))
975 42a999d1 Guido Trotter
    self.done.put('SHR')
976 42a999d1 Guido Trotter
977 42a999d1 Guido Trotter
  def testDecoratedFunctions(self):
978 42a999d1 Guido Trotter
    self._doItExclusive()
979 158206e0 Manuel Franceschini
    self.assertFalse(_decoratorlock._is_owned())
980 42a999d1 Guido Trotter
    self._doItSharer()
981 158206e0 Manuel Franceschini
    self.assertFalse(_decoratorlock._is_owned())
982 42a999d1 Guido Trotter
983 42a999d1 Guido Trotter
  def testSharersCanCoexist(self):
984 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
985 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
986 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
987 42a999d1 Guido Trotter
    _decoratorlock.release()
988 42a999d1 Guido Trotter
989 4607c978 Iustin Pop
  @_Repeat
990 42a999d1 Guido Trotter
  def testExclusiveBlocksExclusive(self):
991 42a999d1 Guido Trotter
    _decoratorlock.acquire()
992 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
993 42a999d1 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
994 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
995 42a999d1 Guido Trotter
    _decoratorlock.release()
996 4607c978 Iustin Pop
    self._waitThreads()
997 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
998 42a999d1 Guido Trotter
999 4607c978 Iustin Pop
  @_Repeat
1000 42a999d1 Guido Trotter
  def testExclusiveBlocksSharer(self):
1001 42a999d1 Guido Trotter
    _decoratorlock.acquire()
1002 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
1003 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1004 42a999d1 Guido Trotter
    _decoratorlock.release()
1005 4607c978 Iustin Pop
    self._waitThreads()
1006 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
1007 42a999d1 Guido Trotter
1008 4607c978 Iustin Pop
  @_Repeat
1009 42a999d1 Guido Trotter
  def testSharerBlocksExclusive(self):
1010 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
1011 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
1012 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1013 42a999d1 Guido Trotter
    _decoratorlock.release()
1014 4607c978 Iustin Pop
    self._waitThreads()
1015 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
1016 42a999d1 Guido Trotter
1017 42a999d1 Guido Trotter
1018 4607c978 Iustin Pop
class TestLockSet(_ThreadedTestCase):
1019 aaae9bc0 Guido Trotter
  """LockSet tests"""
1020 aaae9bc0 Guido Trotter
1021 aaae9bc0 Guido Trotter
  def setUp(self):
1022 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
1023 4607c978 Iustin Pop
    self._setUpLS()
1024 aaae9bc0 Guido Trotter
1025 4607c978 Iustin Pop
  def _setUpLS(self):
1026 4607c978 Iustin Pop
    """Helper to (re)initialize the lock set"""
1027 4607c978 Iustin Pop
    self.resources = ['one', 'two', 'three']
1028 7f93570a Iustin Pop
    self.ls = locking.LockSet(self.resources, "TestLockSet")
1029 4607c978 Iustin Pop
1030 aaae9bc0 Guido Trotter
  def testResources(self):
1031 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._names(), set(self.resources))
1032 7f93570a Iustin Pop
    newls = locking.LockSet([], "TestLockSet.testResources")
1033 aaae9bc0 Guido Trotter
    self.assertEquals(newls._names(), set())
1034 aaae9bc0 Guido Trotter
1035 aaae9bc0 Guido Trotter
  def testAcquireRelease(self):
1036 0cc00929 Guido Trotter
    self.assert_(self.ls.acquire('one'))
1037 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
1038 aaae9bc0 Guido Trotter
    self.ls.release()
1039 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1040 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
1041 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
1042 aaae9bc0 Guido Trotter
    self.ls.release()
1043 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1044 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'three'])
1045 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
1046 aaae9bc0 Guido Trotter
    self.ls.release('one')
1047 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
1048 aaae9bc0 Guido Trotter
    self.ls.release(['three'])
1049 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two']))
1050 aaae9bc0 Guido Trotter
    self.ls.release()
1051 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1052 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
1053 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
1054 aaae9bc0 Guido Trotter
    self.ls.release()
1055 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1056 aaae9bc0 Guido Trotter
1057 aaae9bc0 Guido Trotter
  def testNoDoubleAcquire(self):
1058 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
1059 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
1060 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
1061 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
1062 aaae9bc0 Guido Trotter
    self.ls.release()
1063 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'])
1064 aaae9bc0 Guido Trotter
    self.ls.release('one')
1065 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
1066 aaae9bc0 Guido Trotter
    self.ls.release('three')
1067 aaae9bc0 Guido Trotter
1068 aaae9bc0 Guido Trotter
  def testNoWrongRelease(self):
1069 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
1070 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
1071 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release, 'two')
1072 aaae9bc0 Guido Trotter
1073 aaae9bc0 Guido Trotter
  def testAddRemove(self):
1074 aaae9bc0 Guido Trotter
    self.ls.add('four')
1075 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1076 aaae9bc0 Guido Trotter
    self.assert_('four' in self.ls._names())
1077 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six', 'seven'], acquired=1)
1078 aaae9bc0 Guido Trotter
    self.assert_('five' in self.ls._names())
1079 aaae9bc0 Guido Trotter
    self.assert_('six' in self.ls._names())
1080 aaae9bc0 Guido Trotter
    self.assert_('seven' in self.ls._names())
1081 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
1082 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
1083 aaae9bc0 Guido Trotter
    self.assert_('five' not in self.ls._names())
1084 aaae9bc0 Guido Trotter
    self.assert_('six' not in self.ls._names())
1085 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven']))
1086 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight', acquired=1)
1087 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
1088 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
1089 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set([]))
1090 d2aff862 Guido Trotter
    self.ls.acquire(None, shared=1)
1091 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight')
1092 d2aff862 Guido Trotter
    self.ls.release()
1093 d2aff862 Guido Trotter
    self.ls.acquire(None)
1094 d2aff862 Guido Trotter
    self.ls.add('eight', acquired=1)
1095 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._names())
1096 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._list_owned())
1097 d2aff862 Guido Trotter
    self.ls.add('nine')
1098 d2aff862 Guido Trotter
    self.assert_('nine' in self.ls._names())
1099 d2aff862 Guido Trotter
    self.assert_('nine' not in self.ls._list_owned())
1100 aaae9bc0 Guido Trotter
    self.ls.release()
1101 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
1102 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
1103 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
1104 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
1105 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
1106 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
1107 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
1108 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
1109 aaae9bc0 Guido Trotter
1110 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
1111 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
1112 5e0a6daf Michael Hanselmann
    self.assertEquals(self.ls.remove('one'), ['one'])
1113 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
1114 5e0a6daf Michael Hanselmann
    self.assertEquals(self.ls.remove(['two', 'three']),
1115 3f404fc5 Guido Trotter
                      ['two', 'three'])
1116 aaae9bc0 Guido Trotter
1117 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
1118 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
1119 aaae9bc0 Guido Trotter
    self.ls.add('four')
1120 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
1121 aaae9bc0 Guido Trotter
1122 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
1123 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
1124 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
1125 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
1126 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
1127 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
1128 aaae9bc0 Guido Trotter
1129 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
1130 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
1131 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
1132 d4803c24 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
1133 d4803c24 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
1134 d4803c24 Guido Trotter
    self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
1135 3b7ed473 Guido Trotter
    # I can still add/remove elements...
1136 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
1137 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
1138 3b7ed473 Guido Trotter
    self.ls.release()
1139 3b7ed473 Guido Trotter
    # share the set-lock
1140 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
1141 3b7ed473 Guido Trotter
    # adding new elements is not possible
1142 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
1143 3b7ed473 Guido Trotter
    self.ls.release()
1144 3b7ed473 Guido Trotter
1145 d4f6a91c Guido Trotter
  def testAcquireWithRepetitions(self):
1146 d4f6a91c Guido Trotter
    self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
1147 d4f6a91c Guido Trotter
                      set(['two', 'two', 'three']))
1148 d4f6a91c Guido Trotter
    self.ls.release(['two', 'two'])
1149 d4f6a91c Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['three']))
1150 d4f6a91c Guido Trotter
1151 2e1d6d96 Guido Trotter
  def testEmptyAcquire(self):
1152 2e1d6d96 Guido Trotter
    # Acquire an empty list of locks...
1153 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([]), set())
1154 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1155 2e1d6d96 Guido Trotter
    # New locks can still be addded
1156 2e1d6d96 Guido Trotter
    self.assert_(self.ls.add('six'))
1157 2e1d6d96 Guido Trotter
    # "re-acquiring" is not an issue, since we had really acquired nothing
1158 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([], shared=1), set())
1159 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1160 2e1d6d96 Guido Trotter
    # We haven't really acquired anything, so we cannot release
1161 2e1d6d96 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
1162 2e1d6d96 Guido Trotter
1163 84e344d4 Michael Hanselmann
  def _doLockSet(self, names, shared):
1164 aaae9bc0 Guido Trotter
    try:
1165 84e344d4 Michael Hanselmann
      self.ls.acquire(names, shared=shared)
1166 aaae9bc0 Guido Trotter
      self.done.put('DONE')
1167 aaae9bc0 Guido Trotter
      self.ls.release()
1168 aaae9bc0 Guido Trotter
    except errors.LockError:
1169 aaae9bc0 Guido Trotter
      self.done.put('ERR')
1170 aaae9bc0 Guido Trotter
1171 84e344d4 Michael Hanselmann
  def _doAddSet(self, names):
1172 3b7ed473 Guido Trotter
    try:
1173 84e344d4 Michael Hanselmann
      self.ls.add(names, acquired=1)
1174 3b7ed473 Guido Trotter
      self.done.put('DONE')
1175 3b7ed473 Guido Trotter
      self.ls.release()
1176 3b7ed473 Guido Trotter
    except errors.LockError:
1177 3b7ed473 Guido Trotter
      self.done.put('ERR')
1178 3b7ed473 Guido Trotter
1179 84e344d4 Michael Hanselmann
  def _doRemoveSet(self, names):
1180 84e344d4 Michael Hanselmann
    self.done.put(self.ls.remove(names))
1181 aaae9bc0 Guido Trotter
1182 4607c978 Iustin Pop
  @_Repeat
1183 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
1184 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
1185 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
1186 4607c978 Iustin Pop
    self._waitThreads()
1187 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1188 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two', 'three'], 1))
1189 4607c978 Iustin Pop
    self._waitThreads()
1190 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1191 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
1192 4607c978 Iustin Pop
    self._waitThreads()
1193 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1194 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
1195 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
1196 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1197 aaae9bc0 Guido Trotter
    self.ls.release()
1198 4607c978 Iustin Pop
    self._waitThreads()
1199 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1200 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1201 aaae9bc0 Guido Trotter
1202 4607c978 Iustin Pop
  @_Repeat
1203 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
1204 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
1205 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
1206 4607c978 Iustin Pop
    self._waitThreads()
1207 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1208 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 0))
1209 4607c978 Iustin Pop
    self._waitThreads()
1210 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1211 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1212 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
1213 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
1214 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 0))
1215 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 1))
1216 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
1217 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 1))
1218 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1219 aaae9bc0 Guido Trotter
    self.ls.release()
1220 4607c978 Iustin Pop
    self._waitThreads()
1221 4607c978 Iustin Pop
    for _ in range(6):
1222 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
1223 aaae9bc0 Guido Trotter
1224 4607c978 Iustin Pop
  @_Repeat
1225 5aab242c Michael Hanselmann
  def testSimpleAcquireTimeoutExpiring(self):
1226 5aab242c Michael Hanselmann
    names = sorted(self.ls._names())
1227 5aab242c Michael Hanselmann
    self.assert_(len(names) >= 3)
1228 5aab242c Michael Hanselmann
1229 5aab242c Michael Hanselmann
    # Get name of first lock
1230 5aab242c Michael Hanselmann
    first = names[0]
1231 5aab242c Michael Hanselmann
1232 5aab242c Michael Hanselmann
    # Get name of last lock
1233 5aab242c Michael Hanselmann
    last = names.pop()
1234 5aab242c Michael Hanselmann
1235 5aab242c Michael Hanselmann
    checks = [
1236 5aab242c Michael Hanselmann
      # Block first and try to lock it again
1237 5aab242c Michael Hanselmann
      (first, first),
1238 5aab242c Michael Hanselmann
1239 5aab242c Michael Hanselmann
      # Block last and try to lock all locks
1240 5aab242c Michael Hanselmann
      (None, first),
1241 5aab242c Michael Hanselmann
1242 5aab242c Michael Hanselmann
      # Block last and try to lock it again
1243 5aab242c Michael Hanselmann
      (last, last),
1244 5aab242c Michael Hanselmann
      ]
1245 5aab242c Michael Hanselmann
1246 5aab242c Michael Hanselmann
    for (wanted, block) in checks:
1247 5aab242c Michael Hanselmann
      # Lock in exclusive mode
1248 5aab242c Michael Hanselmann
      self.assert_(self.ls.acquire(block, shared=0))
1249 5aab242c Michael Hanselmann
1250 5aab242c Michael Hanselmann
      def _AcquireOne():
1251 5aab242c Michael Hanselmann
        # Try to get the same lock again with a timeout (should never succeed)
1252 23683c26 Michael Hanselmann
        acquired = self.ls.acquire(wanted, timeout=0.1, shared=0)
1253 23683c26 Michael Hanselmann
        if acquired:
1254 5aab242c Michael Hanselmann
          self.done.put("acquired")
1255 5aab242c Michael Hanselmann
          self.ls.release()
1256 5aab242c Michael Hanselmann
        else:
1257 23683c26 Michael Hanselmann
          self.assert_(acquired is None)
1258 158206e0 Manuel Franceschini
          self.assertFalse(self.ls._list_owned())
1259 158206e0 Manuel Franceschini
          self.assertFalse(self.ls._is_owned())
1260 5aab242c Michael Hanselmann
          self.done.put("not acquired")
1261 5aab242c Michael Hanselmann
1262 5aab242c Michael Hanselmann
      self._addThread(target=_AcquireOne)
1263 5aab242c Michael Hanselmann
1264 5aab242c Michael Hanselmann
      # Wait for timeout in thread to expire
1265 5aab242c Michael Hanselmann
      self._waitThreads()
1266 5aab242c Michael Hanselmann
1267 5aab242c Michael Hanselmann
      # Release exclusive lock again
1268 5aab242c Michael Hanselmann
      self.ls.release()
1269 5aab242c Michael Hanselmann
1270 5aab242c Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "not acquired")
1271 5aab242c Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
1272 5aab242c Michael Hanselmann
1273 5aab242c Michael Hanselmann
  @_Repeat
1274 5aab242c Michael Hanselmann
  def testDelayedAndExpiringLockAcquire(self):
1275 5aab242c Michael Hanselmann
    self._setUpLS()
1276 5aab242c Michael Hanselmann
    self.ls.add(['five', 'six', 'seven', 'eight', 'nine'])
1277 5aab242c Michael Hanselmann
1278 5aab242c Michael Hanselmann
    for expire in (False, True):
1279 5aab242c Michael Hanselmann
      names = sorted(self.ls._names())
1280 5aab242c Michael Hanselmann
      self.assertEqual(len(names), 8)
1281 5aab242c Michael Hanselmann
1282 5aab242c Michael Hanselmann
      lock_ev = dict([(i, threading.Event()) for i in names])
1283 5aab242c Michael Hanselmann
1284 5aab242c Michael Hanselmann
      # Lock all in exclusive mode
1285 5aab242c Michael Hanselmann
      self.assert_(self.ls.acquire(names, shared=0))
1286 5aab242c Michael Hanselmann
1287 5aab242c Michael Hanselmann
      if expire:
1288 5aab242c Michael Hanselmann
        # We'll wait at least 300ms per lock
1289 5aab242c Michael Hanselmann
        lockwait = len(names) * [0.3]
1290 5aab242c Michael Hanselmann
1291 5aab242c Michael Hanselmann
        # Fail if we can't acquire all locks in 400ms. There are 8 locks, so
1292 5aab242c Michael Hanselmann
        # this gives us up to 2.4s to fail.
1293 5aab242c Michael Hanselmann
        lockall_timeout = 0.4
1294 5aab242c Michael Hanselmann
      else:
1295 5aab242c Michael Hanselmann
        # This should finish rather quickly
1296 5aab242c Michael Hanselmann
        lockwait = None
1297 5aab242c Michael Hanselmann
        lockall_timeout = len(names) * 5.0
1298 5aab242c Michael Hanselmann
1299 5aab242c Michael Hanselmann
      def _LockAll():
1300 5aab242c Michael Hanselmann
        def acquire_notification(name):
1301 5aab242c Michael Hanselmann
          if not expire:
1302 5aab242c Michael Hanselmann
            self.done.put("getting %s" % name)
1303 5aab242c Michael Hanselmann
1304 5aab242c Michael Hanselmann
          # Kick next lock
1305 5aab242c Michael Hanselmann
          lock_ev[name].set()
1306 5aab242c Michael Hanselmann
1307 5aab242c Michael Hanselmann
        if self.ls.acquire(names, shared=0, timeout=lockall_timeout,
1308 5aab242c Michael Hanselmann
                           test_notify=acquire_notification):
1309 5aab242c Michael Hanselmann
          self.done.put("got all")
1310 5aab242c Michael Hanselmann
          self.ls.release()
1311 5aab242c Michael Hanselmann
        else:
1312 5aab242c Michael Hanselmann
          self.done.put("timeout on all")
1313 5aab242c Michael Hanselmann
1314 5aab242c Michael Hanselmann
        # Notify all locks
1315 5aab242c Michael Hanselmann
        for ev in lock_ev.values():
1316 5aab242c Michael Hanselmann
          ev.set()
1317 5aab242c Michael Hanselmann
1318 5aab242c Michael Hanselmann
      t = self._addThread(target=_LockAll)
1319 5aab242c Michael Hanselmann
1320 5aab242c Michael Hanselmann
      for idx, name in enumerate(names):
1321 5aab242c Michael Hanselmann
        # Wait for actual acquire on this lock to start
1322 5aab242c Michael Hanselmann
        lock_ev[name].wait(10.0)
1323 5aab242c Michael Hanselmann
1324 5aab242c Michael Hanselmann
        if expire and t.isAlive():
1325 5aab242c Michael Hanselmann
          # Wait some time after getting the notification to make sure the lock
1326 5aab242c Michael Hanselmann
          # acquire will expire
1327 5aab242c Michael Hanselmann
          SafeSleep(lockwait[idx])
1328 5aab242c Michael Hanselmann
1329 5aab242c Michael Hanselmann
        self.ls.release(names=name)
1330 5aab242c Michael Hanselmann
1331 158206e0 Manuel Franceschini
      self.assertFalse(self.ls._list_owned())
1332 5aab242c Michael Hanselmann
1333 5aab242c Michael Hanselmann
      self._waitThreads()
1334 5aab242c Michael Hanselmann
1335 5aab242c Michael Hanselmann
      if expire:
1336 5aab242c Michael Hanselmann
        # Not checking which locks were actually acquired. Doing so would be
1337 5aab242c Michael Hanselmann
        # too timing-dependant.
1338 5aab242c Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "timeout on all")
1339 5aab242c Michael Hanselmann
      else:
1340 5aab242c Michael Hanselmann
        for i in names:
1341 5aab242c Michael Hanselmann
          self.assertEqual(self.done.get_nowait(), "getting %s" % i)
1342 5aab242c Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "got all")
1343 5aab242c Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
1344 5aab242c Michael Hanselmann
1345 5aab242c Michael Hanselmann
  @_Repeat
1346 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
1347 aaae9bc0 Guido Trotter
    self.ls.add('four')
1348 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
1349 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 0))
1350 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 1))
1351 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
1352 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
1353 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1354 aaae9bc0 Guido Trotter
    self.ls.remove('one')
1355 aaae9bc0 Guido Trotter
    self.ls.release()
1356 4607c978 Iustin Pop
    self._waitThreads()
1357 4607c978 Iustin Pop
    for i in range(4):
1358 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'ERR')
1359 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
1360 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 1))
1361 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 0))
1362 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 1))
1363 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 0))
1364 aaae9bc0 Guido Trotter
    self.ls.remove('five')
1365 aaae9bc0 Guido Trotter
    self.ls.release()
1366 4607c978 Iustin Pop
    self._waitThreads()
1367 4607c978 Iustin Pop
    for i in range(4):
1368 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
1369 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
1370 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['four', 'six'], ))
1371 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1372 aaae9bc0 Guido Trotter
    self.ls.remove('four')
1373 4607c978 Iustin Pop
    self._waitThreads()
1374 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['six'])
1375 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two']))
1376 4607c978 Iustin Pop
    self._waitThreads()
1377 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['two'])
1378 aaae9bc0 Guido Trotter
    self.ls.release()
1379 4607c978 Iustin Pop
    # reset lockset
1380 4607c978 Iustin Pop
    self._setUpLS()
1381 aaae9bc0 Guido Trotter
1382 4607c978 Iustin Pop
  @_Repeat
1383 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
1384 3b7ed473 Guido Trotter
    # share the set-lock...
1385 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
1386 3b7ed473 Guido Trotter
    # ...another thread can share it too
1387 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1388 4607c978 Iustin Pop
    self._waitThreads()
1389 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1390 3b7ed473 Guido Trotter
    # ...or just share some elements
1391 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'three'], 1))
1392 4607c978 Iustin Pop
    self._waitThreads()
1393 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1394 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
1395 4607c978 Iustin Pop
    t = self._addThread(target=self._doAddSet, args=(['nine']))
1396 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two'], ))
1397 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1398 3b7ed473 Guido Trotter
    # this just releases the set-lock
1399 3b7ed473 Guido Trotter
    self.ls.release([])
1400 4607c978 Iustin Pop
    t.join(60)
1401 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1402 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
1403 3b7ed473 Guido Trotter
    self.ls.release()
1404 4607c978 Iustin Pop
    self._waitThreads()
1405 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), ['two'])
1406 4607c978 Iustin Pop
    # reset lockset
1407 4607c978 Iustin Pop
    self._setUpLS()
1408 3b7ed473 Guido Trotter
1409 4607c978 Iustin Pop
  @_Repeat
1410 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
1411 3b7ed473 Guido Trotter
    # acquire the set-lock...
1412 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
1413 3b7ed473 Guido Trotter
    # ...no one can do anything else
1414 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1415 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1416 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three'], 0))
1417 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two'], 1))
1418 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1419 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1420 3b7ed473 Guido Trotter
    self.ls.release()
1421 4607c978 Iustin Pop
    self._waitThreads()
1422 4607c978 Iustin Pop
    for _ in range(5):
1423 4607c978 Iustin Pop
      self.assertEqual(self.done.get(True, 1), 'DONE')
1424 4607c978 Iustin Pop
    # cleanup
1425 4607c978 Iustin Pop
    self._setUpLS()
1426 3b7ed473 Guido Trotter
1427 4607c978 Iustin Pop
  @_Repeat
1428 d2aff862 Guido Trotter
  def testConcurrentSetLockAdd(self):
1429 d2aff862 Guido Trotter
    self.ls.acquire('one')
1430 d2aff862 Guido Trotter
    # Another thread wants the whole SetLock
1431 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1432 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1433 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1434 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'four')
1435 d2aff862 Guido Trotter
    self.ls.release()
1436 4607c978 Iustin Pop
    self._waitThreads()
1437 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1438 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1439 d2aff862 Guido Trotter
    self.ls.acquire(None)
1440 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1441 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1442 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1443 d2aff862 Guido Trotter
    self.ls.add('four')
1444 d2aff862 Guido Trotter
    self.ls.add('five', acquired=1)
1445 d2aff862 Guido Trotter
    self.ls.add('six', acquired=1, shared=1)
1446 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(),
1447 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'five', 'six']))
1448 d2aff862 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
1449 d2aff862 Guido Trotter
    self.assertEquals(self.ls._names(),
1450 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'four', 'five', 'six']))
1451 d2aff862 Guido Trotter
    self.ls.release()
1452 4607c978 Iustin Pop
    self._waitThreads()
1453 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1454 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1455 4607c978 Iustin Pop
    self._setUpLS()
1456 d2aff862 Guido Trotter
1457 4607c978 Iustin Pop
  @_Repeat
1458 b2dabfd6 Guido Trotter
  def testEmptyLockSet(self):
1459 b2dabfd6 Guido Trotter
    # get the set-lock
1460 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
1461 b2dabfd6 Guido Trotter
    # now empty it...
1462 b2dabfd6 Guido Trotter
    self.ls.remove(['one', 'two', 'three'])
1463 b2dabfd6 Guido Trotter
    # and adds/locks by another thread still wait
1464 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1465 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1466 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1467 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1468 b2dabfd6 Guido Trotter
    self.ls.release()
1469 4607c978 Iustin Pop
    self._waitThreads()
1470 4607c978 Iustin Pop
    for _ in range(3):
1471 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'DONE')
1472 b2dabfd6 Guido Trotter
    # empty it again...
1473 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
1474 b2dabfd6 Guido Trotter
    # now share it...
1475 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None, shared=1), set())
1476 b2dabfd6 Guido Trotter
    # other sharers can go, adds still wait
1477 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1478 4607c978 Iustin Pop
    self._waitThreads()
1479 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1480 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1481 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1482 b2dabfd6 Guido Trotter
    self.ls.release()
1483 4607c978 Iustin Pop
    self._waitThreads()
1484 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1485 4607c978 Iustin Pop
    self._setUpLS()
1486 b2dabfd6 Guido Trotter
1487 3dbe3ddf Michael Hanselmann
  def testAcquireWithNamesDowngrade(self):
1488 3dbe3ddf Michael Hanselmann
    self.assertEquals(self.ls.acquire("two", shared=0), set(["two"]))
1489 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls._is_owned())
1490 3dbe3ddf Michael Hanselmann
    self.assertFalse(self.ls._get_lock()._is_owned())
1491 3dbe3ddf Michael Hanselmann
    self.ls.release()
1492 3dbe3ddf Michael Hanselmann
    self.assertFalse(self.ls._is_owned())
1493 3dbe3ddf Michael Hanselmann
    self.assertFalse(self.ls._get_lock()._is_owned())
1494 3dbe3ddf Michael Hanselmann
    # Can't downgrade after releasing
1495 3dbe3ddf Michael Hanselmann
    self.assertRaises(AssertionError, self.ls.downgrade, "two")
1496 3dbe3ddf Michael Hanselmann
1497 3dbe3ddf Michael Hanselmann
  def testDowngrade(self):
1498 3dbe3ddf Michael Hanselmann
    # Not owning anything, must raise an exception
1499 3dbe3ddf Michael Hanselmann
    self.assertFalse(self.ls._is_owned())
1500 3dbe3ddf Michael Hanselmann
    self.assertRaises(AssertionError, self.ls.downgrade)
1501 3dbe3ddf Michael Hanselmann
1502 3dbe3ddf Michael Hanselmann
    self.assertFalse(compat.any(i._is_owned()
1503 3dbe3ddf Michael Hanselmann
                                for i in self.ls._get_lockdict().values()))
1504 3dbe3ddf Michael Hanselmann
1505 3dbe3ddf Michael Hanselmann
    self.assertEquals(self.ls.acquire(None, shared=0),
1506 3dbe3ddf Michael Hanselmann
                      set(["one", "two", "three"]))
1507 3dbe3ddf Michael Hanselmann
    self.assertRaises(AssertionError, self.ls.downgrade, "unknown lock")
1508 3dbe3ddf Michael Hanselmann
1509 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls._get_lock()._is_owned(shared=0))
1510 3dbe3ddf Michael Hanselmann
    self.assertTrue(compat.all(i._is_owned(shared=0)
1511 3dbe3ddf Michael Hanselmann
                               for i in self.ls._get_lockdict().values()))
1512 3dbe3ddf Michael Hanselmann
1513 3dbe3ddf Michael Hanselmann
    # Start downgrading locks
1514 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls.downgrade(names=["one"]))
1515 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls._get_lock()._is_owned(shared=0))
1516 3dbe3ddf Michael Hanselmann
    self.assertTrue(compat.all(lock._is_owned(shared=[0, 1][int(name == "one")])
1517 3dbe3ddf Michael Hanselmann
                               for name, lock in
1518 3dbe3ddf Michael Hanselmann
                                 self.ls._get_lockdict().items()))
1519 3dbe3ddf Michael Hanselmann
1520 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls.downgrade(names="two"))
1521 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls._get_lock()._is_owned(shared=0))
1522 3dbe3ddf Michael Hanselmann
    should_share = lambda name: [0, 1][int(name in ("one", "two"))]
1523 3dbe3ddf Michael Hanselmann
    self.assertTrue(compat.all(lock._is_owned(shared=should_share(name))
1524 3dbe3ddf Michael Hanselmann
                               for name, lock in
1525 3dbe3ddf Michael Hanselmann
                                 self.ls._get_lockdict().items()))
1526 3dbe3ddf Michael Hanselmann
1527 3dbe3ddf Michael Hanselmann
    # Downgrading the last exclusive lock to shared must downgrade the
1528 3dbe3ddf Michael Hanselmann
    # lockset-internal lock too
1529 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls.downgrade(names="three"))
1530 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls._get_lock()._is_owned(shared=1))
1531 3dbe3ddf Michael Hanselmann
    self.assertTrue(compat.all(i._is_owned(shared=1)
1532 3dbe3ddf Michael Hanselmann
                               for i in self.ls._get_lockdict().values()))
1533 3dbe3ddf Michael Hanselmann
1534 3dbe3ddf Michael Hanselmann
    # Downgrading a shared lock must be a no-op
1535 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls.downgrade(names=["one", "three"]))
1536 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls._get_lock()._is_owned(shared=1))
1537 3dbe3ddf Michael Hanselmann
    self.assertTrue(compat.all(i._is_owned(shared=1)
1538 3dbe3ddf Michael Hanselmann
                               for i in self.ls._get_lockdict().values()))
1539 3dbe3ddf Michael Hanselmann
1540 3dbe3ddf Michael Hanselmann
    self.ls.release()
1541 3dbe3ddf Michael Hanselmann
1542 887c7aa6 Michael Hanselmann
  def testPriority(self):
1543 887c7aa6 Michael Hanselmann
    def _Acquire(prev, next, name, priority, success_fn):
1544 887c7aa6 Michael Hanselmann
      prev.wait()
1545 887c7aa6 Michael Hanselmann
      self.assert_(self.ls.acquire(name, shared=0,
1546 887c7aa6 Michael Hanselmann
                                   priority=priority,
1547 887c7aa6 Michael Hanselmann
                                   test_notify=lambda _: next.set()))
1548 887c7aa6 Michael Hanselmann
      try:
1549 887c7aa6 Michael Hanselmann
        success_fn()
1550 887c7aa6 Michael Hanselmann
      finally:
1551 887c7aa6 Michael Hanselmann
        self.ls.release()
1552 887c7aa6 Michael Hanselmann
1553 887c7aa6 Michael Hanselmann
    # Get all in exclusive mode
1554 887c7aa6 Michael Hanselmann
    self.assert_(self.ls.acquire(locking.ALL_SET, shared=0))
1555 887c7aa6 Michael Hanselmann
1556 887c7aa6 Michael Hanselmann
    done_two = Queue.Queue(0)
1557 887c7aa6 Michael Hanselmann
1558 887c7aa6 Michael Hanselmann
    first = threading.Event()
1559 887c7aa6 Michael Hanselmann
    prev = first
1560 887c7aa6 Michael Hanselmann
1561 887c7aa6 Michael Hanselmann
    acquires = [("one", prio, self.done) for prio in range(1, 33)]
1562 887c7aa6 Michael Hanselmann
    acquires.extend([("two", prio, done_two) for prio in range(1, 33)])
1563 887c7aa6 Michael Hanselmann
1564 887c7aa6 Michael Hanselmann
    # Use a deterministic random generator
1565 887c7aa6 Michael Hanselmann
    random.Random(741).shuffle(acquires)
1566 887c7aa6 Michael Hanselmann
1567 887c7aa6 Michael Hanselmann
    for (name, prio, done) in acquires:
1568 887c7aa6 Michael Hanselmann
      ev = threading.Event()
1569 887c7aa6 Michael Hanselmann
      self._addThread(target=_Acquire,
1570 887c7aa6 Michael Hanselmann
                      args=(prev, ev, name, prio,
1571 887c7aa6 Michael Hanselmann
                            compat.partial(done.put, "Prio%s" % prio)))
1572 887c7aa6 Michael Hanselmann
      prev = ev
1573 887c7aa6 Michael Hanselmann
1574 887c7aa6 Michael Hanselmann
    # Start acquires
1575 887c7aa6 Michael Hanselmann
    first.set()
1576 887c7aa6 Michael Hanselmann
1577 887c7aa6 Michael Hanselmann
    # Wait for last acquire to start
1578 887c7aa6 Michael Hanselmann
    prev.wait()
1579 887c7aa6 Michael Hanselmann
1580 887c7aa6 Michael Hanselmann
    # Let threads acquire locks
1581 887c7aa6 Michael Hanselmann
    self.ls.release()
1582 887c7aa6 Michael Hanselmann
1583 887c7aa6 Michael Hanselmann
    # Wait for threads to finish
1584 887c7aa6 Michael Hanselmann
    self._waitThreads()
1585 887c7aa6 Michael Hanselmann
1586 887c7aa6 Michael Hanselmann
    for i in range(1, 33):
1587 887c7aa6 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "Prio%s" % i)
1588 887c7aa6 Michael Hanselmann
      self.assertEqual(done_two.get_nowait(), "Prio%s" % i)
1589 887c7aa6 Michael Hanselmann
1590 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1591 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, done_two.get_nowait)
1592 887c7aa6 Michael Hanselmann
1593 aaae9bc0 Guido Trotter
1594 4607c978 Iustin Pop
class TestGanetiLockManager(_ThreadedTestCase):
1595 7ee7c0c7 Guido Trotter
1596 7ee7c0c7 Guido Trotter
  def setUp(self):
1597 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
1598 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
1599 819ca990 Guido Trotter
    self.nodegroups=['g1', 'g2']
1600 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
1601 819ca990 Guido Trotter
    self.GL = locking.GanetiLockManager(self.nodes, self.nodegroups,
1602 819ca990 Guido Trotter
                                        self.instances)
1603 7ee7c0c7 Guido Trotter
1604 7ee7c0c7 Guido Trotter
  def tearDown(self):
1605 7ee7c0c7 Guido Trotter
    # Don't try this at home...
1606 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1607 7ee7c0c7 Guido Trotter
1608 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
1609 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
1610 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
1611 b10b9d74 Guido Trotter
    # This relationship is also used in the Processor to recursively acquire
1612 b10b9d74 Guido Trotter
    # the right locks. Again, please don't break it.
1613 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
1614 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
1615 7ee7c0c7 Guido Trotter
1616 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
1617 819ca990 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager, [], [], [])
1618 7ee7c0c7 Guido Trotter
1619 7ee7c0c7 Guido Trotter
  def testLockNames(self):
1620 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1621 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1622 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP),
1623 819ca990 Guido Trotter
                     set(self.nodegroups))
1624 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1625 cdb08f44 Michael Hanselmann
                     set(self.instances))
1626 7ee7c0c7 Guido Trotter
1627 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
1628 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1629 819ca990 Guido Trotter
    self.GL = locking.GanetiLockManager([], [], [])
1630 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1631 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1632 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set())
1633 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1634 7ee7c0c7 Guido Trotter
1635 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1636 819ca990 Guido Trotter
    self.GL = locking.GanetiLockManager(self.nodes, self.nodegroups, [])
1637 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1638 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1639 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP),
1640 819ca990 Guido Trotter
                                    set(self.nodegroups))
1641 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1642 7ee7c0c7 Guido Trotter
1643 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1644 819ca990 Guido Trotter
    self.GL = locking.GanetiLockManager([], [], self.instances)
1645 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1646 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1647 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set())
1648 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1649 cdb08f44 Michael Hanselmann
                     set(self.instances))
1650 7ee7c0c7 Guido Trotter
1651 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
1652 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1653 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
1654 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
1655 819ca990 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODEGROUP, ['g2'])
1656 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
1657 04e1bfaf Guido Trotter
    self.GL.release(locking.LEVEL_NODE, ['n2'])
1658 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
1659 819ca990 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODEGROUP), set(['g2']))
1660 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
1661 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1662 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
1663 819ca990 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODEGROUP), set(['g2']))
1664 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
1665 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_NODEGROUP)
1666 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1667 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
1668 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
1669 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
1670 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
1671 7ee7c0c7 Guido Trotter
1672 90c942d1 Guido Trotter
  def testAcquireWholeSets(self):
1673 90c942d1 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1674 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
1675 90c942d1 Guido Trotter
                      set(self.instances))
1676 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
1677 90c942d1 Guido Trotter
                      set(self.instances))
1678 819ca990 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODEGROUP, None),
1679 819ca990 Guido Trotter
                      set(self.nodegroups))
1680 819ca990 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODEGROUP),
1681 819ca990 Guido Trotter
                      set(self.nodegroups))
1682 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
1683 90c942d1 Guido Trotter
                      set(self.nodes))
1684 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
1685 90c942d1 Guido Trotter
                      set(self.nodes))
1686 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1687 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_NODEGROUP)
1688 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1689 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1690 d4f6a91c Guido Trotter
1691 d4f6a91c Guido Trotter
  def testAcquireWholeAndPartial(self):
1692 d4f6a91c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1693 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
1694 d4f6a91c Guido Trotter
                      set(self.instances))
1695 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
1696 d4f6a91c Guido Trotter
                      set(self.instances))
1697 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
1698 d4f6a91c Guido Trotter
                      set(['n2']))
1699 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
1700 d4f6a91c Guido Trotter
                      set(['n2']))
1701 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1702 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1703 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1704 90c942d1 Guido Trotter
1705 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
1706 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1707 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
1708 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1709 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
1710 819ca990 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1711 819ca990 Guido Trotter
                      locking.LEVEL_NODEGROUP, ['g1'])
1712 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1713 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
1714 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1715 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1716 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1717 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1718 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1719 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
1720 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1721 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1722 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1723 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1724 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1725 819ca990 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODEGROUP, None)
1726 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_NODEGROUP, ['g1'])
1727 819ca990 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1728 819ca990 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1729 819ca990 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1730 819ca990 Guido Trotter
                      locking.LEVEL_CLUSTER)
1731 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_NODEGROUP)
1732 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1733 7ee7c0c7 Guido Trotter
1734 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
1735 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1736 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n2'])
1737 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1738 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
1739 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1740 819ca990 Guido Trotter
                      locking.LEVEL_NODEGROUP, ['g1'])
1741 819ca990 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1742 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
1743 7ee7c0c7 Guido Trotter
1744 4badc36c Guido Trotter
  def testModifiableLevels(self):
1745 4badc36c Guido Trotter
    self.assertRaises(AssertionError, self.GL.add, locking.LEVEL_CLUSTER,
1746 4badc36c Guido Trotter
                      ['BGL2'])
1747 4badc36c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'])
1748 4badc36c Guido Trotter
    self.GL.add(locking.LEVEL_INSTANCE, ['i4'])
1749 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_INSTANCE, ['i3'])
1750 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_INSTANCE, ['i1'])
1751 4badc36c Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set(['i2', 'i4']))
1752 4badc36c Guido Trotter
    self.GL.add(locking.LEVEL_NODE, ['n3'])
1753 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_NODE, ['n1'])
1754 4badc36c Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(['n2', 'n3']))
1755 819ca990 Guido Trotter
    self.GL.add(locking.LEVEL_NODEGROUP, ['g3'])
1756 819ca990 Guido Trotter
    self.GL.remove(locking.LEVEL_NODEGROUP, ['g2'])
1757 819ca990 Guido Trotter
    self.GL.remove(locking.LEVEL_NODEGROUP, ['g1'])
1758 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set(['g3']))
1759 4badc36c Guido Trotter
    self.assertRaises(AssertionError, self.GL.remove, locking.LEVEL_CLUSTER,
1760 4badc36c Guido Trotter
                      ['BGL2'])
1761 4badc36c Guido Trotter
1762 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
1763 7ee7c0c7 Guido Trotter
  # some locks at another level.
1764 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
1765 7ee7c0c7 Guido Trotter
    try:
1766 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1767 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
1768 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
1769 7ee7c0c7 Guido Trotter
      self.GL.release(level)
1770 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
1771 7ee7c0c7 Guido Trotter
    except errors.LockError:
1772 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
1773 7ee7c0c7 Guido Trotter
1774 4607c978 Iustin Pop
  @_Repeat
1775 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
1776 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1777 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1778 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1779 4607c978 Iustin Pop
    self._waitThreads()
1780 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1781 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
1782 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1783 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1784 4607c978 Iustin Pop
    self._waitThreads()
1785 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1786 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1787 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i3', 1))
1788 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1789 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1790 4607c978 Iustin Pop
    self._waitThreads()
1791 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1792 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
1793 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1794 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 1))
1795 4607c978 Iustin Pop
    self._waitThreads()
1796 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1797 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1798 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 0))
1799 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1800 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1801 4607c978 Iustin Pop
    self._waitThreads()
1802 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
1803 4607c978 Iustin Pop
    self.GL.release(locking.LEVEL_CLUSTER, ['BGL'])
1804 7ee7c0c7 Guido Trotter
1805 7ee7c0c7 Guido Trotter
1806 19b9ba9a Michael Hanselmann
class TestLockMonitor(_ThreadedTestCase):
1807 19b9ba9a Michael Hanselmann
  def setUp(self):
1808 19b9ba9a Michael Hanselmann
    _ThreadedTestCase.setUp(self)
1809 19b9ba9a Michael Hanselmann
    self.lm = locking.LockMonitor()
1810 19b9ba9a Michael Hanselmann
1811 19b9ba9a Michael Hanselmann
  def testSingleThread(self):
1812 19b9ba9a Michael Hanselmann
    locks = []
1813 19b9ba9a Michael Hanselmann
1814 19b9ba9a Michael Hanselmann
    for i in range(100):
1815 19b9ba9a Michael Hanselmann
      name = "TestLock%s" % i
1816 19b9ba9a Michael Hanselmann
      locks.append(locking.SharedLock(name, monitor=self.lm))
1817 19b9ba9a Michael Hanselmann
1818 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), len(locks))
1819 24d16f76 Michael Hanselmann
    result = objects.QueryResponse.FromDict(self.lm.QueryLocks(["name"]))
1820 24d16f76 Michael Hanselmann
    self.assertEqual(len(result.fields), 1)
1821 24d16f76 Michael Hanselmann
    self.assertEqual(len(result.data), 100)
1822 c31825f7 Michael Hanselmann
1823 19b9ba9a Michael Hanselmann
    # Delete all locks
1824 19b9ba9a Michael Hanselmann
    del locks[:]
1825 19b9ba9a Michael Hanselmann
1826 19b9ba9a Michael Hanselmann
    # The garbage collector might needs some time
1827 19b9ba9a Michael Hanselmann
    def _CheckLocks():
1828 19b9ba9a Michael Hanselmann
      if self.lm._locks:
1829 19b9ba9a Michael Hanselmann
        raise utils.RetryAgain()
1830 19b9ba9a Michael Hanselmann
1831 19b9ba9a Michael Hanselmann
    utils.Retry(_CheckLocks, 0.1, 30.0)
1832 19b9ba9a Michael Hanselmann
1833 19b9ba9a Michael Hanselmann
    self.assertFalse(self.lm._locks)
1834 19b9ba9a Michael Hanselmann
1835 19b9ba9a Michael Hanselmann
  def testMultiThread(self):
1836 19b9ba9a Michael Hanselmann
    locks = []
1837 19b9ba9a Michael Hanselmann
1838 19b9ba9a Michael Hanselmann
    def _CreateLock(prev, next, name):
1839 19b9ba9a Michael Hanselmann
      prev.wait()
1840 19b9ba9a Michael Hanselmann
      locks.append(locking.SharedLock(name, monitor=self.lm))
1841 19b9ba9a Michael Hanselmann
      if next:
1842 19b9ba9a Michael Hanselmann
        next.set()
1843 19b9ba9a Michael Hanselmann
1844 19b9ba9a Michael Hanselmann
    expnames = []
1845 19b9ba9a Michael Hanselmann
1846 19b9ba9a Michael Hanselmann
    first = threading.Event()
1847 19b9ba9a Michael Hanselmann
    prev = first
1848 19b9ba9a Michael Hanselmann
1849 19b9ba9a Michael Hanselmann
    # Use a deterministic random generator
1850 19b9ba9a Michael Hanselmann
    for i in random.Random(4263).sample(range(100), 33):
1851 19b9ba9a Michael Hanselmann
      name = "MtTestLock%s" % i
1852 19b9ba9a Michael Hanselmann
      expnames.append(name)
1853 19b9ba9a Michael Hanselmann
1854 19b9ba9a Michael Hanselmann
      ev = threading.Event()
1855 19b9ba9a Michael Hanselmann
      self._addThread(target=_CreateLock, args=(prev, ev, name))
1856 19b9ba9a Michael Hanselmann
      prev = ev
1857 19b9ba9a Michael Hanselmann
1858 19b9ba9a Michael Hanselmann
    # Add locks
1859 19b9ba9a Michael Hanselmann
    first.set()
1860 19b9ba9a Michael Hanselmann
    self._waitThreads()
1861 19b9ba9a Michael Hanselmann
1862 19b9ba9a Michael Hanselmann
    # Check order in which locks were added
1863 19b9ba9a Michael Hanselmann
    self.assertEqual([i.name for i in locks], expnames)
1864 19b9ba9a Michael Hanselmann
1865 19b9ba9a Michael Hanselmann
    # Check query result
1866 24d16f76 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner", "pending"])
1867 24d16f76 Michael Hanselmann
    self.assert_(isinstance(result, dict))
1868 24d16f76 Michael Hanselmann
    response = objects.QueryResponse.FromDict(result)
1869 24d16f76 Michael Hanselmann
    self.assertEqual(response.data,
1870 cfb084ae René Nussbaumer
                     [[(constants.RS_NORMAL, name),
1871 cfb084ae René Nussbaumer
                       (constants.RS_NORMAL, None),
1872 cfb084ae René Nussbaumer
                       (constants.RS_NORMAL, None),
1873 cfb084ae René Nussbaumer
                       (constants.RS_NORMAL, [])]
1874 c31825f7 Michael Hanselmann
                      for name in utils.NiceSort(expnames)])
1875 24d16f76 Michael Hanselmann
    self.assertEqual(len(response.fields), 4)
1876 24d16f76 Michael Hanselmann
    self.assertEqual(["name", "mode", "owner", "pending"],
1877 24d16f76 Michael Hanselmann
                     [fdef.name for fdef in response.fields])
1878 19b9ba9a Michael Hanselmann
1879 19b9ba9a Michael Hanselmann
    # Test exclusive acquire
1880 19b9ba9a Michael Hanselmann
    for tlock in locks[::4]:
1881 19b9ba9a Michael Hanselmann
      tlock.acquire(shared=0)
1882 19b9ba9a Michael Hanselmann
      try:
1883 19b9ba9a Michael Hanselmann
        def _GetExpResult(name):
1884 19b9ba9a Michael Hanselmann
          if tlock.name == name:
1885 cfb084ae René Nussbaumer
            return [(constants.RS_NORMAL, name),
1886 cfb084ae René Nussbaumer
                    (constants.RS_NORMAL, "exclusive"),
1887 cfb084ae René Nussbaumer
                    (constants.RS_NORMAL,
1888 24d16f76 Michael Hanselmann
                     [threading.currentThread().getName()]),
1889 cfb084ae René Nussbaumer
                    (constants.RS_NORMAL, [])]
1890 cfb084ae René Nussbaumer
          return [(constants.RS_NORMAL, name),
1891 cfb084ae René Nussbaumer
                  (constants.RS_NORMAL, None),
1892 cfb084ae René Nussbaumer
                  (constants.RS_NORMAL, None),
1893 cfb084ae René Nussbaumer
                  (constants.RS_NORMAL, [])]
1894 24d16f76 Michael Hanselmann
1895 24d16f76 Michael Hanselmann
        result = self.lm.QueryLocks(["name", "mode", "owner", "pending"])
1896 24d16f76 Michael Hanselmann
        self.assertEqual(objects.QueryResponse.FromDict(result).data,
1897 19b9ba9a Michael Hanselmann
                         [_GetExpResult(name)
1898 19b9ba9a Michael Hanselmann
                          for name in utils.NiceSort(expnames)])
1899 19b9ba9a Michael Hanselmann
      finally:
1900 19b9ba9a Michael Hanselmann
        tlock.release()
1901 19b9ba9a Michael Hanselmann
1902 19b9ba9a Michael Hanselmann
    # Test shared acquire
1903 73c25d35 Michael Hanselmann
    def _Acquire(lock, shared, ev, notify):
1904 19b9ba9a Michael Hanselmann
      lock.acquire(shared=shared)
1905 19b9ba9a Michael Hanselmann
      try:
1906 73c25d35 Michael Hanselmann
        notify.set()
1907 19b9ba9a Michael Hanselmann
        ev.wait()
1908 19b9ba9a Michael Hanselmann
      finally:
1909 19b9ba9a Michael Hanselmann
        lock.release()
1910 19b9ba9a Michael Hanselmann
1911 19b9ba9a Michael Hanselmann
    for tlock1 in locks[::11]:
1912 19b9ba9a Michael Hanselmann
      for tlock2 in locks[::-15]:
1913 19b9ba9a Michael Hanselmann
        if tlock2 == tlock1:
1914 73c25d35 Michael Hanselmann
          # Avoid deadlocks
1915 19b9ba9a Michael Hanselmann
          continue
1916 19b9ba9a Michael Hanselmann
1917 19b9ba9a Michael Hanselmann
        for tlock3 in locks[::10]:
1918 73c25d35 Michael Hanselmann
          if tlock3 in (tlock2, tlock1):
1919 73c25d35 Michael Hanselmann
            # Avoid deadlocks
1920 19b9ba9a Michael Hanselmann
            continue
1921 19b9ba9a Michael Hanselmann
1922 73c25d35 Michael Hanselmann
          releaseev = threading.Event()
1923 19b9ba9a Michael Hanselmann
1924 19b9ba9a Michael Hanselmann
          # Acquire locks
1925 73c25d35 Michael Hanselmann
          acquireev = []
1926 19b9ba9a Michael Hanselmann
          tthreads1 = []
1927 19b9ba9a Michael Hanselmann
          for i in range(3):
1928 73c25d35 Michael Hanselmann
            ev = threading.Event()
1929 19b9ba9a Michael Hanselmann
            tthreads1.append(self._addThread(target=_Acquire,
1930 73c25d35 Michael Hanselmann
                                             args=(tlock1, 1, releaseev, ev)))
1931 73c25d35 Michael Hanselmann
            acquireev.append(ev)
1932 73c25d35 Michael Hanselmann
1933 73c25d35 Michael Hanselmann
          ev = threading.Event()
1934 73c25d35 Michael Hanselmann
          tthread2 = self._addThread(target=_Acquire,
1935 73c25d35 Michael Hanselmann
                                     args=(tlock2, 1, releaseev, ev))
1936 73c25d35 Michael Hanselmann
          acquireev.append(ev)
1937 73c25d35 Michael Hanselmann
1938 73c25d35 Michael Hanselmann
          ev = threading.Event()
1939 73c25d35 Michael Hanselmann
          tthread3 = self._addThread(target=_Acquire,
1940 73c25d35 Michael Hanselmann
                                     args=(tlock3, 0, releaseev, ev))
1941 73c25d35 Michael Hanselmann
          acquireev.append(ev)
1942 73c25d35 Michael Hanselmann
1943 73c25d35 Michael Hanselmann
          # Wait for all locks to be acquired
1944 73c25d35 Michael Hanselmann
          for i in acquireev:
1945 73c25d35 Michael Hanselmann
            i.wait()
1946 19b9ba9a Michael Hanselmann
1947 19b9ba9a Michael Hanselmann
          # Check query result
1948 24d16f76 Michael Hanselmann
          result = self.lm.QueryLocks(["name", "mode", "owner"])
1949 24d16f76 Michael Hanselmann
          response = objects.QueryResponse.FromDict(result)
1950 24d16f76 Michael Hanselmann
          for (name, mode, owner) in response.data:
1951 24d16f76 Michael Hanselmann
            (name_status, name_value) = name
1952 24d16f76 Michael Hanselmann
            (owner_status, owner_value) = owner
1953 24d16f76 Michael Hanselmann
1954 cfb084ae René Nussbaumer
            self.assertEqual(name_status, constants.RS_NORMAL)
1955 cfb084ae René Nussbaumer
            self.assertEqual(owner_status, constants.RS_NORMAL)
1956 24d16f76 Michael Hanselmann
1957 24d16f76 Michael Hanselmann
            if name_value == tlock1.name:
1958 cfb084ae René Nussbaumer
              self.assertEqual(mode, (constants.RS_NORMAL, "shared"))
1959 24d16f76 Michael Hanselmann
              self.assertEqual(set(owner_value),
1960 24d16f76 Michael Hanselmann
                               set(i.getName() for i in tthreads1))
1961 19b9ba9a Michael Hanselmann
              continue
1962 19b9ba9a Michael Hanselmann
1963 24d16f76 Michael Hanselmann
            if name_value == tlock2.name:
1964 cfb084ae René Nussbaumer
              self.assertEqual(mode, (constants.RS_NORMAL, "shared"))
1965 24d16f76 Michael Hanselmann
              self.assertEqual(owner_value, [tthread2.getName()])
1966 19b9ba9a Michael Hanselmann
              continue
1967 19b9ba9a Michael Hanselmann
1968 24d16f76 Michael Hanselmann
            if name_value == tlock3.name:
1969 cfb084ae René Nussbaumer
              self.assertEqual(mode, (constants.RS_NORMAL, "exclusive"))
1970 24d16f76 Michael Hanselmann
              self.assertEqual(owner_value, [tthread3.getName()])
1971 19b9ba9a Michael Hanselmann
              continue
1972 19b9ba9a Michael Hanselmann
1973 24d16f76 Michael Hanselmann
            self.assert_(name_value in expnames)
1974 cfb084ae René Nussbaumer
            self.assertEqual(mode, (constants.RS_NORMAL, None))
1975 24d16f76 Michael Hanselmann
            self.assert_(owner_value is None)
1976 19b9ba9a Michael Hanselmann
1977 19b9ba9a Michael Hanselmann
          # Release locks again
1978 73c25d35 Michael Hanselmann
          releaseev.set()
1979 19b9ba9a Michael Hanselmann
1980 19b9ba9a Michael Hanselmann
          self._waitThreads()
1981 19b9ba9a Michael Hanselmann
1982 24d16f76 Michael Hanselmann
          result = self.lm.QueryLocks(["name", "mode", "owner"])
1983 24d16f76 Michael Hanselmann
          self.assertEqual(objects.QueryResponse.FromDict(result).data,
1984 cfb084ae René Nussbaumer
                           [[(constants.RS_NORMAL, name),
1985 cfb084ae René Nussbaumer
                             (constants.RS_NORMAL, None),
1986 cfb084ae René Nussbaumer
                             (constants.RS_NORMAL, None)]
1987 19b9ba9a Michael Hanselmann
                            for name in utils.NiceSort(expnames)])
1988 19b9ba9a Michael Hanselmann
1989 19b9ba9a Michael Hanselmann
  def testDelete(self):
1990 19b9ba9a Michael Hanselmann
    lock = locking.SharedLock("TestLock", monitor=self.lm)
1991 19b9ba9a Michael Hanselmann
1992 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), 1)
1993 24d16f76 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
1994 24d16f76 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data,
1995 cfb084ae René Nussbaumer
                     [[(constants.RS_NORMAL, lock.name),
1996 cfb084ae René Nussbaumer
                       (constants.RS_NORMAL, None),
1997 cfb084ae René Nussbaumer
                       (constants.RS_NORMAL, None)]])
1998 19b9ba9a Michael Hanselmann
1999 19b9ba9a Michael Hanselmann
    lock.delete()
2000 19b9ba9a Michael Hanselmann
2001 24d16f76 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2002 24d16f76 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data,
2003 cfb084ae René Nussbaumer
                     [[(constants.RS_NORMAL, lock.name),
2004 cfb084ae René Nussbaumer
                       (constants.RS_NORMAL, "deleted"),
2005 cfb084ae René Nussbaumer
                       (constants.RS_NORMAL, None)]])
2006 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), 1)
2007 19b9ba9a Michael Hanselmann
2008 c31825f7 Michael Hanselmann
  def testPending(self):
2009 c31825f7 Michael Hanselmann
    def _Acquire(lock, shared, prev, next):
2010 c31825f7 Michael Hanselmann
      prev.wait()
2011 c31825f7 Michael Hanselmann
2012 c31825f7 Michael Hanselmann
      lock.acquire(shared=shared, test_notify=next.set)
2013 c31825f7 Michael Hanselmann
      try:
2014 c31825f7 Michael Hanselmann
        pass
2015 c31825f7 Michael Hanselmann
      finally:
2016 c31825f7 Michael Hanselmann
        lock.release()
2017 c31825f7 Michael Hanselmann
2018 c31825f7 Michael Hanselmann
    lock = locking.SharedLock("ExcLock", monitor=self.lm)
2019 c31825f7 Michael Hanselmann
2020 c31825f7 Michael Hanselmann
    for shared in [0, 1]:
2021 c31825f7 Michael Hanselmann
      lock.acquire()
2022 c31825f7 Michael Hanselmann
      try:
2023 c31825f7 Michael Hanselmann
        self.assertEqual(len(self.lm._locks), 1)
2024 24d16f76 Michael Hanselmann
        result = self.lm.QueryLocks(["name", "mode", "owner"])
2025 24d16f76 Michael Hanselmann
        self.assertEqual(objects.QueryResponse.FromDict(result).data,
2026 cfb084ae René Nussbaumer
                         [[(constants.RS_NORMAL, lock.name),
2027 cfb084ae René Nussbaumer
                           (constants.RS_NORMAL, "exclusive"),
2028 cfb084ae René Nussbaumer
                           (constants.RS_NORMAL,
2029 24d16f76 Michael Hanselmann
                            [threading.currentThread().getName()])]])
2030 c31825f7 Michael Hanselmann
2031 c31825f7 Michael Hanselmann
        threads = []
2032 c31825f7 Michael Hanselmann
2033 c31825f7 Michael Hanselmann
        first = threading.Event()
2034 c31825f7 Michael Hanselmann
        prev = first
2035 c31825f7 Michael Hanselmann
2036 c31825f7 Michael Hanselmann
        for i in range(5):
2037 c31825f7 Michael Hanselmann
          ev = threading.Event()
2038 c31825f7 Michael Hanselmann
          threads.append(self._addThread(target=_Acquire,
2039 c31825f7 Michael Hanselmann
                                          args=(lock, shared, prev, ev)))
2040 c31825f7 Michael Hanselmann
          prev = ev
2041 c31825f7 Michael Hanselmann
2042 c31825f7 Michael Hanselmann
        # Start acquires
2043 c31825f7 Michael Hanselmann
        first.set()
2044 c31825f7 Michael Hanselmann
2045 c31825f7 Michael Hanselmann
        # Wait for last acquire to start waiting
2046 c31825f7 Michael Hanselmann
        prev.wait()
2047 c31825f7 Michael Hanselmann
2048 c31825f7 Michael Hanselmann
        # NOTE: This works only because QueryLocks will acquire the
2049 c31825f7 Michael Hanselmann
        # lock-internal lock again and won't be able to get the information
2050 c31825f7 Michael Hanselmann
        # until it has the lock. By then the acquire should be registered in
2051 c31825f7 Michael Hanselmann
        # SharedLock.__pending (otherwise it's a bug).
2052 c31825f7 Michael Hanselmann
2053 c31825f7 Michael Hanselmann
        # All acquires are waiting now
2054 c31825f7 Michael Hanselmann
        if shared:
2055 24d16f76 Michael Hanselmann
          pending = [("shared", utils.NiceSort(t.getName() for t in threads))]
2056 c31825f7 Michael Hanselmann
        else:
2057 c31825f7 Michael Hanselmann
          pending = [("exclusive", [t.getName()]) for t in threads]
2058 c31825f7 Michael Hanselmann
2059 24d16f76 Michael Hanselmann
        result = self.lm.QueryLocks(["name", "mode", "owner", "pending"])
2060 24d16f76 Michael Hanselmann
        self.assertEqual(objects.QueryResponse.FromDict(result).data,
2061 cfb084ae René Nussbaumer
                         [[(constants.RS_NORMAL, lock.name),
2062 cfb084ae René Nussbaumer
                           (constants.RS_NORMAL, "exclusive"),
2063 cfb084ae René Nussbaumer
                           (constants.RS_NORMAL,
2064 24d16f76 Michael Hanselmann
                            [threading.currentThread().getName()]),
2065 cfb084ae René Nussbaumer
                           (constants.RS_NORMAL, pending)]])
2066 c31825f7 Michael Hanselmann
2067 c31825f7 Michael Hanselmann
        self.assertEqual(len(self.lm._locks), 1)
2068 c31825f7 Michael Hanselmann
      finally:
2069 c31825f7 Michael Hanselmann
        lock.release()
2070 c31825f7 Michael Hanselmann
2071 c31825f7 Michael Hanselmann
      self._waitThreads()
2072 c31825f7 Michael Hanselmann
2073 c31825f7 Michael Hanselmann
      # No pending acquires
2074 24d16f76 Michael Hanselmann
      result = self.lm.QueryLocks(["name", "mode", "owner", "pending"])
2075 24d16f76 Michael Hanselmann
      self.assertEqual(objects.QueryResponse.FromDict(result).data,
2076 cfb084ae René Nussbaumer
                       [[(constants.RS_NORMAL, lock.name),
2077 cfb084ae René Nussbaumer
                         (constants.RS_NORMAL, None),
2078 cfb084ae René Nussbaumer
                         (constants.RS_NORMAL, None),
2079 cfb084ae René Nussbaumer
                         (constants.RS_NORMAL, [])]])
2080 c31825f7 Michael Hanselmann
2081 c31825f7 Michael Hanselmann
      self.assertEqual(len(self.lm._locks), 1)
2082 c31825f7 Michael Hanselmann
2083 e4e35357 Michael Hanselmann
  def testDeleteAndRecreate(self):
2084 e4e35357 Michael Hanselmann
    lname = "TestLock101923193"
2085 e4e35357 Michael Hanselmann
2086 e4e35357 Michael Hanselmann
    # Create some locks with the same name and keep all references
2087 e4e35357 Michael Hanselmann
    locks = [locking.SharedLock(lname, monitor=self.lm)
2088 e4e35357 Michael Hanselmann
             for _ in range(5)]
2089 e4e35357 Michael Hanselmann
2090 e4e35357 Michael Hanselmann
    self.assertEqual(len(self.lm._locks), len(locks))
2091 e4e35357 Michael Hanselmann
2092 e4e35357 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2093 e4e35357 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data,
2094 e4e35357 Michael Hanselmann
                     [[(constants.RS_NORMAL, lname),
2095 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None),
2096 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None)]] * 5)
2097 e4e35357 Michael Hanselmann
2098 e4e35357 Michael Hanselmann
    locks[2].delete()
2099 e4e35357 Michael Hanselmann
2100 e4e35357 Michael Hanselmann
    # Check information order
2101 e4e35357 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2102 e4e35357 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data,
2103 e4e35357 Michael Hanselmann
                     [[(constants.RS_NORMAL, lname),
2104 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None),
2105 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None)]] * 2 +
2106 e4e35357 Michael Hanselmann
                     [[(constants.RS_NORMAL, lname),
2107 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, "deleted"),
2108 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None)]] +
2109 e4e35357 Michael Hanselmann
                     [[(constants.RS_NORMAL, lname),
2110 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None),
2111 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None)]] * 2)
2112 e4e35357 Michael Hanselmann
2113 e4e35357 Michael Hanselmann
    locks[1].acquire(shared=0)
2114 e4e35357 Michael Hanselmann
2115 e4e35357 Michael Hanselmann
    last_status = [
2116 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2117 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None),
2118 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None)],
2119 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2120 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, "exclusive"),
2121 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, [threading.currentThread().getName()])],
2122 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2123 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, "deleted"),
2124 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None)],
2125 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2126 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None),
2127 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None)],
2128 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2129 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None),
2130 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None)],
2131 e4e35357 Michael Hanselmann
      ]
2132 e4e35357 Michael Hanselmann
2133 e4e35357 Michael Hanselmann
    # Check information order
2134 e4e35357 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2135 e4e35357 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data, last_status)
2136 e4e35357 Michael Hanselmann
2137 e4e35357 Michael Hanselmann
    self.assertEqual(len(set(self.lm._locks.values())), len(locks))
2138 e4e35357 Michael Hanselmann
    self.assertEqual(len(self.lm._locks), len(locks))
2139 e4e35357 Michael Hanselmann
2140 e4e35357 Michael Hanselmann
    # Check lock deletion
2141 e4e35357 Michael Hanselmann
    for idx in range(len(locks)):
2142 e4e35357 Michael Hanselmann
      del locks[0]
2143 e4e35357 Michael Hanselmann
      assert gc.isenabled()
2144 e4e35357 Michael Hanselmann
      gc.collect()
2145 e4e35357 Michael Hanselmann
      self.assertEqual(len(self.lm._locks), len(locks))
2146 e4e35357 Michael Hanselmann
      result = self.lm.QueryLocks(["name", "mode", "owner"])
2147 e4e35357 Michael Hanselmann
      self.assertEqual(objects.QueryResponse.FromDict(result).data,
2148 e4e35357 Michael Hanselmann
                       last_status[idx + 1:])
2149 e4e35357 Michael Hanselmann
2150 e4e35357 Michael Hanselmann
    # All locks should have been deleted
2151 e4e35357 Michael Hanselmann
    assert not locks
2152 e4e35357 Michael Hanselmann
    self.assertFalse(self.lm._locks)
2153 e4e35357 Michael Hanselmann
2154 e4e35357 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2155 e4e35357 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data, [])
2156 e4e35357 Michael Hanselmann
2157 19b9ba9a Michael Hanselmann
2158 162c1c1f Guido Trotter
if __name__ == '__main__':
2159 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()