| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2016 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 will be pickled and then compressed. |
| 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 xrange(0, len(compressed_data), self.CHUNK_SIZE): |
| 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 |