Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 1a2eb2dc

History | View | Annotate | Download (81.7 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 fd7b69c0 Michael Hanselmann
# 02110-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 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.sl.is_owned())
273 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
274 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned())
275 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned(shared=1))
276 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.sl.is_owned(shared=0))
277 162c1c1f Guido Trotter
    self.sl.release()
278 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.sl.is_owned())
279 162c1c1f Guido Trotter
    self.sl.acquire()
280 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned())
281 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.sl.is_owned(shared=1))
282 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned(shared=0))
283 162c1c1f Guido Trotter
    self.sl.release()
284 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.sl.is_owned())
285 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
286 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned())
287 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned(shared=1))
288 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.sl.is_owned(shared=0))
289 162c1c1f Guido Trotter
    self.sl.release()
290 ee2b99e3 Michael Hanselmann
    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 26082b7e Michael Hanselmann
    self.assertTrue(self.sl.delete(timeout=60))
437 26082b7e Michael Hanselmann
438 26082b7e Michael Hanselmann
  def testDeleteTimeoutFail(self):
439 26082b7e Michael Hanselmann
    ready = threading.Event()
440 26082b7e Michael Hanselmann
    finish = threading.Event()
441 26082b7e Michael Hanselmann
442 26082b7e Michael Hanselmann
    def fn():
443 26082b7e Michael Hanselmann
      self.sl.acquire(shared=0)
444 26082b7e Michael Hanselmann
      ready.set()
445 26082b7e Michael Hanselmann
446 26082b7e Michael Hanselmann
      finish.wait()
447 26082b7e Michael Hanselmann
      self.sl.release()
448 26082b7e Michael Hanselmann
449 26082b7e Michael Hanselmann
    self._addThread(target=fn)
450 26082b7e Michael Hanselmann
    ready.wait()
451 26082b7e Michael Hanselmann
452 26082b7e Michael Hanselmann
    # Test if deleting a lock owned in exclusive mode by another thread fails
453 26082b7e Michael Hanselmann
    # to delete when a timeout is used
454 26082b7e Michael Hanselmann
    self.assertFalse(self.sl.delete(timeout=0.02))
455 26082b7e Michael Hanselmann
456 26082b7e Michael Hanselmann
    finish.set()
457 26082b7e Michael Hanselmann
    self._waitThreads()
458 26082b7e Michael Hanselmann
459 26082b7e Michael Hanselmann
    self.assertTrue(self.sl.delete())
460 26082b7e Michael Hanselmann
    self.assertRaises(errors.LockError, self.sl.acquire)
461 a66bd91b Michael Hanselmann
462 84152b96 Guido Trotter
  def testNoDeleteIfSharer(self):
463 84152b96 Guido Trotter
    self.sl.acquire(shared=1)
464 84152b96 Guido Trotter
    self.assertRaises(AssertionError, self.sl.delete)
465 84152b96 Guido Trotter
466 4607c978 Iustin Pop
  @_Repeat
467 a95fd5d7 Guido Trotter
  def testDeletePendingSharersExclusiveDelete(self):
468 a95fd5d7 Guido Trotter
    self.sl.acquire()
469 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
470 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
471 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
472 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
473 a95fd5d7 Guido Trotter
    self.sl.delete()
474 4607c978 Iustin Pop
    self._waitThreads()
475 4607c978 Iustin Pop
    # The threads who were pending return ERR
476 4607c978 Iustin Pop
    for _ in range(4):
477 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'ERR')
478 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
479 a95fd5d7 Guido Trotter
480 4607c978 Iustin Pop
  @_Repeat
481 a95fd5d7 Guido Trotter
  def testDeletePendingDeleteExclusiveSharers(self):
482 a95fd5d7 Guido Trotter
    self.sl.acquire()
483 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
484 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
485 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
486 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
487 a95fd5d7 Guido Trotter
    self.sl.delete()
488 4607c978 Iustin Pop
    self._waitThreads()
489 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
490 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
491 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
492 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
493 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
494 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
495 a95fd5d7 Guido Trotter
496 84e344d4 Michael Hanselmann
  @_Repeat
497 84e344d4 Michael Hanselmann
  def testExclusiveAcquireTimeout(self):
498 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
499 008b92fa Michael Hanselmann
      on_queue = threading.Event()
500 008b92fa Michael Hanselmann
      release_exclusive = threading.Event()
501 008b92fa Michael Hanselmann
502 008b92fa Michael Hanselmann
      def _LockExclusive():
503 008b92fa Michael Hanselmann
        self.sl.acquire(shared=0, test_notify=on_queue.set)
504 008b92fa Michael Hanselmann
        self.done.put("A: start wait")
505 008b92fa Michael Hanselmann
        release_exclusive.wait()
506 008b92fa Michael Hanselmann
        self.done.put("A: end wait")
507 008b92fa Michael Hanselmann
        self.sl.release()
508 008b92fa Michael Hanselmann
509 008b92fa Michael Hanselmann
      # Start thread to hold lock in exclusive mode
510 008b92fa Michael Hanselmann
      self._addThread(target=_LockExclusive)
511 84e344d4 Michael Hanselmann
512 008b92fa Michael Hanselmann
      # Wait for wait to begin
513 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get(timeout=60), "A: start wait")
514 008b92fa Michael Hanselmann
515 008b92fa Michael Hanselmann
      # Wait up to 60s to get lock, but release exclusive lock as soon as we're
516 008b92fa Michael Hanselmann
      # on the queue
517 008b92fa Michael Hanselmann
      self.failUnless(self.sl.acquire(shared=shared, timeout=60,
518 008b92fa Michael Hanselmann
                                      test_notify=release_exclusive.set))
519 2042aa94 Michael Hanselmann
520 84e344d4 Michael Hanselmann
      self.done.put("got 2nd")
521 84e344d4 Michael Hanselmann
      self.sl.release()
522 84e344d4 Michael Hanselmann
523 84e344d4 Michael Hanselmann
      self._waitThreads()
524 84e344d4 Michael Hanselmann
525 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "A: end wait")
526 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "got 2nd")
527 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
528 84e344d4 Michael Hanselmann
529 84e344d4 Michael Hanselmann
  @_Repeat
530 84e344d4 Michael Hanselmann
  def testAcquireExpiringTimeout(self):
531 84e344d4 Michael Hanselmann
    def _AcquireWithTimeout(shared, timeout):
532 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=shared, timeout=timeout):
533 84e344d4 Michael Hanselmann
        self.done.put("timeout")
534 84e344d4 Michael Hanselmann
535 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
536 84e344d4 Michael Hanselmann
      # Lock exclusively
537 84e344d4 Michael Hanselmann
      self.sl.acquire()
538 84e344d4 Michael Hanselmann
539 84e344d4 Michael Hanselmann
      # Start shared acquires with timeout between 0 and 20 ms
540 f1501b3f Michael Hanselmann
      for i in range(11):
541 84e344d4 Michael Hanselmann
        self._addThread(target=_AcquireWithTimeout,
542 84e344d4 Michael Hanselmann
                        args=(shared, i * 2.0 / 1000.0))
543 84e344d4 Michael Hanselmann
544 84e344d4 Michael Hanselmann
      # Wait for threads to finish (makes sure the acquire timeout expires
545 84e344d4 Michael Hanselmann
      # before releasing the lock)
546 84e344d4 Michael Hanselmann
      self._waitThreads()
547 84e344d4 Michael Hanselmann
548 84e344d4 Michael Hanselmann
      # Release lock
549 84e344d4 Michael Hanselmann
      self.sl.release()
550 84e344d4 Michael Hanselmann
551 f1501b3f Michael Hanselmann
      for _ in range(11):
552 84e344d4 Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "timeout")
553 84e344d4 Michael Hanselmann
554 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
555 84e344d4 Michael Hanselmann
556 84e344d4 Michael Hanselmann
  @_Repeat
557 84e344d4 Michael Hanselmann
  def testSharedSkipExclusiveAcquires(self):
558 84e344d4 Michael Hanselmann
    # Tests whether shared acquires jump in front of exclusive acquires in the
559 84e344d4 Michael Hanselmann
    # queue.
560 84e344d4 Michael Hanselmann
561 008b92fa Michael Hanselmann
    def _Acquire(shared, name, notify_ev, wait_ev):
562 008b92fa Michael Hanselmann
      if notify_ev:
563 008b92fa Michael Hanselmann
        notify_fn = notify_ev.set
564 008b92fa Michael Hanselmann
      else:
565 008b92fa Michael Hanselmann
        notify_fn = None
566 84e344d4 Michael Hanselmann
567 008b92fa Michael Hanselmann
      if wait_ev:
568 008b92fa Michael Hanselmann
        wait_ev.wait()
569 008b92fa Michael Hanselmann
570 008b92fa Michael Hanselmann
      if not self.sl.acquire(shared=shared, test_notify=notify_fn):
571 84e344d4 Michael Hanselmann
        return
572 84e344d4 Michael Hanselmann
573 84e344d4 Michael Hanselmann
      self.done.put(name)
574 84e344d4 Michael Hanselmann
      self.sl.release()
575 84e344d4 Michael Hanselmann
576 008b92fa Michael Hanselmann
    # Get exclusive lock while we fill the queue
577 008b92fa Michael Hanselmann
    self.sl.acquire()
578 84e344d4 Michael Hanselmann
579 008b92fa Michael Hanselmann
    shrcnt1 = 5
580 008b92fa Michael Hanselmann
    shrcnt2 = 7
581 008b92fa Michael Hanselmann
    shrcnt3 = 9
582 008b92fa Michael Hanselmann
    shrcnt4 = 2
583 84e344d4 Michael Hanselmann
584 008b92fa Michael Hanselmann
    # Add acquires using threading.Event for synchronization. They'll be
585 008b92fa Michael Hanselmann
    # acquired exactly in the order defined in this list.
586 008b92fa Michael Hanselmann
    acquires = (shrcnt1 * [(1, "shared 1")] +
587 008b92fa Michael Hanselmann
                3 * [(0, "exclusive 1")] +
588 008b92fa Michael Hanselmann
                shrcnt2 * [(1, "shared 2")] +
589 008b92fa Michael Hanselmann
                shrcnt3 * [(1, "shared 3")] +
590 008b92fa Michael Hanselmann
                shrcnt4 * [(1, "shared 4")] +
591 008b92fa Michael Hanselmann
                3 * [(0, "exclusive 2")])
592 84e344d4 Michael Hanselmann
593 008b92fa Michael Hanselmann
    ev_cur = None
594 008b92fa Michael Hanselmann
    ev_prev = None
595 008b92fa Michael Hanselmann
596 008b92fa Michael Hanselmann
    for args in acquires:
597 008b92fa Michael Hanselmann
      ev_cur = threading.Event()
598 008b92fa Michael Hanselmann
      self._addThread(target=_Acquire, args=args + (ev_cur, ev_prev))
599 008b92fa Michael Hanselmann
      ev_prev = ev_cur
600 008b92fa Michael Hanselmann
601 008b92fa Michael Hanselmann
    # Wait for last acquire to start
602 008b92fa Michael Hanselmann
    ev_prev.wait()
603 84e344d4 Michael Hanselmann
604 84e344d4 Michael Hanselmann
    # Expect 6 pending exclusive acquires and 1 for all shared acquires
605 008b92fa Michael Hanselmann
    # together
606 008b92fa Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 7)
607 84e344d4 Michael Hanselmann
608 84e344d4 Michael Hanselmann
    # Release exclusive lock and wait
609 84e344d4 Michael Hanselmann
    self.sl.release()
610 84e344d4 Michael Hanselmann
611 84e344d4 Michael Hanselmann
    self._waitThreads()
612 84e344d4 Michael Hanselmann
613 84e344d4 Michael Hanselmann
    # Check sequence
614 008b92fa Michael Hanselmann
    for _ in range(shrcnt1 + shrcnt2 + shrcnt3 + shrcnt4):
615 84e344d4 Michael Hanselmann
      # Shared locks aren't guaranteed to be notified in order, but they'll be
616 84e344d4 Michael Hanselmann
      # first
617 2042aa94 Michael Hanselmann
      tmp = self.done.get_nowait()
618 008b92fa Michael Hanselmann
      if tmp == "shared 1":
619 008b92fa Michael Hanselmann
        shrcnt1 -= 1
620 008b92fa Michael Hanselmann
      elif tmp == "shared 2":
621 008b92fa Michael Hanselmann
        shrcnt2 -= 1
622 008b92fa Michael Hanselmann
      elif tmp == "shared 3":
623 008b92fa Michael Hanselmann
        shrcnt3 -= 1
624 008b92fa Michael Hanselmann
      elif tmp == "shared 4":
625 008b92fa Michael Hanselmann
        shrcnt4 -= 1
626 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt1, 0)
627 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt2, 0)
628 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt3, 0)
629 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt3, 0)
630 84e344d4 Michael Hanselmann
631 f1501b3f Michael Hanselmann
    for _ in range(3):
632 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive 1")
633 84e344d4 Michael Hanselmann
634 f1501b3f Michael Hanselmann
    for _ in range(3):
635 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive 2")
636 84e344d4 Michael Hanselmann
637 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
638 84e344d4 Michael Hanselmann
639 3dbe3ddf Michael Hanselmann
  def testIllegalDowngrade(self):
640 3dbe3ddf Michael Hanselmann
    # Not yet acquired
641 3dbe3ddf Michael Hanselmann
    self.assertRaises(AssertionError, self.sl.downgrade)
642 3dbe3ddf Michael Hanselmann
643 3dbe3ddf Michael Hanselmann
    # Acquire in shared mode, downgrade should be no-op
644 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl.acquire(shared=1))
645 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.sl.is_owned(shared=1))
646 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl.downgrade())
647 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.sl.is_owned(shared=1))
648 3dbe3ddf Michael Hanselmann
    self.sl.release()
649 3dbe3ddf Michael Hanselmann
650 3dbe3ddf Michael Hanselmann
  def testDowngrade(self):
651 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl.acquire())
652 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.sl.is_owned(shared=0))
653 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.sl.downgrade())
654 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.sl.is_owned(shared=1))
655 3dbe3ddf Michael Hanselmann
    self.sl.release()
656 3dbe3ddf Michael Hanselmann
657 3dbe3ddf Michael Hanselmann
  @_Repeat
658 3dbe3ddf Michael Hanselmann
  def testDowngradeJumpsAheadOfExclusive(self):
659 3dbe3ddf Michael Hanselmann
    def _KeepExclusive(ev_got, ev_downgrade, ev_release):
660 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl.acquire())
661 ee2b99e3 Michael Hanselmann
      self.assertTrue(self.sl.is_owned(shared=0))
662 3dbe3ddf Michael Hanselmann
      ev_got.set()
663 3dbe3ddf Michael Hanselmann
      ev_downgrade.wait()
664 ee2b99e3 Michael Hanselmann
      self.assertTrue(self.sl.is_owned(shared=0))
665 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl.downgrade())
666 ee2b99e3 Michael Hanselmann
      self.assertTrue(self.sl.is_owned(shared=1))
667 3dbe3ddf Michael Hanselmann
      ev_release.wait()
668 ee2b99e3 Michael Hanselmann
      self.assertTrue(self.sl.is_owned(shared=1))
669 3dbe3ddf Michael Hanselmann
      self.sl.release()
670 3dbe3ddf Michael Hanselmann
671 3dbe3ddf Michael Hanselmann
    def _KeepExclusive2(ev_started, ev_release):
672 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl.acquire(test_notify=ev_started.set))
673 ee2b99e3 Michael Hanselmann
      self.assertTrue(self.sl.is_owned(shared=0))
