blob: 1c8208b16651146019fd15b4df5023a9ceb0d3c7 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
from storage.item import Item
class BaseIndex(dict):
def __init__(self, storage, name, fields):
super(BaseIndex, self).__init__()
self.storage = storage
self.name = name
self.fields = fields[:]
def _add_item(self, key, obj):
raise NotImplemented
def _find_item(self, key):
raise NotImplemented
def _delete_item(self, key):
raise NotImplemented
def _get_item_key(self, obj):
key = []
for field_name in self.fields:
if type(obj) is dict:
val = obj.get(field_name)
else:
val = getattr(obj, field_name, None)
# update index only if all the fields have values
if not val:
return None
key.append(str(val))
return "_".join(key)
def add(self, obj):
key = self._get_item_key(obj)
if key:
self._add_item(key, obj)
def find(self, **kwargs):
key = self._get_item_key(kwargs)
if key:
return self._find_item(key)
else:
return None
def delete(self, obj):
key = self._get_item_key(obj)
if key:
self._delete_item(key)
class BaseStorage(object):
index_cls = BaseIndex
def __init__(self, ioloop, *indexes):
'''
Initialize the in-memory storage and create indexes defined as a list of parameters.
The indexed fields must be coma-separated.
Example:
M = MPinStorage("mpinid", "mpinid,wid") #Will create two indexes: by mpinid and by mpinid and wid
'''
self.ioloop = ioloop
self.indexes = {}
# Create indexes
for index in indexes:
index_fields = map(lambda x: x.strip(), index.split(","))
index_name = ",".join(index_fields)
self.indexes[index_name] = self.index_cls(
storage=self,
name=index_name,
fields=index_fields,
)
def _add_item(self, item):
raise NotImplemented
def _find_item(self, index, **kwargs):
raise NotImplemented
def _delete_item(self, item):
raise NotImplemented
def _delete_from_indexes(self, item):
for index in self.indexes.itervalues():
index.delete(item)
def _storage_change(self):
pass
def update_item(self, item):
self.update_index(item)
self._add_item(item)
def add(self, expire_time=None, **kwargs):
item = Item(self, expire_time, **kwargs)
self._add_item(item)
return item
def find(self, **kwargs):
correct_index = None
for index in self.indexes.itervalues():
if sorted(kwargs.keys()) == sorted(index.fields):
correct_index = index
break
if correct_index is not None:
return self._find_item(correct_index, **kwargs)
else:
return None
def delete(self, item):
self._delete_item(item)
self._delete_from_indexes(item)
def update_index(self, item):
for index in self.indexes.itervalues():
index.add(item)