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