674 3dbe3ddf Michael Hanselmann
      ev_release.wait()
675 ee2b99e3 Michael Hanselmann
      self.assertTrue(self.sl.is_owned(shared=0))
676 3dbe3ddf Michael Hanselmann
      self.sl.release()
677 3dbe3ddf Michael Hanselmann
678 3dbe3ddf Michael Hanselmann
    def _KeepShared(ev_started, ev_got, ev_release):
679 3dbe3ddf Michael Hanselmann
      self.assertTrue(self.sl.acquire(shared=1, test_notify=ev_started.set))
680 ee2b99e3 Michael Hanselmann
      self.assertTrue(self.sl.is_owned(shared=1))
681 3dbe3ddf Michael Hanselmann
      ev_got.set()
682 3dbe3ddf Michael Hanselmann
      ev_release.wait()
683 ee2b99e3 Michael Hanselmann
      self.assertTrue(self.sl.is_owned(shared=1))
684 3dbe3ddf Michael Hanselmann
      self.sl.release()
685 3dbe3ddf Michael Hanselmann
686 3dbe3ddf Michael Hanselmann
    # Acquire lock in exclusive mode
687 3dbe3ddf Michael Hanselmann
    ev_got_excl1 = threading.Event()
688 3dbe3ddf Michael Hanselmann
    ev_downgrade_excl1 = threading.Event()
689 3dbe3ddf Michael Hanselmann
    ev_release_excl1 = threading.Event()
690 3dbe3ddf Michael Hanselmann
    th_excl1 = self._addThread(target=_KeepExclusive,
691 3dbe3ddf Michael Hanselmann
                               args=(ev_got_excl1, ev_downgrade_excl1,
692 3dbe3ddf Michael Hanselmann
                                     ev_release_excl1))
693 3dbe3ddf Michael Hanselmann
    ev_got_excl1.wait()
694 3dbe3ddf Michael Hanselmann
695 3dbe3ddf Michael Hanselmann
    # Start a second exclusive acquire
696 3dbe3ddf Michael Hanselmann
    ev_started_excl2 = threading.Event()
697 3dbe3ddf Michael Hanselmann
    ev_release_excl2 = threading.Event()
698 3dbe3ddf Michael Hanselmann
    th_excl2 = self._addThread(target=_KeepExclusive2,
699 3dbe3ddf Michael Hanselmann
                               args=(ev_started_excl2, ev_release_excl2))
700 3dbe3ddf Michael Hanselmann
    ev_started_excl2.wait()
701 3dbe3ddf Michael Hanselmann
702 3dbe3ddf Michael Hanselmann
    # Start shared acquires, will jump ahead of second exclusive acquire when
703 3dbe3ddf Michael Hanselmann
    # first exclusive acquire downgrades
704 3dbe3ddf Michael Hanselmann
    ev_shared = [(threading.Event(), threading.Event()) for _ in range(5)]
705 3dbe3ddf Michael Hanselmann
    ev_release_shared = threading.Event()
706 3dbe3ddf Michael Hanselmann
707 3dbe3ddf Michael Hanselmann
    th_shared = [self._addThread(target=_KeepShared,
708 3dbe3ddf Michael Hanselmann
                                 args=(ev_started, ev_got, ev_release_shared))
709 3dbe3ddf Michael Hanselmann
                 for (ev_started, ev_got) in ev_shared]
710 3dbe3ddf Michael Hanselmann
711 3dbe3ddf Michael Hanselmann
    # Wait for all shared acquires to start
712 3dbe3ddf Michael Hanselmann
    for (ev, _) in ev_shared:
713 3dbe3ddf Michael Hanselmann
      ev.wait()
714 3dbe3ddf Michael Hanselmann
715 3dbe3ddf Michael Hanselmann
    # Check lock information
716 44b4eddc Michael Hanselmann
    self.assertEqual(self.sl.GetLockInfo(set([query.LQ_MODE, query.LQ_OWNER])),
717 44b4eddc Michael Hanselmann
                     [(self.sl.name, "exclusive", [th_excl1.getName()], None)])
718 44b4eddc Michael Hanselmann
    [(_, _, _, pending), ] = self.sl.GetLockInfo(set([query.LQ_PENDING]))
719 3dbe3ddf Michael Hanselmann
    self.assertEqual([(pendmode, sorted(waiting))
720 3dbe3ddf Michael Hanselmann
                      for (pendmode, waiting) in pending],
721 3dbe3ddf Michael Hanselmann
                     [("exclusive", [th_excl2.getName()]),
722 3dbe3ddf Michael Hanselmann
                      ("shared", sorted(th.getName() for th in th_shared))])
723 3dbe3ddf Michael Hanselmann
724 3dbe3ddf Michael Hanselmann
    # Shared acquires won't start until the exclusive lock is downgraded
725 3dbe3ddf Michael Hanselmann
    ev_downgrade_excl1.set()
726 3dbe3ddf Michael Hanselmann
727 3dbe3ddf Michael Hanselmann
    # Wait for all shared acquires to be successful
728 3dbe3ddf Michael Hanselmann
    for (_, ev) in ev_shared:
729 3dbe3ddf Michael Hanselmann
      ev.wait()
730 3dbe3ddf Michael Hanselmann
731 3dbe3ddf Michael Hanselmann
    # Check lock information again
732 44b4eddc Michael Hanselmann
    self.assertEqual(self.sl.GetLockInfo(set([query.LQ_MODE,
733 44b4eddc Michael Hanselmann
                                              query.LQ_PENDING])),
734 44b4eddc Michael Hanselmann
                     [(self.sl.name, "shared", None,
735 44b4eddc Michael Hanselmann
                       [("exclusive", [th_excl2.getName()])])])
736 44b4eddc Michael Hanselmann
    [(_, _, owner, _), ] = self.sl.GetLockInfo(set([query.LQ_OWNER]))
737 3dbe3ddf Michael Hanselmann
    self.assertEqual(set(owner), set([th_excl1.getName()] +
738 3dbe3ddf Michael Hanselmann
                                     [th.getName() for th in th_shared]))
739 3dbe3ddf Michael Hanselmann
740 3dbe3ddf Michael Hanselmann
    ev_release_excl1.set()
741 3dbe3ddf Michael Hanselmann
    ev_release_excl2.set()
742 3dbe3ddf Michael Hanselmann
    ev_release_shared.set()
743 3dbe3ddf Michael Hanselmann
744 3dbe3ddf Michael Hanselmann
    self._waitThreads()
745 3dbe3ddf Michael Hanselmann
746 44b4eddc Michael Hanselmann
    self.assertEqual(self.sl.GetLockInfo(set([query.LQ_MODE, query.LQ_OWNER,
747 44b4eddc Michael Hanselmann
                                              query.LQ_PENDING])),
748 44b4eddc Michael Hanselmann
                     [(self.sl.name, None, None, [])])
749 3dbe3ddf Michael Hanselmann
750 84e344d4 Michael Hanselmann
  @_Repeat
751 84e344d4 Michael Hanselmann
  def testMixedAcquireTimeout(self):
752 51e3bb92 Michael Hanselmann
    sync = threading.Event()
753 84e344d4 Michael Hanselmann
754 84e344d4 Michael Hanselmann
    def _AcquireShared(ev):
755 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=1, timeout=None):
756 84e344d4 Michael Hanselmann
        return
757 84e344d4 Michael Hanselmann
758 84e344d4 Michael Hanselmann
      self.done.put("shared")
759 84e344d4 Michael Hanselmann
760 84e344d4 Michael Hanselmann
      # Notify main thread
761 84e344d4 Michael Hanselmann
      ev.set()
762 84e344d4 Michael Hanselmann
763 51e3bb92 Michael Hanselmann
      # Wait for notification from main thread
764 51e3bb92 Michael Hanselmann
      sync.wait()
765 84e344d4 Michael Hanselmann
766 84e344d4 Michael Hanselmann
      # Release lock
767 84e344d4 Michael Hanselmann
      self.sl.release()
768 84e344d4 Michael Hanselmann
769 84e344d4 Michael Hanselmann
    acquires = []
770 f1501b3f Michael Hanselmann
    for _ in range(3):
771 84e344d4 Michael Hanselmann
      ev = threading.Event()
772 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireShared, args=(ev, ))
773 84e344d4 Michael Hanselmann
      acquires.append(ev)
774 84e344d4 Michael Hanselmann
775 84e344d4 Michael Hanselmann
    # Wait for all acquires to finish
776 84e344d4 Michael Hanselmann
    for i in acquires:
777 84e344d4 Michael Hanselmann
      i.wait()
778 84e344d4 Michael Hanselmann
779 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
780 84e344d4 Michael Hanselmann
781 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
782 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
783 84e344d4 Michael Hanselmann
784 84e344d4 Michael Hanselmann
    # Acquire exclusive without timeout
785 51e3bb92 Michael Hanselmann
    exclsync = threading.Event()
786 84e344d4 Michael Hanselmann
    exclev = threading.Event()
787 84e344d4 Michael Hanselmann
788 84e344d4 Michael Hanselmann
    def _AcquireExclusive():
789 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=0):
790 84e344d4 Michael Hanselmann
        return
791 84e344d4 Michael Hanselmann
792 84e344d4 Michael Hanselmann
      self.done.put("exclusive")
793 84e344d4 Michael Hanselmann
794 84e344d4 Michael Hanselmann
      # Notify main thread
795 84e344d4 Michael Hanselmann
      exclev.set()
796 84e344d4 Michael Hanselmann
797 51e3bb92 Michael Hanselmann
      # Wait for notification from main thread
798 51e3bb92 Michael Hanselmann
      exclsync.wait()
799 84e344d4 Michael Hanselmann
800 84e344d4 Michael Hanselmann
      self.sl.release()
801 84e344d4 Michael Hanselmann
802 84e344d4 Michael Hanselmann
    self._addThread(target=_AcquireExclusive)
803 84e344d4 Michael Hanselmann
804 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
805 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
806 84e344d4 Michael Hanselmann
807 84e344d4 Michael Hanselmann
    # Make all shared holders release their locks
808 51e3bb92 Michael Hanselmann
    sync.set()
809 84e344d4 Michael Hanselmann
810 84e344d4 Michael Hanselmann
    # Wait for exclusive acquire to succeed
811 84e344d4 Michael Hanselmann
    exclev.wait()
812 84e344d4 Michael Hanselmann
813 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
814 84e344d4 Michael Hanselmann
815 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
816 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
817 84e344d4 Michael Hanselmann
818 84e344d4 Michael Hanselmann
    def _AcquireSharedSimple():
819 84e344d4 Michael Hanselmann
      if self.sl.acquire(shared=1, timeout=None):
820 84e344d4 Michael Hanselmann
        self.done.put("shared2")
821 84e344d4 Michael Hanselmann
        self.sl.release()
822 84e344d4 Michael Hanselmann
823 f1501b3f Michael Hanselmann
    for _ in range(10):
824 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireSharedSimple)
825 84e344d4 Michael Hanselmann
826 84e344d4 Michael Hanselmann
    # Tell exclusive lock to release
827 51e3bb92 Michael Hanselmann
    exclsync.set()
828 84e344d4 Michael Hanselmann
829 84e344d4 Michael Hanselmann
    # Wait for everything to finish
830 84e344d4 Michael Hanselmann
    self._waitThreads()
831 84e344d4 Michael Hanselmann
832 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
833 84e344d4 Michael Hanselmann
834 84e344d4 Michael Hanselmann
    # Check sequence
835 f1501b3f Michael Hanselmann
    for _ in range(3):
836 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared")
837 84e344d4 Michael Hanselmann
838 84e344d4 Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "exclusive")
839 84e344d4 Michael Hanselmann
840 f1501b3f Michael Hanselmann
    for _ in range(10):
841 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared2")
842 84e344d4 Michael Hanselmann
843 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
844 84e344d4 Michael Hanselmann
845 887c7aa6 Michael Hanselmann
  def testPriority(self):
846 887c7aa6 Michael Hanselmann
    # Acquire in exclusive mode
847 887c7aa6 Michael Hanselmann
    self.assert_(self.sl.acquire(shared=0))
848 887c7aa6 Michael Hanselmann
849 887c7aa6 Michael Hanselmann
    # Queue acquires
850 887c7aa6 Michael Hanselmann
    def _Acquire(prev, next, shared, priority, result):
851 887c7aa6 Michael Hanselmann
      prev.wait()
852 887c7aa6 Michael Hanselmann
      self.sl.acquire(shared=shared, priority=priority, test_notify=next.set)
853 887c7aa6 Michael Hanselmann
      try:
854 887c7aa6 Michael Hanselmann
        self.done.put(result)
855 887c7aa6 Michael Hanselmann
      finally:
856 887c7aa6 Michael Hanselmann
        self.sl.release()
857 887c7aa6 Michael Hanselmann
858 887c7aa6 Michael Hanselmann
    counter = itertools.count(0)
859 887c7aa6 Michael Hanselmann
    priorities = range(-20, 30)
860 887c7aa6 Michael Hanselmann
    first = threading.Event()
861 887c7aa6 Michael Hanselmann
    prev = first
862 887c7aa6 Michael Hanselmann
863 887c7aa6 Michael Hanselmann
    # Data structure:
864 887c7aa6 Michael Hanselmann
    # {
865 887c7aa6 Michael Hanselmann
    #   priority:
866 887c7aa6 Michael Hanselmann
    #     [(shared/exclusive, set(acquire names), set(pending threads)),
867 887c7aa6 Michael Hanselmann
    #      (shared/exclusive, ...),
868 887c7aa6 Michael Hanselmann
    #      ...,
869 887c7aa6 Michael Hanselmann
    #     ],
870 887c7aa6 Michael Hanselmann
    # }
871 887c7aa6 Michael Hanselmann
    perprio = {}
872 887c7aa6 Michael Hanselmann
873 887c7aa6 Michael Hanselmann
    # References shared acquire per priority in L{perprio}. Data structure:
874 887c7aa6 Michael Hanselmann
    # {
875 887c7aa6 Michael Hanselmann
    #   priority: (shared=1, set(acquire names), set(pending threads)),
876 887c7aa6 Michael Hanselmann
    # }
877 887c7aa6 Michael Hanselmann
    prioshared = {}
878 887c7aa6 Michael Hanselmann
879 887c7aa6 Michael Hanselmann
    for seed in [4979, 9523, 14902, 32440]:
880 887c7aa6 Michael Hanselmann
      # Use a deterministic random generator
881 887c7aa6 Michael Hanselmann
      rnd = random.Random(seed)
882 887c7aa6 Michael Hanselmann
      for priority in [rnd.choice(priorities) for _ in range(30)]:
883 887c7aa6 Michael Hanselmann
        modes = [0, 1]
884 887c7aa6 Michael Hanselmann
        rnd.shuffle(modes)
885 887c7aa6 Michael Hanselmann
        for shared in modes:
886 887c7aa6 Michael Hanselmann
          # Unique name
887 887c7aa6 Michael Hanselmann
          acqname = "%s/shr=%s/prio=%s" % (counter.next(), shared, priority)
888 887c7aa6 Michael Hanselmann
889 887c7aa6 Michael Hanselmann
          ev = threading.Event()
890 887c7aa6 Michael Hanselmann
          thread = self._addThread(target=_Acquire,
891 887c7aa6 Michael Hanselmann
                                   args=(prev, ev, shared, priority, acqname))
892 887c7aa6 Michael Hanselmann
          prev = ev
