Commit 5b61b676 authored by Julien Muchembled's avatar Julien Muchembled

client: fix cache corruption when appending a noncurrent value

parent 3d0fab20
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import math import math
from bisect import insort
class CacheItem(object): class CacheItem(object):
...@@ -38,6 +39,9 @@ class CacheItem(object): ...@@ -38,6 +39,9 @@ class CacheItem(object):
pass pass
return '<%s%s>' % (self.__class__.__name__, s) return '<%s%s>' % (self.__class__.__name__, s)
def __lt__(self, other):
return self.tid < other.tid
class ClientCache(object): class ClientCache(object):
"""In-memory pickle cache based on Multi-Queue cache algorithm """In-memory pickle cache based on Multi-Queue cache algorithm
...@@ -198,10 +202,7 @@ class ClientCache(object): ...@@ -198,10 +202,7 @@ class ClientCache(object):
self._oid_dict[oid] = [item] self._oid_dict[oid] = [item]
else: else:
if next_tid: if next_tid:
for i, x in enumerate(item_list): insort(item_list, item)
if tid < x.tid:
break
item_list.insert(i, item)
else: else:
prev = item_list[-1] prev = item_list[-1]
item.counter = prev.counter item.counter = prev.counter
...@@ -236,18 +237,21 @@ def test(self): ...@@ -236,18 +237,21 @@ def test(self):
self.assertEqual(cache.load(1, 10), None) self.assertEqual(cache.load(1, 10), None)
self.assertEqual(cache.load(1, None), None) self.assertEqual(cache.load(1, None), None)
self.assertRaises(KeyError, cache.invalidate, 1, 10) self.assertRaises(KeyError, cache.invalidate, 1, 10)
data = 'foo', 5, 10 data = '5', 5, 10
# 2 identical stores happens if 2 threads got a cache miss at the same time # 2 identical stores happens if 2 threads got a cache miss at the same time
# (which currently never happens in NEO, due to a lock) # (which currently never happens in NEO, due to a lock)
cache.store(1, *data) cache.store(1, *data)
cache.store(1, *data) cache.store(1, *data)
self.assertEqual(cache.load(1, 10), data) self.assertEqual(cache.load(1, 10), data)
self.assertEqual(cache.load(1, None), None) self.assertEqual(cache.load(1, None), None)
data = 'bar', 10, None data = '15', 15, None
cache.store(1, *data) cache.store(1, *data)
self.assertEqual(cache.load(1, None), data) self.assertEqual(cache.load(1, None), data)
cache.invalidate(1, 20) cache.invalidate(1, 20)
self.assertEqual(cache.load(1, 20), ('bar', 10, 20)) self.assertEqual(cache.load(1, 20), ('15', 15, 20))
cache.store(1, '10', 10, 15)
cache.store(1, '20', 20, 21)
self.assertEqual([5,10,15,20], [x.tid for x in cache._oid_dict[1]])
if __name__ == '__main__': if __name__ == '__main__':
import unittest import unittest
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment