示例#1
0
 def test_unlock(self):
     """
     test normal unlock after lock
     """
     client = RwlockClient()
     rwlock = client.lock('N1', Rwlock.READ)
     self.assertEqual(client.unlock(rwlock), True)
示例#2
0
 def test_lock(self):
     """
     test simple lock
     """
     client = RwlockClient()
     rwlock = client.lock('N1', Rwlock.READ)
     self.assertEqual(rwlock.status, Rwlock.OK)
     self.assertEqual(rwlock.name, 'N1')
     self.assertEqual(rwlock.mode, Rwlock.READ)
     self.assertEqual(rwlock.node, socket.gethostname())
     self.assertEqual(rwlock.pid, str(os.getpid()))
     client.unlock(rwlock)
示例#3
0
    def test_clear_all(self):
        """test _clean_all"""
        # Make rsrc, lock, owner, wait keys by using apis
        # then just call _clear_all(), gc must not be running
        RwlockClient().lock('N-CLEAR-ALL', Rwlock.WRITE)
        client2_command = '''\
from redisrwlock import Rwlock, RwlockClient
RwlockClient().lock('N-CLEAR-ALL', Rwlock.WRITE, timeout=Rwlock.FOREVER)
'''
        client2 = subprocess.Popen(['python3', '-c', client2_command])
        time.sleep(1)
        self.assertTrue(RwlockClient()._clear_all())
        client2.wait()
        self.assertTrue(RwlockClient()._clear_all())
示例#4
0
 def test_RwlockClient_node(self):
     """
     test RwlockClient with non-default node name
     """
     client = RwlockClient(redis=redis.StrictRedis(port=7777),
                           node='client-node-a')
     self.assertEqual(client.node, 'client-node-a')
示例#5
0
 def test_lock_fail_nowait(self):
     """test lock fail with no wait"""
     # Simulate other process
     client1 = RwlockClient(pid=str(os.getpid() - 1))
     client2 = RwlockClient()
     rwlock1 = client1.lock('N1', Rwlock.READ)
     rwlock2 = client2.lock('N1', Rwlock.WRITE)
     self.assertEqual(rwlock2.status, Rwlock.FAIL)
     client1.unlock(rwlock1)
示例#6
0
    def test_gc_wait(self):
        """test gc when there is stale wait set"""
        # Client1: N-GC1 ------------ terminate client2 --- gc
        # Client2:       N-GC1 - wait
        client1 = RwlockClient()
        rwlock1_1 = client1.lock('N-GC1', Rwlock.READ)
        client2_command = '''\
from redisrwlock import Rwlock, RwlockClient
import sys
client = RwlockClient()
rwlock2_1 = client.lock('N-GC1', Rwlock.WRITE, timeout=Rwlock.FOREVER)
'''
        client2 = subprocess.Popen(['python3', '-c', client2_command])
        time.sleep(0.5)  # enough time for client2 to start wait
        client2.terminate()
        client2.wait()
        message = 'gc: 0 lock(s), 1 wait(s), 0 owner(s)'
        self.assertTrue(runGcExpect(message))
        client1.unlock(rwlock1_1)
示例#7
0
    def test_gc(self):
        """
        test gc by lock then exit without unlock
        """
        # Client1: N-GC1 --- exit
        # Client2: -------------- gc --- N-GC1
        client1_command = '''\
from redisrwlock import Rwlock, RwlockClient
client = RwlockClient()
client.lock('N-GC1', Rwlock.READ)
'''
        client1 = subprocess.Popen(['python3', '-c', client1_command])
        client1.wait()
        message = 'gc: 1 lock(s), 0 wait(s), 1 owner(s)'
        self.assertTrue(runGcExpect(message))
        client2 = RwlockClient()
        rwlock2 = client2.lock('N-GC1', Rwlock.WRITE)
        self.assertEqual(rwlock2.status, Rwlock.OK)
        client2.unlock(rwlock2)
示例#8
0
 def test_lock_fail_timeout(self):
     """test lock fail with timeout"""
     # Simulate other process
     client1 = RwlockClient(pid=str(os.getpid() - 1))
     client2 = RwlockClient()
     rwlock1 = client1.lock('N1', Rwlock.READ)
     t1 = time.monotonic()
     rwlock2 = client2.lock('N1', Rwlock.WRITE, timeout=0.2)
     t2 = time.monotonic()
     self.assertTrue(t2 - t1 > 0.2)
     self.assertEqual(rwlock2.status, Rwlock.TIMEOUT)
     client1.unlock(rwlock1)
示例#9
0
    def test_deadlock(self):
        """test deadlock detection"""
        # Client1: N-DL1 --------------- N-DL2
        # Client2:       N-DL2 --- N-DL1 (victim)
        client1 = RwlockClient()
        rwlock1_1 = client1.lock('N-DL1', Rwlock.WRITE, timeout=Rwlock.FOREVER)
        client2_command = '''\
from redisrwlock import Rwlock, RwlockClient
import sys
client = RwlockClient()
rwlock2_2 = client.lock('N-DL2', Rwlock.WRITE, timeout=Rwlock.FOREVER)
rwlock2_1 = client.lock('N-DL1', Rwlock.WRITE, timeout=Rwlock.FOREVER)
status = 0 if rwlock2_1.status == Rwlock.DEADLOCK else 1
client.unlock(rwlock2_2) # unblock client1 from lock
sys.exit(status)
'''
        client2 = subprocess.Popen(['python3', '-c', client2_command])
        time.sleep(1)
        t1 = time.monotonic()
        rwlock1_2 = client1.lock('N-DL2', Rwlock.READ, timeout=2)
        t2 = time.monotonic()
        self.assertTrue(t2 - t1 < 2)
        self.assertEqual(rwlock1_2.status, Rwlock.OK)
        client1.unlock(rwlock1_1)
        client1.unlock(rwlock1_2)
        self.assertEqual(client2.wait(), 0)