893 887c7aa6 Michael Hanselmann
894 887c7aa6 Michael Hanselmann
          # Record expected aqcuire, see above for structure
895 887c7aa6 Michael Hanselmann
          data = (shared, set([acqname]), set([thread]))
896 887c7aa6 Michael Hanselmann
          priolist = perprio.setdefault(priority, [])
897 887c7aa6 Michael Hanselmann
          if shared:
898 887c7aa6 Michael Hanselmann
            priosh = prioshared.get(priority, None)
899 887c7aa6 Michael Hanselmann
            if priosh:
900 887c7aa6 Michael Hanselmann
              # Shared acquires are merged
901 887c7aa6 Michael Hanselmann
              for i, j in zip(priosh[1:], data[1:]):
902 887c7aa6 Michael Hanselmann
                i.update(j)
903 887c7aa6 Michael Hanselmann
              assert data[0] == priosh[0]
904 887c7aa6 Michael Hanselmann
            else:
905 887c7aa6 Michael Hanselmann
              prioshared[priority] = data
906 887c7aa6 Michael Hanselmann
              priolist.append(data)
907 887c7aa6 Michael Hanselmann
          else:
908 887c7aa6 Michael Hanselmann
            priolist.append(data)
909 887c7aa6 Michael Hanselmann
910 887c7aa6 Michael Hanselmann
    # Start all acquires and wait for them
911 887c7aa6 Michael Hanselmann
    first.set()
912 887c7aa6 Michael Hanselmann
    prev.wait()
913 887c7aa6 Michael Hanselmann
914 887c7aa6 Michael Hanselmann
    # Check lock information
915 44b4eddc Michael Hanselmann
    self.assertEqual(self.sl.GetLockInfo(set()),
916 44b4eddc Michael Hanselmann
                     [(self.sl.name, None, None, None)])
917 44b4eddc Michael Hanselmann
    self.assertEqual(self.sl.GetLockInfo(set([query.LQ_MODE, query.LQ_OWNER])),
918 44b4eddc Michael Hanselmann
                     [(self.sl.name, "exclusive",
919 44b4eddc Michael Hanselmann
                       [threading.currentThread().getName()], None)])
920 24d16f76 Michael Hanselmann
921 44b4eddc Michael Hanselmann
    self._VerifyPrioPending(self.sl.GetLockInfo(set([query.LQ_PENDING])),
922 44b4eddc Michael Hanselmann
                            perprio)
923 887c7aa6 Michael Hanselmann
924 887c7aa6 Michael Hanselmann
    # Let threads acquire the lock
925 887c7aa6 Michael Hanselmann
    self.sl.release()
926 887c7aa6 Michael Hanselmann
927 887c7aa6 Michael Hanselmann
    # Wait for everything to finish
928 887c7aa6 Michael Hanselmann
    self._waitThreads()
929 887c7aa6 Michael Hanselmann
930 887c7aa6 Michael Hanselmann
    self.assert_(self.sl._check_empty())
931 887c7aa6 Michael Hanselmann
932 887c7aa6 Michael Hanselmann
    # Check acquires by priority
933 887c7aa6 Michael Hanselmann
    for acquires in [perprio[i] for i in sorted(perprio.keys())]:
934 887c7aa6 Michael Hanselmann
      for (_, names, _) in acquires:
935 887c7aa6 Michael Hanselmann
        # For shared acquires, the set will contain 1..n entries. For exclusive
936 887c7aa6 Michael Hanselmann
        # acquires only one.
937 887c7aa6 Michael Hanselmann
        while names:
938 887c7aa6 Michael Hanselmann
          names.remove(self.done.get_nowait())
939 887c7aa6 Michael Hanselmann
      self.assertFalse(compat.any(names for (_, names, _) in acquires))
940 887c7aa6 Michael Hanselmann
941 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
942 887c7aa6 Michael Hanselmann
943 44b4eddc Michael Hanselmann
  def _VerifyPrioPending(self, ((name, mode, owner, pending), ), perprio):
944 24d16f76 Michael Hanselmann
    self.assertEqual(name, self.sl.name)
945 24d16f76 Michael Hanselmann
    self.assert_(mode is None)
946 24d16f76 Michael Hanselmann
    self.assert_(owner is None)
947 24d16f76 Michael Hanselmann
948 24d16f76 Michael Hanselmann
    self.assertEqual([(pendmode, sorted(waiting))
949 24d16f76 Michael Hanselmann
                      for (pendmode, waiting) in pending],
950 24d16f76 Michael Hanselmann
                     [(["exclusive", "shared"][int(bool(shared))],
951 24d16f76 Michael Hanselmann
                       sorted(t.getName() for t in threads))
952 24d16f76 Michael Hanselmann
                      for acquires in [perprio[i]
953 24d16f76 Michael Hanselmann
                                       for i in sorted(perprio.keys())]
954 24d16f76 Michael Hanselmann
                      for (shared, _, threads) in acquires])
955 24d16f76 Michael Hanselmann
956 8d7d8b57 Michael Hanselmann
  class _FakeTimeForSpuriousNotifications:
957 8d7d8b57 Michael Hanselmann
    def __init__(self, now, check_end):
958 8d7d8b57 Michael Hanselmann
      self.now = now
959 8d7d8b57 Michael Hanselmann
      self.check_end = check_end
960 8d7d8b57 Michael Hanselmann
961 8d7d8b57 Michael Hanselmann
      # Deterministic random number generator
962 8d7d8b57 Michael Hanselmann
      self.rnd = random.Random(15086)
963 8d7d8b57 Michael Hanselmann
964 8d7d8b57 Michael Hanselmann
    def time(self):
965 8d7d8b57 Michael Hanselmann
      # Advance time if the random number generator thinks so (this is to test
966 8d7d8b57 Michael Hanselmann
      # multiple notifications without advancing the time)
967 8d7d8b57 Michael Hanselmann
      if self.rnd.random() < 0.3:
968 8d7d8b57 Michael Hanselmann
        self.now += self.rnd.random()
969 8d7d8b57 Michael Hanselmann
970 8d7d8b57 Michael Hanselmann
      self.check_end(self.now)
971 8d7d8b57 Michael Hanselmann
972 8d7d8b57 Michael Hanselmann
      return self.now
973 8d7d8b57 Michael Hanselmann
974 8d7d8b57 Michael Hanselmann
  @_Repeat
975 8d7d8b57 Michael Hanselmann
  def testAcquireTimeoutWithSpuriousNotifications(self):
976 8d7d8b57 Michael Hanselmann
    ready = threading.Event()
977 8d7d8b57 Michael Hanselmann
    locked = threading.Event()
978 8d7d8b57 Michael Hanselmann
    req = Queue.Queue(0)
979 8d7d8b57 Michael Hanselmann
980 8d7d8b57 Michael Hanselmann
    epoch = 4000.0
981 8d7d8b57 Michael Hanselmann
    timeout = 60.0
982 8d7d8b57 Michael Hanselmann
983 8d7d8b57 Michael Hanselmann
    def check_end(now):
984 8d7d8b57 Michael Hanselmann
      self.assertFalse(locked.isSet())
985 8d7d8b57 Michael Hanselmann
986 8d7d8b57 Michael Hanselmann
      # If we waited long enough (in virtual time), tell main thread to release
987 8d7d8b57 Michael Hanselmann
      # lock, otherwise tell it to notify once more
988 8d7d8b57 Michael Hanselmann
      req.put(now < (epoch + (timeout * 0.8)))
989 8d7d8b57 Michael Hanselmann
990 8d7d8b57 Michael Hanselmann
    time_fn = self._FakeTimeForSpuriousNotifications(epoch, check_end).time
991 8d7d8b57 Michael Hanselmann
992 8d7d8b57 Michael Hanselmann
    sl = locking.SharedLock("test", _time_fn=time_fn)
993 8d7d8b57 Michael Hanselmann
994 8d7d8b57 Michael Hanselmann
    # Acquire in exclusive mode
995 8d7d8b57 Michael Hanselmann
    sl.acquire(shared=0)
996 8d7d8b57 Michael Hanselmann
997 8d7d8b57 Michael Hanselmann
    def fn():
998 8d7d8b57 Michael Hanselmann
      self.assertTrue(sl.acquire(shared=0, timeout=timeout,
999 8d7d8b57 Michael Hanselmann
                                 test_notify=ready.set))
1000 8d7d8b57 Michael Hanselmann
      locked.set()
1001 8d7d8b57 Michael Hanselmann
      sl.release()
1002 8d7d8b57 Michael Hanselmann
      self.done.put("success")
1003 8d7d8b57 Michael Hanselmann
1004 8d7d8b57 Michael Hanselmann
    # Start acquire with timeout and wait for it to be ready
1005 8d7d8b57 Michael Hanselmann
    self._addThread(target=fn)
1006 8d7d8b57 Michael Hanselmann
    ready.wait()
1007 8d7d8b57 Michael Hanselmann
1008 8d7d8b57 Michael Hanselmann
    # The separate thread is now waiting to acquire the lock, so start sending
1009 8d7d8b57 Michael Hanselmann
    # spurious notifications.
1010 8d7d8b57 Michael Hanselmann
1011 8d7d8b57 Michael Hanselmann
    # Wait for separate thread to ask for another notification
1012 8d7d8b57 Michael Hanselmann
    count = 0
1013 8d7d8b57 Michael Hanselmann
    while req.get():
1014 8d7d8b57 Michael Hanselmann
      # After sending the notification, the lock will take a short amount of
1015 8d7d8b57 Michael Hanselmann
      # time to notice and to retrieve the current time
1016 8d7d8b57 Michael Hanselmann
      sl._notify_topmost()
1017 8d7d8b57 Michael Hanselmann
      count += 1
1018 8d7d8b57 Michael Hanselmann
1019 8d7d8b57 Michael Hanselmann
    self.assertTrue(count > 100, "Not enough notifications were sent")
1020 8d7d8b57 Michael Hanselmann
1021 8d7d8b57 Michael Hanselmann
    self.assertFalse(locked.isSet())
1022 8d7d8b57 Michael Hanselmann
1023 8d7d8b57 Michael Hanselmann
    # Some notifications have been sent, now actually release the lock
1024 8d7d8b57 Michael Hanselmann
    sl.release()
1025 8d7d8b57 Michael Hanselmann
1026 8d7d8b57 Michael Hanselmann
    # Wait for lock to be acquired
1027 8d7d8b57 Michael Hanselmann
    locked.wait()
1028 8d7d8b57 Michael Hanselmann
1029 8d7d8b57 Michael Hanselmann
    self._waitThreads()
1030 8d7d8b57 Michael Hanselmann
1031 8d7d8b57 Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "success")
1032 8d7d8b57 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1033 8d7d8b57 Michael Hanselmann
1034 162c1c1f Guido Trotter
1035 1a4e32d0 Guido Trotter
class TestSharedLockInCondition(_ThreadedTestCase):
1036 1a4e32d0 Guido Trotter
  """SharedLock as a condition lock tests"""
1037 1a4e32d0 Guido Trotter
1038 1a4e32d0 Guido Trotter
  def setUp(self):
1039 1a4e32d0 Guido Trotter
    _ThreadedTestCase.setUp(self)
1040 7f93570a Iustin Pop
    self.sl = locking.SharedLock("TestSharedLockInCondition")
1041 7f890059 Guido Trotter
    self.setCondition()
1042 7f890059 Guido Trotter
1043 7f890059 Guido Trotter
  def setCondition(self):
1044 1a4e32d0 Guido Trotter
    self.cond = threading.Condition(self.sl)
1045 1a4e32d0 Guido Trotter
1046 1a4e32d0 Guido Trotter
  def testKeepMode(self):
1047 1a4e32d0 Guido Trotter
    self.cond.acquire(shared=1)
1048 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned(shared=1))
1049 1a4e32d0 Guido Trotter
    self.cond.wait(0)
1050 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned(shared=1))
1051 1a4e32d0 Guido Trotter
    self.cond.release()
1052 1a4e32d0 Guido Trotter
    self.cond.acquire(shared=0)
1053 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned(shared=0))
1054 1a4e32d0 Guido Trotter
    self.cond.wait(0)
1055 ee2b99e3 Michael Hanselmann
    self.assert_(self.sl.is_owned(shared=0))
1056 1a4e32d0 Guido Trotter
    self.cond.release()
1057 1a4e32d0 Guido Trotter
1058 1a4e32d0 Guido Trotter
1059 7f890059 Guido Trotter
class TestSharedLockInPipeCondition(TestSharedLockInCondition):
1060 7f890059 Guido Trotter
  """SharedLock as a pipe condition lock tests"""
1061 7f890059 Guido Trotter
1062 7f890059 Guido Trotter
  def setCondition(self):
1063 7f890059 Guido Trotter
    self.cond = locking.PipeCondition(self.sl)
1064 7f890059 Guido Trotter
1065 7f890059 Guido Trotter
1066 4607c978 Iustin Pop
class TestSSynchronizedDecorator(_ThreadedTestCase):
1067 42a999d1 Guido Trotter
  """Shared Lock Synchronized decorator test"""
1068 42a999d1 Guido Trotter
1069 42a999d1 Guido Trotter
  def setUp(self):
1070 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
1071 42a999d1 Guido Trotter
1072 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock)
1073 42a999d1 Guido Trotter
  def _doItExclusive(self):
1074 ee2b99e3 Michael Hanselmann
    self.assert_(_decoratorlock.is_owned())
1075 42a999d1 Guido Trotter
    self.done.put('EXC')
1076 42a999d1 Guido Trotter
1077 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock, shared=1)
1078 42a999d1 Guido Trotter
  def _doItSharer(self):
1079 ee2b99e3 Michael Hanselmann
    self.assert_(_decoratorlock.is_owned(shared=1))
1080 42a999d1 Guido Trotter
    self.done.put('SHR')
1081 42a999d1 Guido Trotter
1082 42a999d1 Guido Trotter
  def testDecoratedFunctions(self):
1083 42a999d1 Guido Trotter
    self._doItExclusive()
1084 ee2b99e3 Michael Hanselmann
    self.assertFalse(_decoratorlock.is_owned())
1085 42a999d1 Guido Trotter
    self._doItSharer()
1086 ee2b99e3 Michael Hanselmann
    self.assertFalse(_decoratorlock.is_owned())
1087 42a999d1 Guido Trotter
1088 42a999d1 Guido Trotter
  def testSharersCanCoexist(self):
1089 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
1090 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
1091 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
1092 42a999d1 Guido Trotter
    _decoratorlock.release()
1093 42a999d1 Guido Trotter
1094 4607c978 Iustin Pop
  @_Repeat
1095 42a999d1 Guido Trotter
  def testExclusiveBlocksExclusive(self):
1096 42a999d1 Guido Trotter
    _decoratorlock.acquire()
1097 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
1098 42a999d1 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
1099 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1100 42a999d1 Guido Trotter
    _decoratorlock.release()
1101 4607c978 Iustin Pop
    self._waitThreads()
1102 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
1103 42a999d1 Guido Trotter
1104 4607c978 Iustin Pop
  @_Repeat
1105 42a999d1 Guido Trotter
  def testExclusiveBlocksSharer(self):
1106 42a999d1 Guido Trotter
    _decoratorlock.acquire()
1107 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
1108 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1109 42a999d1 Guido Trotter
    _decoratorlock.release()
1110 4607c978 Iustin Pop
    self._waitThreads()
1111 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
1112 42a999d1 Guido Trotter
1113 4607c978 Iustin Pop
  @_Repeat
1114 42a999d1 Guido Trotter
  def testSharerBlocksExclusive(self):
