Ejemplo n.º 1
0
    def test_thread_locality(self):
        store = localstore.LocalStore()
        store['name'] = "Hi"
        q = Queue()

        def do_test():
            sleep(0.1)
            t = current_thread()
            name = t.name
            store[name] = 1
            store['name'] = name
            q.put(dict(store))

        threads = []
        for x in range(5):
            t = Thread(target=do_test, name='thread%x' % x)
            t.start()
            threads.append(t)
        for t in threads:
            t.join()
        # assert none of the thread stuff touched our queue
        self.assertEqual(store['name'], 'Hi')
        self.assertEqual(q.qsize(), 5)
        qcontents = []
        while not q.empty():
            qcontents.append(q.get())
        self.assertEqual(len(qcontents), 5)
        for d in qcontents:
            self.assertEqual(len(d), 2)
            self.assertNotEqual(d['name'], 'Hi')
            self.assertEqual(d[d['name']], 1)
Ejemplo n.º 2
0
 def test_thread_locality(self):
     store = localstore.LocalStore()
     store['name'] = "Hi"
     q = Queue()
     def do_test():
         sleep(0.1)
         t = current_thread()
         name = t.name
         store[name] = 1
         store['name'] = name
         q.put(dict(store))
     threads = []
     for x in range(5):
         t = Thread(target=do_test, name='thread%x' % x)
         t.start()
         threads.append(t)
     for t in threads:
         t.join()
     # assert none of the thread stuff touched our queue
     self.assertEqual(store['name'], 'Hi')
     self.assertEqual(q.qsize(), 5)
     qcontents = []
     while not q.empty():
         qcontents.append(q.get())
     self.assertEqual(len(qcontents), 5)
     for d in qcontents:
         self.assertEqual(len(d), 2)
         self.assertNotEqual(d['name'], 'Hi')
         self.assertEqual(d[d['name']], 1)
Ejemplo n.º 3
0
    def test_transaction_rollback(self):
        """Tests johnny's handling of transaction rollbacks.

        Similar to the commit, this sets up a write to a db in a transaction,
        reads from it (to force a cache write of sometime), then rolls back."""
        if not is_multithreading_safe(db_using='default'):
            print("\n  Skipping test requiring multiple threads.")
            return

        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        q = Queue()
        other = lambda x: self._run_threaded(x, q)

        # load some data
        start = Genre.objects.get(id=1)
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        # these should be the same and should have hit cache
        self.assertTrue(hit)
        self.assertEqual(ostart, start)
        # enter manual transaction management
        transaction.enter_transaction_management()
        managed()
        start.title = 'Jackie Chan Novels'
        # local invalidation, this key should hit the localstore!
        nowlen = len(cache.local)
        start.save()
        self.assertNotEqual(nowlen, len(cache.local))
        # perform a read OUTSIDE this transaction... it should still see the
        # old gen key, and should still find the "old" data
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertNotEqual(ostart.title, start.title)
        # perform a READ inside the transaction;  this should hit the localstore
        # but not the outside!
        nowlen = len(cache.local)
        start2 = Genre.objects.get(id=1)
        self.assertEqual(start2.title, start.title)
        self.assertTrue(len(cache.local) > nowlen)
        transaction.rollback()
        # we rollback, and flush all johnny keys related to this transaction
        # subsequent gets should STILL hit the cache in the other thread
        # and indeed, in this thread.

        self.assertFalse(transaction.is_dirty())
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        start = Genre.objects.get(id=1)
        self.assertEqual(ostart.title, start.title)
        managed(False)
        transaction.leave_transaction_management()
Ejemplo n.º 4
0
    def test_transaction_rollback(self):
        """Tests johnny's handling of transaction rollbacks.

        Similar to the commit, this sets up a write to a db in a transaction,
        reads from it (to force a cache write of sometime), then rolls back."""
        if not is_multithreading_safe(db_using='default'):
            print("\n  Skipping test requiring multiple threads.")
            return

        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        q = Queue()
        other = lambda x: self._run_threaded(x, q)

        # load some data
        start = Genre.objects.get(id=1)
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        # these should be the same and should have hit cache
        self.assertTrue(hit)
        self.assertEqual(ostart, start)
        # enter manual transaction management
        transaction.enter_transaction_management()
        managed()
        start.title = 'Jackie Chan Novels'
        # local invalidation, this key should hit the localstore!
        nowlen = len(cache.local)
        start.save()
        self.assertNotEqual(nowlen, len(cache.local))
        # perform a read OUTSIDE this transaction... it should still see the
        # old gen key, and should still find the "old" data
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertNotEqual(ostart.title, start.title)
        # perform a READ inside the transaction;  this should hit the localstore
        # but not the outside!
        nowlen = len(cache.local)
        start2 = Genre.objects.get(id=1)
        self.assertEqual(start2.title, start.title)
        self.assertTrue(len(cache.local) > nowlen)
        transaction.rollback()
        # we rollback, and flush all johnny keys related to this transaction
        # subsequent gets should STILL hit the cache in the other thread
        # and indeed, in this thread.

        self.assertFalse(transaction.is_dirty())
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        start = Genre.objects.get(id=1)
        self.assertEqual(ostart.title, start.title)
        managed(False)
        transaction.leave_transaction_management()
