Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 7578ab0a

History | View | Annotate | Download (66.4 kB)

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