##// END OF EJS Templates
caches: use a gevent compatible file-lock mechanism....
marcink -
r2878:bb23dd31 default
parent child Browse files
Show More
@@ -17,16 +17,24 b''
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 import time
21 import errno
22 import logging
23
24 import gevent
20
25
21 from dogpile.cache.backends import memory as memory_backend
26 from dogpile.cache.backends import memory as memory_backend
22 from dogpile.cache.backends import file as file_backend
27 from dogpile.cache.backends import file as file_backend
23 from dogpile.cache.backends import redis as redis_backend
28 from dogpile.cache.backends import redis as redis_backend
24 from dogpile.cache.backends.file import NO_VALUE, compat
29 from dogpile.cache.backends.file import NO_VALUE, compat, FileLock
30 from dogpile.cache.util import memoized_property
25
31
26 from rhodecode.lib.memory_lru_debug import LRUDict
32 from rhodecode.lib.memory_lru_debug import LRUDict
27
33
28 _default_max_size = 1024
34 _default_max_size = 1024
29
35
36 log = logging.getLogger(__name__)
37
30
38
31 class LRUMemoryBackend(memory_backend.MemoryBackend):
39 class LRUMemoryBackend(memory_backend.MemoryBackend):
32
40
@@ -44,9 +52,45 b' class Serializer(object):'
44 return compat.pickle.loads(value)
52 return compat.pickle.loads(value)
45
53
46
54
55 class CustomLockFactory(FileLock):
56
57 @memoized_property
58 def _module(self):
59 import fcntl
60 flock_org = fcntl.flock
61
62 def gevent_flock(fd, operation):
63 """
64 Gevent compatible flock
65 """
66 # set non-blocking, this will cause an exception if we cannot acquire a lock
67 operation |= fcntl.LOCK_NB
68 start_lock_time = time.time()
69 timeout = 60 * 5 # 5min
70 while True:
71 try:
72 flock_org(fd, operation)
73 # lock has been acquired
74 break
75 except (OSError, IOError) as e:
76 # raise on other errors than Resource temporarily unavailable
77 if e.errno != errno.EAGAIN:
78 raise
79 elif (time.time() - start_lock_time) > timeout:
80 # waited to much time on a lock, better fail than loop for ever
81 raise
82
83 log.debug('Failed to acquire lock, retry in 0.1')
84 gevent.sleep(0.1)
85
86 fcntl.flock = gevent_flock
87 return fcntl
88
89
47 class FileNamespaceBackend(Serializer, file_backend.DBMBackend):
90 class FileNamespaceBackend(Serializer, file_backend.DBMBackend):
48
91
49 def __init__(self, arguments):
92 def __init__(self, arguments):
93 arguments['lock_factory'] = CustomLockFactory
50 super(FileNamespaceBackend, self).__init__(arguments)
94 super(FileNamespaceBackend, self).__init__(arguments)
51
95
52 def list_keys(self, prefix=''):
96 def list_keys(self, prefix=''):
General Comments 0
You need to be logged in to leave comments. Login now