Ejemplo n.º 5
0
    def test_transaction_commit(self):
        """Test transaction support in Johnny."""
        if not is_multithreading_safe(db_using='default'):
            print("\n  Skipping test requiring multiple threads.")
            return

        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        q = Queue()
        other = lambda x: self._run_threaded(x, q)
        # load some data
        start = Genre.objects.get(id=1)
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        # these should be the same and should have hit cache
        self.assertTrue(hit)
        self.assertEqual(ostart, start)
        # enter manual transaction management
        transaction.enter_transaction_management()
        managed()
        start.title = 'Jackie Chan Novels'
        # local invalidation, this key should hit the localstore!
        nowlen = len(cache.local)
        start.save()
        self.assertNotEqual(nowlen, len(cache.local))
        # perform a read OUTSIDE this transaction... it should still see the
        # old gen key, and should still find the "old" data
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertNotEqual(ostart.title, start.title)
        transaction.commit()
        # now that we commit, we push the localstore keys out;  this should be
        # a cache miss, because we never read it inside the previous transaction
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertFalse(hit)
        self.assertEqual(ostart.title, start.title)
        managed(False)
        transaction.leave_transaction_management()
Ejemplo n.º 6
0
    def test_transaction_commit(self):
        """Test transaction support in Johnny."""
        if not is_multithreading_safe(db_using='default'):
            print("\n  Skipping test requiring multiple threads.")
            return

        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        q = Queue()
        other = lambda x: self._run_threaded(x, q)
        # load some data
        start = Genre.objects.get(id=1)
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        # these should be the same and should have hit cache
        self.assertTrue(hit)
        self.assertEqual(ostart, start)
        # enter manual transaction management
        transaction.enter_transaction_management()
        managed()
        start.title = 'Jackie Chan Novels'
        # local invalidation, this key should hit the localstore!
        nowlen = len(cache.local)
        start.save()
        self.assertNotEqual(nowlen, len(cache.local))
        # perform a read OUTSIDE this transaction... it should still see the
        # old gen key, and should still find the "old" data
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertNotEqual(ostart.title, start.title)
        transaction.commit()
        # now that we commit, we push the localstore keys out;  this should be
        # a cache miss, because we never read it inside the previous transaction
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertFalse(hit)
        self.assertEqual(ostart.title, start.title)
        managed(False)
        transaction.leave_transaction_management()
Ejemplo n.º 7
0
    def test_savepoints(self):
        """tests savepoints for multiple db's"""
        q = Queue()
        other = lambda x: self._run_threaded(x, q, {'Genre': Genre})

        if len(getattr(settings, "DATABASES", [])) <= 1:
            print("\n  Skipping multi database tests")
            return

        if not is_multithreading_safe():
            print("\n  Skipping test requiring multiple threads.")
            return

        for name, db in settings.DATABASES.items():
            con = connections[name]
            if not con.features.uses_savepoints:
                print("\n  Skipping test requiring savepoints.")
                return

        # sanity check 
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        self.assertTrue("default" in getattr(settings, "DATABASES"))
        self.assertTrue("second" in getattr(settings, "DATABASES"))

        g1 = Genre.objects.using("default").get(pk=1)
        start_g1 = g1.title
        g2 = Genre.objects.using("second").get(pk=1)

        transaction.enter_transaction_management(using='default')
        managed(using='default')
        transaction.enter_transaction_management(using='second')
        managed(using='second')

        g1.title = "Rollback savepoint"
        g1.save()

        g2.title = "Committed savepoint"
        g2.save(using="second")
        sid2 = transaction.savepoint(using="second")

        sid = transaction.savepoint(using="default")
        g1.title = "Dirty text"
        g1.save()

        #other thread should see the original key and cache object from memcache,
        #not the local cache version
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertEqual(ostart.title, start_g1)
        #should not be a hit due to rollback
        transaction.savepoint_rollback(sid, using="default")
        g1 = Genre.objects.using("default").get(pk=1)

        # i think it should be "Rollback Savepoint" here
        self.assertEqual(g1.title, start_g1)

        #will be pushed to dirty in commit
        g2 = Genre.objects.using("second").get(pk=1)
        self.assertEqual(g2.title, "Committed savepoint")
        transaction.savepoint_commit(sid2, using="second")

        #other thread should still see original version even 
        #after savepoint commit
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertEqual(ostart.title, start_g1)

        with self.assertNumQueries(0, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)

        transaction.commit(using="second")
        managed(False, using='second')

        with self.assertNumQueries(0, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)
        self.assertEqual(g2.title, "Committed savepoint")

        #now committed and cached, other thread should reflect new title
        #without a hit to the db
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, g2.title)
        self.assertTrue(hit)

        managed(False, 'default')
        transaction.leave_transaction_management("default")
        transaction.leave_transaction_management("second")
