Skip to content
Snippets Groups Projects
Commit 7be249d4 authored by Anael Beutot's avatar Anael Beutot
Browse files

Refactored TagDB into two classes.

New class RootDB has no parents and handles RPC calls to the cc-server in a
transparent fashion from its children.
parent 4f433c7b
No related branches found
No related tags found
No related merge requests found
......@@ -12,7 +12,7 @@ from sjrpc.utils import ConnectionProxy, RpcHandler, threadless
from ccnode import __version__
from ccnode.config import NodeConfigParser
from ccnode.tags import Tag, get_tags, TagDB
from ccnode.tags import Tag, get_tags, RootTagDB
from ccnode.jobs import JobManager
from ccnode.exc import PluginError
......@@ -210,7 +210,7 @@ class MainLoop(object):
self.main_plugin = None
# tag database
self.tag_db = TagDB(self, tags=DEFAULT_TAGS)
self.tag_db = RootTagDB(self, tags=DEFAULT_TAGS)
# job manages
self.job_manager = JobManager(self)
......@@ -266,7 +266,7 @@ class MainLoop(object):
self.registered_plugins.add(plugin)
# register tags
self.tag_db.update_from_db(plugin.tag_db)
plugin.tag_db.set_parent(self.tag_db)
# register handler
self.rpc_handler.update(plugin.rpc_handler)
......@@ -280,14 +280,7 @@ class MainLoop(object):
raise PluginError('Plugin was not registered, cannot remove')
# remove tags
for db_name, tag_db in plugin.tag_db:
for tag_name in tag_db:
del self.tag_db[db_name][tag_name]
if not self.tag_db[db_name]: # if there's no more tag in the db
del self.tag_db[db_name]
self.tag_db.delete_from_db(plugin.tag_db)
plugin.tag_db.set_parent(None)
# remove handlers
for handler_name in plugin.rpc_handler:
......
......@@ -20,7 +20,7 @@ class Base(object):
self.main = kwargs.pop('loop')
# plugins may define tags (see :mod:`ccnode.tags`)
self.tag_db = TagDB(self.main, parent_db=self.main.tag_db)
self.tag_db = TagDB()
# plugins may define handler functions that would be called by the
# server
......
......@@ -222,19 +222,17 @@ class TagDB(object):
Handles common operations such as registering tag on the cc-server, updating
its values, etc.
TagDB can have a parent TagDB, in this case, the latter will handle tag
TagDB can have a parent TagDB, in this case, the latter could handle tag
registration on the cc-server.
"""
def __init__(self, main, parent_db=None, tags=None, sub_tags=None):
def __init__(self, parent_db=None, tags=None, sub_tags=None):
"""
:param main: MainLoop instance
:param TagDB parent_db: TagDB parent object
:param iterable tags: initial tags
:param dict sub_tags: initial subtags
"""
self.main = weakref.proxy(main)
self.parent = parent_db
self._parent = parent_db
if tags is None:
tags = tuple()
......@@ -254,9 +252,116 @@ class TagDB(object):
for tag in tags:
self.add_sub_tag(sub_id, tag)
def set_parent(self, parent):
"""Set parent tag database."""
# check if previous parent
if self._parent is not None:
# we must remove tags from old parent
self._parent.remove_tags(self.db['__main__'])
for sub_id in self.db:
if sub_id == '__main__':
continue
self._parent.remove_sub_object(sub_id)
# set new parent
self._parent = parent
if self._parent is not None:
# add tags in new parent
self._parent.add_tags(self.db['__main__'].itervalues())
for sub_id, db in self.db.iteritems():
if sub_id == '__main__':
continue
self._parent.add_sub_object(sub_id, db.itervalues())
# tag handling part, used by plugins
def add_tags(self, tags):
"""
:param iterable tags: list of tags to add
"""
for tag in tags:
self.add_tag(tag)
def add_sub_tags(self, sub_id, tags):
for tag in tags:
self.add_sub_tag(sub_id, tag)
def remove_tags(self, tag_names):
"""
:param iterable tag_names: list of tag names to remove
"""
for name in tag_names:
self.remove_tag(name)
def add_tag(self, tag):
# set special attributes on tag instance
if self._parent is not None:
self._parent.add_tag(tag)
self.db['__main__'][tag.name] = tag
def remove_tag(self, tag_name):
self.db['__main__'].pop(tag_name)
if self._parent is not None:
self._parent.remove_tag(tag_name)
def add_sub_tag(self, sub_id, tag):
if self._parent is not None:
self._parent.add_sub_tag(sub_id, tag)
self.db[sub_id][tag.name] = tag
def remove_sub_tag(self, sub_id, tag_name):
self.db[sub_id].pop(tag_name)
if self._parent is not None:
self._parent.remove_sub_tag(sub_id, tag_name)
def add_sub_object(self, sub_id, tags):
if self._parent is not None:
# tags will be added after
self._parent.add_sub_object(sub_id, tuple())
# add sub object tags
for t in tags:
self.add_sub_tag(sub_id, t)
def remove_sub_object(self, sub_id):
self.db.pop(sub_id)
if self._parent is not None:
self._parent.remove_sub_object(sub_id)
# dict like
def get(self, key, default=None):
return self.db.get(key, default)
def __getitem__(self, key):
return self.db[key]
def keys(self):
return self.db.keys()
def iteritems(self):
return self.db.iteritems()
def itervalues(self):
return self.db.itervalues()
# end dict like
class RootTagDB(TagDB):
"""Root tag database.
It takes care of tag registration with cc-server. It has no parent.
"""
def __init__(self, main, tags=None, sub_tags=None):
"""
:param main: MainLoop instance
:param tags: initial tags
:param sub_tags: initial sub tags
"""
self.main = main
#: dict for async call storage, keep a part of log message
self.async_calls = dict()
TagDB.__init__(self, tags=tags, sub_tags=sub_tags)
# RPC part
def rpc_call(self, opaque, callback, remote_name, *args, **kwargs):
"""Local helper for all rpc calls.
......@@ -270,6 +375,7 @@ class TagDB(object):
"""
# call only if connected and authenticated to the cc-server
if self.main.rpc_authenticated:
# logger.debug('RPC call %s %s', remote_name, args)
self.async_calls[self.main.rpc_con.rpc.async_call_cb(
callback, remote_name, *args, **kwargs)] = opaque
......@@ -355,122 +461,56 @@ class TagDB(object):
'Error while trying to update tag %s, %s("%s")')
# end RPC part
# tag handling part, used by plugins
def add_tags(self, tags):
"""
:param iterable tags: list of tags to add
"""
for tag in tags:
self.add_tag(tag)
def add_sub_tags(self, sub_id, tags):
for tag in tags:
self.add_sub_tag(sub_id, tag)
def remove_tags(self, tag_names):
"""
:param iterable tag_names: list of tag names to remove
"""
for name in tag_names:
self.remove_tag(name)
def add_tag(self, tag):
# set special attributes on tag instance
if self.parent is None:
tag.db = self
tag.sub_id = '__main__'
tag.start(self.main.evloop)
# register tag on the cc-server
if tag.value is not None:
self.rpc_register_tag(tag)
else:
self.parent.add_tag(tag)
tag.db = self
tag.sub_id = '__main__'
tag.start(self.main.evloop)
# register tag on the cc-server
if tag.value is not None:
self.rpc_register_tag(tag)
self.db['__main__'][tag.name] = tag
def remove_tag(self, tag_name):
tag = self.db['__main__'].pop(tag_name)
if self.parent is None:
tag.db = None
tag.sub_id = None
tag.stop()
# unregister tag on the cc-server
if tag.value is not None:
self.rpc_unregister_tag(tag_name)
else:
self.parent.remove_tag(tag_name)
tag.db = None
tag.sub_id = None
tag.stop()
# unregister tag on the cc-server
if tag.value is not None:
self.rpc_unregister_tag(tag_name)
def add_sub_tag(self, sub_id, tag):
if self.parent is None:
tag.db = self
tag.sub_id = sub_id
tag.start(self.main.evloop)
# register tag to the cc-server
if tag.value is not None:
self.rpc_register_sub_tag(sub_id, tag)
else:
self.parent.add_sub_tag(sub_id, tag)
tag.db = self
tag.sub_id = sub_id
tag.start(self.main.evloop)
# register tag to the cc-server
if tag.value is not None:
self.rpc_register_sub_tag(sub_id, tag)
self.db[sub_id][tag.name] = tag
def remove_sub_tag(self, sub_id, tag_name):
tag = self.db[sub_id].pop(tag_name)
if self.parent is None:
tag.db = None
tag.sub_id = None
tag.stop()
# unregister tag to the cc-server
if tag.value is not None:
self.rpc_unregister_sub_tag(sub_id, tag_name)
else:
self.parent.remove_sub_tag(sub_id, tag_name)
tag.db = None
tag.sub_id = None
tag.stop()
# unregister tag to the cc-server
if tag.value is not None:
self.rpc_unregister_sub_tag(sub_id, tag_name)
def add_sub_object(self, sub_id, tags):
if self.parent is None:
self.rpc_register_sub_object(sub_id)
else:
# tags will be added after
self.parent.add_sub_object(sub_id, tuple())
self.rpc_register_sub_object(sub_id)
# FIXME not sure this is needed
# add sub object tags
for t in tags:
self.add_sub_tag(sub_id, t)
def remove_sub_object(self, sub_id):
if self.parent is None:
for name in self.db[sub_id].keys():
self.remove_sub_tag(sub_id, name)
del self.db[sub_id]
self.rpc_unregister_sub_object(sub_id)
else:
sub_tags = self.db.pop(sub_id)
self.parent.remove_sub_object(sub_id)
# dict like
def get(self, key, default=None):
return self.db.get(key, default)
def __getitem__(self, key):
return self.db[key]
def keys(self):
return self.db.keys()
def iteritems(self):
return self.db.iteritems()
def itervalues(self):
return self.db.itervalues()
def update_from_db(self, tag_db):
"""Update self tag db from other instance."""
self.add_tags(tag_db['__main__'].itervalues())
for sub_id, db in tag_db.iteritems():
if sub_id == '__main__':
continue
self.add_sub_tags(sub_id, db.itervalues())
def delete_from_db(self, tag_db):
self.remove_tags(tag_db['__main__'])
for sub_id in tag_db:
if sub_id == '__main__':
continue
self.remove_suobject(sub_id)
for tag in self.db[sub_id].itervalues():
tag.stop()
tag.db = None
tag.sub_id = None
# we don't need to unregister each sub tag on the cc-server because
# it will be done when we unregister the object
del self.db[sub_id]
self.rpc_unregister_sub_object(sub_id)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment