Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 import cStringIO | |
| 6 import pickle | |
| 7 import zlib | |
| 8 | |
| 9 from google.appengine.api import memcache | |
| 10 | |
| 11 from lib.cache import Cache | |
| 12 | |
| 13 | |
| 14 class PickledMemCache(Cache): | |
| 15 """A memcache-backed implementation of the interface Cache. | |
| 16 | |
| 17 The data to be cached should be pickleable. | |
| 18 Limitation: size of the pickled data and key should be <= 1MB. | |
| 19 """ | |
| 20 def Get(self, key): | |
| 21 return memcache.get(key) | |
| 22 | |
| 23 def Set(self, key, data, expire_time=0): | |
| 24 return memcache.set(key, data, time=expire_time) | |
| 25 | |
| 26 | |
| 27 class _CachedItemMetaData(object): | |
| 28 def __init__(self, number): | |
| 29 self.number = number | |
| 30 | |
| 31 | |
| 32 class CompressedMemCache(Cache): | |
| 33 """A memcache-backed implementation of the interface Cache with compression. | |
| 34 | |
| 35 The data to be cached would be pickled and then compressed. | |
|
wrengr
2016/12/06 21:52:56
"would" -> "will"
Sharu Jiang
2016/12/06 23:58:16
Done.
| |
| 36 Data still > 1MB will be split into sub-piece and stored separately. | |
| 37 During retrieval, if any sub-piece is missing, None is returned. | |
| 38 """ | |
| 39 CHUNK_SIZE = 990000 | |
| 40 | |
| 41 def Get(self, key): | |
| 42 data = memcache.get(key) | |
| 43 if isinstance(data, _CachedItemMetaData): | |
| 44 num = data.number | |
| 45 sub_keys = ['%s-%s' % (key, i) for i in range(num)] | |
| 46 all_data = memcache.get_multi(sub_keys) | |
| 47 if len(all_data) != num: # Some data is missing. | |
| 48 return None | |
| 49 | |
| 50 data_output = cStringIO.StringIO() | |
| 51 for sub_key in sub_keys: | |
| 52 data_output.write(all_data[sub_key]) | |
| 53 data = data_output.getvalue() | |
| 54 | |
| 55 return None if data is None else pickle.loads(zlib.decompress(data)) | |
| 56 | |
| 57 def Set(self, key, data, expire_time=0): | |
| 58 pickled_data = pickle.dumps(data) | |
| 59 compressed_data = zlib.compress(pickled_data) | |
| 60 | |
| 61 all_data = {} | |
| 62 if len(compressed_data) > self.CHUNK_SIZE: | |
| 63 num = 0 | |
| 64 for index in range(0, len(compressed_data), self.CHUNK_SIZE): | |
|
wrengr
2016/12/06 21:52:56
It's better to use xrange rather than range here.
Sharu Jiang
2016/12/06 23:58:16
Done.
| |
| 65 sub_key = '%s-%s' % (key, num) | |
| 66 all_data[sub_key] = compressed_data[index : index + self.CHUNK_SIZE] | |
| 67 num += 1 | |
| 68 | |
| 69 all_data[key] = _CachedItemMetaData(num) | |
| 70 else: | |
| 71 all_data[key] = compressed_data | |
| 72 | |
| 73 keys_not_set = memcache.set_multi(all_data, time=expire_time) | |
| 74 return len(keys_not_set) == 0 | |
| 75 | |
| OLD | NEW |