Ejemplo n.º 8
0
    def test_transactions(self):
        """Tests transaction rollbacks and local cache for multiple dbs"""

        if len(getattr(settings, "DATABASES", [])) <= 1:
            print("\n  Skipping multi database tests")
            return

        if not is_multithreading_safe():
            print("\n  Skipping test requiring multiple threads.")
            return

        for conname in connections:
            con = connections[conname]
            if not base.supports_transactions(con):
                print("\n  Skipping test requiring transactions.")
                return

        q = Queue()
        other = lambda x: self._run_threaded(x, q, {'Genre': Genre})


        # sanity check 
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        self.assertTrue("default" in getattr(settings, "DATABASES"))
        self.assertTrue("second" in getattr(settings, "DATABASES"))

        # this should seed this fetch in the global cache
        g1 = Genre.objects.using("default").get(pk=1)
        g2 = Genre.objects.using("second").get(pk=1)
        start_g1 = g1.title

        transaction.enter_transaction_management(using='default')
        managed(using='default')
        transaction.enter_transaction_management(using='second')
        managed(using='second')

        g1.title = "Testing a rollback"
        g2.title = "Testing a commit"
        g1.save()
        g2.save()

        # test outside of transaction, should be cache hit and 
        # not contain the local changes
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, start_g1)
        self.assertTrue(hit)

        transaction.rollback(using='default')
        transaction.commit(using='second')
        managed(False, using='default')
        managed(False, using='second')

        #other thread should have seen rollback
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, start_g1)
        self.assertTrue(hit)

        #should be a cache hit due to rollback
        with self.assertNumQueries(0, using='default'):
            g1 = Genre.objects.using("default").get(pk=1)
        #should be a db hit due to commit
        with self.assertNumQueries(1, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)

        #other thread sould now be accessing the cache after the get
        #from the commit.
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, g2.title)
        self.assertTrue(hit)

        self.assertEqual(g1.title, start_g1)
        self.assertEqual(g2.title, "Testing a commit")
        transaction.leave_transaction_management("default")
        transaction.leave_transaction_management("second")
Ejemplo n.º 9
0
 def __init__(self):
     self.q = Queue()
     qc_hit.connect(self._hit)
     qc_miss.connect(self._miss)
     qc_skip.connect(self._skip)
Ejemplo n.º 10
0
class message_queue(object):
    """Return a message queue that gets 'hit' or 'miss' messages.  The signal
    handlers use weakrefs, so if we don't save references to this object they
    will get gc'd pretty fast."""
    def __init__(self):
        self.q = Queue()
        qc_hit.connect(self._hit)
        qc_miss.connect(self._miss)
        qc_skip.connect(self._skip)

    def _hit(self, *a, **k): self.q.put(True)
    def _miss(self, *a, **k): self.q.put(False)
    def _skip(self, *a, **k): self.q.put(False)

    def clear(self):
        while not self.q.empty():
            self.q.get_nowait()
    def get(self): return self.q.get()
    def get_nowait(self): return self.q.get_nowait()
    def qsize(self): return self.q.qsize()
    def empty(self): return self.q.empty()
Ejemplo n.º 11
0
 def __init__(self):
     self.q = Queue()
     qc_hit.connect(self._hit)
     qc_miss.connect(self._miss)
     qc_skip.connect(self._skip)
Ejemplo n.º 12
0
class message_queue(object):
    """Return a message queue that gets 'hit' or 'miss' messages.  The signal
    handlers use weakrefs, so if we don't save references to this object they
    will get gc'd pretty fast."""
    def __init__(self):
        self.q = Queue()
        qc_hit.connect(self._hit)
        qc_miss.connect(self._miss)
        qc_skip.connect(self._skip)

    def _hit(self, *a, **k):
        self.q.put(True)

    def _miss(self, *a, **k):
        self.q.put(False)

    def _skip(self, *a, **k):
        self.q.put(False)

    def clear(self):
        while not self.q.empty():
            self.q.get_nowait()

    def get(self):
        return self.q.get()

    def get_nowait(self):
        return self.q.get_nowait()

    def qsize(self):
        return self.q.qsize()

    def empty(self):
        return self.q.empty()
