pypsyc/mjacob2/pypsyc/server/__init__.py

106 lines
3.5 KiB
Python

"""
pypsyc.server
~~~~~~~~~~~~~
:copyright: 2010 by Manuel Jacob
:license: MIT
"""
import signal
from pkg_resources import iter_entry_points
from twisted.internet import reactor
from pypsyc.core.mmp import Uni, Header
from pypsyc.core.psyc import PSYCObject, PSYCPacket
from pypsyc.server.db import Database
from pypsyc.server.routing import _TreeNode, Routing
from pypsyc.server.multicast import ContextMaster
from pypsyc.server.webif import run_webif
from pypsyc.util import schedule
class Entity(PSYCObject, _TreeNode):
def __init__(self, parent=None, name='', server=None):
_TreeNode.__init__(self, parent, name)
self.server = (server or self._root.server)
if parent is None:
uni = Uni('psyc://%s/' % self.server.hostname)
else:
uni = parent.uni.chain(name)
PSYCObject.__init__(self, self.server.routing.route_singlecast, uni)
self.context_master = ContextMaster(self)
self.packages = {}
def castmsg(self, packet=None, header=None, **kwds):
if packet is None:
packet = PSYCPacket.from_kwds(**kwds)
header = Header() if header is None else Header(header)
header['_context'] = self.uni
header._init()
self.server.routing.route_multicast(header, packet.render())
class Server(object):
def __init__(self, hostname, interface, psyc_port, webif_port, db_file):
self.hostname = hostname
self.routing = Routing(hostname, interface)
self.root = Entity(server=self)
self.routing.init(self.root)
if psyc_port:
self.routing.listen(psyc_port)
self.database = Database(db_file)
schedule(self._load_entities)
if webif_port:
schedule(run_webif, self, interface, webif_port, None)
signal.signal(signal.SIGINT, self.shutdown)
signal.signal(signal.SIGTERM, self.shutdown)
try:
signal.signal(signal.SIGBREAK, self.shutdown)
except AttributeError:
pass
def _load_entities(self):
self.database.execute(
'CREATE TABLE IF NOT EXISTS packages ('
'entity TEXT, package TEXT, PRIMARY KEY (entity, package))')
entities = self.database.fetch('SELECT entity, package FROM packages')
for entity_name, package_name in entities:
self._load_package(entity_name, package_name)
def _load_package(self, entity_name, package_name):
if entity_name is None:
entity = self.root
else:
try:
entity = self.root.children[entity_name]
except KeyError:
entity = Entity(self.root, entity_name)
assert package_name not in entity.packages
l = list(iter_entry_points('pypsyc.server.packages', package_name))
assert len(l) == 1
package = l[0].load()(entity)
entity.packages[package_name] = package
return package
def add_package(self, entity_name, package_name):
package = self._load_package(entity_name, package_name)
self.database.execute('INSERT INTO packages VALUES (?, ?)',
entity_name, package_name)
return package
def add_place(self, name):
return self.add_package('@' + name, 'place')
def register_person(self, name, password):
person = self.add_package('~' + name, 'person')
person.register(password)
return person
def shutdown(self, signum=None, frame=None):
self.database.stop()
reactor.stop()