1115 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
1116 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
1117 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1118 42a999d1 Guido Trotter
    _decoratorlock.release()
1119 4607c978 Iustin Pop
    self._waitThreads()
1120 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
1121 42a999d1 Guido Trotter
1122 42a999d1 Guido Trotter
1123 4607c978 Iustin Pop
class TestLockSet(_ThreadedTestCase):
1124 aaae9bc0 Guido Trotter
  """LockSet tests"""
1125 aaae9bc0 Guido Trotter
1126 aaae9bc0 Guido Trotter
  def setUp(self):
1127 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
1128 4607c978 Iustin Pop
    self._setUpLS()
1129 aaae9bc0 Guido Trotter
1130 4607c978 Iustin Pop
  def _setUpLS(self):
1131 4607c978 Iustin Pop
    """Helper to (re)initialize the lock set"""
1132 4607c978 Iustin Pop
    self.resources = ['one', 'two', 'three']
1133 7f93570a Iustin Pop
    self.ls = locking.LockSet(self.resources, "TestLockSet")
1134 4607c978 Iustin Pop
1135 aaae9bc0 Guido Trotter
  def testResources(self):
1136 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._names(), set(self.resources))
1137 7f93570a Iustin Pop
    newls = locking.LockSet([], "TestLockSet.testResources")
1138 aaae9bc0 Guido Trotter
    self.assertEquals(newls._names(), set())
1139 aaae9bc0 Guido Trotter
1140 c6a622cf Michael Hanselmann
  def testCheckOwnedUnknown(self):
1141 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned("certainly-not-owning-this-one"))
1142 c6a622cf Michael Hanselmann
    for shared in [-1, 0, 1, 6378, 24255]:
1143 c6a622cf Michael Hanselmann
      self.assertFalse(self.ls.check_owned("certainly-not-owning-this-one",
1144 c6a622cf Michael Hanselmann
                                           shared=shared))
1145 c6a622cf Michael Hanselmann
1146 c6a622cf Michael Hanselmann
  def testCheckOwnedUnknownWhileHolding(self):
1147 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned([]))
1148 c6a622cf Michael Hanselmann
    self.ls.acquire("one", shared=1)
1149 c6a622cf Michael Hanselmann
    self.assertRaises(errors.LockError, self.ls.check_owned, "nonexist")
1150 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("one", shared=1))
1151 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned("one", shared=0))
1152 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned(["one", "two"]))
1153 c6a622cf Michael Hanselmann
    self.assertRaises(errors.LockError, self.ls.check_owned,
1154 c6a622cf Michael Hanselmann
                      ["one", "nonexist"])
1155 c6a622cf Michael Hanselmann
    self.assertRaises(errors.LockError, self.ls.check_owned, "")
1156 c6a622cf Michael Hanselmann
    self.ls.release()
1157 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned([]))
1158 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned("one"))
1159 c6a622cf Michael Hanselmann
1160 aaae9bc0 Guido Trotter
  def testAcquireRelease(self):
1161 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned(self.ls._names()))
1162 0cc00929 Guido Trotter
    self.assert_(self.ls.acquire('one'))
1163 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['one']))
1164 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("one"))
1165 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("one", shared=0))
1166 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned("one", shared=1))
1167 aaae9bc0 Guido Trotter
    self.ls.release()
1168 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set())
1169 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned(self.ls._names()))
1170 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
1171 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['one']))
1172 aaae9bc0 Guido Trotter
    self.ls.release()
1173 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set())
1174 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'three'])
1175 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['one', 'two', 'three']))
1176 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned(self.ls._names()))
1177 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned(self.ls._names(), shared=0))
1178 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned(self.ls._names(), shared=1))
1179 aaae9bc0 Guido Trotter
    self.ls.release('one')
1180 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned(["one"]))
1181 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned(["two", "three"]))
1182 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned(["two", "three"], shared=0))
1183 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned(["two", "three"], shared=1))
1184 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['two', 'three']))
1185 aaae9bc0 Guido Trotter
    self.ls.release(['three'])
1186 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['two']))
1187 aaae9bc0 Guido Trotter
    self.ls.release()
1188 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set())
1189 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
1190 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['one', 'three']))
1191 aaae9bc0 Guido Trotter
    self.ls.release()
1192 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set())
1193 c6a622cf Michael Hanselmann
    for name in self.ls._names():
1194 c6a622cf Michael Hanselmann
      self.assertFalse(self.ls.check_owned(name))
1195 aaae9bc0 Guido Trotter
1196 aaae9bc0 Guido Trotter
  def testNoDoubleAcquire(self):
1197 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
1198 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
1199 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
1200 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
1201 aaae9bc0 Guido Trotter
    self.ls.release()
1202 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'])
1203 aaae9bc0 Guido Trotter
    self.ls.release('one')
1204 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
1205 aaae9bc0 Guido Trotter
    self.ls.release('three')
1206 aaae9bc0 Guido Trotter
1207 aaae9bc0 Guido Trotter
  def testNoWrongRelease(self):
1208 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
1209 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
1210 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release, 'two')
1211 aaae9bc0 Guido Trotter
1212 aaae9bc0 Guido Trotter
  def testAddRemove(self):
1213 aaae9bc0 Guido Trotter
    self.ls.add('four')
1214 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set())
1215 aaae9bc0 Guido Trotter
    self.assert_('four' in self.ls._names())
1216 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six', 'seven'], acquired=1)
1217 aaae9bc0 Guido Trotter
    self.assert_('five' in self.ls._names())
1218 aaae9bc0 Guido Trotter
    self.assert_('six' in self.ls._names())
1219 aaae9bc0 Guido Trotter
    self.assert_('seven' in self.ls._names())
1220 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['five', 'six', 'seven']))
1221 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
1222 aaae9bc0 Guido Trotter
    self.assert_('five' not in self.ls._names())
1223 aaae9bc0 Guido Trotter
    self.assert_('six' not in self.ls._names())
1224 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['seven']))
1225 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight', acquired=1)
1226 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
1227 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
1228 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set([]))
1229 d2aff862 Guido Trotter
    self.ls.acquire(None, shared=1)
1230 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight')
1231 d2aff862 Guido Trotter
    self.ls.release()
1232 d2aff862 Guido Trotter
    self.ls.acquire(None)
1233 d2aff862 Guido Trotter
    self.ls.add('eight', acquired=1)
1234 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._names())
1235 ee2b99e3 Michael Hanselmann
    self.assert_('eight' in self.ls.list_owned())
1236 d2aff862 Guido Trotter
    self.ls.add('nine')
1237 d2aff862 Guido Trotter
    self.assert_('nine' in self.ls._names())
1238 ee2b99e3 Michael Hanselmann
    self.assert_('nine' not in self.ls.list_owned())
1239 aaae9bc0 Guido Trotter
    self.ls.release()
1240 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
1241 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
1242 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
1243 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
1244 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
1245 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
1246 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
1247 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
1248 aaae9bc0 Guido Trotter
1249 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
1250 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
1251 5e0a6daf Michael Hanselmann
    self.assertEquals(self.ls.remove('one'), ['one'])
1252 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
1253 5e0a6daf Michael Hanselmann
    self.assertEquals(self.ls.remove(['two', 'three']),
1254 3f404fc5 Guido Trotter
                      ['two', 'three'])
1255 aaae9bc0 Guido Trotter
1256 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
1257 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
1258 aaae9bc0 Guido Trotter
    self.ls.add('four')
1259 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
1260 aaae9bc0 Guido Trotter
1261 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
1262 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
1263 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
1264 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
1265 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
1266 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
1267 aaae9bc0 Guido Trotter
1268 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
1269 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
1270 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
1271 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['one', 'two', 'three']))
1272 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.is_owned(), True)
1273 d4803c24 Guido Trotter
    self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
1274 3b7ed473 Guido Trotter
    # I can still add/remove elements...
1275 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
1276 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
1277 3b7ed473 Guido Trotter
    self.ls.release()
1278 3b7ed473 Guido Trotter
    # share the set-lock
1279 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
1280 3b7ed473 Guido Trotter
    # adding new elements is not possible
1281 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
1282 3b7ed473 Guido Trotter
    self.ls.release()
1283 3b7ed473 Guido Trotter
1284 d4f6a91c Guido Trotter
  def testAcquireWithRepetitions(self):
1285 d4f6a91c Guido Trotter
    self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
1286 d4f6a91c Guido Trotter
                      set(['two', 'two', 'three']))
1287 d4f6a91c Guido Trotter
    self.ls.release(['two', 'two'])
1288 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set(['three']))
1289 d4f6a91c Guido Trotter
1290 2e1d6d96 Guido Trotter
  def testEmptyAcquire(self):
1291 2e1d6d96 Guido Trotter
    # Acquire an empty list of locks...
1292 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([]), set())
1293 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set())
1294 2e1d6d96 Guido Trotter
    # New locks can still be addded
1295 2e1d6d96 Guido Trotter
    self.assert_(self.ls.add('six'))
1296 2e1d6d96 Guido Trotter
    # "re-acquiring" is not an issue, since we had really acquired nothing
1297 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([], shared=1), set())
1298 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(), set())
1299 2e1d6d96 Guido Trotter
    # We haven't really acquired anything, so we cannot release
1300 2e1d6d96 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
1301 2e1d6d96 Guido Trotter
1302 84e344d4 Michael Hanselmann
  def _doLockSet(self, names, shared):
1303 aaae9bc0 Guido Trotter
    try:
1304 84e344d4 Michael Hanselmann
      self.ls.acquire(names, shared=shared)
1305 aaae9bc0 Guido Trotter
      self.done.put('DONE')
1306 aaae9bc0 Guido Trotter
      self.ls.release()
1307 aaae9bc0 Guido Trotter
    except errors.LockError:
1308 aaae9bc0 Guido Trotter
      self.done.put('ERR')
1309 aaae9bc0 Guido Trotter
1310 84e344d4 Michael Hanselmann
  def _doAddSet(self, names):
1311 3b7ed473 Guido Trotter
    try:
1312 84e344d4 Michael Hanselmann
      self.ls.add(names, acquired=1)
1313 3b7ed473 Guido Trotter
      self.done.put('DONE')
1314 3b7ed473 Guido Trotter
      self.ls.release()
1315 3b7ed473 Guido Trotter
    except errors.LockError:
1316 3b7ed473 Guido Trotter
      self.done.put('ERR')
1317 3b7ed473 Guido Trotter
1318 84e344d4 Michael Hanselmann
  def _doRemoveSet(self, names):
1319 84e344d4 Michael Hanselmann
    self.done.put(self.ls.remove(names))
1320 aaae9bc0 Guido Trotter
1321 4607c978 Iustin Pop
  @_Repeat
1322 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
1323 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
1324 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
1325 4607c978 Iustin Pop
    self._waitThreads()
1326 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1327 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two', 'three'], 1))
1328 4607c978 Iustin Pop
    self._waitThreads()
1329 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1330 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
1331 4607c978 Iustin Pop
    self._waitThreads()
1332 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1333 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
1334 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
1335 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1336 aaae9bc0 Guido Trotter
    self.ls.release()
1337 4607c978 Iustin Pop
    self._waitThreads()
1338 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1339 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1340 aaae9bc0 Guido Trotter
1341 4607c978 Iustin Pop
  @_Repeat
1342 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
1343 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
1344 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
1345 4607c978 Iustin Pop
    self._waitThreads()
1346 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1347 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 0))
1348 4607c978 Iustin Pop
    self._waitThreads()
1349 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1350 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
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._addThread(target=self._doLockSet, args=('one', 0))
1354 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 1))
1355 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
1356 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 1))
1357 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1358 aaae9bc0 Guido Trotter
    self.ls.release()
1359 4607c978 Iustin Pop
    self._waitThreads()
1360 4607c978 Iustin Pop
    for _ in range(6):
1361 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
1362 aaae9bc0 Guido Trotter
1363 4607c978 Iustin Pop
  @_Repeat
1364 5aab242c Michael Hanselmann
  def testSimpleAcquireTimeoutExpiring(self):
1365 5aab242c Michael Hanselmann
    names = sorted(self.ls._names())
1366 5aab242c Michael Hanselmann
    self.assert_(len(names) >= 3)
1367 5aab242c Michael Hanselmann
1368 5aab242c Michael Hanselmann
    # Get name of first lock
1369 5aab242c Michael Hanselmann
    first = names[0]
1370 5aab242c Michael Hanselmann
1371 5aab242c Michael Hanselmann
    # Get name of last lock
1372 5aab242c Michael Hanselmann
    last = names.pop()
1373 5aab242c Michael Hanselmann
1374 5aab242c Michael Hanselmann
    checks = [
1375 5aab242c Michael Hanselmann
      # Block first and try to lock it again
1376 5aab242c Michael Hanselmann
      (first, first),
1377 5aab242c Michael Hanselmann
1378 5aab242c Michael Hanselmann
      # Block last and try to lock all locks
1379 5aab242c Michael Hanselmann
      (None, first),
1380 5aab242c Michael Hanselmann
1381 5aab242c Michael Hanselmann
      # Block last and try to lock it again
1382 5aab242c Michael Hanselmann
      (last, last),
1383 5aab242c Michael Hanselmann
      ]
1384 5aab242c Michael Hanselmann
1385 5aab242c Michael Hanselmann
    for (wanted, block) in checks:
1386 5aab242c Michael Hanselmann
      # Lock in exclusive mode
1387 5aab242c Michael Hanselmann
      self.assert_(self.ls.acquire(block, shared=0))
1388 5aab242c Michael Hanselmann
1389 5aab242c Michael Hanselmann
      def _AcquireOne():
1390 5aab242c Michael Hanselmann
        # Try to get the same lock again with a timeout (should never succeed)
1391 23683c26 Michael Hanselmann
        acquired = self.ls.acquire(wanted, timeout=0.1, shared=0)
1392 23683c26 Michael Hanselmann
        if acquired:
1393 5aab242c Michael Hanselmann
          self.done.put("acquired")
1394 5aab242c Michael Hanselmann
          self.ls.release()
1395 5aab242c Michael Hanselmann
        else:
1396 23683c26 Michael Hanselmann
          self.assert_(acquired is None)
1397 ee2b99e3 Michael Hanselmann
          self.assertFalse(self.ls.list_owned())
1398 ee2b99e3 Michael Hanselmann
          self.assertFalse(self.ls.is_owned())
1399 5aab242c Michael Hanselmann
          self.done.put("not acquired")
1400 5aab242c Michael Hanselmann
1401 5aab242c Michael Hanselmann
      self._addThread(target=_AcquireOne)
1402 5aab242c Michael Hanselmann
1403 5aab242c Michael Hanselmann
      # Wait for timeout in thread to expire
1404 5aab242c Michael Hanselmann
      self._waitThreads()
1405 5aab242c Michael Hanselmann
1406 5aab242c Michael Hanselmann
      # Release exclusive lock again
1407 5aab242c Michael Hanselmann
      self.ls.release()
1408 5aab242c Michael Hanselmann
1409 5aab242c Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "not acquired")
1410 5aab242c Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
1411 5aab242c Michael Hanselmann
1412 5aab242c Michael Hanselmann
  @_Repeat
1413 5aab242c Michael Hanselmann
  def testDelayedAndExpiringLockAcquire(self):
1414 5aab242c Michael Hanselmann
    self._setUpLS()
1415 5aab242c Michael Hanselmann
    self.ls.add(['five', 'six', 'seven', 'eight', 'nine'])