Ejemplo n.º 13
0
    def test_savepoints(self):
        """tests savepoints for multiple db's"""
        q = Queue()
        other = lambda x: self._run_threaded(x, q, {'Genre': Genre})

        if len(getattr(settings, "DATABASES", [])) <= 1:
            print("\n  Skipping multi database tests")
            return

        if not is_multithreading_safe():
            print("\n  Skipping test requiring multiple threads.")
            return

        for name, db in settings.DATABASES.items():
            con = connections[name]
            if not con.features.uses_savepoints:
                print("\n  Skipping test requiring savepoints.")
                return

        # sanity check
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        self.assertTrue("default" in getattr(settings, "DATABASES"))
        self.assertTrue("second" in getattr(settings, "DATABASES"))

        g1 = Genre.objects.using("default").get(pk=1)
        start_g1 = g1.title
        g2 = Genre.objects.using("second").get(pk=1)
        start_g2 = g2.title

        transaction.enter_transaction_management(using='default')
        managed(using='default')
        transaction.enter_transaction_management(using='second')
        managed(using='second')

        g1.title = "Rollback savepoint"
        g1.save()

        g2.title = "Committed savepoint"
        g2.save(using="second")
        sid2 = transaction.savepoint(using="second")

        sid = transaction.savepoint(using="default")
        g1.title = "Dirty text"
        g1.save()

        #other thread should see the original key and cache object from memcache,
        #not the local cache version
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertEqual(ostart.title, start_g1)
        #should not be a hit due to rollback
        transaction.savepoint_rollback(sid, using="default")
        g1 = Genre.objects.using("default").get(pk=1)

        # i think it should be "Rollback Savepoint" here
        self.assertEqual(g1.title, start_g1)

        #will be pushed to dirty in commit
        g2 = Genre.objects.using("second").get(pk=1)
        self.assertEqual(g2.title, "Committed savepoint")
        transaction.savepoint_commit(sid2, using="second")

        #other thread should still see original version even
        #after savepoint commit
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertEqual(ostart.title, start_g2)

        with self.assertNumQueries(0, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)

        transaction.commit(using="second")
        managed(False, using='second')

        with self.assertNumQueries(0, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)
        self.assertEqual(g2.title, "Committed savepoint")

        #now committed and cached, other thread should reflect new title
        #without a hit to the db
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, g2.title)
        self.assertTrue(hit)

        transaction.commit(using="default")
        managed(False, 'default')
        transaction.leave_transaction_management("default")
        transaction.leave_transaction_management("second")
Ejemplo n.º 14
0
    def test_transactions(self):
        """Tests transaction rollbacks and local cache for multiple dbs"""

        if len(getattr(settings, "DATABASES", [])) <= 1:
            print("\n  Skipping multi database tests")
            return

        if not is_multithreading_safe():
            print("\n  Skipping test requiring multiple threads.")
            return

        for conname in connections:
            con = connections[conname]
            if not base.supports_transactions(con):
                print("\n  Skipping test requiring transactions.")
                return

        q = Queue()
        other = lambda x: self._run_threaded(x, q, {'Genre': Genre})

        # sanity check
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        self.assertTrue("default" in getattr(settings, "DATABASES"))
        self.assertTrue("second" in getattr(settings, "DATABASES"))

        # this should seed this fetch in the global cache
        g1 = Genre.objects.using("default").get(pk=1)
        g2 = Genre.objects.using("second").get(pk=1)
        start_g1 = g1.title

        transaction.enter_transaction_management(using='default')
        managed(using='default')
        transaction.enter_transaction_management(using='second')
        managed(using='second')

        g1.title = "Testing a rollback"
        g2.title = "Testing a commit"
        g1.save()
        g2.save()

        # test outside of transaction, should be cache hit and
        # not contain the local changes
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, start_g1)
        self.assertTrue(hit)

        transaction.rollback(using='default')
        transaction.commit(using='second')
        managed(False, using='default')
        managed(False, using='second')

        #other thread should have seen rollback
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, start_g1)
        self.assertTrue(hit)

        #should be a cache hit due to rollback
        with self.assertNumQueries(0, using='default'):
            g1 = Genre.objects.using("default").get(pk=1)
        #should be a db hit due to commit
        with self.assertNumQueries(1, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)

        #other thread sould now be accessing the cache after the get
        #from the commit.
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, g2.title)
        self.assertTrue(hit)

        self.assertEqual(g1.title, start_g1)
        self.assertEqual(g2.title, "Testing a commit")
        transaction.leave_transaction_management("default")
        transaction.leave_transaction_management("second")