blob: 8b25b82ef0915bafd8ab3d2cab8a61876472d780 [file] [log] [blame]
#
# Copyright 2017 the original author or authors.
#
# 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.
#
"""
A config rev object that persists itself
"""
from bz2 import compress, decompress
import structlog
from simplejson import dumps, loads
from voltha.core.config.config_rev import ConfigRevision, children_fields
log = structlog.get_logger()
class PersistedConfigRevision(ConfigRevision):
compress = False
__slots__ = ('_kv_store',)
def __init__(self, branch, data, children=None):
self._kv_store = branch._node._root._kv_store
super(PersistedConfigRevision, self).__init__(branch, data, children)
def _finalize(self):
super(PersistedConfigRevision, self)._finalize()
self.store()
def __del__(self):
try:
if self._hash:
if self._config.__weakref__ is None:
if self._config._hash in self._kv_store:
del self._kv_store[self._config._hash]
assert self.__weakref__ is None
if self._hash in self._kv_store:
del self._kv_store[self._hash]
except Exception, e:
# this should never happen
log.exception('del-error', hash=self.hash, e=e)
def store(self):
try:
# crude serialization of children hash and config data hash
if self._hash in self._kv_store:
return
self.store_config()
children_lists = {}
for field_name, children in self._children.iteritems():
hashes = [rev.hash for rev in children]
children_lists[field_name] = hashes
data = dict(
children=children_lists,
config=self._config._hash
)
blob = dumps(data)
if self.compress:
blob = compress(blob)
self._kv_store[self._hash] = blob
except Exception, e:
log.exception('store-error', e=e)
@classmethod
def load(cls, branch, kv_store, msg_cls, hash):
# Update the branch's config store
blob = kv_store[hash]
if cls.compress:
blob = decompress(blob)
data = loads(blob)
config_hash = data['config']
config_data = cls.load_config(kv_store, msg_cls, config_hash)
children_list = data['children']
assembled_children = {}
node = branch._node
for field_name, meta in children_fields(msg_cls).iteritems():
child_msg_cls = tmp_cls_loader(meta.module, meta.type)
children = []
for child_hash in children_list[field_name]:
child_node = node._mknode(child_msg_cls)
child_node.load_latest(child_hash)
child_rev = child_node.latest
children.append(child_rev)
assembled_children[field_name] = children
rev = cls(branch, config_data, assembled_children)
return rev
def store_config(self):
if self._config._hash in self._kv_store:
return
# crude serialization of config data
blob = self._config._data.SerializeToString()
if self.compress:
blob = compress(blob)
self._kv_store[self._config._hash] = blob
@classmethod
def load_config(cls, kv_store, msg_cls, config_hash):
blob = kv_store[config_hash]
if cls.compress:
blob = decompress(blob)
# TODO use a loader later on
data = msg_cls()
data.ParseFromString(blob)
return data
def tmp_cls_loader(module_name, cls_name):
# TODO this shall be generalized
from voltha.protos import voltha_pb2, health_pb2, adapter_pb2, \
logical_device_pb2, device_pb2, openflow_13_pb2, bbf_fiber_base_pb2, \
bbf_fiber_traffic_descriptor_profile_body_pb2, \
bbf_fiber_tcont_body_pb2, bbf_fiber_gemport_body_pb2, \
bbf_fiber_multicast_gemport_body_pb2, \
bbf_fiber_multicast_distribution_set_body_pb2, \
omci_mib_db_pb2, \
omci_alarm_db_pb2
return getattr(locals()[module_name], cls_name)