1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from cache_chain_object_store import CacheChainObjectStore 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from environment import GetAppVersion 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from memcache_object_store import MemcacheObjectStore 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from test_object_store import TestObjectStore 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from persistent_object_store import PersistentObjectStore 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)_unspecified = object() 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class ObjectStoreCreator(object): 14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) '''Creates ObjectStores with a namespacing and behaviour configuration. 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) The initial configuration is specified on object store construction. When 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) creating ObjectStores via Create this configuration can be overridden (or 18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) via the variants of Create which do this automatically). 19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ''' 20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def __init__(self, 21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # TODO(kalman): rename start_dirty? 22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) start_empty=_unspecified, 23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # Override for testing. A custom ObjectStore type to construct 24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # on Create(). Useful with TestObjectStore, for example. 25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) store_type=None, 26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # Override for testing. Whether the ObjectStore type specified 27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # with |store_type| should be wrapped e.g. with Caching. This is 28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # useful to override when specific state tests/manipulations are 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # being done on the underlying object store. 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) disable_wrappers=False): 31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if start_empty is _unspecified: 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) raise ValueError('start_empty must be specified (typically False)') 33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._start_empty = start_empty 34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._store_type = store_type 35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if disable_wrappers and store_type is None: 36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) raise ValueError('disable_wrappers much specify a store_type') 37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._disable_wrappers = disable_wrappers 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) @staticmethod 40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def ForTest(start_empty=False, 41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) store_type=TestObjectStore, 42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) disable_wrappers=True): 43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ObjectStoreCreator(start_empty=start_empty, 44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) store_type=store_type, 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) disable_wrappers=disable_wrappers) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def Create(self, 48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) cls, 49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) category=None, 50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # Override any of these for a custom configuration. 51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) start_empty=_unspecified, 52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) app_version=_unspecified): 53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # Resolve namespace components. 54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if start_empty is not _unspecified: 55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) start_empty = bool(start_empty) 56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) start_empty = self._start_empty 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if app_version is _unspecified: 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) app_version = GetAppVersion() 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # Reserve & and = for namespace separators. 62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for component in (category, app_version): 63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if component and ('&' in component or '=' in component): 64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) raise ValueError('%s cannot be used in a namespace') 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) namespace = '&'.join( 67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) '%s=%s' % (key, value) 68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for key, value in (('class', cls.__name__), 69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ('category', category), 70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ('app_version', app_version)) 71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if value is not None) 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self._disable_wrappers: 74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self._store_type(namespace, start_empty=start_empty) 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if self._store_type is not None: 77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) chain = (self._store_type(namespace),) 78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) chain = (MemcacheObjectStore(namespace), PersistentObjectStore(namespace)) 80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return CacheChainObjectStore(chain, start_empty=start_empty) 81