aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenmgr/lib/server/channel.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/xenmgr/lib/server/channel.py')
-rwxr-xr-xtools/xenmgr/lib/server/channel.py141
1 files changed, 122 insertions, 19 deletions
diff --git a/tools/xenmgr/lib/server/channel.py b/tools/xenmgr/lib/server/channel.py
index 04f7441f7a..130d23254f 100755
--- a/tools/xenmgr/lib/server/channel.py
+++ b/tools/xenmgr/lib/server/channel.py
@@ -41,14 +41,28 @@ class ChannelFactory:
def domChannel(self, dom):
"""Get the channel for the given domain.
+ Construct if necessary.
"""
for chan in self.channels.values():
+ if not isinstance(chan, Channel): continue
if chan.dom == dom:
return chan
chan = Channel(self, dom)
self.addChannel(chan)
return chan
+ def virqChannel(self, virq):
+ """Get the channel for the given virq.
+ Construct if necessary.
+ """
+ for chan in self.channels.values():
+ if not isinstance(chan, VirqChannel): continue
+ if chan.virq == virq:
+ return chan
+ chan = VirqChannel(self, virq)
+ self.addChannel(chan)
+ return chan
+
def channelClosed(self, channel):
"""The given channel has been closed - remove it.
"""
@@ -70,28 +84,127 @@ def channelFactory():
inst = ChannelFactory()
return inst
-class Channel:
+class BaseChannel:
+ """Abstract superclass for channels.
+
+ The subclass constructor must set idx to the port to use.
+ """
+
+ def __init__(self, factory):
+ self.factory = factory
+ self.idx = -1
+ self.closed = 0
+
+ def getIndex(self):
+ """Get the channel index.
+ """
+ return self.idx
+
+ def notificationReceived(self, type):
+ """Called when a notification is received.
+ Closes the channel on error, otherwise calls
+ handleNotification(type), which should be defined
+ in a subclass.
+ """
+ #print 'notificationReceived> type=', type, self
+ if self.closed: return
+ if type == self.factory.notifier.EXCEPTION:
+ print 'notificationReceived> EXCEPTION'
+ info = xc.evtchn_status(self.idx)
+ if info['status'] == 'unbound':
+ print 'notificationReceived> EXCEPTION closing...'
+ self.close()
+ return
+ self.handleNotification(type)
+
+ def close(self):
+ """Close the channel. Calls channelClosed() on the factory.
+ Override in subclass.
+ """
+ self.factory.channelClosed(self)
+
+ def handleNotification(self, type):
+ """Handle notification.
+ Define in subclass.
+ """
+ pass
+
+
+class VirqChannel(BaseChannel):
+ """A channel for handling a virq.
+ """
+
+ def __init__(self, factory, virq):
+ """Create a channel for the given virq using the given factory.
+
+ Do not call directly, use virqChannel on the factory.
+ """
+ BaseChannel.__init__(self, factory)
+ self.virq = virq
+ # Notification port (int).
+ self.port = xc.evtchn_bind_virq(virq)
+ self.idx = port
+ # Clients to call when a virq arrives.
+ self.clients = []
+
+ def __repr__(self):
+ return ('<VirqChannel virq=%d port=%d>'
+ % (self.virq, self.port))
+
+ def getVirq(self):
+ """Get the channel's virq.
+ """
+ return self.virq
+
+ def close(self):
+ """Close the channel. Calls lostChannel(self) on all its clients and
+ channelClosed() on the factory.
+ """
+ for c in self.clients:
+ c.lostChannel(self)
+ del self.clients
+ BaseChannel.close(self)
+
+ def registerClient(self, client):
+ """Register a client. The client will be called with
+ client.virqReceived(virq) when a virq is received.
+ The client will be called with client.lostChannel(self) if the
+ channel is closed.
+ """
+ self.clients.append(client)
+
+ def handleNotification(self, type):
+ for c in self.clients:
+ c.virqReceived(self.virq)
+
+ def notify(self):
+ xc.evtchn_send(self.port)
+
+
+class Channel(BaseChannel):
"""A control channel to a domain. Messages for the domain device controllers
are multiplexed over the channel (console, block devs, net devs).
"""
def __init__(self, factory, dom):
"""Create a channel to the given domain using the given factory.
+
+ Do not call directly, use domChannel on the factory.
"""
- self.factory = factory
+ BaseChannel.__init__(self, factory)
+ # Domain.
self.dom = dom
+ # Domain port (object).
self.port = self.factory.createPort(dom)
+ # Channel port (int).
self.idx = self.port.local_port
+ # Registered devices.
self.devs = []
+ # Devices indexed by the message types they handle.
self.devs_by_type = {}
- self.closed = 0
+ # Output queue.
self.queue = []
- def getIndex(self):
- """Get the channel index.
- """
- return self.idx
-
def getLocalPort(self):
"""Get the local port.
"""
@@ -153,23 +266,13 @@ class Channel:
self.port.local_port,
self.port.remote_port))
- def notificationReceived(self, type):
- #print 'notificationReceived> type=', type, self
- if self.closed: return
- if type == self.factory.notifier.EXCEPTION:
- print 'notificationReceived> EXCEPTION'
- info = xc.evtchn_status(self.idx)
- if info['status'] == 'unbound':
- print 'notificationReceived> EXCEPTION closing...'
- self.close()
- return
+ def handleNotification(self, type):
work = 0
work += self.handleRequests()
work += self.handleResponses()
work += self.handleWrites()
if work:
self.notify()
- #print 'notificationReceived<', work
def notify(self):
self.port.notify()