**** CubicPower OpenStack Study ****
# Copyright 2013 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
import six
NOTSET = object()
@six.add_metaclass(abc.ABCMeta)
**** CubicPower OpenStack Study ****
class BaseCache(object):
"""Base Cache Abstraction
:params parsed_url: Parsed url object.
:params options: A dictionary with configuration parameters
for the cache. For example:
-
**** CubicPower OpenStack Study ****
def __init__(self, parsed_url, options=None):
self._parsed_url = parsed_url
self._options = options or {}
self._default_ttl = int(self._options.get('default_ttl', 0))
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def _set(self, key, value, ttl, not_exists=False):
"""Implementations of this class have to override this method."""
**** CubicPower OpenStack Study ****
def set(self, key, value, ttl, not_exists=False):
"""Sets or updates a cache entry
NOTE: Thread-safety is required and has to be
guaranteed by the backend implementation.
:params key: Item key as string.
:type key: `unicode string`
:params value: Value to assign to the key. This
can be anything that is handled
by the current backend.
:params ttl: Key's timeout in seconds. 0 means
no timeout.
:type ttl: int
:params not_exists: If True, the key will be set
if it doesn't exist. Otherwise,
it'll always be set.
:type not_exists: bool
:returns: True if the operation succeeds, False otherwise.
"""
if ttl is None:
ttl = self._default_ttl
return self._set(key, value, ttl, not_exists)
**** CubicPower OpenStack Study ****
def __setitem__(self, key, value):
self.set(key, value, self._default_ttl)
**** CubicPower OpenStack Study ****
def setdefault(self, key, value):
"""Sets the key value to `value` if it doesn't exist
:params key: Item key as string.
:type key: `unicode string`
:params value: Value to assign to the key. This
can be anything that is handled
by the current backend.
"""
try:
return self[key]
except KeyError:
self[key] = value
return value
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def _get(self, key, default):
"""Implementations of this class have to override this method."""
**** CubicPower OpenStack Study ****
def get(self, key, default=None):
"""Gets one item from the cache
NOTE: Thread-safety is required and it has to be
guaranteed by the backend implementation.
:params key: Key for the item to retrieve
from the cache.
:params default: The default value to return.
:returns: `key`'s value in the cache if it exists,
otherwise `default` should be returned.
"""
return self._get(key, default)
**** CubicPower OpenStack Study ****
def __getitem__(self, key):
value = self.get(key, NOTSET)
if value is NOTSET:
raise KeyError
return value
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def __delitem__(self, key):
"""Removes an item from cache.
NOTE: Thread-safety is required and it has to be
guaranteed by the backend implementation.
:params key: The key to remove.
:returns: The key value if there's one
"""
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def _clear(self):
"""Implementations of this class have to override this method."""
**** CubicPower OpenStack Study ****
def clear(self):
"""Removes all items from the cache.
NOTE: Thread-safety is required and it has to be
guaranteed by the backend implementation.
"""
return self._clear()
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def _incr(self, key, delta):
"""Implementations of this class have to override this method."""
**** CubicPower OpenStack Study ****
def incr(self, key, delta=1):
"""Increments the value for a key
:params key: The key for the value to be incremented
:params delta: Number of units by which to increment
the value. Pass a negative number to
decrement the value.
:returns: The new value
"""
return self._incr(key, delta)
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def _append_tail(self, key, tail):
"""Implementations of this class have to override this method."""
**** CubicPower OpenStack Study ****
def append_tail(self, key, tail):
"""Appends `tail` to `key`'s value.
:params key: The key of the value to which
`tail` should be appended.
:params tail: The list of values to append to the
original.
:returns: The new value
"""
if not hasattr(tail, "__iter__"):
raise TypeError('Tail must be an iterable')
if not isinstance(tail, list):
# NOTE(flaper87): Make sure we pass a list
# down to the implementation. Not all drivers
# have support for generators, sets or other
# iterables.
tail = list(tail)
return self._append_tail(key, tail)
**** CubicPower OpenStack Study ****
def append(self, key, value):
"""Appends `value` to `key`'s value.
:params key: The key of the value to which
`tail` should be appended.
:params value: The value to append to the
original.
:returns: The new value
"""
return self.append_tail(key, [value])
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def __contains__(self, key):
"""Verifies that a key exists.
:params key: The key to verify.
:returns: True if the key exists,
otherwise False.
"""
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def _get_many(self, keys, default):
"""Implementations of this class have to override this method."""
return ((k, self.get(k, default=default)) for k in keys)
**** CubicPower OpenStack Study ****
def get_many(self, keys, default=NOTSET):
"""Gets keys' value from cache
:params keys: List of keys to retrieve.
:params default: The default value to return
for each key that is not in
the cache.
:returns: A generator of (key, value)
"""
return self._get_many(keys, default)
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def _set_many(self, data, ttl):
"""Implementations of this class have to override this method."""
for key, value in data.items():
self.set(key, value, ttl=ttl)
**** CubicPower OpenStack Study ****
def set_many(self, data, ttl=None):
"""Puts several items into the cache at once
Depending on the backend, this operation may or may
not be efficient. The default implementation calls
set for each (key, value) pair passed, other backends
support set_many operations as part of their protocols.
:params data: A dictionary like {key: val} to store
in the cache.
:params ttl: Key's timeout in seconds.
"""
if ttl is None:
ttl = self._default_ttl
self._set_many(data, ttl)
**** CubicPower OpenStack Study ****
def update(self, **kwargs):
"""Sets several (key, value) paris.
Refer to the `set_many` docstring.
"""
self.set_many(kwargs, ttl=self._default_ttl)
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def _unset_many(self, keys):
"""Implementations of this class have to override this method."""
for key in keys:
del self[key]
**** CubicPower OpenStack Study ****
def unset_many(self, keys):
"""Removes several keys from the cache at once
:params keys: List of keys to unset.
"""
self._unset_many(keys)