1416 5aab242c Michael Hanselmann
1417 5aab242c Michael Hanselmann
    for expire in (False, True):
1418 5aab242c Michael Hanselmann
      names = sorted(self.ls._names())
1419 5aab242c Michael Hanselmann
      self.assertEqual(len(names), 8)
1420 5aab242c Michael Hanselmann
1421 5aab242c Michael Hanselmann
      lock_ev = dict([(i, threading.Event()) for i in names])
1422 5aab242c Michael Hanselmann
1423 5aab242c Michael Hanselmann
      # Lock all in exclusive mode
1424 5aab242c Michael Hanselmann
      self.assert_(self.ls.acquire(names, shared=0))
1425 5aab242c Michael Hanselmann
1426 5aab242c Michael Hanselmann
      if expire:
1427 5aab242c Michael Hanselmann
        # We'll wait at least 300ms per lock
1428 5aab242c Michael Hanselmann
        lockwait = len(names) * [0.3]
1429 5aab242c Michael Hanselmann
1430 5aab242c Michael Hanselmann
        # Fail if we can't acquire all locks in 400ms. There are 8 locks, so
1431 5aab242c Michael Hanselmann
        # this gives us up to 2.4s to fail.
1432 5aab242c Michael Hanselmann
        lockall_timeout = 0.4
1433 5aab242c Michael Hanselmann
      else:
1434 5aab242c Michael Hanselmann
        # This should finish rather quickly
1435 5aab242c Michael Hanselmann
        lockwait = None
1436 5aab242c Michael Hanselmann
        lockall_timeout = len(names) * 5.0
1437 5aab242c Michael Hanselmann
1438 5aab242c Michael Hanselmann
      def _LockAll():
1439 5aab242c Michael Hanselmann
        def acquire_notification(name):
1440 5aab242c Michael Hanselmann
          if not expire:
1441 5aab242c Michael Hanselmann
            self.done.put("getting %s" % name)
1442 5aab242c Michael Hanselmann
1443 5aab242c Michael Hanselmann
          # Kick next lock
1444 5aab242c Michael Hanselmann
          lock_ev[name].set()
1445 5aab242c Michael Hanselmann
1446 5aab242c Michael Hanselmann
        if self.ls.acquire(names, shared=0, timeout=lockall_timeout,
1447 5aab242c Michael Hanselmann
                           test_notify=acquire_notification):
1448 5aab242c Michael Hanselmann
          self.done.put("got all")
1449 5aab242c Michael Hanselmann
          self.ls.release()
1450 5aab242c Michael Hanselmann
        else:
1451 5aab242c Michael Hanselmann
          self.done.put("timeout on all")
1452 5aab242c Michael Hanselmann
1453 5aab242c Michael Hanselmann
        # Notify all locks
1454 5aab242c Michael Hanselmann
        for ev in lock_ev.values():
1455 5aab242c Michael Hanselmann
          ev.set()
1456 5aab242c Michael Hanselmann
1457 5aab242c Michael Hanselmann
      t = self._addThread(target=_LockAll)
1458 5aab242c Michael Hanselmann
1459 5aab242c Michael Hanselmann
      for idx, name in enumerate(names):
1460 5aab242c Michael Hanselmann
        # Wait for actual acquire on this lock to start
1461 5aab242c Michael Hanselmann
        lock_ev[name].wait(10.0)
1462 5aab242c Michael Hanselmann
1463 5aab242c Michael Hanselmann
        if expire and t.isAlive():
1464 5aab242c Michael Hanselmann
          # Wait some time after getting the notification to make sure the lock
1465 5aab242c Michael Hanselmann
          # acquire will expire
1466 5aab242c Michael Hanselmann
          SafeSleep(lockwait[idx])
1467 5aab242c Michael Hanselmann
1468 5aab242c Michael Hanselmann
        self.ls.release(names=name)
1469 5aab242c Michael Hanselmann
1470 ee2b99e3 Michael Hanselmann
      self.assertFalse(self.ls.list_owned())
1471 5aab242c Michael Hanselmann
1472 5aab242c Michael Hanselmann
      self._waitThreads()
1473 5aab242c Michael Hanselmann
1474 5aab242c Michael Hanselmann
      if expire:
1475 5aab242c Michael Hanselmann
        # Not checking which locks were actually acquired. Doing so would be
1476 5aab242c Michael Hanselmann
        # too timing-dependant.
1477 5aab242c Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "timeout on all")
1478 5aab242c Michael Hanselmann
      else:
1479 5aab242c Michael Hanselmann
        for i in names:
1480 5aab242c Michael Hanselmann
          self.assertEqual(self.done.get_nowait(), "getting %s" % i)
1481 5aab242c Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "got all")
1482 5aab242c Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
1483 5aab242c Michael Hanselmann
1484 5aab242c Michael Hanselmann
  @_Repeat
1485 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
1486 aaae9bc0 Guido Trotter
    self.ls.add('four')
1487 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
1488 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 0))
1489 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 1))
1490 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
1491 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
1492 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1493 aaae9bc0 Guido Trotter
    self.ls.remove('one')
1494 aaae9bc0 Guido Trotter
    self.ls.release()
1495 4607c978 Iustin Pop
    self._waitThreads()
1496 4607c978 Iustin Pop
    for i in range(4):
1497 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'ERR')
1498 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
1499 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 1))
1500 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 0))
1501 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 1))
1502 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 0))
1503 aaae9bc0 Guido Trotter
    self.ls.remove('five')
1504 aaae9bc0 Guido Trotter
    self.ls.release()
1505 4607c978 Iustin Pop
    self._waitThreads()
1506 4607c978 Iustin Pop
    for i in range(4):
1507 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
1508 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
1509 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['four', 'six'], ))
1510 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1511 aaae9bc0 Guido Trotter
    self.ls.remove('four')
1512 4607c978 Iustin Pop
    self._waitThreads()
1513 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['six'])
1514 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two']))
1515 4607c978 Iustin Pop
    self._waitThreads()
1516 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['two'])
1517 aaae9bc0 Guido Trotter
    self.ls.release()
1518 4607c978 Iustin Pop
    # reset lockset
1519 4607c978 Iustin Pop
    self._setUpLS()
1520 aaae9bc0 Guido Trotter
1521 4607c978 Iustin Pop
  @_Repeat
1522 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
1523 3b7ed473 Guido Trotter
    # share the set-lock...
1524 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
1525 3b7ed473 Guido Trotter
    # ...another thread can share it too
1526 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1527 4607c978 Iustin Pop
    self._waitThreads()
1528 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1529 3b7ed473 Guido Trotter
    # ...or just share some elements
1530 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'three'], 1))
1531 4607c978 Iustin Pop
    self._waitThreads()
1532 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1533 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
1534 4607c978 Iustin Pop
    t = self._addThread(target=self._doAddSet, args=(['nine']))
1535 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two'], ))
1536 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1537 3b7ed473 Guido Trotter
    # this just releases the set-lock
1538 3b7ed473 Guido Trotter
    self.ls.release([])
1539 4607c978 Iustin Pop
    t.join(60)
1540 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1541 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
1542 3b7ed473 Guido Trotter
    self.ls.release()
1543 4607c978 Iustin Pop
    self._waitThreads()
1544 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), ['two'])
1545 4607c978 Iustin Pop
    # reset lockset
1546 4607c978 Iustin Pop
    self._setUpLS()
1547 3b7ed473 Guido Trotter
1548 4607c978 Iustin Pop
  @_Repeat
1549 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
1550 3b7ed473 Guido Trotter
    # acquire the set-lock...
1551 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
1552 3b7ed473 Guido Trotter
    # ...no one can do anything else
1553 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1554 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1555 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three'], 0))
1556 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two'], 1))
1557 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1558 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1559 3b7ed473 Guido Trotter
    self.ls.release()
1560 4607c978 Iustin Pop
    self._waitThreads()
1561 4607c978 Iustin Pop
    for _ in range(5):
1562 4607c978 Iustin Pop
      self.assertEqual(self.done.get(True, 1), 'DONE')
1563 4607c978 Iustin Pop
    # cleanup
1564 4607c978 Iustin Pop
    self._setUpLS()
1565 3b7ed473 Guido Trotter
1566 4607c978 Iustin Pop
  @_Repeat
1567 d2aff862 Guido Trotter
  def testConcurrentSetLockAdd(self):
1568 d2aff862 Guido Trotter
    self.ls.acquire('one')
1569 d2aff862 Guido Trotter
    # Another thread wants the whole SetLock
1570 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1571 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1572 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1573 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'four')
1574 d2aff862 Guido Trotter
    self.ls.release()
1575 4607c978 Iustin Pop
    self._waitThreads()
1576 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1577 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1578 d2aff862 Guido Trotter
    self.ls.acquire(None)
1579 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1580 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1581 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1582 d2aff862 Guido Trotter
    self.ls.add('four')
1583 d2aff862 Guido Trotter
    self.ls.add('five', acquired=1)
1584 d2aff862 Guido Trotter
    self.ls.add('six', acquired=1, shared=1)
1585 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.list_owned(),
1586 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'five', 'six']))
1587 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.ls.is_owned(), True)
1588 d2aff862 Guido Trotter
    self.assertEquals(self.ls._names(),
1589 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'four', 'five', 'six']))
1590 d2aff862 Guido Trotter
    self.ls.release()
1591 4607c978 Iustin Pop
    self._waitThreads()
1592 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1593 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1594 4607c978 Iustin Pop
    self._setUpLS()
1595 d2aff862 Guido Trotter
1596 4607c978 Iustin Pop
  @_Repeat
1597 b2dabfd6 Guido Trotter
  def testEmptyLockSet(self):
1598 b2dabfd6 Guido Trotter
    # get the set-lock
1599 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
1600 b2dabfd6 Guido Trotter
    # now empty it...
1601 b2dabfd6 Guido Trotter
    self.ls.remove(['one', 'two', 'three'])
1602 b2dabfd6 Guido Trotter
    # and adds/locks by another thread still wait
1603 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1604 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1605 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1606 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1607 b2dabfd6 Guido Trotter
    self.ls.release()
1608 4607c978 Iustin Pop
    self._waitThreads()
1609 4607c978 Iustin Pop
    for _ in range(3):
1610 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'DONE')
1611 b2dabfd6 Guido Trotter
    # empty it again...
1612 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
1613 b2dabfd6 Guido Trotter
    # now share it...
1614 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None, shared=1), set())
1615 b2dabfd6 Guido Trotter
    # other sharers can go, adds still wait
1616 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1617 4607c978 Iustin Pop
    self._waitThreads()
1618 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1619 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1620 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1621 b2dabfd6 Guido Trotter
    self.ls.release()
1622 4607c978 Iustin Pop
    self._waitThreads()
1623 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1624 4607c978 Iustin Pop
    self._setUpLS()
1625 b2dabfd6 Guido Trotter
1626 3dbe3ddf Michael Hanselmann
  def testAcquireWithNamesDowngrade(self):
1627 3dbe3ddf Michael Hanselmann
    self.assertEquals(self.ls.acquire("two", shared=0), set(["two"]))
1628 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.ls.is_owned())
1629 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.ls._get_lock().is_owned())
1630 3dbe3ddf Michael Hanselmann
    self.ls.release()
1631 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.ls.is_owned())
1632 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.ls._get_lock().is_owned())
1633 3dbe3ddf Michael Hanselmann
    # Can't downgrade after releasing
1634 3dbe3ddf Michael Hanselmann
    self.assertRaises(AssertionError, self.ls.downgrade, "two")
1635 3dbe3ddf Michael Hanselmann
1636 3dbe3ddf Michael Hanselmann
  def testDowngrade(self):
1637 3dbe3ddf Michael Hanselmann
    # Not owning anything, must raise an exception
1638 ee2b99e3 Michael Hanselmann
    self.assertFalse(self.ls.is_owned())
1639 3dbe3ddf Michael Hanselmann
    self.assertRaises(AssertionError, self.ls.downgrade)
1640 3dbe3ddf Michael Hanselmann
1641 ee2b99e3 Michael Hanselmann
    self.assertFalse(compat.any(i.is_owned()
1642 3dbe3ddf Michael Hanselmann
                                for i in self.ls._get_lockdict().values()))
1643 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned(self.ls._names()))
1644 c6a622cf Michael Hanselmann
    for name in self.ls._names():
1645 c6a622cf Michael Hanselmann
      self.assertFalse(self.ls.check_owned(name))
1646 3dbe3ddf Michael Hanselmann
1647 3dbe3ddf Michael Hanselmann
    self.assertEquals(self.ls.acquire(None, shared=0),
1648 3dbe3ddf Michael Hanselmann
                      set(["one", "two", "three"]))
1649 3dbe3ddf Michael Hanselmann
    self.assertRaises(AssertionError, self.ls.downgrade, "unknown lock")
1650 3dbe3ddf Michael Hanselmann
1651 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned(self.ls._names(), shared=0))
1652 c6a622cf Michael Hanselmann
    for name in self.ls._names():
1653 c6a622cf Michael Hanselmann
      self.assertTrue(self.ls.check_owned(name))
1654 c6a622cf Michael Hanselmann
      self.assertTrue(self.ls.check_owned(name, shared=0))
1655 c6a622cf Michael Hanselmann
      self.assertFalse(self.ls.check_owned(name, shared=1))
1656 c6a622cf Michael Hanselmann
1657 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.ls._get_lock().is_owned(shared=0))
1658 ee2b99e3 Michael Hanselmann
    self.assertTrue(compat.all(i.is_owned(shared=0)
1659 3dbe3ddf Michael Hanselmann
                               for i in self.ls._get_lockdict().values()))
1660 3dbe3ddf Michael Hanselmann
1661 3dbe3ddf Michael Hanselmann
    # Start downgrading locks
1662 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls.downgrade(names=["one"]))
1663 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.ls._get_lock().is_owned(shared=0))
1664 ee2b99e3 Michael Hanselmann
    self.assertTrue(compat.all(lock.is_owned(shared=[0, 1][int(name == "one")])
1665 3dbe3ddf Michael Hanselmann
                               for name, lock in
1666 3dbe3ddf Michael Hanselmann
                                 self.ls._get_lockdict().items()))
1667 3dbe3ddf Michael Hanselmann
1668 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned("one", shared=0))
1669 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("one", shared=1))
1670 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("two", shared=0))
1671 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("three", shared=0))
1672 c6a622cf Michael Hanselmann
1673 c6a622cf Michael Hanselmann
    # Downgrade second lock
1674 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls.downgrade(names="two"))
1675 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.ls._get_lock().is_owned(shared=0))
1676 3dbe3ddf Michael Hanselmann
    should_share = lambda name: [0, 1][int(name in ("one", "two"))]
1677 ee2b99e3 Michael Hanselmann
    self.assertTrue(compat.all(lock.is_owned(shared=should_share(name))
1678 3dbe3ddf Michael Hanselmann
                               for name, lock in
1679 3dbe3ddf Michael Hanselmann
                                 self.ls._get_lockdict().items()))
1680 3dbe3ddf Michael Hanselmann
1681 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned("one", shared=0))
1682 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("one", shared=1))
1683 c6a622cf Michael Hanselmann
    self.assertFalse(self.ls.check_owned("two", shared=0))
1684 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("two", shared=1))
1685 c6a622cf Michael Hanselmann
    self.assertTrue(self.ls.check_owned("three", shared=0))
1686 c6a622cf Michael Hanselmann
1687 3dbe3ddf Michael Hanselmann
    # Downgrading the last exclusive lock to shared must downgrade the
1688 3dbe3ddf Michael Hanselmann
    # lockset-internal lock too