示例#10
0
 def test_unlock_excessive(self):
     """
     test call unlock more than lock
     """
     client = RwlockClient()
     rwlock = client.lock('N1', Rwlock.READ)
     client.unlock(rwlock)
     self.assertEqual(client.unlock(rwlock), False)
示例#11
0
 def test_lock_nesting(self):
     """
     test lock again for already owned one
     """
     client = RwlockClient()
     # R then R
     rwlock1 = client.lock('N1', Rwlock.READ)
     rwlock2 = client.lock('N1', Rwlock.READ)
     self.assertEqual(rwlock2.status, Rwlock.OK)
     self.assertEqual(rwlock2.name, 'N1')
     self.assertEqual(rwlock2.mode, Rwlock.READ)
     self.assertEqual(rwlock2.pid, rwlock1.pid)
     client.unlock(rwlock2)
     client.unlock(rwlock1)
     # R then W
     rwlock1 = client.lock('N2', Rwlock.READ)
     rwlock2 = client.lock('N2', Rwlock.WRITE)
     self.assertEqual(rwlock2.status, Rwlock.OK)
     self.assertEqual(rwlock2.name, 'N2')
     self.assertEqual(rwlock2.mode, Rwlock.WRITE)
     self.assertEqual(rwlock2.pid, rwlock1.pid)
     client.unlock(rwlock2)
     client.unlock(rwlock1)
示例#12
0
    def test_deadlock_with_many_locks(self):
        """test deadlock when victim has many granted locks.

        cover [lock can be deleted if DEADLOCK victim unlocked]
        in _oldest_lock_access_time()"""
        # Client1: N-DL1 ------------------- N-DL2
        # Client2:       ... N-DL2 --- N-DL1 (victim)
        # In '...', have many locks unrelated to deadlock
        client1 = RwlockClient()
        rwlock1_1 = client1.lock('N-DL1', Rwlock.WRITE, timeout=Rwlock.FOREVER)
        client2_command = '''\
from redisrwlock import Rwlock, RwlockClient
import sys
client = RwlockClient()
# locks many unrelated successfully
rwlock2_many = list()
for i in range(0, 1000):
    rwlock2_many.append(client.lock('N-DL2-#' + str(i), Rwlock.READ))
rwlock2_2 = client.lock('N-DL2', Rwlock.WRITE, timeout=Rwlock.FOREVER)
rwlock2_1 = client.lock('N-DL1', Rwlock.WRITE, timeout=Rwlock.FOREVER)
status = 0 if rwlock2_1.status == Rwlock.DEADLOCK else 1
client.unlock(rwlock2_2)  # unblock client1 from lock
for i in range(0, 1000):
    client.unlock(rwlock2_many[999 - i])
sys.exit(status)
'''
        client2 = subprocess.Popen(['python3', '-c', client2_command])
        time.sleep(2)
        # I noticed more chance to be covered
        # when debug messages suppressed
        lvl = logging.getLogger().getEffectiveLevel()
        logging.getLogger().setLevel(logging.WARNING)
        t1 = time.monotonic()
        rwlock1_2 = client1.lock('N-DL2', Rwlock.READ, timeout=2,
                                 retry_interval=0)
        t2 = time.monotonic()
        logging.getLogger().setLevel(lvl)
        self.assertTrue(t2 - t1 < 2)
        self.assertEqual(rwlock1_2.status, Rwlock.OK)
        client1.unlock(rwlock1_1)
        client1.unlock(rwlock1_2)
        self.assertEqual(client2.wait(), 0)
示例#13
0
import os
import redis

from functools import wraps

from redisrwlock import Rwlock, RwlockClient

_rw_rdb = redis.StrictRedis(host=os.getenv('REDISTOGO_URL', 'redis'))
_client = RwlockClient(redis=_rw_rdb)
"""
Define reader-writer lock RAII helpers
"""


class WriterLock():
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        self.lock = _client.lock(self.name,
                                 Rwlock.WRITE,
                                 timeout=Rwlock.FOREVER)
        if self.lock.status == Rwlock.OK:
            return self
        elif self.lock.status == Rwlock.DEADLOCK:
            raise Exception('Deadlock in redis WriterLock')

    def __exit__(self, type, value, traceback):
        _client.unlock(self.lock)

示例#14
0
 def test_RwlockClient_redis_connection(self):
     """
     test RwlockClient with non-default redis connection
     """
     client = RwlockClient(redis=redis.StrictRedis(port=7777))
     self.assertIsNotNone(client)
示例#15
0
def cleanUpRedisKeys():
    return RwlockClient()._clear_all()