1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """File based cache for the discovery document.
16
17 The cache is stored in a single file so that multiple processes can
18 share the same cache. It locks the file whenever accesing to the
19 file. When the cache content is corrupted, it will be initialized with
20 an empty cache.
21 """
22
23 from __future__ import division
24
25 import datetime
26 import json
27 import logging
28 import os
29 import tempfile
30 import threading
31
32 from oauth2client.contrib.locked_file import LockedFile
33
34 from . import base
35 from ..discovery_cache import DISCOVERY_DOC_MAX_AGE
36
37 logger = logging.getLogger(__name__)
38
39 FILENAME = 'google-api-python-client-discovery-doc.cache'
40 EPOCH = datetime.datetime.utcfromtimestamp(0)
41
42
44 try:
45 return (date - EPOCH).total_seconds()
46 except AttributeError:
47
48
49 delta = date - EPOCH
50 return ((delta.microseconds + (delta.seconds + delta.days * 24 * 3600)
51 * 10**6) / 10**6)
52
53
55 f.file_handle().seek(0)
56 try:
57 cache = json.load(f.file_handle())
58 except Exception:
59
60
61 cache = {}
62 f.file_handle().truncate(0)
63 f.file_handle().seek(0)
64 json.dump(cache, f.file_handle())
65 return cache
66
67
69 """A file based cache for the discovery documents."""
70
72 """Constructor.
73
74 Args:
75 max_age: Cache expiration in seconds.
76 """
77 self._max_age = max_age
78 self._file = os.path.join(tempfile.gettempdir(), FILENAME)
79 f = LockedFile(self._file, 'a+', 'r')
80 try:
81 f.open_and_lock()
82 if f.is_locked():
83 _read_or_initialize_cache(f)
84
85
86 except Exception as e:
87 logging.warning(e, exc_info=True)
88 finally:
89 f.unlock_and_close()
90
92 f = LockedFile(self._file, 'r+', 'r')
93 try:
94 f.open_and_lock()
95 if f.is_locked():
96 cache = _read_or_initialize_cache(f)
97 if url in cache:
98 content, t = cache.get(url, (None, 0))
99 if _to_timestamp(datetime.datetime.now()) < t + self._max_age:
100 return content
101 return None
102 else:
103 logger.debug('Could not obtain a lock for the cache file.')
104 return None
105 except Exception as e:
106 logger.warning(e, exc_info=True)
107 finally:
108 f.unlock_and_close()
109
110 - def set(self, url, content):
111 f = LockedFile(self._file, 'r+', 'r')
112 try:
113 f.open_and_lock()
114 if f.is_locked():
115 cache = _read_or_initialize_cache(f)
116 cache[url] = (content, _to_timestamp(datetime.datetime.now()))
117
118 for k, (_, timestamp) in list(cache.items()):
119 if _to_timestamp(datetime.datetime.now()) >= timestamp + self._max_age:
120 del cache[k]
121 f.file_handle().truncate(0)
122 f.file_handle().seek(0)
123 json.dump(cache, f.file_handle())
124 else:
125 logger.debug('Could not obtain a lock for the cache file.')
126 except Exception as e:
127 logger.warning(e, exc_info=True)
128 finally:
129 f.unlock_and_close()
130
131
132 cache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)
133