1689 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls.downgrade(names="three"))
1690 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.ls._get_lock().is_owned(shared=1))
1691 ee2b99e3 Michael Hanselmann
    self.assertTrue(compat.all(i.is_owned(shared=1)
1692 3dbe3ddf Michael Hanselmann
                               for i in self.ls._get_lockdict().values()))
1693 3dbe3ddf Michael Hanselmann
1694 c6a622cf Michael Hanselmann
    # Verify owned locks
1695 c6a622cf Michael Hanselmann
    for name in self.ls._names():
1696 c6a622cf Michael Hanselmann
      self.assertTrue(self.ls.check_owned(name, shared=1))
1697 c6a622cf Michael Hanselmann
1698 3dbe3ddf Michael Hanselmann
    # Downgrading a shared lock must be a no-op
1699 3dbe3ddf Michael Hanselmann
    self.assertTrue(self.ls.downgrade(names=["one", "three"]))
1700 ee2b99e3 Michael Hanselmann
    self.assertTrue(self.ls._get_lock().is_owned(shared=1))
1701 ee2b99e3 Michael Hanselmann
    self.assertTrue(compat.all(i.is_owned(shared=1)
1702 3dbe3ddf Michael Hanselmann
                               for i in self.ls._get_lockdict().values()))
1703 3dbe3ddf Michael Hanselmann
1704 3dbe3ddf Michael Hanselmann
    self.ls.release()
1705 3dbe3ddf Michael Hanselmann
1706 887c7aa6 Michael Hanselmann
  def testPriority(self):
1707 887c7aa6 Michael Hanselmann
    def _Acquire(prev, next, name, priority, success_fn):
1708 887c7aa6 Michael Hanselmann
      prev.wait()
1709 887c7aa6 Michael Hanselmann
      self.assert_(self.ls.acquire(name, shared=0,
1710 887c7aa6 Michael Hanselmann
                                   priority=priority,
1711 887c7aa6 Michael Hanselmann
                                   test_notify=lambda _: next.set()))
1712 887c7aa6 Michael Hanselmann
      try:
1713 887c7aa6 Michael Hanselmann
        success_fn()
1714 887c7aa6 Michael Hanselmann
      finally:
1715 887c7aa6 Michael Hanselmann
        self.ls.release()
1716 887c7aa6 Michael Hanselmann
1717 887c7aa6 Michael Hanselmann
    # Get all in exclusive mode
1718 887c7aa6 Michael Hanselmann
    self.assert_(self.ls.acquire(locking.ALL_SET, shared=0))
1719 887c7aa6 Michael Hanselmann
1720 887c7aa6 Michael Hanselmann
    done_two = Queue.Queue(0)
1721 887c7aa6 Michael Hanselmann
1722 887c7aa6 Michael Hanselmann
    first = threading.Event()
1723 887c7aa6 Michael Hanselmann
    prev = first
1724 887c7aa6 Michael Hanselmann
1725 887c7aa6 Michael Hanselmann
    acquires = [("one", prio, self.done) for prio in range(1, 33)]
1726 887c7aa6 Michael Hanselmann
    acquires.extend([("two", prio, done_two) for prio in range(1, 33)])
1727 887c7aa6 Michael Hanselmann
1728 887c7aa6 Michael Hanselmann
    # Use a deterministic random generator
1729 887c7aa6 Michael Hanselmann
    random.Random(741).shuffle(acquires)
1730 887c7aa6 Michael Hanselmann
1731 887c7aa6 Michael Hanselmann
    for (name, prio, done) in acquires:
1732 887c7aa6 Michael Hanselmann
      ev = threading.Event()
1733 887c7aa6 Michael Hanselmann
      self._addThread(target=_Acquire,
1734 887c7aa6 Michael Hanselmann
                      args=(prev, ev, name, prio,
1735 887c7aa6 Michael Hanselmann
                            compat.partial(done.put, "Prio%s" % prio)))
1736 887c7aa6 Michael Hanselmann
      prev = ev
1737 887c7aa6 Michael Hanselmann
1738 887c7aa6 Michael Hanselmann
    # Start acquires
1739 887c7aa6 Michael Hanselmann
    first.set()
1740 887c7aa6 Michael Hanselmann
1741 887c7aa6 Michael Hanselmann
    # Wait for last acquire to start
1742 887c7aa6 Michael Hanselmann
    prev.wait()
1743 887c7aa6 Michael Hanselmann
1744 887c7aa6 Michael Hanselmann
    # Let threads acquire locks
1745 887c7aa6 Michael Hanselmann
    self.ls.release()
1746 887c7aa6 Michael Hanselmann
1747 887c7aa6 Michael Hanselmann
    # Wait for threads to finish
1748 887c7aa6 Michael Hanselmann
    self._waitThreads()
1749 887c7aa6 Michael Hanselmann
1750 887c7aa6 Michael Hanselmann
    for i in range(1, 33):
1751 887c7aa6 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "Prio%s" % i)
1752 887c7aa6 Michael Hanselmann
      self.assertEqual(done_two.get_nowait(), "Prio%s" % i)
1753 887c7aa6 Michael Hanselmann
1754 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1755 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, done_two.get_nowait)
1756 887c7aa6 Michael Hanselmann
1757 aaae9bc0 Guido Trotter
1758 4607c978 Iustin Pop
class TestGanetiLockManager(_ThreadedTestCase):
1759 7ee7c0c7 Guido Trotter
1760 7ee7c0c7 Guido Trotter
  def setUp(self):
1761 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
1762 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
1763 819ca990 Guido Trotter
    self.nodegroups=['g1', 'g2']
1764 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
1765 819ca990 Guido Trotter
    self.GL = locking.GanetiLockManager(self.nodes, self.nodegroups,
1766 819ca990 Guido Trotter
                                        self.instances)
1767 7ee7c0c7 Guido Trotter
1768 7ee7c0c7 Guido Trotter
  def tearDown(self):
1769 7ee7c0c7 Guido Trotter
    # Don't try this at home...
1770 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1771 7ee7c0c7 Guido Trotter
1772 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
1773 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
1774 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
1775 b10b9d74 Guido Trotter
    # This relationship is also used in the Processor to recursively acquire
1776 b10b9d74 Guido Trotter
    # the right locks. Again, please don't break it.
1777 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
1778 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
1779 7ee7c0c7 Guido Trotter
1780 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
1781 819ca990 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager, [], [], [])
1782 7ee7c0c7 Guido Trotter
1783 7ee7c0c7 Guido Trotter
  def testLockNames(self):
1784 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1785 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1786 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP),
1787 819ca990 Guido Trotter
                     set(self.nodegroups))
1788 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1789 cdb08f44 Michael Hanselmann
                     set(self.instances))
1790 7ee7c0c7 Guido Trotter
1791 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
1792 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1793 819ca990 Guido Trotter
    self.GL = locking.GanetiLockManager([], [], [])
1794 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1795 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1796 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set())
1797 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1798 7ee7c0c7 Guido Trotter
1799 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1800 819ca990 Guido Trotter
    self.GL = locking.GanetiLockManager(self.nodes, self.nodegroups, [])
1801 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1802 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1803 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP),
1804 819ca990 Guido Trotter
                                    set(self.nodegroups))
1805 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1806 7ee7c0c7 Guido Trotter
1807 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1808 819ca990 Guido Trotter
    self.GL = locking.GanetiLockManager([], [], self.instances)
1809 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1810 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1811 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set())
1812 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1813 cdb08f44 Michael Hanselmann
                     set(self.instances))
1814 7ee7c0c7 Guido Trotter
1815 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
1816 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1817 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
1818 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
1819 819ca990 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODEGROUP, ['g2'])
1820 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
1821 c6a622cf Michael Hanselmann
    self.assertTrue(self.GL.check_owned(locking.LEVEL_NODE, ["n1", "n2"],
1822 c6a622cf Michael Hanselmann
                                        shared=1))
1823 c6a622cf Michael Hanselmann
    self.assertFalse(self.GL.check_owned(locking.LEVEL_INSTANCE, ["i1", "i3"]))
1824 04e1bfaf Guido Trotter
    self.GL.release(locking.LEVEL_NODE, ['n2'])
1825 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODE), set(['n1']))
1826 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODEGROUP), set(['g2']))
1827 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_INSTANCE), set(['i1']))
1828 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1829 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODE), set())
1830 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODEGROUP), set(['g2']))
1831 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_INSTANCE), set(['i1']))
1832 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_NODEGROUP)
1833 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1834 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
1835 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
1836 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
1837 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_INSTANCE), set(['i3']))
1838 7ee7c0c7 Guido Trotter
1839 90c942d1 Guido Trotter
  def testAcquireWholeSets(self):
1840 90c942d1 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1841 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
1842 90c942d1 Guido Trotter
                      set(self.instances))
1843 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_INSTANCE),
1844 90c942d1 Guido Trotter
                      set(self.instances))
1845 819ca990 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODEGROUP, None),
1846 819ca990 Guido Trotter
                      set(self.nodegroups))
1847 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODEGROUP),
1848 819ca990 Guido Trotter
                      set(self.nodegroups))
1849 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
1850 90c942d1 Guido Trotter
                      set(self.nodes))
1851 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODE),
1852 90c942d1 Guido Trotter
                      set(self.nodes))
1853 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1854 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_NODEGROUP)
1855 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1856 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1857 d4f6a91c Guido Trotter
1858 d4f6a91c Guido Trotter
  def testAcquireWholeAndPartial(self):
1859 d4f6a91c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1860 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
1861 d4f6a91c Guido Trotter
                      set(self.instances))
1862 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_INSTANCE),
1863 d4f6a91c Guido Trotter
                      set(self.instances))
1864 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
1865 d4f6a91c Guido Trotter
                      set(['n2']))
1866 ee2b99e3 Michael Hanselmann
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODE),
1867 d4f6a91c Guido Trotter
                      set(['n2']))
1868 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1869 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1870 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1871 90c942d1 Guido Trotter
1872 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
1873 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1874 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
1875 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1876 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
1877 819ca990 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1878 819ca990 Guido Trotter
                      locking.LEVEL_NODEGROUP, ['g1'])
1879 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1880 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
1881 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1882 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1883 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1884 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1885 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1886 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
1887 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1888 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1889 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1890 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1891 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1892 819ca990 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODEGROUP, None)
1893 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_NODEGROUP, ['g1'])
1894 819ca990 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1895 819ca990 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1896 819ca990 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1897 819ca990 Guido Trotter
                      locking.LEVEL_CLUSTER)
1898 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_NODEGROUP)
1899 819ca990 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1900 7ee7c0c7 Guido Trotter
1901 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
1902 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1903 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n2'])
1904 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1905 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
1906 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1907 819ca990 Guido Trotter
                      locking.LEVEL_NODEGROUP, ['g1'])
1908 819ca990 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1909 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
1910 7ee7c0c7 Guido Trotter
1911 4badc36c Guido Trotter
  def testModifiableLevels(self):
1912 4badc36c Guido Trotter
    self.assertRaises(AssertionError, self.GL.add, locking.LEVEL_CLUSTER,
1913 4badc36c Guido Trotter
                      ['BGL2'])
1914 4badc36c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'])
1915 4badc36c Guido Trotter
    self.GL.add(locking.LEVEL_INSTANCE, ['i4'])
1916 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_INSTANCE, ['i3'])
1917 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_INSTANCE, ['i1'])
1918 4badc36c Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set(['i2', 'i4']))
1919 4badc36c Guido Trotter
    self.GL.add(locking.LEVEL_NODE, ['n3'])
1920 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_NODE, ['n1'])
1921 4badc36c Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(['n2', 'n3']))
1922 819ca990 Guido Trotter
    self.GL.add(locking.LEVEL_NODEGROUP, ['g3'])
1923 819ca990 Guido Trotter
    self.GL.remove(locking.LEVEL_NODEGROUP, ['g2'])
1924 819ca990 Guido Trotter
    self.GL.remove(locking.LEVEL_NODEGROUP, ['g1'])
1925 819ca990 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set(['g3']))
1926 4badc36c Guido Trotter
    self.assertRaises(AssertionError, self.GL.remove, locking.LEVEL_CLUSTER,
1927 4badc36c Guido Trotter
                      ['BGL2'])
1928 4badc36c Guido Trotter
1929 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
1930 7ee7c0c7 Guido Trotter
  # some locks at another level.
1931 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
1932 7ee7c0c7 Guido Trotter
    try:
1933 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1934 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
1935 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
1936 7ee7c0c7 Guido Trotter
      self.GL.release(level)
1937 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
1938 7ee7c0c7 Guido Trotter
    except errors.LockError:
1939 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
1940 7ee7c0c7 Guido Trotter
1941 4607c978 Iustin Pop
  @_Repeat
1942 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
1943 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1944 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1945 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1946 4607c978 Iustin Pop
    self._waitThreads()
1947 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1948 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
1949 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1950 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1951 4607c978 Iustin Pop
    self._waitThreads()
1952 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1953 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1954 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i3', 1))
1955 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1956 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1957 4607c978 Iustin Pop
    self._waitThreads()
1958 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1959 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
1960 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1961 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 1))
1962 4607c978 Iustin Pop
    self._waitThreads()
1963 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1964 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1965 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 0))
1966 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1967 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1968 4607c978 Iustin Pop
    self._waitThreads()
1969 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
1970 4607c978 Iustin Pop
    self.GL.release(locking.LEVEL_CLUSTER, ['BGL'])
1971 7ee7c0c7 Guido Trotter
1972 7ee7c0c7 Guido Trotter
1973 19b9ba9a Michael Hanselmann
class TestLockMonitor(_ThreadedTestCase):
1974 19b9ba9a Michael Hanselmann
  def setUp(self):
1975 19b9ba9a Michael Hanselmann
    _ThreadedTestCase.setUp(self)
1976 19b9ba9a Michael Hanselmann
    self.lm = locking.LockMonitor()
1977 19b9ba9a Michael Hanselmann
1978 19b9ba9a Michael Hanselmann
  def testSingleThread(self):
1979 19b9ba9a Michael Hanselmann
    locks = []
1980 19b9ba9a Michael Hanselmann
1981 19b9ba9a Michael Hanselmann
    for i in range(100):
1982 19b9ba9a Michael Hanselmann
      name = "TestLock%s" % i
1983 19b9ba9a Michael Hanselmann
      locks.append(locking.SharedLock(name, monitor=self.lm))
1984 19b9ba9a Michael Hanselmann
1985 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), len(locks))
1986 24d16f76 Michael Hanselmann
    result = objects.QueryResponse.FromDict(self.lm.QueryLocks(["name"]))
1987 24d16f76 Michael Hanselmann
    self.assertEqual(len(result.fields), 1)
1988 24d16f76 Michael Hanselmann
    self.assertEqual(len(result.data), 100)
1989 c31825f7 Michael Hanselmann
1990 19b9ba9a Michael Hanselmann
    # Delete all locks
1991 19b9ba9a Michael Hanselmann
    del locks[:]
1992 19b9ba9a Michael Hanselmann
1993 19b9ba9a Michael Hanselmann
    # The garbage collector might needs some time
1994 19b9ba9a Michael Hanselmann
    def _CheckLocks():
1995 19b9ba9a Michael Hanselmann
      if self.lm._locks:
1996 19b9ba9a Michael Hanselmann
        raise utils.RetryAgain()
1997 19b9ba9a Michael Hanselmann
1998 19b9ba9a Michael Hanselmann
    utils.Retry(_CheckLocks, 0.1, 30.0)
