def Create( self, cls, category=None, # Override any of these for a custom configuration. start_empty=_unspecified, app_version=_unspecified): # Resolve namespace components. if start_empty is not _unspecified: start_empty = bool(start_empty) else: start_empty = self._start_empty if app_version is _unspecified: app_version = GetAppVersion() # Reserve & and = for namespace separators. for component in (category, app_version): if component and ('&' in component or '=' in component): raise ValueError('%s cannot be used in a namespace') namespace = '&'.join('%s=%s' % (key, value) for key, value in (('class', cls.__name__), ('category', category), ('app_version', app_version)) if value is not None) if self._disable_wrappers: return self._store_type(namespace, start_empty=start_empty) if self._store_type is not None: chain = (self._store_type(namespace), ) else: chain = (MemcacheObjectStore(namespace), PersistentObjectStore(namespace)) return CacheChainObjectStore(chain, start_empty=start_empty)
class InMemoryObjectStore(ObjectStore): def __init__(self, branch): self._branch = branch self._cache = {} self._object_store = MemcacheObjectStore() def _MakeNamespace(self, namespace): return 'ObjectStore.%s.%s' % (self._branch, namespace) def SetMulti(self, mapping, namespace, time=CACHE_TIMEOUT): namespace = self._MakeNamespace(namespace) for k, v in mapping.iteritems(): if namespace not in self._cache: self._cache[namespace] = {} self._cache[namespace][k] = _CacheEntry(v, time) # TODO(cduvall): Use a batch set? App Engine kept throwing: # ValueError: Values may not be more than 1000000 bytes in length # for the batch set. self._object_store.Set(k, v, namespace, time=time) def GetMulti(self, keys, namespace, time=CACHE_TIMEOUT): namespace = self._MakeNamespace(namespace) keys = keys[:] mapping = {} if namespace not in self._cache: self._cache[namespace] = {} for key in keys: cache_entry = self._cache[namespace].get(key, None) if cache_entry is None or cache_entry.HasExpired(): mapping[key] = None else: mapping[key] = cache_entry.value keys.remove(key) future = self._object_store.GetMulti(keys, namespace, time=time) return Future(delegate=_AsyncGetFuture(self._cache, time, namespace, future, mapping)) def Delete(self, key, namespace): namespace = self._MakeNamespace(namespace) if namespace in self._cache and key in self._cache[namespace]: self._cache[namespace].pop(key) self._object_store.Delete(key, namespace)
def Create(self, category=None, start_empty=False): '''Creates a new object store with the top namespace given in the constructor with an optional |category| for classes that need multiple object stores (e.g. one for stat and one for read). ''' namespace = self._name if category is not None: assert not any(c.isdigit() for c in category) namespace = '%s/%s' % (namespace, category) if self._store_type is not None: return self._store_type(namespace, start_empty=start_empty) return CacheChainObjectStore( (MemcacheObjectStore(namespace), PersistentObjectStore(namespace)), start_empty=start_empty)
def Create(self, version=None, category=None): '''Creates a new object store with the top namespace given in the constructor, at version |version|, with an optional |category| for classes that need multiple object stores (e.g. one for stat and one for read). ''' namespace = self._name if category is not None: assert not any(c.isdigit() for c in category) namespace = '%s/%s' % (namespace, category) if version is not None: assert isinstance(version, int) namespace = '%s/%s' % (namespace, version) if self._store_type is not None: return self._store_type(namespace) return InMemoryObjectStore(MemcacheObjectStore(namespace))
def __init__(self, branch): self._branch = branch self._cache = {} self._object_store = MemcacheObjectStore()