1999 19b9ba9a Michael Hanselmann
2000 19b9ba9a Michael Hanselmann
    self.assertFalse(self.lm._locks)
2001 19b9ba9a Michael Hanselmann
2002 19b9ba9a Michael Hanselmann
  def testMultiThread(self):
2003 19b9ba9a Michael Hanselmann
    locks = []
2004 19b9ba9a Michael Hanselmann
2005 19b9ba9a Michael Hanselmann
    def _CreateLock(prev, next, name):
2006 19b9ba9a Michael Hanselmann
      prev.wait()
2007 19b9ba9a Michael Hanselmann
      locks.append(locking.SharedLock(name, monitor=self.lm))
2008 19b9ba9a Michael Hanselmann
      if next:
2009 19b9ba9a Michael Hanselmann
        next.set()
2010 19b9ba9a Michael Hanselmann
2011 19b9ba9a Michael Hanselmann
    expnames = []
2012 19b9ba9a Michael Hanselmann
2013 19b9ba9a Michael Hanselmann
    first = threading.Event()
2014 19b9ba9a Michael Hanselmann
    prev = first
2015 19b9ba9a Michael Hanselmann
2016 19b9ba9a Michael Hanselmann
    # Use a deterministic random generator
2017 19b9ba9a Michael Hanselmann
    for i in random.Random(4263).sample(range(100), 33):
2018 19b9ba9a Michael Hanselmann
      name = "MtTestLock%s" % i
2019 19b9ba9a Michael Hanselmann
      expnames.append(name)
2020 19b9ba9a Michael Hanselmann
2021 19b9ba9a Michael Hanselmann
      ev = threading.Event()
2022 19b9ba9a Michael Hanselmann
      self._addThread(target=_CreateLock, args=(prev, ev, name))
2023 19b9ba9a Michael Hanselmann
      prev = ev
2024 19b9ba9a Michael Hanselmann
2025 19b9ba9a Michael Hanselmann
    # Add locks
2026 19b9ba9a Michael Hanselmann
    first.set()
2027 19b9ba9a Michael Hanselmann
    self._waitThreads()
2028 19b9ba9a Michael Hanselmann
2029 19b9ba9a Michael Hanselmann
    # Check order in which locks were added
2030 19b9ba9a Michael Hanselmann
    self.assertEqual([i.name for i in locks], expnames)
2031 19b9ba9a Michael Hanselmann
2032 19b9ba9a Michael Hanselmann
    # Check query result
2033 24d16f76 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner", "pending"])
2034 24d16f76 Michael Hanselmann
    self.assert_(isinstance(result, dict))
2035 24d16f76 Michael Hanselmann
    response = objects.QueryResponse.FromDict(result)
2036 24d16f76 Michael Hanselmann
    self.assertEqual(response.data,
2037 cfb084ae Renรฉ Nussbaumer
                     [[(constants.RS_NORMAL, name),
2038 cfb084ae Renรฉ Nussbaumer
                       (constants.RS_NORMAL, None),
2039 cfb084ae Renรฉ Nussbaumer
                       (constants.RS_NORMAL, None),
2040 cfb084ae Renรฉ Nussbaumer
                       (constants.RS_NORMAL, [])]
2041 c31825f7 Michael Hanselmann
                      for name in utils.NiceSort(expnames)])
2042 24d16f76 Michael Hanselmann
    self.assertEqual(len(response.fields), 4)
2043 24d16f76 Michael Hanselmann
    self.assertEqual(["name", "mode", "owner", "pending"],
2044 24d16f76 Michael Hanselmann
                     [fdef.name for fdef in response.fields])
2045 19b9ba9a Michael Hanselmann
2046 19b9ba9a Michael Hanselmann
    # Test exclusive acquire
2047 19b9ba9a Michael Hanselmann
    for tlock in locks[::4]:
2048 19b9ba9a Michael Hanselmann
      tlock.acquire(shared=0)
2049 19b9ba9a Michael Hanselmann
      try:
2050 19b9ba9a Michael Hanselmann
        def _GetExpResult(name):
2051 19b9ba9a Michael Hanselmann
          if tlock.name == name:
2052 cfb084ae Renรฉ Nussbaumer
            return [(constants.RS_NORMAL, name),
2053 cfb084ae Renรฉ Nussbaumer
                    (constants.RS_NORMAL, "exclusive"),
2054 cfb084ae Renรฉ Nussbaumer
                    (constants.RS_NORMAL,
2055 24d16f76 Michael Hanselmann
                     [threading.currentThread().getName()]),
2056 cfb084ae Renรฉ Nussbaumer
                    (constants.RS_NORMAL, [])]
2057 cfb084ae Renรฉ Nussbaumer
          return [(constants.RS_NORMAL, name),
2058 cfb084ae Renรฉ Nussbaumer
                  (constants.RS_NORMAL, None),
2059 cfb084ae Renรฉ Nussbaumer
                  (constants.RS_NORMAL, None),
2060 cfb084ae Renรฉ Nussbaumer
                  (constants.RS_NORMAL, [])]
2061 24d16f76 Michael Hanselmann
2062 24d16f76 Michael Hanselmann
        result = self.lm.QueryLocks(["name", "mode", "owner", "pending"])
2063 24d16f76 Michael Hanselmann
        self.assertEqual(objects.QueryResponse.FromDict(result).data,
2064 19b9ba9a Michael Hanselmann
                         [_GetExpResult(name)
2065 19b9ba9a Michael Hanselmann
                          for name in utils.NiceSort(expnames)])
2066 19b9ba9a Michael Hanselmann
      finally:
2067 19b9ba9a Michael Hanselmann
        tlock.release()
2068 19b9ba9a Michael Hanselmann
2069 19b9ba9a Michael Hanselmann
    # Test shared acquire
2070 73c25d35 Michael Hanselmann
    def _Acquire(lock, shared, ev, notify):
2071 19b9ba9a Michael Hanselmann
      lock.acquire(shared=shared)
2072 19b9ba9a Michael Hanselmann
      try:
2073 73c25d35 Michael Hanselmann
        notify.set()
2074 19b9ba9a Michael Hanselmann
        ev.wait()
2075 19b9ba9a Michael Hanselmann
      finally:
2076 19b9ba9a Michael Hanselmann
        lock.release()
2077 19b9ba9a Michael Hanselmann
2078 19b9ba9a Michael Hanselmann
    for tlock1 in locks[::11]:
2079 19b9ba9a Michael Hanselmann
      for tlock2 in locks[::-15]:
2080 19b9ba9a Michael Hanselmann
        if tlock2 == tlock1:
2081 73c25d35 Michael Hanselmann
          # Avoid deadlocks
2082 19b9ba9a Michael Hanselmann
          continue
2083 19b9ba9a Michael Hanselmann
2084 19b9ba9a Michael Hanselmann
        for tlock3 in locks[::10]:
2085 73c25d35 Michael Hanselmann
          if tlock3 in (tlock2, tlock1):
2086 73c25d35 Michael Hanselmann
            # Avoid deadlocks
2087 19b9ba9a Michael Hanselmann
            continue
2088 19b9ba9a Michael Hanselmann
2089 73c25d35 Michael Hanselmann
          releaseev = threading.Event()
2090 19b9ba9a Michael Hanselmann
2091 19b9ba9a Michael Hanselmann
          # Acquire locks
2092 73c25d35 Michael Hanselmann
          acquireev = []
2093 19b9ba9a Michael Hanselmann
          tthreads1 = []
2094 19b9ba9a Michael Hanselmann
          for i in range(3):
2095 73c25d35 Michael Hanselmann
            ev = threading.Event()
2096 19b9ba9a Michael Hanselmann
            tthreads1.append(self._addThread(target=_Acquire,
2097 73c25d35 Michael Hanselmann
                                             args=(tlock1, 1, releaseev, ev)))
2098 73c25d35 Michael Hanselmann
            acquireev.append(ev)
2099 73c25d35 Michael Hanselmann
2100 73c25d35 Michael Hanselmann
          ev = threading.Event()
2101 73c25d35 Michael Hanselmann
          tthread2 = self._addThread(target=_Acquire,
2102 73c25d35 Michael Hanselmann
                                     args=(tlock2, 1, releaseev, ev))
2103 73c25d35 Michael Hanselmann
          acquireev.append(ev)
2104 73c25d35 Michael Hanselmann
2105 73c25d35 Michael Hanselmann
          ev = threading.Event()
2106 73c25d35 Michael Hanselmann
          tthread3 = self._addThread(target=_Acquire,
2107 73c25d35 Michael Hanselmann
                                     args=(tlock3, 0, releaseev, ev))
2108 73c25d35 Michael Hanselmann
          acquireev.append(ev)
2109 73c25d35 Michael Hanselmann
2110 73c25d35 Michael Hanselmann
          # Wait for all locks to be acquired
2111 73c25d35 Michael Hanselmann
          for i in acquireev:
2112 73c25d35 Michael Hanselmann
            i.wait()
2113 19b9ba9a Michael Hanselmann
2114 19b9ba9a Michael Hanselmann
          # Check query result
2115 24d16f76 Michael Hanselmann
          result = self.lm.QueryLocks(["name", "mode", "owner"])
2116 24d16f76 Michael Hanselmann
          response = objects.QueryResponse.FromDict(result)
2117 24d16f76 Michael Hanselmann
          for (name, mode, owner) in response.data:
2118 24d16f76 Michael Hanselmann
            (name_status, name_value) = name
2119 24d16f76 Michael Hanselmann
            (owner_status, owner_value) = owner
2120 24d16f76 Michael Hanselmann
2121 cfb084ae Renรฉ Nussbaumer
            self.assertEqual(name_status, constants.RS_NORMAL)
2122 cfb084ae Renรฉ Nussbaumer
            self.assertEqual(owner_status, constants.RS_NORMAL)
2123 24d16f76 Michael Hanselmann
2124 24d16f76 Michael Hanselmann
            if name_value == tlock1.name:
2125 cfb084ae Renรฉ Nussbaumer
              self.assertEqual(mode, (constants.RS_NORMAL, "shared"))
2126 24d16f76 Michael Hanselmann
              self.assertEqual(set(owner_value),
2127 24d16f76 Michael Hanselmann
                               set(i.getName() for i in tthreads1))
2128 19b9ba9a Michael Hanselmann
              continue
2129 19b9ba9a Michael Hanselmann
2130 24d16f76 Michael Hanselmann
            if name_value == tlock2.name:
2131 cfb084ae Renรฉ Nussbaumer
              self.assertEqual(mode, (constants.RS_NORMAL, "shared"))
2132 24d16f76 Michael Hanselmann
              self.assertEqual(owner_value, [tthread2.getName()])
2133 19b9ba9a Michael Hanselmann
              continue
2134 19b9ba9a Michael Hanselmann
2135 24d16f76 Michael Hanselmann
            if name_value == tlock3.name:
2136 cfb084ae Renรฉ Nussbaumer
              self.assertEqual(mode, (constants.RS_NORMAL, "exclusive"))
2137 24d16f76 Michael Hanselmann
              self.assertEqual(owner_value, [tthread3.getName()])
2138 19b9ba9a Michael Hanselmann
              continue
2139 19b9ba9a Michael Hanselmann
2140 24d16f76 Michael Hanselmann
            self.assert_(name_value in expnames)
2141 cfb084ae Renรฉ Nussbaumer
            self.assertEqual(mode, (constants.RS_NORMAL, None))
2142 24d16f76 Michael Hanselmann
            self.assert_(owner_value is None)
2143 19b9ba9a Michael Hanselmann
2144 19b9ba9a Michael Hanselmann
          # Release locks again
2145 73c25d35 Michael Hanselmann
          releaseev.set()
2146 19b9ba9a Michael Hanselmann
2147 19b9ba9a Michael Hanselmann
          self._waitThreads()
2148 19b9ba9a Michael Hanselmann
2149 24d16f76 Michael Hanselmann
          result = self.lm.QueryLocks(["name", "mode", "owner"])
2150 24d16f76 Michael Hanselmann
          self.assertEqual(objects.QueryResponse.FromDict(result).data,
2151 cfb084ae Renรฉ Nussbaumer
                           [[(constants.RS_NORMAL, name),
2152 cfb084ae Renรฉ Nussbaumer
                             (constants.RS_NORMAL, None),
2153 cfb084ae Renรฉ Nussbaumer
                             (constants.RS_NORMAL, None)]
2154 19b9ba9a Michael Hanselmann
                            for name in utils.NiceSort(expnames)])
2155 19b9ba9a Michael Hanselmann
2156 19b9ba9a Michael Hanselmann
  def testDelete(self):
2157 19b9ba9a Michael Hanselmann
    lock = locking.SharedLock("TestLock", monitor=self.lm)
2158 19b9ba9a Michael Hanselmann
2159 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), 1)
2160 24d16f76 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2161 24d16f76 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data,
2162 cfb084ae Renรฉ Nussbaumer
                     [[(constants.RS_NORMAL, lock.name),
2163 cfb084ae Renรฉ Nussbaumer
                       (constants.RS_NORMAL, None),
2164 cfb084ae Renรฉ Nussbaumer
                       (constants.RS_NORMAL, None)]])
2165 19b9ba9a Michael Hanselmann
2166 19b9ba9a Michael Hanselmann
    lock.delete()
2167 19b9ba9a Michael Hanselmann
2168 24d16f76 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2169 24d16f76 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data,
2170 cfb084ae Renรฉ Nussbaumer
                     [[(constants.RS_NORMAL, lock.name),
2171 cfb084ae Renรฉ Nussbaumer
                       (constants.RS_NORMAL, "deleted"),
2172 cfb084ae Renรฉ Nussbaumer
                       (constants.RS_NORMAL, None)]])
2173 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), 1)
2174 19b9ba9a Michael Hanselmann
2175 c31825f7 Michael Hanselmann
  def testPending(self):
2176 c31825f7 Michael Hanselmann
    def _Acquire(lock, shared, prev, next):
2177 c31825f7 Michael Hanselmann
      prev.wait()
2178 c31825f7 Michael Hanselmann
2179 c31825f7 Michael Hanselmann
      lock.acquire(shared=shared, test_notify=next.set)
2180 c31825f7 Michael Hanselmann
      try:
2181 c31825f7 Michael Hanselmann
        pass
2182 c31825f7 Michael Hanselmann
      finally:
2183 c31825f7 Michael Hanselmann
        lock.release()
2184 c31825f7 Michael Hanselmann
2185 c31825f7 Michael Hanselmann
    lock = locking.SharedLock("ExcLock", monitor=self.lm)
2186 c31825f7 Michael Hanselmann
2187 c31825f7 Michael Hanselmann
    for shared in [0, 1]:
2188 c31825f7 Michael Hanselmann
      lock.acquire()
2189 c31825f7 Michael Hanselmann
      try:
2190 c31825f7 Michael Hanselmann
        self.assertEqual(len(self.lm._locks), 1)
2191 24d16f76 Michael Hanselmann
        result = self.lm.QueryLocks(["name", "mode", "owner"])
2192 24d16f76 Michael Hanselmann
        self.assertEqual(objects.QueryResponse.FromDict(result).data,
2193 cfb084ae Renรฉ Nussbaumer
                         [[(constants.RS_NORMAL, lock.name),
2194 cfb084ae Renรฉ Nussbaumer
                           (constants.RS_NORMAL, "exclusive"),
2195 cfb084ae Renรฉ Nussbaumer
                           (constants.RS_NORMAL,
2196 24d16f76 Michael Hanselmann
                            [threading.currentThread().getName()])]])
2197 c31825f7 Michael Hanselmann
2198 c31825f7 Michael Hanselmann
        threads = []
2199 c31825f7 Michael Hanselmann
2200 c31825f7 Michael Hanselmann
        first = threading.Event()
2201 c31825f7 Michael Hanselmann
        prev = first
2202 c31825f7 Michael Hanselmann
2203 c31825f7 Michael Hanselmann
        for i in range(5):
2204 c31825f7 Michael Hanselmann
          ev = threading.Event()
2205 c31825f7 Michael Hanselmann
          threads.append(self._addThread(target=_Acquire,
2206 c31825f7 Michael Hanselmann
                                          args=(lock, shared, prev, ev)))
2207 c31825f7 Michael Hanselmann
          prev = ev
2208 c31825f7 Michael Hanselmann
2209 c31825f7 Michael Hanselmann
        # Start acquires
2210 c31825f7 Michael Hanselmann
        first.set()
2211 c31825f7 Michael Hanselmann
2212 c31825f7 Michael Hanselmann
        # Wait for last acquire to start waiting
2213 c31825f7 Michael Hanselmann
        prev.wait()
2214 c31825f7 Michael Hanselmann
2215 c31825f7 Michael Hanselmann
        # NOTE: This works only because QueryLocks will acquire the
2216 c31825f7 Michael Hanselmann
        # lock-internal lock again and won't be able to get the information
2217 c31825f7 Michael Hanselmann
        # until it has the lock. By then the acquire should be registered in
2218 c31825f7 Michael Hanselmann
        # SharedLock.__pending (otherwise it's a bug).
2219 c31825f7 Michael Hanselmann
2220 c31825f7 Michael Hanselmann
        # All acquires are waiting now
2221 c31825f7 Michael Hanselmann
        if shared:
2222 24d16f76 Michael Hanselmann
          pending = [("shared", utils.NiceSort(t.getName() for t in threads))]
2223 c31825f7 Michael Hanselmann
        else:
2224 c31825f7 Michael Hanselmann
          pending = [("exclusive", [t.getName()]) for t in threads]
2225 c31825f7 Michael Hanselmann
2226 24d16f76 Michael Hanselmann
        result = self.lm.QueryLocks(["name", "mode", "owner", "pending"])
2227 24d16f76 Michael Hanselmann
        self.assertEqual(objects.QueryResponse.FromDict(result).data,
2228 cfb084ae Renรฉ Nussbaumer
                         [[(constants.RS_NORMAL, lock.name),
2229 cfb084ae Renรฉ Nussbaumer
                           (constants.RS_NORMAL, "exclusive"),
2230 cfb084ae Renรฉ Nussbaumer
                           (constants.RS_NORMAL,
2231 24d16f76 Michael Hanselmann
                            [threading.currentThread().getName()]),
2232 cfb084ae Renรฉ Nussbaumer
                           (constants.RS_NORMAL, pending)]])
2233 c31825f7 Michael Hanselmann
2234 c31825f7 Michael Hanselmann
        self.assertEqual(len(self.lm._locks), 1)
2235 c31825f7 Michael Hanselmann
      finally:
2236 c31825f7 Michael Hanselmann
        lock.release()
2237 c31825f7 Michael Hanselmann
2238 c31825f7 Michael Hanselmann
      self._waitThreads()
2239 c31825f7 Michael Hanselmann
2240 c31825f7 Michael Hanselmann
      # No pending acquires
2241 24d16f76 Michael Hanselmann
      result = self.lm.QueryLocks(["name", "mode", "owner", "pending"])
2242 24d16f76 Michael Hanselmann
      self.assertEqual(objects.QueryResponse.FromDict(result).data,
2243 cfb084ae Renรฉ Nussbaumer
                       [[(constants.RS_NORMAL, lock.name),
2244 cfb084ae Renรฉ Nussbaumer
                         (constants.RS_NORMAL, None),
2245 cfb084ae Renรฉ Nussbaumer
                         (constants.RS_NORMAL, None),
2246 cfb084ae Renรฉ Nussbaumer
                         (constants.RS_NORMAL, [])]])
2247 c31825f7 Michael Hanselmann
2248 c31825f7 Michael Hanselmann
      self.assertEqual(len(self.lm._locks), 1)
2249 c31825f7 Michael Hanselmann
2250 e4e35357 Michael Hanselmann
  def testDeleteAndRecreate(self):
2251 e4e35357 Michael Hanselmann
    lname = "TestLock101923193"
2252 e4e35357 Michael Hanselmann
2253 e4e35357 Michael Hanselmann
    # Create some locks with the same name and keep all references
2254 e4e35357 Michael Hanselmann
    locks = [locking.SharedLock(lname, monitor=self.lm)
2255 e4e35357 Michael Hanselmann
             for _ in range(5)]
2256 e4e35357 Michael Hanselmann
2257 e4e35357 Michael Hanselmann
    self.assertEqual(len(self.lm._locks), len(locks))
2258 e4e35357 Michael Hanselmann
2259 e4e35357 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2260 e4e35357 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data,
2261 e4e35357 Michael Hanselmann
                     [[(constants.RS_NORMAL, lname),
2262 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None),
2263 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None)]] * 5)
2264 e4e35357 Michael Hanselmann
2265 e4e35357 Michael Hanselmann
    locks[2].delete()
2266 e4e35357 Michael Hanselmann
2267 e4e35357 Michael Hanselmann
    # Check information order
2268 e4e35357 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2269 e4e35357 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data,
2270 e4e35357 Michael Hanselmann
                     [[(constants.RS_NORMAL, lname),
2271 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None),
2272 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None)]] * 2 +
2273 e4e35357 Michael Hanselmann
                     [[(constants.RS_NORMAL, lname),
2274 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, "deleted"),
2275 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None)]] +
2276 e4e35357 Michael Hanselmann
                     [[(constants.RS_NORMAL, lname),
2277 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None),
2278 e4e35357 Michael Hanselmann
                       (constants.RS_NORMAL, None)]] * 2)
2279 e4e35357 Michael Hanselmann
2280 e4e35357 Michael Hanselmann
    locks[1].acquire(shared=0)
2281 e4e35357 Michael Hanselmann
2282 e4e35357 Michael Hanselmann
    last_status = [
2283 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2284 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None),
2285 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None)],
2286 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2287 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, "exclusive"),
2288 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, [threading.currentThread().getName()])],
2289 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2290 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, "deleted"),
2291 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None)],
2292 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2293 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None),
2294 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None)],
2295 e4e35357 Michael Hanselmann
      [(constants.RS_NORMAL, lname),
2296 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None),
2297 e4e35357 Michael Hanselmann
       (constants.RS_NORMAL, None)],
2298 e4e35357 Michael Hanselmann
      ]
2299 e4e35357 Michael Hanselmann
2300 e4e35357 Michael Hanselmann
    # Check information order
2301 e4e35357 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2302 e4e35357 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data, last_status)
2303 e4e35357 Michael Hanselmann
2304 e4e35357 Michael Hanselmann
    self.assertEqual(len(set(self.lm._locks.values())), len(locks))
2305 e4e35357 Michael Hanselmann
    self.assertEqual(len(self.lm._locks), len(locks))
2306 e4e35357 Michael Hanselmann
2307 e4e35357 Michael Hanselmann
    # Check lock deletion
2308 e4e35357 Michael Hanselmann
    for idx in range(len(locks)):
2309 e4e35357 Michael Hanselmann
      del locks[0]
2310 e4e35357 Michael Hanselmann
      assert gc.isenabled()
2311 e4e35357 Michael Hanselmann
      gc.collect()
2312 e4e35357 Michael Hanselmann
      self.assertEqual(len(self.lm._locks), len(locks))
2313 e4e35357 Michael Hanselmann
      result = self.lm.QueryLocks(["name", "mode", "owner"])
2314 e4e35357 Michael Hanselmann
      self.assertEqual(objects.QueryResponse.FromDict(result).data,
2315 e4e35357 Michael Hanselmann
                       last_status[idx + 1:])
2316 e4e35357 Michael Hanselmann
2317 e4e35357 Michael Hanselmann
    # All locks should have been deleted
2318 e4e35357 Michael Hanselmann
    assert not locks
2319 e4e35357 Michael Hanselmann
    self.assertFalse(self.lm._locks)
2320 e4e35357 Michael Hanselmann
2321 e4e35357 Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2322 e4e35357 Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data, [])
2323 e4e35357 Michael Hanselmann
2324 44b4eddc Michael Hanselmann
  class _FakeLock:
2325 44b4eddc Michael Hanselmann
    def __init__(self):
2326 44b4eddc Michael Hanselmann
      self._info = []
2327 44b4eddc Michael Hanselmann
2328 44b4eddc Michael Hanselmann
    def AddResult(self, *args):
2329 44b4eddc Michael Hanselmann
      self._info.append(args)
2330 44b4eddc Michael Hanselmann
2331 44b4eddc Michael Hanselmann
    def CountPending(self):
2332 44b4eddc Michael Hanselmann
      return len(self._info)
2333 44b4eddc Michael Hanselmann
2334 44b4eddc Michael Hanselmann
    def GetLockInfo(self, requested):
2335 44b4eddc Michael Hanselmann
      (exp_requested, result) = self._info.pop(0)
2336 44b4eddc Michael Hanselmann
2337 44b4eddc Michael Hanselmann
      if exp_requested != requested:
2338 44b4eddc Michael Hanselmann
        raise Exception("Requested information (%s) does not match"
2339 44b4eddc Michael Hanselmann
                        " expectations (%s)" % (requested, exp_requested))
2340 44b4eddc Michael Hanselmann
2341 44b4eddc Michael Hanselmann
      return result
2342 44b4eddc Michael Hanselmann
2343 44b4eddc Michael Hanselmann
  def testMultipleResults(self):
2344 44b4eddc Michael Hanselmann
    fl1 = self._FakeLock()
2345 44b4eddc Michael Hanselmann
    fl2 = self._FakeLock()
2346 44b4eddc Michael Hanselmann
2347 44b4eddc Michael Hanselmann
    self.lm.RegisterLock(fl1)
2348 44b4eddc Michael Hanselmann
    self.lm.RegisterLock(fl2)
2349 44b4eddc Michael Hanselmann
2350 44b4eddc Michael Hanselmann
    # Empty information
2351 44b4eddc Michael Hanselmann
    for i in [fl1, fl2]:
2352 44b4eddc Michael Hanselmann
      i.AddResult(set([query.LQ_MODE, query.LQ_OWNER]), [])
2353 44b4eddc Michael Hanselmann
    result = self.lm.QueryLocks(["name", "mode", "owner"])
2354 44b4eddc Michael Hanselmann
    self.assertEqual(objects.QueryResponse.FromDict(result).data, [])
2355 44b4eddc Michael Hanselmann
    for i in [fl1, fl2]:
2356 44b4eddc Michael Hanselmann
      self.assertEqual(i.CountPending(), 0)
2357 44b4eddc Michael Hanselmann
2358 44b4eddc Michael Hanselmann
    # Check ordering
2359 44b4eddc Michael Hanselmann
    for fn in [lambda x: x, reversed, sorted]:
2360 44b4eddc Michael Hanselmann
      fl1.AddResult(set(), list(fn([
2361 44b4eddc Michael Hanselmann
        ("aaa", None, None, None),
2362 44b4eddc Michael Hanselmann
        ("bbb", None, None, None),
2363 44b4eddc Michael Hanselmann
        ])))
2364 44b4eddc Michael Hanselmann
      fl2.AddResult(set(), [])
2365 44b4eddc Michael Hanselmann
      result = self.lm.QueryLocks(["name"])
2366 44b4eddc Michael Hanselmann
      self.assertEqual(objects.QueryResponse.FromDict(result).data, [
2367 44b4eddc Michael Hanselmann
        [(constants.RS_NORMAL, "aaa")],
2368 44b4eddc Michael Hanselmann
        [(constants.RS_NORMAL, "bbb")],
2369 44b4eddc Michael Hanselmann
        ])
2370 44b4eddc Michael Hanselmann
      for i in [fl1, fl2]:
2371 44b4eddc Michael Hanselmann
        self.assertEqual(i.CountPending(), 0)
2372 44b4eddc Michael Hanselmann
2373 44b4eddc Michael Hanselmann
      for fn2 in [lambda x: x, reversed, sorted]:
2374 44b4eddc Michael Hanselmann
        fl1.AddResult(set([query.LQ_MODE]), list(fn([
2375 44b4eddc Michael Hanselmann
          # Same name, but different information
2376 44b4eddc Michael Hanselmann
          ("aaa", "mode0", None, None),
2377 44b4eddc Michael Hanselmann
          ("aaa", "mode1", None, None),
2378 44b4eddc Michael Hanselmann
          ("aaa", "mode2", None, None),
2379 44b4eddc Michael Hanselmann
          ("aaa", "mode3", None, None),
2380 44b4eddc Michael Hanselmann
          ])))
2381 44b4eddc Michael Hanselmann
        fl2.AddResult(set([query.LQ_MODE]), [
2382 44b4eddc Michael Hanselmann
          ("zzz", "end", None, None),
2383 44b4eddc Michael Hanselmann
          ("000", "start", None, None),
2384 44b4eddc Michael Hanselmann
          ] + list(fn2([
2385 44b4eddc Michael Hanselmann
          ("aaa", "b200", None, None),
2386 44b4eddc Michael Hanselmann
          ("aaa", "b300", None, None),
2387 44b4eddc Michael Hanselmann
          ])))
2388 44b4eddc Michael Hanselmann
        result = self.lm.QueryLocks(["name", "mode"])
2389 44b4eddc Michael Hanselmann
        self.assertEqual(objects.QueryResponse.FromDict(result).data, [
2390 44b4eddc Michael Hanselmann
          [(constants.RS_NORMAL, "000"), (constants.RS_NORMAL, "start")],
2391 44b4eddc Michael Hanselmann
          ] + list(fn([
2392 44b4eddc Michael Hanselmann
          # Name is the same, so order must be equal to incoming order
2393 44b4eddc Michael Hanselmann
          [(constants.RS_NORMAL, "aaa"), (constants.RS_NORMAL, "mode0")],
2394 44b4eddc Michael Hanselmann
          [(constants.RS_NORMAL, "aaa"), (constants.RS_NORMAL, "mode1")],
2395 44b4eddc Michael Hanselmann
          [(constants.RS_NORMAL, "aaa"), (constants.RS_NORMAL, "mode2")],
2396 44b4eddc Michael Hanselmann
          [(constants.RS_NORMAL, "aaa"), (constants.RS_NORMAL, "mode3")],
2397 44b4eddc Michael Hanselmann
          ])) + list(fn2([
2398 44b4eddc Michael Hanselmann
          [(constants.RS_NORMAL, "aaa"), (constants.RS_NORMAL, "b200")],
2399 44b4eddc Michael Hanselmann
          [(constants.RS_NORMAL, "aaa"), (constants.RS_NORMAL, "b300")],
2400 44b4eddc Michael Hanselmann
          ])) + [
2401 44b4eddc Michael Hanselmann
          [(constants.RS_NORMAL, "zzz"), (constants.RS_NORMAL, "end")],
2402 44b4eddc Michael Hanselmann
          ])
2403 44b4eddc Michael Hanselmann
        for i in [fl1, fl2]:
2404 44b4eddc Michael Hanselmann
          self.assertEqual(i.CountPending(), 0)
2405 44b4eddc Michael Hanselmann
2406 19b9ba9a Michael Hanselmann
2407 2f96c43c Michael Hanselmann
if __name__ == "__main__":
2408 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()